All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 00/10] spi: Add Allwinner A31 SPI driver
@ 2019-02-09 13:14 Jagan Teki
  2019-02-09 13:14 ` [U-Boot] [PATCH 01/10] spi: sun4i: Poll for rxfifo empty Jagan Teki
                   ` (9 more replies)
  0 siblings, 10 replies; 27+ messages in thread
From: Jagan Teki @ 2019-02-09 13:14 UTC (permalink / raw)
  To: u-boot

This series add support for Allwinner A31 SPI controller driver.

Compared to previous version[1] separate driver for A31, this patchset 
is trying to tune the existing sun4i_spi code by adding register set, 
register bits to support both A10, A31 SPI controllers.

Any inputs?
Jagan.

Jagan Teki (10):
  spi: sun4i: Poll for rxfifo empty
  clk: sunxi: Implement SPI clocks, resets
  spi: sun4i: Simplify reg writes using set/clrbits_le32
  spi: sun4i: Access registers and bits via enum offsets
  spi: sun4i: Support fifo_depth via drvdata
  spi: sun4i: Add CLK support
  spi: sun4: Add A31 spi controller support
  spi: sun4i: Driver cleanup
  spi: kconfig: Enable SUN4I_SPI by default if ARCH_SUNXI
  board: sopine: Enable SPI/SPI-FLASH

 .../sun50i-a64-sopine-baseboard-u-boot.dtsi   |  12 +
 configs/sopine_baseboard_defconfig            |   4 +
 drivers/clk/sunxi/clk_a10.c                   |  10 +
 drivers/clk/sunxi/clk_a10s.c                  |   7 +
 drivers/clk/sunxi/clk_a23.c                   |   7 +
 drivers/clk/sunxi/clk_a31.c                   |  13 +
 drivers/clk/sunxi/clk_a64.c                   |   7 +
 drivers/clk/sunxi/clk_a80.c                   |  13 +
 drivers/clk/sunxi/clk_a83t.c                  |   7 +
 drivers/clk/sunxi/clk_h3.c                    |   7 +
 drivers/clk/sunxi/clk_h6.c                    |   9 +
 drivers/clk/sunxi/clk_r40.c                   |  13 +
 drivers/clk/sunxi/clk_v3s.c                   |   4 +
 drivers/spi/Kconfig                           |   5 +-
 drivers/spi/sun4i_spi.c                       | 436 ++++++++++++------
 15 files changed, 418 insertions(+), 136 deletions(-)
 create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi

-- 
2.18.0.321.gffc6fa0e3

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

* [U-Boot] [PATCH 01/10] spi: sun4i: Poll for rxfifo empty
  2019-02-09 13:14 [U-Boot] [PATCH 00/10] spi: Add Allwinner A31 SPI driver Jagan Teki
@ 2019-02-09 13:14 ` Jagan Teki
  2019-02-13  1:11   ` André Przywara
  2019-02-09 13:14 ` [U-Boot] [PATCH 02/10] clk: sunxi: Implement SPI clocks, resets Jagan Teki
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2019-02-09 13:14 UTC (permalink / raw)
  To: u-boot

To drain rx fifo the fifo need to poll till the fifo
count become empty.

The current code is using wait_for_bit logic on control
register with exchange burst mode mask, which is not a
proper way of waiting for draining fifo.

So, add code for polling fifo status register till rxfifo
count become empty.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/spi/sun4i_spi.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
index 38cc743c61..87b396a96e 100644
--- a/drivers/spi/sun4i_spi.c
+++ b/drivers/spi/sun4i_spi.c
@@ -31,6 +31,8 @@
 
 #include <asm/arch/clock.h>
 
+#include <linux/iopoll.h>
+
 #define SUN4I_FIFO_DEPTH	64
 
 #define SUN4I_RXDATA_REG	0x00
@@ -46,7 +48,6 @@
 #define SUN4I_CTL_LMTF			BIT(6)
 #define SUN4I_CTL_TF_RST		BIT(8)
 #define SUN4I_CTL_RF_RST		BIT(9)
-#define SUN4I_CTL_XCH_MASK		0x0400
 #define SUN4I_CTL_XCH			BIT(10)
 #define SUN4I_CTL_CS_MASK		0x3000
 #define SUN4I_CTL_CS(cs)		(((cs) << 12) & SUN4I_CTL_CS_MASK)
@@ -308,7 +309,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
 	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
 
 	u32 len = bitlen / 8;
-	u32 reg;
+	u32 reg, rx_fifocnt;
 	u8 nbytes;
 	int ret;
 
@@ -343,10 +344,12 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
 		reg = readl(&priv->regs->ctl);
 		writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);
 
-		/* Wait transfer to complete */
-		ret = wait_for_bit_le32(&priv->regs->ctl, SUN4I_CTL_XCH_MASK,
-					false, SUN4I_SPI_TIMEOUT_US, false);
-		if (ret) {
+		/* Wait till RX FIFO to be empty */
+		ret = readl_poll_timeout(&priv->regs->ctl, rx_fifocnt,
+					 !(((rx_fifocnt & SUN4I_FIFO_STA_RF_CNT_MASK) >>
+					 SUN4I_FIFO_STA_RF_CNT_BITS) < nbytes),
+					 SUN4I_SPI_TIMEOUT_US);
+		if (ret < 0) {
 			printf("ERROR: sun4i_spi: Timeout transferring data\n");
 			sun4i_spi_set_cs(bus, slave_plat->cs, false);
 			return ret;
-- 
2.18.0.321.gffc6fa0e3

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

* [U-Boot] [PATCH 02/10] clk: sunxi: Implement SPI clocks, resets
  2019-02-09 13:14 [U-Boot] [PATCH 00/10] spi: Add Allwinner A31 SPI driver Jagan Teki
  2019-02-09 13:14 ` [U-Boot] [PATCH 01/10] spi: sun4i: Poll for rxfifo empty Jagan Teki
@ 2019-02-09 13:14 ` Jagan Teki
  2019-02-13  1:13   ` André Przywara
  2019-02-09 13:14 ` [U-Boot] [PATCH 03/10] spi: sun4i: Simplify reg writes using set/clrbits_le32 Jagan Teki
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2019-02-09 13:14 UTC (permalink / raw)
  To: u-boot

- Implement SPI AHB, MOD clocks via ccu_clk_gate for all
  supported Allwinner SoCs
- Implement SPI resets via ccu_reset for all supported
  Allwinner SoCs.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/clk/sunxi/clk_a10.c  | 10 ++++++++++
 drivers/clk/sunxi/clk_a10s.c |  7 +++++++
 drivers/clk/sunxi/clk_a23.c  |  7 +++++++
 drivers/clk/sunxi/clk_a31.c  | 13 +++++++++++++
 drivers/clk/sunxi/clk_a64.c  |  7 +++++++
 drivers/clk/sunxi/clk_a80.c  | 13 +++++++++++++
 drivers/clk/sunxi/clk_a83t.c |  7 +++++++
 drivers/clk/sunxi/clk_h3.c   |  7 +++++++
 drivers/clk/sunxi/clk_h6.c   |  9 +++++++++
 drivers/clk/sunxi/clk_r40.c  | 13 +++++++++++++
 drivers/clk/sunxi/clk_v3s.c  |  4 ++++
 11 files changed, 97 insertions(+)

diff --git a/drivers/clk/sunxi/clk_a10.c b/drivers/clk/sunxi/clk_a10.c
index 2aa41efe17..b8b57e2b31 100644
--- a/drivers/clk/sunxi/clk_a10.c
+++ b/drivers/clk/sunxi/clk_a10.c
@@ -22,6 +22,10 @@ static struct ccu_clk_gate a10_gates[] = {
 	[CLK_AHB_MMC1]		= GATE(0x060, BIT(9)),
 	[CLK_AHB_MMC2]		= GATE(0x060, BIT(10)),
 	[CLK_AHB_MMC3]		= GATE(0x060, BIT(11)),
+	[CLK_AHB_SPI0]		= GATE(0x060, BIT(20)),
+	[CLK_AHB_SPI1]		= GATE(0x060, BIT(21)),
+	[CLK_AHB_SPI2]		= GATE(0x060, BIT(22)),
+	[CLK_AHB_SPI3]		= GATE(0x060, BIT(23)),
 
 	[CLK_APB1_UART0]	= GATE(0x06c, BIT(16)),
 	[CLK_APB1_UART1]	= GATE(0x06c, BIT(17)),
@@ -32,9 +36,15 @@ static struct ccu_clk_gate a10_gates[] = {
 	[CLK_APB1_UART6]	= GATE(0x06c, BIT(22)),
 	[CLK_APB1_UART7]	= GATE(0x06c, BIT(23)),
 
+	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
+	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
+	[CLK_SPI2]		= GATE(0x0a8, BIT(31)),
+
 	[CLK_USB_OHCI0]		= GATE(0x0cc, BIT(6)),
 	[CLK_USB_OHCI1]		= GATE(0x0cc, BIT(7)),
 	[CLK_USB_PHY]		= GATE(0x0cc, BIT(8)),
+
+	[CLK_SPI3]		= GATE(0x0d4, BIT(31)),
 };
 
 static struct ccu_reset a10_resets[] = {
diff --git a/drivers/clk/sunxi/clk_a10s.c b/drivers/clk/sunxi/clk_a10s.c
index 87b74e52dc..c6fcede822 100644
--- a/drivers/clk/sunxi/clk_a10s.c
+++ b/drivers/clk/sunxi/clk_a10s.c
@@ -19,12 +19,19 @@ static struct ccu_clk_gate a10s_gates[] = {
 	[CLK_AHB_MMC0]		= GATE(0x060, BIT(8)),
 	[CLK_AHB_MMC1]		= GATE(0x060, BIT(9)),
 	[CLK_AHB_MMC2]		= GATE(0x060, BIT(10)),
+	[CLK_AHB_SPI0]		= GATE(0x060, BIT(20)),
+	[CLK_AHB_SPI1]		= GATE(0x060, BIT(21)),
+	[CLK_AHB_SPI2]		= GATE(0x060, BIT(22)),
 
 	[CLK_APB1_UART0]	= GATE(0x06c, BIT(16)),
 	[CLK_APB1_UART1]	= GATE(0x06c, BIT(17)),
 	[CLK_APB1_UART2]	= GATE(0x06c, BIT(18)),
 	[CLK_APB1_UART3]	= GATE(0x06c, BIT(19)),
 
+	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
+	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
+	[CLK_SPI2]		= GATE(0x0a8, BIT(31)),
+
 	[CLK_USB_OHCI]		= GATE(0x0cc, BIT(6)),
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
diff --git a/drivers/clk/sunxi/clk_a23.c b/drivers/clk/sunxi/clk_a23.c
index 1ef2359286..c16019215e 100644
--- a/drivers/clk/sunxi/clk_a23.c
+++ b/drivers/clk/sunxi/clk_a23.c
@@ -16,6 +16,8 @@ static struct ccu_clk_gate a23_gates[] = {
 	[CLK_BUS_MMC0]		= GATE(0x060, BIT(8)),
 	[CLK_BUS_MMC1]		= GATE(0x060, BIT(9)),
 	[CLK_BUS_MMC2]		= GATE(0x060, BIT(10)),
+	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
+	[CLK_BUS_SPI1]		= GATE(0x060, BIT(21)),
 	[CLK_BUS_OTG]		= GATE(0x060, BIT(24)),
 	[CLK_BUS_EHCI]		= GATE(0x060, BIT(26)),
 	[CLK_BUS_OHCI]		= GATE(0x060, BIT(29)),
@@ -26,6 +28,9 @@ static struct ccu_clk_gate a23_gates[] = {
 	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
 	[CLK_BUS_UART4]		= GATE(0x06c, BIT(20)),
 
+	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
+	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
+
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
 	[CLK_USB_HSIC]		= GATE(0x0cc, BIT(10)),
@@ -41,6 +46,8 @@ static struct ccu_reset a23_resets[] = {
 	[RST_BUS_MMC0]		= RESET(0x2c0, BIT(8)),
 	[RST_BUS_MMC1]		= RESET(0x2c0, BIT(9)),
 	[RST_BUS_MMC2]		= RESET(0x2c0, BIT(10)),
+	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
+	[RST_BUS_SPI1]		= RESET(0x2c0, BIT(21)),
 	[RST_BUS_OTG]		= RESET(0x2c0, BIT(24)),
 	[RST_BUS_EHCI]		= RESET(0x2c0, BIT(26)),
 	[RST_BUS_OHCI]		= RESET(0x2c0, BIT(29)),
diff --git a/drivers/clk/sunxi/clk_a31.c b/drivers/clk/sunxi/clk_a31.c
index 5bd8b7dccc..fa6e3eeef0 100644
--- a/drivers/clk/sunxi/clk_a31.c
+++ b/drivers/clk/sunxi/clk_a31.c
@@ -17,6 +17,10 @@ static struct ccu_clk_gate a31_gates[] = {
 	[CLK_AHB1_MMC1]		= GATE(0x060, BIT(9)),
 	[CLK_AHB1_MMC2]		= GATE(0x060, BIT(10)),
 	[CLK_AHB1_MMC3]		= GATE(0x060, BIT(11)),
+	[CLK_AHB1_SPI0]		= GATE(0x060, BIT(20)),
+	[CLK_AHB1_SPI1]		= GATE(0x060, BIT(21)),
+	[CLK_AHB1_SPI2]		= GATE(0x060, BIT(22)),
+	[CLK_AHB1_SPI3]		= GATE(0x060, BIT(23)),
 	[CLK_AHB1_OTG]		= GATE(0x060, BIT(24)),
 	[CLK_AHB1_EHCI0]	= GATE(0x060, BIT(26)),
 	[CLK_AHB1_EHCI1]	= GATE(0x060, BIT(27)),
@@ -31,6 +35,11 @@ static struct ccu_clk_gate a31_gates[] = {
 	[CLK_APB2_UART4]	= GATE(0x06c, BIT(20)),
 	[CLK_APB2_UART5]	= GATE(0x06c, BIT(21)),
 
+	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
+	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
+	[CLK_SPI2]		= GATE(0x0a8, BIT(31)),
+	[CLK_SPI3]		= GATE(0x0ac, BIT(31)),
+
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
 	[CLK_USB_PHY2]		= GATE(0x0cc, BIT(10)),
@@ -48,6 +57,10 @@ static struct ccu_reset a31_resets[] = {
 	[RST_AHB1_MMC1]		= RESET(0x2c0, BIT(9)),
 	[RST_AHB1_MMC2]		= RESET(0x2c0, BIT(10)),
 	[RST_AHB1_MMC3]		= RESET(0x2c0, BIT(11)),
+	[RST_AHB1_SPI0]		= RESET(0x2c0, BIT(20)),
+	[RST_AHB1_SPI1]		= RESET(0x2c0, BIT(21)),
+	[RST_AHB1_SPI2]		= RESET(0x2c0, BIT(22)),
+	[RST_AHB1_SPI3]		= RESET(0x2c0, BIT(23)),
 	[RST_AHB1_OTG]		= RESET(0x2c0, BIT(24)),
 	[RST_AHB1_EHCI0]	= RESET(0x2c0, BIT(26)),
 	[RST_AHB1_EHCI1]	= RESET(0x2c0, BIT(27)),
diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
index 910275fbce..322d6cd557 100644
--- a/drivers/clk/sunxi/clk_a64.c
+++ b/drivers/clk/sunxi/clk_a64.c
@@ -16,6 +16,8 @@ static const struct ccu_clk_gate a64_gates[] = {
 	[CLK_BUS_MMC0]		= GATE(0x060, BIT(8)),
 	[CLK_BUS_MMC1]		= GATE(0x060, BIT(9)),
 	[CLK_BUS_MMC2]		= GATE(0x060, BIT(10)),
+	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
+	[CLK_BUS_SPI1]		= GATE(0x060, BIT(21)),
 	[CLK_BUS_OTG]		= GATE(0x060, BIT(23)),
 	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(24)),
 	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(25)),
@@ -28,6 +30,9 @@ static const struct ccu_clk_gate a64_gates[] = {
 	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
 	[CLK_BUS_UART4]		= GATE(0x06c, BIT(20)),
 
+	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
+	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
+
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
 	[CLK_USB_HSIC]		= GATE(0x0cc, BIT(10)),
@@ -44,6 +49,8 @@ static const struct ccu_reset a64_resets[] = {
 	[RST_BUS_MMC0]		= RESET(0x2c0, BIT(8)),
 	[RST_BUS_MMC1]		= RESET(0x2c0, BIT(9)),
 	[RST_BUS_MMC2]		= RESET(0x2c0, BIT(10)),
+	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
+	[RST_BUS_SPI1]		= RESET(0x2c0, BIT(21)),
 	[RST_BUS_OTG]           = RESET(0x2c0, BIT(23)),
 	[RST_BUS_EHCI0]         = RESET(0x2c0, BIT(24)),
 	[RST_BUS_EHCI1]         = RESET(0x2c0, BIT(25)),
diff --git a/drivers/clk/sunxi/clk_a80.c b/drivers/clk/sunxi/clk_a80.c
index aec1d80c46..fb76aad528 100644
--- a/drivers/clk/sunxi/clk_a80.c
+++ b/drivers/clk/sunxi/clk_a80.c
@@ -13,7 +13,16 @@
 #include <dt-bindings/reset/sun9i-a80-ccu.h>
 
 static const struct ccu_clk_gate a80_gates[] = {
+	[CLK_SPI0]		= GATE(0x430, BIT(31)),
+	[CLK_SPI1]		= GATE(0x434, BIT(31)),
+	[CLK_SPI2]		= GATE(0x438, BIT(31)),
+	[CLK_SPI3]		= GATE(0x43c, BIT(31)),
+
 	[CLK_BUS_MMC]		= GATE(0x580, BIT(8)),
+	[CLK_BUS_SPI0]		= GATE(0x580, BIT(20)),
+	[CLK_BUS_SPI1]		= GATE(0x580, BIT(21)),
+	[CLK_BUS_SPI2]		= GATE(0x580, BIT(22)),
+	[CLK_BUS_SPI3]		= GATE(0x580, BIT(23)),
 
 	[CLK_BUS_UART0]		= GATE(0x594, BIT(16)),
 	[CLK_BUS_UART1]		= GATE(0x594, BIT(17)),
@@ -25,6 +34,10 @@ static const struct ccu_clk_gate a80_gates[] = {
 
 static const struct ccu_reset a80_resets[] = {
 	[RST_BUS_MMC]		= RESET(0x5a0, BIT(8)),
+	[RST_BUS_SPI0]		= RESET(0x5a0, BIT(20)),
+	[RST_BUS_SPI1]		= RESET(0x5a0, BIT(21)),
+	[RST_BUS_SPI2]		= RESET(0x5a0, BIT(22)),
+	[RST_BUS_SPI3]		= RESET(0x5a0, BIT(23)),
 
 	[RST_BUS_UART0]		= RESET(0x5b4, BIT(16)),
 	[RST_BUS_UART1]		= RESET(0x5b4, BIT(17)),
diff --git a/drivers/clk/sunxi/clk_a83t.c b/drivers/clk/sunxi/clk_a83t.c
index b5a555da36..36f7e14c45 100644
--- a/drivers/clk/sunxi/clk_a83t.c
+++ b/drivers/clk/sunxi/clk_a83t.c
@@ -16,6 +16,8 @@ static struct ccu_clk_gate a83t_gates[] = {
 	[CLK_BUS_MMC0]		= GATE(0x060, BIT(8)),
 	[CLK_BUS_MMC1]		= GATE(0x060, BIT(9)),
 	[CLK_BUS_MMC2]		= GATE(0x060, BIT(10)),
+	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
+	[CLK_BUS_SPI1]		= GATE(0x060, BIT(21)),
 	[CLK_BUS_OTG]		= GATE(0x060, BIT(24)),
 	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(26)),
 	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(27)),
@@ -27,6 +29,9 @@ static struct ccu_clk_gate a83t_gates[] = {
 	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
 	[CLK_BUS_UART4]		= GATE(0x06c, BIT(20)),
 
+	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
+	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
+
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
 	[CLK_USB_HSIC]		= GATE(0x0cc, BIT(10)),
@@ -42,6 +47,8 @@ static struct ccu_reset a83t_resets[] = {
 	[RST_BUS_MMC0]		= RESET(0x2c0, BIT(8)),
 	[RST_BUS_MMC1]		= RESET(0x2c0, BIT(9)),
 	[RST_BUS_MMC2]		= RESET(0x2c0, BIT(10)),
+	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
+	[RST_BUS_SPI1]		= RESET(0x2c0, BIT(21)),
 	[RST_BUS_OTG]		= RESET(0x2c0, BIT(24)),
 	[RST_BUS_EHCI0]		= RESET(0x2c0, BIT(26)),
 	[RST_BUS_EHCI1]		= RESET(0x2c0, BIT(27)),
diff --git a/drivers/clk/sunxi/clk_h3.c b/drivers/clk/sunxi/clk_h3.c
index 416aec2b89..5f99ef7342 100644
--- a/drivers/clk/sunxi/clk_h3.c
+++ b/drivers/clk/sunxi/clk_h3.c
@@ -16,6 +16,8 @@ static struct ccu_clk_gate h3_gates[] = {
 	[CLK_BUS_MMC0]		= GATE(0x060, BIT(8)),
 	[CLK_BUS_MMC1]		= GATE(0x060, BIT(9)),
 	[CLK_BUS_MMC2]		= GATE(0x060, BIT(10)),
+	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
+	[CLK_BUS_SPI1]		= GATE(0x060, BIT(21)),
 	[CLK_BUS_OTG]		= GATE(0x060, BIT(23)),
 	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(24)),
 	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(25)),
@@ -31,6 +33,9 @@ static struct ccu_clk_gate h3_gates[] = {
 	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
 	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
 
+	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
+	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
+
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
 	[CLK_USB_PHY2]		= GATE(0x0cc, BIT(10)),
@@ -50,6 +55,8 @@ static struct ccu_reset h3_resets[] = {
 	[RST_BUS_MMC0]		= RESET(0x2c0, BIT(8)),
 	[RST_BUS_MMC1]		= RESET(0x2c0, BIT(9)),
 	[RST_BUS_MMC2]		= RESET(0x2c0, BIT(10)),
+	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
+	[RST_BUS_SPI1]		= RESET(0x2c0, BIT(21)),
 	[RST_BUS_OTG]		= RESET(0x2c0, BIT(23)),
 	[RST_BUS_EHCI0]		= RESET(0x2c0, BIT(24)),
 	[RST_BUS_EHCI1]		= RESET(0x2c0, BIT(25)),
diff --git a/drivers/clk/sunxi/clk_h6.c b/drivers/clk/sunxi/clk_h6.c
index 902612da91..71f0c78656 100644
--- a/drivers/clk/sunxi/clk_h6.c
+++ b/drivers/clk/sunxi/clk_h6.c
@@ -20,6 +20,12 @@ static struct ccu_clk_gate h6_gates[] = {
 	[CLK_BUS_UART1]		= GATE(0x90c, BIT(1)),
 	[CLK_BUS_UART2]		= GATE(0x90c, BIT(2)),
 	[CLK_BUS_UART3]		= GATE(0x90c, BIT(3)),
+
+	[CLK_SPI0]		= GATE(0x940, BIT(31)),
+	[CLK_SPI1]		= GATE(0x944, BIT(31)),
+
+	[CLK_BUS_SPI0]		= GATE(0x96c, BIT(0)),
+	[CLK_BUS_SPI1]		= GATE(0x96c, BIT(1)),
 };
 
 static struct ccu_reset h6_resets[] = {
@@ -30,6 +36,9 @@ static struct ccu_reset h6_resets[] = {
 	[RST_BUS_UART1]		= RESET(0x90c, BIT(17)),
 	[RST_BUS_UART2]		= RESET(0x90c, BIT(18)),
 	[RST_BUS_UART3]		= RESET(0x90c, BIT(19)),
+
+	[RST_BUS_SPI0]		= RESET(0x96c, BIT(16)),
+	[RST_BUS_SPI1]		= RESET(0x96c, BIT(17)),
 };
 
 static const struct ccu_desc h6_ccu_desc = {
diff --git a/drivers/clk/sunxi/clk_r40.c b/drivers/clk/sunxi/clk_r40.c
index b9457e1971..92907281f1 100644
--- a/drivers/clk/sunxi/clk_r40.c
+++ b/drivers/clk/sunxi/clk_r40.c
@@ -17,6 +17,10 @@ static struct ccu_clk_gate r40_gates[] = {
 	[CLK_BUS_MMC1]		= GATE(0x060, BIT(9)),
 	[CLK_BUS_MMC2]		= GATE(0x060, BIT(10)),
 	[CLK_BUS_MMC3]		= GATE(0x060, BIT(11)),
+	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
+	[CLK_BUS_SPI1]		= GATE(0x060, BIT(21)),
+	[CLK_BUS_SPI2]		= GATE(0x060, BIT(22)),
+	[CLK_BUS_SPI3]		= GATE(0x060, BIT(23)),
 	[CLK_BUS_OTG]		= GATE(0x060, BIT(25)),
 	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(26)),
 	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(27)),
@@ -34,6 +38,11 @@ static struct ccu_clk_gate r40_gates[] = {
 	[CLK_BUS_UART6]		= GATE(0x06c, BIT(22)),
 	[CLK_BUS_UART7]		= GATE(0x06c, BIT(23)),
 
+	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
+	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
+	[CLK_SPI2]		= GATE(0x0a8, BIT(31)),
+	[CLK_SPI3]		= GATE(0x0ac, BIT(31)),
+
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
 	[CLK_USB_PHY2]		= GATE(0x0cc, BIT(10)),
@@ -51,6 +60,10 @@ static struct ccu_reset r40_resets[] = {
 	[RST_BUS_MMC1]		= RESET(0x2c0, BIT(9)),
 	[RST_BUS_MMC2]		= RESET(0x2c0, BIT(10)),
 	[RST_BUS_MMC3]		= RESET(0x2c0, BIT(11)),
+	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
+	[RST_BUS_SPI1]		= RESET(0x2c0, BIT(21)),
+	[RST_BUS_SPI2]		= RESET(0x2c0, BIT(22)),
+	[RST_BUS_SPI3]		= RESET(0x2c0, BIT(23)),
 	[RST_BUS_OTG]		= RESET(0x2c0, BIT(25)),
 	[RST_BUS_EHCI0]		= RESET(0x2c0, BIT(26)),
 	[RST_BUS_EHCI1]		= RESET(0x2c0, BIT(27)),
diff --git a/drivers/clk/sunxi/clk_v3s.c b/drivers/clk/sunxi/clk_v3s.c
index c8a9027889..789ac72026 100644
--- a/drivers/clk/sunxi/clk_v3s.c
+++ b/drivers/clk/sunxi/clk_v3s.c
@@ -16,12 +16,15 @@ static struct ccu_clk_gate v3s_gates[] = {
 	[CLK_BUS_MMC0]		= GATE(0x060, BIT(8)),
 	[CLK_BUS_MMC1]		= GATE(0x060, BIT(9)),
 	[CLK_BUS_MMC2]		= GATE(0x060, BIT(10)),
+	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
 	[CLK_BUS_OTG]		= GATE(0x060, BIT(24)),
 
 	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
 	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
 	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
 
+	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
+
 	[CLK_USB_PHY0]          = GATE(0x0cc, BIT(8)),
 };
 
@@ -31,6 +34,7 @@ static struct ccu_reset v3s_resets[] = {
 	[RST_BUS_MMC0]		= RESET(0x2c0, BIT(8)),
 	[RST_BUS_MMC1]		= RESET(0x2c0, BIT(9)),
 	[RST_BUS_MMC2]		= RESET(0x2c0, BIT(10)),
+	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
 	[RST_BUS_OTG]		= RESET(0x2c0, BIT(24)),
 
 	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
-- 
2.18.0.321.gffc6fa0e3

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

* [U-Boot] [PATCH 03/10] spi: sun4i: Simplify reg writes using set/clrbits_le32
  2019-02-09 13:14 [U-Boot] [PATCH 00/10] spi: Add Allwinner A31 SPI driver Jagan Teki
  2019-02-09 13:14 ` [U-Boot] [PATCH 01/10] spi: sun4i: Poll for rxfifo empty Jagan Teki
  2019-02-09 13:14 ` [U-Boot] [PATCH 02/10] clk: sunxi: Implement SPI clocks, resets Jagan Teki
@ 2019-02-09 13:14 ` Jagan Teki
  2019-02-13  1:14   ` André Przywara
  2019-02-09 13:14 ` [U-Boot] [PATCH 04/10] spi: sun4i: Access registers and bits via enum offsets Jagan Teki
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2019-02-09 13:14 UTC (permalink / raw)
  To: u-boot

Update the existing register writes using setbits_le32 and
clrbits_le32 in required places.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/spi/sun4i_spi.c | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
index 87b396a96e..5446cebe7c 100644
--- a/drivers/spi/sun4i_spi.c
+++ b/drivers/spi/sun4i_spi.c
@@ -283,20 +283,18 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
 {
 	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
 
-	writel(SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER | SUN4I_CTL_TP |
-	       SUN4I_CTL_CS_MANUAL | SUN4I_CTL_CS_ACTIVE_LOW,
-	       &priv->regs->ctl);
+	setbits_le32(&priv->regs->ctl, SUN4I_CTL_ENABLE |
+		     SUN4I_CTL_MASTER | SUN4I_CTL_TP |
+		     SUN4I_CTL_CS_MANUAL | SUN4I_CTL_CS_ACTIVE_LOW);
+
 	return 0;
 }
 
 static int sun4i_spi_release_bus(struct udevice *dev)
 {
 	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
-	u32 reg;
 
-	reg = readl(&priv->regs->ctl);
-	reg &= ~SUN4I_CTL_ENABLE;
-	writel(reg, &priv->regs->ctl);
+	clrbits_le32(&priv->regs->ctl, SUN4I_CTL_ENABLE);
 
 	return 0;
 }
@@ -309,7 +307,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
 	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
 
 	u32 len = bitlen / 8;
-	u32 reg, rx_fifocnt;
+	u32 rx_fifocnt;
 	u8 nbytes;
 	int ret;
 
@@ -324,10 +322,8 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
 	if (flags & SPI_XFER_BEGIN)
 		sun4i_spi_set_cs(bus, slave_plat->cs, true);
 
-	reg = readl(&priv->regs->ctl);
-
 	/* Reset FIFOs */
-	writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->ctl);
+	setbits_le32(&priv->regs->ctl, SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST);
 
 	while (len) {
 		/* Setup the transfer now... */
@@ -341,8 +337,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
 		sun4i_spi_fill_fifo(priv, nbytes);
 
 		/* Start the transfer */
-		reg = readl(&priv->regs->ctl);
-		writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);
+		setbits_le32(&priv->regs->ctl, SUN4I_CTL_XCH);
 
 		/* Wait till RX FIFO to be empty */
 		ret = readl_poll_timeout(&priv->regs->ctl, rx_fifocnt,
-- 
2.18.0.321.gffc6fa0e3

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

* [U-Boot] [PATCH 04/10] spi: sun4i: Access registers and bits via enum offsets
  2019-02-09 13:14 [U-Boot] [PATCH 00/10] spi: Add Allwinner A31 SPI driver Jagan Teki
                   ` (2 preceding siblings ...)
  2019-02-09 13:14 ` [U-Boot] [PATCH 03/10] spi: sun4i: Simplify reg writes using set/clrbits_le32 Jagan Teki
@ 2019-02-09 13:14 ` Jagan Teki
  2019-02-13  1:15   ` André Przywara
  2019-02-09 13:14 ` [U-Boot] [PATCH 05/10] spi: sun4i: Support fifo_depth via drvdata Jagan Teki
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2019-02-09 13:14 UTC (permalink / raw)
  To: u-boot

Allwinner support two different SPI controllers one for A10 and
another for A31 with minimal changes in register offsets and
respective register bits, but the logic for accessing the SPI
master via SPI slave remains nearly similar.

Add enum offsets for register set and register bits, so-that
it can access both classes of SPI controllers.

Assign same control register for global, transfer and fifo control
registers to make the same code compatible with A31 SPI controller.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/spi/sun4i_spi.c | 162 +++++++++++++++++++++++++++++-----------
 1 file changed, 120 insertions(+), 42 deletions(-)

diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
index 5446cebe7c..c06028890b 100644
--- a/drivers/spi/sun4i_spi.c
+++ b/drivers/spi/sun4i_spi.c
@@ -83,7 +83,6 @@
 #define SUN4I_XMIT_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
 
 #define SUN4I_FIFO_STA_REG	0x28
-#define SUN4I_FIFO_STA_RF_CNT_MASK	0x7f
 #define SUN4I_FIFO_STA_RF_CNT_BITS	0
 #define SUN4I_FIFO_STA_TF_CNT_MASK	0x7f
 #define SUN4I_FIFO_STA_TF_CNT_BITS	16
@@ -93,28 +92,49 @@
 #define SUN4I_SPI_DEFAULT_RATE	1000000
 #define SUN4I_SPI_TIMEOUT_US	1000000
 
-/* sun4i spi register set */
-struct sun4i_spi_regs {
-	u32 rxdata;
-	u32 txdata;
-	u32 ctl;
-	u32 intctl;
-	u32 st;
-	u32 dmactl;
-	u32 wait;
-	u32 cctl;
-	u32 bc;
-	u32 tc;
-	u32 fifo_sta;
+/* sun spi register set */
+enum sun4i_spi_regs {
+	SPI_GCR,
+	SPI_TCR,
+	SPI_FCR,
+	SPI_FSR,
+	SPI_CCR,
+	SPI_BC,
+	SPI_TC,
+	SPI_BCTL,
+	SPI_TXD,
+	SPI_RXD,
+};
+
+/* sun spi register bits */
+enum sun4i_spi_bits {
+	SPI_GCR_TP,
+	SPI_TCR_CPHA,
+	SPI_TCR_CPOL,
+	SPI_TCR_CS_ACTIVE_LOW,
+	SPI_TCR_CS_SEL,
+	SPI_TCR_CS_MASK,
+	SPI_TCR_XCH,
+	SPI_TCR_CS_MANUAL,
+	SPI_TCR_CS_LEVEL,
+	SPI_FCR_TF_RST,
+	SPI_FCR_RF_RST,
+	SPI_FSR_RF_CNT_MASK,
+};
+
+struct sun4i_spi_variant {
+	const unsigned long *regs, *bits;
 };
 
 struct sun4i_spi_platdata {
+	struct sun4i_spi_variant *variant;
 	u32 base_addr;
 	u32 max_hz;
 };
 
 struct sun4i_spi_priv {
-	struct sun4i_spi_regs *regs;
+	struct sun4i_spi_variant *variant;
+	u32 base_addr;
 	u32 freq;
 	u32 mode;
 
@@ -126,10 +146,11 @@ DECLARE_GLOBAL_DATA_PTR;
 
 static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 {
+	struct sun4i_spi_variant *variant = priv->variant;
 	u8 byte;
 
 	while (len--) {
-		byte = readb(&priv->regs->rxdata);
+		byte = readb(priv->base_addr + variant->regs[SPI_RXD]);
 		if (priv->rx_buf)
 			*priv->rx_buf++ = byte;
 	}
@@ -137,30 +158,33 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
 static inline void sun4i_spi_fill_fifo(struct sun4i_spi_priv *priv, int len)
 {
+	struct sun4i_spi_variant *variant = priv->variant;
 	u8 byte;
 
 	while (len--) {
 		byte = priv->tx_buf ? *priv->tx_buf++ : 0;
-		writeb(byte, &priv->regs->txdata);
+		writeb(byte, priv->base_addr + variant->regs[SPI_TXD]);
 	}
 }
 
 static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
 {
 	struct sun4i_spi_priv *priv = dev_get_priv(bus);
+	struct sun4i_spi_variant *variant = priv->variant;
 	u32 reg;
 
-	reg = readl(&priv->regs->ctl);
+	reg = readl(priv->base_addr + variant->regs[SPI_TCR]);
 
-	reg &= ~SUN4I_CTL_CS_MASK;
-	reg |= SUN4I_CTL_CS(cs);
+	reg &= ~variant->bits[SPI_TCR_CS_MASK];
+	reg |= ((cs << variant->bits[SPI_TCR_CS_SEL]) &
+		variant->bits[SPI_TCR_CS_MASK]);
 
 	if (enable)
-		reg &= ~SUN4I_CTL_CS_LEVEL;
+		reg &= ~variant->bits[SPI_TCR_CS_LEVEL];
 	else
-		reg |= SUN4I_CTL_CS_LEVEL;
+		reg |= variant->bits[SPI_TCR_CS_LEVEL];
 
-	writel(reg, &priv->regs->ctl);
+	writel(reg, priv->base_addr + variant->regs[SPI_TCR]);
 }
 
 static int sun4i_spi_parse_pins(struct udevice *dev)
@@ -255,6 +279,7 @@ static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
 	int node = dev_of_offset(bus);
 
 	plat->base_addr = devfdt_get_addr(bus);
+	plat->variant = (struct sun4i_spi_variant *)dev_get_driver_data(bus);
 	plat->max_hz = fdtdec_get_int(gd->fdt_blob, node,
 				      "spi-max-frequency",
 				      SUN4I_SPI_DEFAULT_RATE);
@@ -273,7 +298,8 @@ static int sun4i_spi_probe(struct udevice *bus)
 	sun4i_spi_enable_clock();
 	sun4i_spi_parse_pins(bus);
 
-	priv->regs = (struct sun4i_spi_regs *)(uintptr_t)plat->base_addr;
+	priv->variant = plat->variant;
+	priv->base_addr = plat->base_addr;
 	priv->freq = plat->max_hz;
 
 	return 0;
@@ -282,10 +308,15 @@ static int sun4i_spi_probe(struct udevice *bus)
 static int sun4i_spi_claim_bus(struct udevice *dev)
 {
 	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
+	struct sun4i_spi_variant *variant = priv->variant;
+
+	setbits_le32(priv->base_addr + variant->regs[SPI_GCR],
+		     SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER |
+		     variant->bits[SPI_GCR_TP]);
 
-	setbits_le32(&priv->regs->ctl, SUN4I_CTL_ENABLE |
-		     SUN4I_CTL_MASTER | SUN4I_CTL_TP |
-		     SUN4I_CTL_CS_MANUAL | SUN4I_CTL_CS_ACTIVE_LOW);
+	setbits_le32(priv->base_addr + variant->regs[SPI_TCR],
+		     variant->bits[SPI_TCR_CS_MANUAL] |
+		     variant->bits[SPI_TCR_CS_ACTIVE_LOW]);
 
 	return 0;
 }
@@ -293,8 +324,10 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
 static int sun4i_spi_release_bus(struct udevice *dev)
 {
 	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
+	struct sun4i_spi_variant *variant = priv->variant;
 
-	clrbits_le32(&priv->regs->ctl, SUN4I_CTL_ENABLE);
+	clrbits_le32(priv->base_addr + variant->regs[SPI_GCR],
+		     SUN4I_CTL_ENABLE);
 
 	return 0;
 }
@@ -304,6 +337,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
 {
 	struct udevice *bus = dev->parent;
 	struct sun4i_spi_priv *priv = dev_get_priv(bus);
+	struct sun4i_spi_variant *variant = priv->variant;
 	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
 
 	u32 len = bitlen / 8;
@@ -323,25 +357,32 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
 		sun4i_spi_set_cs(bus, slave_plat->cs, true);
 
 	/* Reset FIFOs */
-	setbits_le32(&priv->regs->ctl, SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST);
+	setbits_le32(priv->base_addr + variant->regs[SPI_FCR],
+		     variant->bits[SPI_FCR_RF_RST] |
+		     variant->bits[SPI_FCR_TF_RST]);
 
 	while (len) {
 		/* Setup the transfer now... */
 		nbytes = min(len, (u32)(SUN4I_FIFO_DEPTH - 1));
 
 		/* Setup the counters */
-		writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bc);
-		writel(SUN4I_XMIT_CNT(nbytes), &priv->regs->tc);
+		writel(SUN4I_BURST_CNT(nbytes),
+		       priv->base_addr + variant->regs[SPI_BC]);
+		writel(SUN4I_XMIT_CNT(nbytes),
+		       priv->base_addr + variant->regs[SPI_TC]);
 
 		/* Fill the TX FIFO */
 		sun4i_spi_fill_fifo(priv, nbytes);
 
 		/* Start the transfer */
-		setbits_le32(&priv->regs->ctl, SUN4I_CTL_XCH);
+		setbits_le32(priv->base_addr + variant->regs[SPI_TCR],
+			     variant->bits[SPI_TCR_XCH]);
 
 		/* Wait till RX FIFO to be empty */
-		ret = readl_poll_timeout(&priv->regs->ctl, rx_fifocnt,
-					 !(((rx_fifocnt & SUN4I_FIFO_STA_RF_CNT_MASK) >>
+		ret = readl_poll_timeout(priv->base_addr + variant->regs[SPI_FSR],
+					 rx_fifocnt,
+					 !(((rx_fifocnt &
+					 variant->bits[SPI_FSR_RF_CNT_MASK]) >>
 					 SUN4I_FIFO_STA_RF_CNT_BITS) < nbytes),
 					 SUN4I_SPI_TIMEOUT_US);
 		if (ret < 0) {
@@ -366,6 +407,7 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
 {
 	struct sun4i_spi_platdata *plat = dev_get_platdata(dev);
 	struct sun4i_spi_priv *priv = dev_get_priv(dev);
+	struct sun4i_spi_variant *variant = priv->variant;
 	unsigned int div;
 	u32 reg;
 
@@ -390,7 +432,7 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
 	 */
 
 	div = SUN4I_SPI_MAX_RATE / (2 * speed);
-	reg = readl(&priv->regs->cctl);
+	reg = readl(priv->base_addr + variant->regs[SPI_CCR]);
 
 	if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
 		if (div > 0)
@@ -405,7 +447,7 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
 	}
 
 	priv->freq = speed;
-	writel(reg, &priv->regs->cctl);
+	writel(reg, priv->base_addr + variant->regs[SPI_CCR]);
 
 	return 0;
 }
@@ -413,19 +455,20 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
 static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
 {
 	struct sun4i_spi_priv *priv = dev_get_priv(dev);
+	struct sun4i_spi_variant *variant = priv->variant;
 	u32 reg;
 
-	reg = readl(&priv->regs->ctl);
-	reg &= ~(SUN4I_CTL_CPOL | SUN4I_CTL_CPHA);
+	reg = readl(priv->base_addr + variant->regs[SPI_TCR]);
+	reg &= ~(variant->bits[SPI_TCR_CPOL] | variant->bits[SPI_TCR_CPHA]);
 
 	if (mode & SPI_CPOL)
-		reg |= SUN4I_CTL_CPOL;
+		reg |= variant->bits[SPI_TCR_CPOL];
 
 	if (mode & SPI_CPHA)
-		reg |= SUN4I_CTL_CPHA;
+		reg |= variant->bits[SPI_TCR_CPHA];
 
 	priv->mode = mode;
-	writel(reg, &priv->regs->ctl);
+	writel(reg, priv->base_addr + variant->regs[SPI_TCR]);
 
 	return 0;
 }
@@ -438,8 +481,43 @@ static const struct dm_spi_ops sun4i_spi_ops = {
 	.set_mode		= sun4i_spi_set_mode,
 };
 
+static const unsigned long sun4i_spi_regs[] = {
+	[SPI_GCR]		= SUN4I_CTL_REG,
+	[SPI_TCR]		= SUN4I_CTL_REG,
+	[SPI_FCR]		= SUN4I_CTL_REG,
+	[SPI_FSR]		= SUN4I_FIFO_STA_REG,
+	[SPI_CCR]		= SUN4I_CLK_CTL_REG,
+	[SPI_BC]		= SUN4I_BURST_CNT_REG,
+	[SPI_TC]		= SUN4I_XMIT_CNT_REG,
+	[SPI_TXD]		= SUN4I_TXDATA_REG,
+	[SPI_RXD]		= SUN4I_RXDATA_REG,
+};
+
+static const unsigned long sun4i_spi_bits[] = {
+	[SPI_GCR_TP]		= BIT(18),
+	[SPI_TCR_CPHA]		= BIT(2),
+	[SPI_TCR_CPOL]		= BIT(3),
+	[SPI_TCR_CS_ACTIVE_LOW] = BIT(4),
+	[SPI_TCR_XCH]		= BIT(10),
+	[SPI_TCR_CS_SEL]	= 12,
+	[SPI_TCR_CS_MASK]	= 0x3000,
+	[SPI_TCR_CS_MANUAL]	= BIT(16),
+	[SPI_TCR_CS_LEVEL]	= BIT(17),
+	[SPI_FCR_TF_RST]	= BIT(8),
+	[SPI_FCR_RF_RST]	= BIT(9),
+	[SPI_FSR_RF_CNT_MASK]	= GENMASK(6, 0),
+};
+
+static const struct sun4i_spi_variant sun4i_a10_spi_variant = {
+	.regs			= sun4i_spi_regs,
+	.bits			= sun4i_spi_bits,
+};
+
 static const struct udevice_id sun4i_spi_ids[] = {
-	{ .compatible = "allwinner,sun4i-a10-spi"  },
+	{
+	  .compatible = "allwinner,sun4i-a10-spi",
+	  .data = (ulong)&sun4i_a10_spi_variant,
+	},
 	{ }
 };
 
-- 
2.18.0.321.gffc6fa0e3

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

* [U-Boot] [PATCH 05/10] spi: sun4i: Support fifo_depth via drvdata
  2019-02-09 13:14 [U-Boot] [PATCH 00/10] spi: Add Allwinner A31 SPI driver Jagan Teki
                   ` (3 preceding siblings ...)
  2019-02-09 13:14 ` [U-Boot] [PATCH 04/10] spi: sun4i: Access registers and bits via enum offsets Jagan Teki
@ 2019-02-09 13:14 ` Jagan Teki
  2019-02-13  1:16   ` André Przywara
  2019-02-09 13:14 ` [U-Boot] [PATCH 06/10] spi: sun4i: Add CLK support Jagan Teki
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2019-02-09 13:14 UTC (permalink / raw)
  To: u-boot

Support fifo_depth via drvdata instead of macro definition, this would
eventually reduce another macro definition for new SPI controller fifo
depth support addition.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/spi/sun4i_spi.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
index c06028890b..d3cf25db6f 100644
--- a/drivers/spi/sun4i_spi.c
+++ b/drivers/spi/sun4i_spi.c
@@ -33,8 +33,6 @@
 
 #include <linux/iopoll.h>
 
-#define SUN4I_FIFO_DEPTH	64
-
 #define SUN4I_RXDATA_REG	0x00
 
 #define SUN4I_TXDATA_REG	0x04
@@ -124,6 +122,7 @@ enum sun4i_spi_bits {
 
 struct sun4i_spi_variant {
 	const unsigned long *regs, *bits;
+	u32 fifo_depth;
 };
 
 struct sun4i_spi_platdata {
@@ -363,7 +362,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
 
 	while (len) {
 		/* Setup the transfer now... */
-		nbytes = min(len, (u32)(SUN4I_FIFO_DEPTH - 1));
+		nbytes = min(len, (priv->variant->fifo_depth - 1));
 
 		/* Setup the counters */
 		writel(SUN4I_BURST_CNT(nbytes),
@@ -511,6 +510,7 @@ static const unsigned long sun4i_spi_bits[] = {
 static const struct sun4i_spi_variant sun4i_a10_spi_variant = {
 	.regs			= sun4i_spi_regs,
 	.bits			= sun4i_spi_bits,
+	.fifo_depth		= 64,
 };
 
 static const struct udevice_id sun4i_spi_ids[] = {
-- 
2.18.0.321.gffc6fa0e3

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

* [U-Boot] [PATCH 06/10] spi: sun4i: Add CLK support
  2019-02-09 13:14 [U-Boot] [PATCH 00/10] spi: Add Allwinner A31 SPI driver Jagan Teki
                   ` (4 preceding siblings ...)
  2019-02-09 13:14 ` [U-Boot] [PATCH 05/10] spi: sun4i: Support fifo_depth via drvdata Jagan Teki
@ 2019-02-09 13:14 ` Jagan Teki
  2019-02-13  1:19   ` André Przywara
  2019-02-09 13:14 ` [U-Boot] [PATCH 07/10] spi: sun4: Add A31 spi controller support Jagan Teki
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2019-02-09 13:14 UTC (permalink / raw)
  To: u-boot

Add CLK support to enable AHB and MOD SPI clocks on sun4i_spi driver.

Note, that the code will enable and disable clock in claim and release
calls to make proper clock and reset handling between claiming and
releasing SPI bus.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/spi/sun4i_spi.c | 56 +++++++++++++++++++++++++++++++++++------
 1 file changed, 48 insertions(+), 8 deletions(-)

diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
index d3cf25db6f..aeed68764c 100644
--- a/drivers/spi/sun4i_spi.c
+++ b/drivers/spi/sun4i_spi.c
@@ -19,6 +19,7 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <spi.h>
 #include <errno.h>
@@ -29,8 +30,6 @@
 #include <asm/gpio.h>
 #include <asm/io.h>
 
-#include <asm/arch/clock.h>
-
 #include <linux/iopoll.h>
 
 #define SUN4I_RXDATA_REG	0x00
@@ -133,6 +132,7 @@ struct sun4i_spi_platdata {
 
 struct sun4i_spi_priv {
 	struct sun4i_spi_variant *variant;
+	struct clk clk_ahb, clk_mod;
 	u32 base_addr;
 	u32 freq;
 	u32 mode;
@@ -263,13 +263,34 @@ static int sun4i_spi_parse_pins(struct udevice *dev)
 	return 0;
 }
 
-static inline void sun4i_spi_enable_clock(void)
+static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
 {
-	struct sunxi_ccm_reg *const ccm =
-		(struct sunxi_ccm_reg *const)SUNXI_CCM_BASE;
+	struct sun4i_spi_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	if (!enable) {
+		clk_disable(&priv->clk_ahb);
+		clk_disable(&priv->clk_mod);
+		return 0;
+	}
 
-	setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_SPI0));
-	writel((1 << 31), &ccm->spi0_clk_cfg);
+	ret = clk_enable(&priv->clk_ahb);
+	if (ret) {
+		dev_err(dev, "failed to enable ahb clock (ret=%d)\n", ret);
+		return ret;
+	}
+
+	ret = clk_enable(&priv->clk_mod);
+	if (ret) {
+		dev_err(dev, "failed to enable mod clock (ret=%d)\n", ret);
+		goto err_ahb;
+	}
+
+	return 0;
+
+err_ahb:
+	clk_disable(&priv->clk_ahb);
+	return ret;
 }
 
 static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
@@ -293,8 +314,20 @@ static int sun4i_spi_probe(struct udevice *bus)
 {
 	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
 	struct sun4i_spi_priv *priv = dev_get_priv(bus);
+	int ret;
+
+	ret = clk_get_by_name(bus, "ahb", &priv->clk_ahb);
+	if (ret) {
+		dev_err(dev, "failed to get ahb clock\n");
+		return ret;
+	}
+
+	ret = clk_get_by_name(bus, "mod", &priv->clk_mod);
+	if (ret) {
+		dev_err(dev, "failed to get mod clock\n");
+		return ret;
+	}
 
-	sun4i_spi_enable_clock();
 	sun4i_spi_parse_pins(bus);
 
 	priv->variant = plat->variant;
@@ -308,6 +341,11 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
 {
 	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
 	struct sun4i_spi_variant *variant = priv->variant;
+	int ret;
+
+	ret = sun4i_spi_set_clock(dev->parent, true);
+	if (ret)
+		return ret;
 
 	setbits_le32(priv->base_addr + variant->regs[SPI_GCR],
 		     SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER |
@@ -328,6 +366,8 @@ static int sun4i_spi_release_bus(struct udevice *dev)
 	clrbits_le32(priv->base_addr + variant->regs[SPI_GCR],
 		     SUN4I_CTL_ENABLE);
 
+	sun4i_spi_set_clock(dev->parent, false);
+
 	return 0;
 }
 
-- 
2.18.0.321.gffc6fa0e3

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

* [U-Boot] [PATCH 07/10] spi: sun4: Add A31 spi controller support
  2019-02-09 13:14 [U-Boot] [PATCH 00/10] spi: Add Allwinner A31 SPI driver Jagan Teki
                   ` (5 preceding siblings ...)
  2019-02-09 13:14 ` [U-Boot] [PATCH 06/10] spi: sun4i: Add CLK support Jagan Teki
@ 2019-02-09 13:14 ` Jagan Teki
  2019-02-13  1:19   ` André Przywara
  2019-02-09 13:14 ` [U-Boot] [PATCH 08/10] spi: sun4i: Driver cleanup Jagan Teki
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2019-02-09 13:14 UTC (permalink / raw)
  To: u-boot

Add A31 spi controller support for existing sun4i_spi driver via driver
data, this would simply add A31 register along with proper register bits
via enum sets.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/spi/Kconfig     |  4 +-
 drivers/spi/sun4i_spi.c | 84 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 85 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index ac7fbab841..15207d23c1 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -223,9 +223,9 @@ config STM32_QSPI
 	  this ST IP core.
 
 config SUN4I_SPI
-	bool "Allwinner A10 SoCs SPI controller"
+	bool "Allwinner A10/A31 SoCs SPI controller"
 	help
-	  SPI driver for Allwinner sun4i, sun5i and sun7i SoCs
+	  This enables using the SPI controller on the Allwinner A10/A31 SoCs.
 
 config TEGRA114_SPI
 	bool "nVidia Tegra114 SPI driver"
diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
index aeed68764c..36f2215f7d 100644
--- a/drivers/spi/sun4i_spi.c
+++ b/drivers/spi/sun4i_spi.c
@@ -24,6 +24,7 @@
 #include <spi.h>
 #include <errno.h>
 #include <fdt_support.h>
+#include <reset.h>
 #include <wait_bit.h>
 
 #include <asm/bitops.h>
@@ -84,6 +85,18 @@
 #define SUN4I_FIFO_STA_TF_CNT_MASK	0x7f
 #define SUN4I_FIFO_STA_TF_CNT_BITS	16
 
+/* sun6i spi registers */
+#define SUN6I_GBL_CTL_REG		0x04
+#define SUN6I_TFR_CTL_REG		0x08
+#define SUN6I_FIFO_CTL_REG		0x18
+#define SUN6I_FIFO_STA_REG		0x1c
+#define SUN6I_CLK_CTL_REG		0x24
+#define SUN6I_BURST_CNT_REG		0x30
+#define SUN6I_XMIT_CNT_REG		0x34
+#define SUN6I_BURST_CTL_REG		0x38
+#define SUN6I_TXDATA_REG		0x200
+#define SUN6I_RXDATA_REG		0x300
+
 #define SUN4I_SPI_MAX_RATE	24000000
 #define SUN4I_SPI_MIN_RATE	3000
 #define SUN4I_SPI_DEFAULT_RATE	1000000
@@ -106,6 +119,7 @@ enum sun4i_spi_regs {
 /* sun spi register bits */
 enum sun4i_spi_bits {
 	SPI_GCR_TP,
+	SPI_GCR_SRST,
 	SPI_TCR_CPHA,
 	SPI_TCR_CPOL,
 	SPI_TCR_CS_ACTIVE_LOW,
@@ -133,6 +147,7 @@ struct sun4i_spi_platdata {
 struct sun4i_spi_priv {
 	struct sun4i_spi_variant *variant;
 	struct clk clk_ahb, clk_mod;
+	struct reset_ctl reset;
 	u32 base_addr;
 	u32 freq;
 	u32 mode;
@@ -255,7 +270,10 @@ static int sun4i_spi_parse_pins(struct udevice *dev)
 			if (pin < 0)
 				break;
 
-			sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
+			if (IS_ENABLED(CONFIG_MACH_SUN50I))
+				sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0);
+			else
+				sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
 			sunxi_gpio_set_drv(pin, drive);
 			sunxi_gpio_set_pull(pin, pull);
 		}
@@ -271,6 +289,8 @@ static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
 	if (!enable) {
 		clk_disable(&priv->clk_ahb);
 		clk_disable(&priv->clk_mod);
+		if (reset_valid(&priv->reset))
+			reset_assert(&priv->reset);
 		return 0;
 	}
 
@@ -286,8 +306,18 @@ static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
 		goto err_ahb;
 	}
 
+	if (reset_valid(&priv->reset)) {
+		ret = reset_deassert(&priv->reset);
+		if (ret) {
+			dev_err(dev, "failed to deassert reset\n");
+			goto err_mod;
+		}
+	}
+
 	return 0;
 
+err_mod:
+	clk_disable(&priv->clk_mod);
 err_ahb:
 	clk_disable(&priv->clk_ahb);
 	return ret;
@@ -328,6 +358,12 @@ static int sun4i_spi_probe(struct udevice *bus)
 		return ret;
 	}
 
+	ret = reset_get_by_index(bus, 0, &priv->reset);
+	if (ret && ret != -ENOENT) {
+		dev_err(dev, "failed to get reset\n");
+		return ret;
+	}
+
 	sun4i_spi_parse_pins(bus);
 
 	priv->variant = plat->variant;
@@ -351,6 +387,10 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
 		     SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER |
 		     variant->bits[SPI_GCR_TP]);
 
+	if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
+		setbits_le32(priv->base_addr + variant->regs[SPI_GCR],
+			     variant->bits[SPI_GCR_SRST]);
+
 	setbits_le32(priv->base_addr + variant->regs[SPI_TCR],
 		     variant->bits[SPI_TCR_CS_MANUAL] |
 		     variant->bits[SPI_TCR_CS_ACTIVE_LOW]);
@@ -409,6 +449,9 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
 		       priv->base_addr + variant->regs[SPI_BC]);
 		writel(SUN4I_XMIT_CNT(nbytes),
 		       priv->base_addr + variant->regs[SPI_TC]);
+		if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
+			writel(SUN4I_BURST_CNT(nbytes),
+			       priv->base_addr + variant->regs[SPI_BCTL]);
 
 		/* Fill the TX FIFO */
 		sun4i_spi_fill_fifo(priv, nbytes);
@@ -547,17 +590,56 @@ static const unsigned long sun4i_spi_bits[] = {
 	[SPI_FSR_RF_CNT_MASK]	= GENMASK(6, 0),
 };
 
+static const unsigned long sun8i_spi_regs[] = {
+	[SPI_GCR]		= SUN6I_GBL_CTL_REG,
+	[SPI_TCR]		= SUN6I_TFR_CTL_REG,
+	[SPI_FCR]		= SUN6I_FIFO_CTL_REG,
+	[SPI_FSR]		= SUN6I_FIFO_STA_REG,
+	[SPI_CCR]		= SUN6I_CLK_CTL_REG,
+	[SPI_BC]		= SUN6I_BURST_CNT_REG,
+	[SPI_TC]		= SUN6I_XMIT_CNT_REG,
+	[SPI_BCTL]		= SUN6I_BURST_CTL_REG,
+	[SPI_TXD]		= SUN6I_TXDATA_REG,
+	[SPI_RXD]		= SUN6I_RXDATA_REG,
+};
+
+static const unsigned long sun8i_spi_bits[] = {
+	[SPI_GCR_TP]		= BIT(7),
+	[SPI_GCR_SRST]		= BIT(31),
+	[SPI_TCR_CPHA]		= BIT(0),
+	[SPI_TCR_CPOL]		= BIT(1),
+	[SPI_TCR_CS_ACTIVE_LOW] = BIT(2),
+	[SPI_TCR_CS_SEL]	= 4,
+	[SPI_TCR_CS_MASK]	= 0x30,
+	[SPI_TCR_CS_MANUAL]	= BIT(6),
+	[SPI_TCR_CS_LEVEL]	= BIT(7),
+	[SPI_TCR_XCH]		= BIT(31),
+	[SPI_FCR_RF_RST]	= BIT(15),
+	[SPI_FCR_TF_RST]	= BIT(31),
+	[SPI_FSR_RF_CNT_MASK]	= GENMASK(7, 0),
+};
+
 static const struct sun4i_spi_variant sun4i_a10_spi_variant = {
 	.regs			= sun4i_spi_regs,
 	.bits			= sun4i_spi_bits,
 	.fifo_depth		= 64,
 };
 
+static const struct sun4i_spi_variant sun8i_h3_spi_variant = {
+	.regs			= sun8i_spi_regs,
+	.bits			= sun8i_spi_bits,
+	.fifo_depth		= 64,
+};
+
 static const struct udevice_id sun4i_spi_ids[] = {
 	{
 	  .compatible = "allwinner,sun4i-a10-spi",
 	  .data = (ulong)&sun4i_a10_spi_variant,
 	},
+	{
+	  .compatible = "allwinner,sun8i-h3-spi",
+	  .data = (ulong)&sun8i_h3_spi_variant,
+	},
 	{ }
 };
 
-- 
2.18.0.321.gffc6fa0e3

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

* [U-Boot] [PATCH 08/10] spi: sun4i: Driver cleanup
  2019-02-09 13:14 [U-Boot] [PATCH 00/10] spi: Add Allwinner A31 SPI driver Jagan Teki
                   ` (6 preceding siblings ...)
  2019-02-09 13:14 ` [U-Boot] [PATCH 07/10] spi: sun4: Add A31 spi controller support Jagan Teki
@ 2019-02-09 13:14 ` Jagan Teki
  2019-02-13  1:20   ` André Przywara
  2019-02-09 13:14 ` [U-Boot] [PATCH 09/10] spi: kconfig: Enable SUN4I_SPI by default if ARCH_SUNXI Jagan Teki
  2019-02-09 13:15 ` [U-Boot] [PATCH 10/10] board: sopine: Enable SPI/SPI-FLASH Jagan Teki
  9 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2019-02-09 13:14 UTC (permalink / raw)
  To: u-boot

- drop unused macros.
- use base instead of base_addr, for better code readability
- move .probe and .ofdata_to_platdata functions in required
  places to add platdata support in future.
- use sentinel sun4i_spi_ids.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/spi/sun4i_spi.c | 224 +++++++++++++++++-----------------------
 1 file changed, 97 insertions(+), 127 deletions(-)

diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
index 36f2215f7d..a32f511245 100644
--- a/drivers/spi/sun4i_spi.c
+++ b/drivers/spi/sun4i_spi.c
@@ -33,57 +33,16 @@
 
 #include <linux/iopoll.h>
 
-#define SUN4I_RXDATA_REG	0x00
-
-#define SUN4I_TXDATA_REG	0x04
-
-#define SUN4I_CTL_REG		0x08
-#define SUN4I_CTL_ENABLE		BIT(0)
-#define SUN4I_CTL_MASTER		BIT(1)
-#define SUN4I_CTL_CPHA			BIT(2)
-#define SUN4I_CTL_CPOL			BIT(3)
-#define SUN4I_CTL_CS_ACTIVE_LOW		BIT(4)
-#define SUN4I_CTL_LMTF			BIT(6)
-#define SUN4I_CTL_TF_RST		BIT(8)
-#define SUN4I_CTL_RF_RST		BIT(9)
-#define SUN4I_CTL_XCH			BIT(10)
-#define SUN4I_CTL_CS_MASK		0x3000
-#define SUN4I_CTL_CS(cs)		(((cs) << 12) & SUN4I_CTL_CS_MASK)
-#define SUN4I_CTL_DHB			BIT(15)
-#define SUN4I_CTL_CS_MANUAL		BIT(16)
-#define SUN4I_CTL_CS_LEVEL		BIT(17)
-#define SUN4I_CTL_TP			BIT(18)
-
-#define SUN4I_INT_CTL_REG	0x0c
-#define SUN4I_INT_CTL_RF_F34		BIT(4)
-#define SUN4I_INT_CTL_TF_E34		BIT(12)
-#define SUN4I_INT_CTL_TC		BIT(16)
-
-#define SUN4I_INT_STA_REG	0x10
-
-#define SUN4I_DMA_CTL_REG	0x14
-
-#define SUN4I_WAIT_REG		0x18
-
-#define SUN4I_CLK_CTL_REG	0x1c
-#define SUN4I_CLK_CTL_CDR2_MASK		0xff
-#define SUN4I_CLK_CTL_CDR2(div)		((div) & SUN4I_CLK_CTL_CDR2_MASK)
-#define SUN4I_CLK_CTL_CDR1_MASK		0xf
-#define SUN4I_CLK_CTL_CDR1(div)		(((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8)
-#define SUN4I_CLK_CTL_DRS		BIT(12)
-
-#define SUN4I_MAX_XFER_SIZE		0xffffff
-
-#define SUN4I_BURST_CNT_REG	0x20
-#define SUN4I_BURST_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
-
-#define SUN4I_XMIT_CNT_REG	0x24
-#define SUN4I_XMIT_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
+DECLARE_GLOBAL_DATA_PTR;
 
-#define SUN4I_FIFO_STA_REG	0x28
-#define SUN4I_FIFO_STA_RF_CNT_BITS	0
-#define SUN4I_FIFO_STA_TF_CNT_MASK	0x7f
-#define SUN4I_FIFO_STA_TF_CNT_BITS	16
+/* sun4i spi registers */
+#define SUN4I_RXDATA_REG		0x00
+#define SUN4I_TXDATA_REG		0x04
+#define SUN4I_CTL_REG			0x08
+#define SUN4I_CLK_CTL_REG		0x1c
+#define SUN4I_BURST_CNT_REG		0x20
+#define SUN4I_XMIT_CNT_REG		0x24
+#define SUN4I_FIFO_STA_REG		0x28
 
 /* sun6i spi registers */
 #define SUN6I_GBL_CTL_REG		0x04
@@ -97,10 +56,23 @@
 #define SUN6I_TXDATA_REG		0x200
 #define SUN6I_RXDATA_REG		0x300
 
-#define SUN4I_SPI_MAX_RATE	24000000
-#define SUN4I_SPI_MIN_RATE	3000
-#define SUN4I_SPI_DEFAULT_RATE	1000000
-#define SUN4I_SPI_TIMEOUT_US	1000000
+/* sun spi bits */
+#define SUN4I_CTL_ENABLE		BIT(0)
+#define SUN4I_CTL_MASTER		BIT(1)
+#define SUN4I_CLK_CTL_CDR2_MASK		0xff
+#define SUN4I_CLK_CTL_CDR2(div)		((div) & SUN4I_CLK_CTL_CDR2_MASK)
+#define SUN4I_CLK_CTL_CDR1_MASK		0xf
+#define SUN4I_CLK_CTL_CDR1(div)		(((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8)
+#define SUN4I_CLK_CTL_DRS		BIT(12)
+#define SUN4I_MAX_XFER_SIZE		0xffffff
+#define SUN4I_BURST_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
+#define SUN4I_XMIT_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
+#define SUN4I_FIFO_STA_RF_CNT_BITS	0
+
+#define SUN4I_SPI_MAX_RATE		24000000
+#define SUN4I_SPI_MIN_RATE		3000
+#define SUN4I_SPI_DEFAULT_RATE		1000000
+#define SUN4I_SPI_TIMEOUT_US		1000000
 
 /* sun spi register set */
 enum sun4i_spi_regs {
@@ -140,7 +112,7 @@ struct sun4i_spi_variant {
 
 struct sun4i_spi_platdata {
 	struct sun4i_spi_variant *variant;
-	u32 base_addr;
+	u32 base;
 	u32 max_hz;
 };
 
@@ -148,7 +120,7 @@ struct sun4i_spi_priv {
 	struct sun4i_spi_variant *variant;
 	struct clk clk_ahb, clk_mod;
 	struct reset_ctl reset;
-	u32 base_addr;
+	u32 base;
 	u32 freq;
 	u32 mode;
 
@@ -156,15 +128,13 @@ struct sun4i_spi_priv {
 	u8 *rx_buf;
 };
 
-DECLARE_GLOBAL_DATA_PTR;
-
 static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 {
 	struct sun4i_spi_variant *variant = priv->variant;
 	u8 byte;
 
 	while (len--) {
-		byte = readb(priv->base_addr + variant->regs[SPI_RXD]);
+		byte = readb(priv->base + variant->regs[SPI_RXD]);
 		if (priv->rx_buf)
 			*priv->rx_buf++ = byte;
 	}
@@ -177,7 +147,7 @@ static inline void sun4i_spi_fill_fifo(struct sun4i_spi_priv *priv, int len)
 
 	while (len--) {
 		byte = priv->tx_buf ? *priv->tx_buf++ : 0;
-		writeb(byte, priv->base_addr + variant->regs[SPI_TXD]);
+		writeb(byte, priv->base + variant->regs[SPI_TXD]);
 	}
 }
 
@@ -187,7 +157,7 @@ static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
 	struct sun4i_spi_variant *variant = priv->variant;
 	u32 reg;
 
-	reg = readl(priv->base_addr + variant->regs[SPI_TCR]);
+	reg = readl(priv->base + variant->regs[SPI_TCR]);
 
 	reg &= ~variant->bits[SPI_TCR_CS_MASK];
 	reg |= ((cs << variant->bits[SPI_TCR_CS_SEL]) &
@@ -198,7 +168,7 @@ static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
 	else
 		reg |= variant->bits[SPI_TCR_CS_LEVEL];
 
-	writel(reg, priv->base_addr + variant->regs[SPI_TCR]);
+	writel(reg, priv->base + variant->regs[SPI_TCR]);
 }
 
 static int sun4i_spi_parse_pins(struct udevice *dev)
@@ -323,56 +293,6 @@ err_ahb:
 	return ret;
 }
 
-static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
-{
-	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
-	int node = dev_of_offset(bus);
-
-	plat->base_addr = devfdt_get_addr(bus);
-	plat->variant = (struct sun4i_spi_variant *)dev_get_driver_data(bus);
-	plat->max_hz = fdtdec_get_int(gd->fdt_blob, node,
-				      "spi-max-frequency",
-				      SUN4I_SPI_DEFAULT_RATE);
-
-	if (plat->max_hz > SUN4I_SPI_MAX_RATE)
-		plat->max_hz = SUN4I_SPI_MAX_RATE;
-
-	return 0;
-}
-
-static int sun4i_spi_probe(struct udevice *bus)
-{
-	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
-	struct sun4i_spi_priv *priv = dev_get_priv(bus);
-	int ret;
-
-	ret = clk_get_by_name(bus, "ahb", &priv->clk_ahb);
-	if (ret) {
-		dev_err(dev, "failed to get ahb clock\n");
-		return ret;
-	}
-
-	ret = clk_get_by_name(bus, "mod", &priv->clk_mod);
-	if (ret) {
-		dev_err(dev, "failed to get mod clock\n");
-		return ret;
-	}
-
-	ret = reset_get_by_index(bus, 0, &priv->reset);
-	if (ret && ret != -ENOENT) {
-		dev_err(dev, "failed to get reset\n");
-		return ret;
-	}
-
-	sun4i_spi_parse_pins(bus);
-
-	priv->variant = plat->variant;
-	priv->base_addr = plat->base_addr;
-	priv->freq = plat->max_hz;
-
-	return 0;
-}
-
 static int sun4i_spi_claim_bus(struct udevice *dev)
 {
 	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
@@ -383,15 +303,15 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
 	if (ret)
 		return ret;
 
-	setbits_le32(priv->base_addr + variant->regs[SPI_GCR],
+	setbits_le32(priv->base + variant->regs[SPI_GCR],
 		     SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER |
 		     variant->bits[SPI_GCR_TP]);
 
 	if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
-		setbits_le32(priv->base_addr + variant->regs[SPI_GCR],
+		setbits_le32(priv->base + variant->regs[SPI_GCR],
 			     variant->bits[SPI_GCR_SRST]);
 
-	setbits_le32(priv->base_addr + variant->regs[SPI_TCR],
+	setbits_le32(priv->base + variant->regs[SPI_TCR],
 		     variant->bits[SPI_TCR_CS_MANUAL] |
 		     variant->bits[SPI_TCR_CS_ACTIVE_LOW]);
 
@@ -403,7 +323,7 @@ static int sun4i_spi_release_bus(struct udevice *dev)
 	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
 	struct sun4i_spi_variant *variant = priv->variant;
 
-	clrbits_le32(priv->base_addr + variant->regs[SPI_GCR],
+	clrbits_le32(priv->base + variant->regs[SPI_GCR],
 		     SUN4I_CTL_ENABLE);
 
 	sun4i_spi_set_clock(dev->parent, false);
@@ -436,7 +356,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
 		sun4i_spi_set_cs(bus, slave_plat->cs, true);
 
 	/* Reset FIFOs */
-	setbits_le32(priv->base_addr + variant->regs[SPI_FCR],
+	setbits_le32(priv->base + variant->regs[SPI_FCR],
 		     variant->bits[SPI_FCR_RF_RST] |
 		     variant->bits[SPI_FCR_TF_RST]);
 
@@ -446,22 +366,22 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
 
 		/* Setup the counters */
 		writel(SUN4I_BURST_CNT(nbytes),
-		       priv->base_addr + variant->regs[SPI_BC]);
+		       priv->base + variant->regs[SPI_BC]);
 		writel(SUN4I_XMIT_CNT(nbytes),
-		       priv->base_addr + variant->regs[SPI_TC]);
+		       priv->base + variant->regs[SPI_TC]);
 		if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
 			writel(SUN4I_BURST_CNT(nbytes),
-			       priv->base_addr + variant->regs[SPI_BCTL]);
+			       priv->base + variant->regs[SPI_BCTL]);
 
 		/* Fill the TX FIFO */
 		sun4i_spi_fill_fifo(priv, nbytes);
 
 		/* Start the transfer */
-		setbits_le32(priv->base_addr + variant->regs[SPI_TCR],
+		setbits_le32(priv->base + variant->regs[SPI_TCR],
 			     variant->bits[SPI_TCR_XCH]);
 
 		/* Wait till RX FIFO to be empty */
-		ret = readl_poll_timeout(priv->base_addr + variant->regs[SPI_FSR],
+		ret = readl_poll_timeout(priv->base + variant->regs[SPI_FSR],
 					 rx_fifocnt,
 					 !(((rx_fifocnt &
 					 variant->bits[SPI_FSR_RF_CNT_MASK]) >>
@@ -514,7 +434,7 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
 	 */
 
 	div = SUN4I_SPI_MAX_RATE / (2 * speed);
-	reg = readl(priv->base_addr + variant->regs[SPI_CCR]);
+	reg = readl(priv->base + variant->regs[SPI_CCR]);
 
 	if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
 		if (div > 0)
@@ -529,7 +449,7 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
 	}
 
 	priv->freq = speed;
-	writel(reg, priv->base_addr + variant->regs[SPI_CCR]);
+	writel(reg, priv->base + variant->regs[SPI_CCR]);
 
 	return 0;
 }
@@ -540,7 +460,7 @@ static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
 	struct sun4i_spi_variant *variant = priv->variant;
 	u32 reg;
 
-	reg = readl(priv->base_addr + variant->regs[SPI_TCR]);
+	reg = readl(priv->base + variant->regs[SPI_TCR]);
 	reg &= ~(variant->bits[SPI_TCR_CPOL] | variant->bits[SPI_TCR_CPHA]);
 
 	if (mode & SPI_CPOL)
@@ -550,7 +470,7 @@ static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
 		reg |= variant->bits[SPI_TCR_CPHA];
 
 	priv->mode = mode;
-	writel(reg, priv->base_addr + variant->regs[SPI_TCR]);
+	writel(reg, priv->base + variant->regs[SPI_TCR]);
 
 	return 0;
 }
@@ -563,6 +483,56 @@ static const struct dm_spi_ops sun4i_spi_ops = {
 	.set_mode		= sun4i_spi_set_mode,
 };
 
+static int sun4i_spi_probe(struct udevice *bus)
+{
+	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
+	struct sun4i_spi_priv *priv = dev_get_priv(bus);
+	int ret;
+
+	ret = clk_get_by_name(bus, "ahb", &priv->clk_ahb);
+	if (ret) {
+		dev_err(dev, "failed to get ahb clock\n");
+		return ret;
+	}
+
+	ret = clk_get_by_name(bus, "mod", &priv->clk_mod);
+	if (ret) {
+		dev_err(dev, "failed to get mod clock\n");
+		return ret;
+	}
+
+	ret = reset_get_by_index(bus, 0, &priv->reset);
+	if (ret && ret != -ENOENT) {
+		dev_err(dev, "failed to get reset\n");
+		return ret;
+	}
+
+	sun4i_spi_parse_pins(bus);
+
+	priv->variant = plat->variant;
+	priv->base = plat->base;
+	priv->freq = plat->max_hz;
+
+	return 0;
+}
+
+static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
+	int node = dev_of_offset(bus);
+
+	plat->base = devfdt_get_addr(bus);
+	plat->variant = (struct sun4i_spi_variant *)dev_get_driver_data(bus);
+	plat->max_hz = fdtdec_get_int(gd->fdt_blob, node,
+				      "spi-max-frequency",
+				      SUN4I_SPI_DEFAULT_RATE);
+
+	if (plat->max_hz > SUN4I_SPI_MAX_RATE)
+		plat->max_hz = SUN4I_SPI_MAX_RATE;
+
+	return 0;
+}
+
 static const unsigned long sun4i_spi_regs[] = {
 	[SPI_GCR]		= SUN4I_CTL_REG,
 	[SPI_TCR]		= SUN4I_CTL_REG,
@@ -640,7 +610,7 @@ static const struct udevice_id sun4i_spi_ids[] = {
 	  .compatible = "allwinner,sun8i-h3-spi",
 	  .data = (ulong)&sun8i_h3_spi_variant,
 	},
-	{ }
+	{ /* sentinel */ }
 };
 
 U_BOOT_DRIVER(sun4i_spi) = {
-- 
2.18.0.321.gffc6fa0e3

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

* [U-Boot] [PATCH 09/10] spi: kconfig: Enable SUN4I_SPI by default if ARCH_SUNXI
  2019-02-09 13:14 [U-Boot] [PATCH 00/10] spi: Add Allwinner A31 SPI driver Jagan Teki
                   ` (7 preceding siblings ...)
  2019-02-09 13:14 ` [U-Boot] [PATCH 08/10] spi: sun4i: Driver cleanup Jagan Teki
@ 2019-02-09 13:14 ` Jagan Teki
  2019-02-13  1:21   ` André Przywara
  2019-02-09 13:15 ` [U-Boot] [PATCH 10/10] board: sopine: Enable SPI/SPI-FLASH Jagan Teki
  9 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2019-02-09 13:14 UTC (permalink / raw)
  To: u-boot

Enable SUN4I_SPI by default for ARCH_SUNXI, so that board
that would require to enable DM_SPI that eventually enable
the SUN4I_SPI driver.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/spi/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 15207d23c1..2fb4862c4a 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -224,6 +224,7 @@ config STM32_QSPI
 
 config SUN4I_SPI
 	bool "Allwinner A10/A31 SoCs SPI controller"
+	default ARCH_SUNXI
 	help
 	  This enables using the SPI controller on the Allwinner A10/A31 SoCs.
 
-- 
2.18.0.321.gffc6fa0e3

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

* [U-Boot] [PATCH 10/10] board: sopine: Enable SPI/SPI-FLASH
  2019-02-09 13:14 [U-Boot] [PATCH 00/10] spi: Add Allwinner A31 SPI driver Jagan Teki
                   ` (8 preceding siblings ...)
  2019-02-09 13:14 ` [U-Boot] [PATCH 09/10] spi: kconfig: Enable SUN4I_SPI by default if ARCH_SUNXI Jagan Teki
@ 2019-02-09 13:15 ` Jagan Teki
  2019-02-13  1:21   ` André Przywara
  9 siblings, 1 reply; 27+ messages in thread
From: Jagan Teki @ 2019-02-09 13:15 UTC (permalink / raw)
  To: u-boot

Sopine has Winbond SPI flash, so enable the same to use
flash on Sopine board.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi | 12 ++++++++++++
 configs/sopine_baseboard_defconfig                   |  4 ++++
 2 files changed, 16 insertions(+)
 create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi

diff --git a/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
new file mode 100644
index 0000000000..02b1ae046e
--- /dev/null
+++ b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include "sunxi-u-boot.dtsi"
+
+/ {
+	aliases {
+		spi0 = &spi0;
+	};
+};
diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig
index 9d7e3a2b6c..a94e3c21fd 100644
--- a/configs/sopine_baseboard_defconfig
+++ b/configs/sopine_baseboard_defconfig
@@ -10,11 +10,15 @@ CONFIG_MMC0_CD_PIN=""
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_SPL_SPI_SUNXI=y
 CONFIG_NR_DRAM_BANKS=1
+CONFIG_CMD_SF=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-sopine-baseboard"
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SUN8I_EMAC=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_OHCI_HCD=y
-- 
2.18.0.321.gffc6fa0e3

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

* [U-Boot] [PATCH 01/10] spi: sun4i: Poll for rxfifo empty
  2019-02-09 13:14 ` [U-Boot] [PATCH 01/10] spi: sun4i: Poll for rxfifo empty Jagan Teki
@ 2019-02-13  1:11   ` André Przywara
  0 siblings, 0 replies; 27+ messages in thread
From: André Przywara @ 2019-02-13  1:11 UTC (permalink / raw)
  To: u-boot

On Sat,  9 Feb 2019 18:44:51 +0530
Jagan Teki <jagan@amarulasolutions.com> wrote:

Hi,

> To drain rx fifo the fifo need to poll till the fifo
> count become empty.
> 
> The current code is using wait_for_bit logic on control
> register with exchange burst mode mask, which is not a
> proper way of waiting for draining fifo.
> 
> So, add code for polling fifo status register till rxfifo
> count become empty.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  drivers/spi/sun4i_spi.c | 15 +++++++++------
>  1 file changed, 9 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
> index 38cc743c61..87b396a96e 100644
> --- a/drivers/spi/sun4i_spi.c
> +++ b/drivers/spi/sun4i_spi.c
> @@ -31,6 +31,8 @@
>  
>  #include <asm/arch/clock.h>
>  
> +#include <linux/iopoll.h>
> +
>  #define SUN4I_FIFO_DEPTH	64
>  
>  #define SUN4I_RXDATA_REG	0x00
> @@ -46,7 +48,6 @@
>  #define SUN4I_CTL_LMTF			BIT(6)
>  #define SUN4I_CTL_TF_RST		BIT(8)
>  #define SUN4I_CTL_RF_RST		BIT(9)
> -#define SUN4I_CTL_XCH_MASK		0x0400
>  #define SUN4I_CTL_XCH			BIT(10)
>  #define SUN4I_CTL_CS_MASK		0x3000
>  #define SUN4I_CTL_CS(cs)		(((cs) << 12) & SUN4I_CTL_CS_MASK)
> @@ -308,7 +309,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
>  	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
>  
>  	u32 len = bitlen / 8;
> -	u32 reg;
> +	u32 reg, rx_fifocnt;
>  	u8 nbytes;
>  	int ret;
>  
> @@ -343,10 +344,12 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
>  		reg = readl(&priv->regs->ctl);
>  		writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);
>  
> -		/* Wait transfer to complete */
> -		ret = wait_for_bit_le32(&priv->regs->ctl, SUN4I_CTL_XCH_MASK,
> -					false, SUN4I_SPI_TIMEOUT_US, false);
> -		if (ret) {
> +		/* Wait till RX FIFO to be empty */
> +		ret = readl_poll_timeout(&priv->regs->ctl, rx_fifocnt,

That's not the right register, it should be regs->fifo_sta.

> +					 !(((rx_fifocnt & SUN4I_FIFO_STA_RF_CNT_MASK) >>
> +					 SUN4I_FIFO_STA_RF_CNT_BITS) < nbytes),

I think removing the negation and using ">=" instead is less confusing.

Cheers,
Andre.


> +					 SUN4I_SPI_TIMEOUT_US);
> +		if (ret < 0) {
>  			printf("ERROR: sun4i_spi: Timeout transferring data\n");
>  			sun4i_spi_set_cs(bus, slave_plat->cs, false);
>  			return ret;

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

* [U-Boot] [PATCH 02/10] clk: sunxi: Implement SPI clocks, resets
  2019-02-09 13:14 ` [U-Boot] [PATCH 02/10] clk: sunxi: Implement SPI clocks, resets Jagan Teki
@ 2019-02-13  1:13   ` André Przywara
  0 siblings, 0 replies; 27+ messages in thread
From: André Przywara @ 2019-02-13  1:13 UTC (permalink / raw)
  To: u-boot

On 09/02/2019 13:14, Jagan Teki wrote:
> - Implement SPI AHB, MOD clocks via ccu_clk_gate for all
>   supported Allwinner SoCs
> - Implement SPI resets via ccu_reset for all supported
>   Allwinner SoCs.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>

Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Cheers,
Andre.

> ---
>  drivers/clk/sunxi/clk_a10.c  | 10 ++++++++++
>  drivers/clk/sunxi/clk_a10s.c |  7 +++++++
>  drivers/clk/sunxi/clk_a23.c  |  7 +++++++
>  drivers/clk/sunxi/clk_a31.c  | 13 +++++++++++++
>  drivers/clk/sunxi/clk_a64.c  |  7 +++++++
>  drivers/clk/sunxi/clk_a80.c  | 13 +++++++++++++
>  drivers/clk/sunxi/clk_a83t.c |  7 +++++++
>  drivers/clk/sunxi/clk_h3.c   |  7 +++++++
>  drivers/clk/sunxi/clk_h6.c   |  9 +++++++++
>  drivers/clk/sunxi/clk_r40.c  | 13 +++++++++++++
>  drivers/clk/sunxi/clk_v3s.c  |  4 ++++
>  11 files changed, 97 insertions(+)
> 
> diff --git a/drivers/clk/sunxi/clk_a10.c b/drivers/clk/sunxi/clk_a10.c
> index 2aa41efe17..b8b57e2b31 100644
> --- a/drivers/clk/sunxi/clk_a10.c
> +++ b/drivers/clk/sunxi/clk_a10.c
> @@ -22,6 +22,10 @@ static struct ccu_clk_gate a10_gates[] = {
>  	[CLK_AHB_MMC1]		= GATE(0x060, BIT(9)),
>  	[CLK_AHB_MMC2]		= GATE(0x060, BIT(10)),
>  	[CLK_AHB_MMC3]		= GATE(0x060, BIT(11)),
> +	[CLK_AHB_SPI0]		= GATE(0x060, BIT(20)),
> +	[CLK_AHB_SPI1]		= GATE(0x060, BIT(21)),
> +	[CLK_AHB_SPI2]		= GATE(0x060, BIT(22)),
> +	[CLK_AHB_SPI3]		= GATE(0x060, BIT(23)),
>  
>  	[CLK_APB1_UART0]	= GATE(0x06c, BIT(16)),
>  	[CLK_APB1_UART1]	= GATE(0x06c, BIT(17)),
> @@ -32,9 +36,15 @@ static struct ccu_clk_gate a10_gates[] = {
>  	[CLK_APB1_UART6]	= GATE(0x06c, BIT(22)),
>  	[CLK_APB1_UART7]	= GATE(0x06c, BIT(23)),
>  
> +	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
> +	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
> +	[CLK_SPI2]		= GATE(0x0a8, BIT(31)),
> +
>  	[CLK_USB_OHCI0]		= GATE(0x0cc, BIT(6)),
>  	[CLK_USB_OHCI1]		= GATE(0x0cc, BIT(7)),
>  	[CLK_USB_PHY]		= GATE(0x0cc, BIT(8)),
> +
> +	[CLK_SPI3]		= GATE(0x0d4, BIT(31)),
>  };
>  
>  static struct ccu_reset a10_resets[] = {
> diff --git a/drivers/clk/sunxi/clk_a10s.c b/drivers/clk/sunxi/clk_a10s.c
> index 87b74e52dc..c6fcede822 100644
> --- a/drivers/clk/sunxi/clk_a10s.c
> +++ b/drivers/clk/sunxi/clk_a10s.c
> @@ -19,12 +19,19 @@ static struct ccu_clk_gate a10s_gates[] = {
>  	[CLK_AHB_MMC0]		= GATE(0x060, BIT(8)),
>  	[CLK_AHB_MMC1]		= GATE(0x060, BIT(9)),
>  	[CLK_AHB_MMC2]		= GATE(0x060, BIT(10)),
> +	[CLK_AHB_SPI0]		= GATE(0x060, BIT(20)),
> +	[CLK_AHB_SPI1]		= GATE(0x060, BIT(21)),
> +	[CLK_AHB_SPI2]		= GATE(0x060, BIT(22)),
>  
>  	[CLK_APB1_UART0]	= GATE(0x06c, BIT(16)),
>  	[CLK_APB1_UART1]	= GATE(0x06c, BIT(17)),
>  	[CLK_APB1_UART2]	= GATE(0x06c, BIT(18)),
>  	[CLK_APB1_UART3]	= GATE(0x06c, BIT(19)),
>  
> +	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
> +	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
> +	[CLK_SPI2]		= GATE(0x0a8, BIT(31)),
> +
>  	[CLK_USB_OHCI]		= GATE(0x0cc, BIT(6)),
>  	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
>  	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
> diff --git a/drivers/clk/sunxi/clk_a23.c b/drivers/clk/sunxi/clk_a23.c
> index 1ef2359286..c16019215e 100644
> --- a/drivers/clk/sunxi/clk_a23.c
> +++ b/drivers/clk/sunxi/clk_a23.c
> @@ -16,6 +16,8 @@ static struct ccu_clk_gate a23_gates[] = {
>  	[CLK_BUS_MMC0]		= GATE(0x060, BIT(8)),
>  	[CLK_BUS_MMC1]		= GATE(0x060, BIT(9)),
>  	[CLK_BUS_MMC2]		= GATE(0x060, BIT(10)),
> +	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
> +	[CLK_BUS_SPI1]		= GATE(0x060, BIT(21)),
>  	[CLK_BUS_OTG]		= GATE(0x060, BIT(24)),
>  	[CLK_BUS_EHCI]		= GATE(0x060, BIT(26)),
>  	[CLK_BUS_OHCI]		= GATE(0x060, BIT(29)),
> @@ -26,6 +28,9 @@ static struct ccu_clk_gate a23_gates[] = {
>  	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
>  	[CLK_BUS_UART4]		= GATE(0x06c, BIT(20)),
>  
> +	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
> +	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
> +
>  	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
>  	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
>  	[CLK_USB_HSIC]		= GATE(0x0cc, BIT(10)),
> @@ -41,6 +46,8 @@ static struct ccu_reset a23_resets[] = {
>  	[RST_BUS_MMC0]		= RESET(0x2c0, BIT(8)),
>  	[RST_BUS_MMC1]		= RESET(0x2c0, BIT(9)),
>  	[RST_BUS_MMC2]		= RESET(0x2c0, BIT(10)),
> +	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
> +	[RST_BUS_SPI1]		= RESET(0x2c0, BIT(21)),
>  	[RST_BUS_OTG]		= RESET(0x2c0, BIT(24)),
>  	[RST_BUS_EHCI]		= RESET(0x2c0, BIT(26)),
>  	[RST_BUS_OHCI]		= RESET(0x2c0, BIT(29)),
> diff --git a/drivers/clk/sunxi/clk_a31.c b/drivers/clk/sunxi/clk_a31.c
> index 5bd8b7dccc..fa6e3eeef0 100644
> --- a/drivers/clk/sunxi/clk_a31.c
> +++ b/drivers/clk/sunxi/clk_a31.c
> @@ -17,6 +17,10 @@ static struct ccu_clk_gate a31_gates[] = {
>  	[CLK_AHB1_MMC1]		= GATE(0x060, BIT(9)),
>  	[CLK_AHB1_MMC2]		= GATE(0x060, BIT(10)),
>  	[CLK_AHB1_MMC3]		= GATE(0x060, BIT(11)),
> +	[CLK_AHB1_SPI0]		= GATE(0x060, BIT(20)),
> +	[CLK_AHB1_SPI1]		= GATE(0x060, BIT(21)),
> +	[CLK_AHB1_SPI2]		= GATE(0x060, BIT(22)),
> +	[CLK_AHB1_SPI3]		= GATE(0x060, BIT(23)),
>  	[CLK_AHB1_OTG]		= GATE(0x060, BIT(24)),
>  	[CLK_AHB1_EHCI0]	= GATE(0x060, BIT(26)),
>  	[CLK_AHB1_EHCI1]	= GATE(0x060, BIT(27)),
> @@ -31,6 +35,11 @@ static struct ccu_clk_gate a31_gates[] = {
>  	[CLK_APB2_UART4]	= GATE(0x06c, BIT(20)),
>  	[CLK_APB2_UART5]	= GATE(0x06c, BIT(21)),
>  
> +	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
> +	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
> +	[CLK_SPI2]		= GATE(0x0a8, BIT(31)),
> +	[CLK_SPI3]		= GATE(0x0ac, BIT(31)),
> +
>  	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
>  	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
>  	[CLK_USB_PHY2]		= GATE(0x0cc, BIT(10)),
> @@ -48,6 +57,10 @@ static struct ccu_reset a31_resets[] = {
>  	[RST_AHB1_MMC1]		= RESET(0x2c0, BIT(9)),
>  	[RST_AHB1_MMC2]		= RESET(0x2c0, BIT(10)),
>  	[RST_AHB1_MMC3]		= RESET(0x2c0, BIT(11)),
> +	[RST_AHB1_SPI0]		= RESET(0x2c0, BIT(20)),
> +	[RST_AHB1_SPI1]		= RESET(0x2c0, BIT(21)),
> +	[RST_AHB1_SPI2]		= RESET(0x2c0, BIT(22)),
> +	[RST_AHB1_SPI3]		= RESET(0x2c0, BIT(23)),
>  	[RST_AHB1_OTG]		= RESET(0x2c0, BIT(24)),
>  	[RST_AHB1_EHCI0]	= RESET(0x2c0, BIT(26)),
>  	[RST_AHB1_EHCI1]	= RESET(0x2c0, BIT(27)),
> diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
> index 910275fbce..322d6cd557 100644
> --- a/drivers/clk/sunxi/clk_a64.c
> +++ b/drivers/clk/sunxi/clk_a64.c
> @@ -16,6 +16,8 @@ static const struct ccu_clk_gate a64_gates[] = {
>  	[CLK_BUS_MMC0]		= GATE(0x060, BIT(8)),
>  	[CLK_BUS_MMC1]		= GATE(0x060, BIT(9)),
>  	[CLK_BUS_MMC2]		= GATE(0x060, BIT(10)),
> +	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
> +	[CLK_BUS_SPI1]		= GATE(0x060, BIT(21)),
>  	[CLK_BUS_OTG]		= GATE(0x060, BIT(23)),
>  	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(24)),
>  	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(25)),
> @@ -28,6 +30,9 @@ static const struct ccu_clk_gate a64_gates[] = {
>  	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
>  	[CLK_BUS_UART4]		= GATE(0x06c, BIT(20)),
>  
> +	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
> +	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
> +
>  	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
>  	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
>  	[CLK_USB_HSIC]		= GATE(0x0cc, BIT(10)),
> @@ -44,6 +49,8 @@ static const struct ccu_reset a64_resets[] = {
>  	[RST_BUS_MMC0]		= RESET(0x2c0, BIT(8)),
>  	[RST_BUS_MMC1]		= RESET(0x2c0, BIT(9)),
>  	[RST_BUS_MMC2]		= RESET(0x2c0, BIT(10)),
> +	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
> +	[RST_BUS_SPI1]		= RESET(0x2c0, BIT(21)),
>  	[RST_BUS_OTG]           = RESET(0x2c0, BIT(23)),
>  	[RST_BUS_EHCI0]         = RESET(0x2c0, BIT(24)),
>  	[RST_BUS_EHCI1]         = RESET(0x2c0, BIT(25)),
> diff --git a/drivers/clk/sunxi/clk_a80.c b/drivers/clk/sunxi/clk_a80.c
> index aec1d80c46..fb76aad528 100644
> --- a/drivers/clk/sunxi/clk_a80.c
> +++ b/drivers/clk/sunxi/clk_a80.c
> @@ -13,7 +13,16 @@
>  #include <dt-bindings/reset/sun9i-a80-ccu.h>
>  
>  static const struct ccu_clk_gate a80_gates[] = {
> +	[CLK_SPI0]		= GATE(0x430, BIT(31)),
> +	[CLK_SPI1]		= GATE(0x434, BIT(31)),
> +	[CLK_SPI2]		= GATE(0x438, BIT(31)),
> +	[CLK_SPI3]		= GATE(0x43c, BIT(31)),
> +
>  	[CLK_BUS_MMC]		= GATE(0x580, BIT(8)),
> +	[CLK_BUS_SPI0]		= GATE(0x580, BIT(20)),
> +	[CLK_BUS_SPI1]		= GATE(0x580, BIT(21)),
> +	[CLK_BUS_SPI2]		= GATE(0x580, BIT(22)),
> +	[CLK_BUS_SPI3]		= GATE(0x580, BIT(23)),
>  
>  	[CLK_BUS_UART0]		= GATE(0x594, BIT(16)),
>  	[CLK_BUS_UART1]		= GATE(0x594, BIT(17)),
> @@ -25,6 +34,10 @@ static const struct ccu_clk_gate a80_gates[] = {
>  
>  static const struct ccu_reset a80_resets[] = {
>  	[RST_BUS_MMC]		= RESET(0x5a0, BIT(8)),
> +	[RST_BUS_SPI0]		= RESET(0x5a0, BIT(20)),
> +	[RST_BUS_SPI1]		= RESET(0x5a0, BIT(21)),
> +	[RST_BUS_SPI2]		= RESET(0x5a0, BIT(22)),
> +	[RST_BUS_SPI3]		= RESET(0x5a0, BIT(23)),
>  
>  	[RST_BUS_UART0]		= RESET(0x5b4, BIT(16)),
>  	[RST_BUS_UART1]		= RESET(0x5b4, BIT(17)),
> diff --git a/drivers/clk/sunxi/clk_a83t.c b/drivers/clk/sunxi/clk_a83t.c
> index b5a555da36..36f7e14c45 100644
> --- a/drivers/clk/sunxi/clk_a83t.c
> +++ b/drivers/clk/sunxi/clk_a83t.c
> @@ -16,6 +16,8 @@ static struct ccu_clk_gate a83t_gates[] = {
>  	[CLK_BUS_MMC0]		= GATE(0x060, BIT(8)),
>  	[CLK_BUS_MMC1]		= GATE(0x060, BIT(9)),
>  	[CLK_BUS_MMC2]		= GATE(0x060, BIT(10)),
> +	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
> +	[CLK_BUS_SPI1]		= GATE(0x060, BIT(21)),
>  	[CLK_BUS_OTG]		= GATE(0x060, BIT(24)),
>  	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(26)),
>  	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(27)),
> @@ -27,6 +29,9 @@ static struct ccu_clk_gate a83t_gates[] = {
>  	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
>  	[CLK_BUS_UART4]		= GATE(0x06c, BIT(20)),
>  
> +	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
> +	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
> +
>  	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
>  	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
>  	[CLK_USB_HSIC]		= GATE(0x0cc, BIT(10)),
> @@ -42,6 +47,8 @@ static struct ccu_reset a83t_resets[] = {
>  	[RST_BUS_MMC0]		= RESET(0x2c0, BIT(8)),
>  	[RST_BUS_MMC1]		= RESET(0x2c0, BIT(9)),
>  	[RST_BUS_MMC2]		= RESET(0x2c0, BIT(10)),
> +	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
> +	[RST_BUS_SPI1]		= RESET(0x2c0, BIT(21)),
>  	[RST_BUS_OTG]		= RESET(0x2c0, BIT(24)),
>  	[RST_BUS_EHCI0]		= RESET(0x2c0, BIT(26)),
>  	[RST_BUS_EHCI1]		= RESET(0x2c0, BIT(27)),
> diff --git a/drivers/clk/sunxi/clk_h3.c b/drivers/clk/sunxi/clk_h3.c
> index 416aec2b89..5f99ef7342 100644
> --- a/drivers/clk/sunxi/clk_h3.c
> +++ b/drivers/clk/sunxi/clk_h3.c
> @@ -16,6 +16,8 @@ static struct ccu_clk_gate h3_gates[] = {
>  	[CLK_BUS_MMC0]		= GATE(0x060, BIT(8)),
>  	[CLK_BUS_MMC1]		= GATE(0x060, BIT(9)),
>  	[CLK_BUS_MMC2]		= GATE(0x060, BIT(10)),
> +	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
> +	[CLK_BUS_SPI1]		= GATE(0x060, BIT(21)),
>  	[CLK_BUS_OTG]		= GATE(0x060, BIT(23)),
>  	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(24)),
>  	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(25)),
> @@ -31,6 +33,9 @@ static struct ccu_clk_gate h3_gates[] = {
>  	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
>  	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
>  
> +	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
> +	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
> +
>  	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
>  	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
>  	[CLK_USB_PHY2]		= GATE(0x0cc, BIT(10)),
> @@ -50,6 +55,8 @@ static struct ccu_reset h3_resets[] = {
>  	[RST_BUS_MMC0]		= RESET(0x2c0, BIT(8)),
>  	[RST_BUS_MMC1]		= RESET(0x2c0, BIT(9)),
>  	[RST_BUS_MMC2]		= RESET(0x2c0, BIT(10)),
> +	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
> +	[RST_BUS_SPI1]		= RESET(0x2c0, BIT(21)),
>  	[RST_BUS_OTG]		= RESET(0x2c0, BIT(23)),
>  	[RST_BUS_EHCI0]		= RESET(0x2c0, BIT(24)),
>  	[RST_BUS_EHCI1]		= RESET(0x2c0, BIT(25)),
> diff --git a/drivers/clk/sunxi/clk_h6.c b/drivers/clk/sunxi/clk_h6.c
> index 902612da91..71f0c78656 100644
> --- a/drivers/clk/sunxi/clk_h6.c
> +++ b/drivers/clk/sunxi/clk_h6.c
> @@ -20,6 +20,12 @@ static struct ccu_clk_gate h6_gates[] = {
>  	[CLK_BUS_UART1]		= GATE(0x90c, BIT(1)),
>  	[CLK_BUS_UART2]		= GATE(0x90c, BIT(2)),
>  	[CLK_BUS_UART3]		= GATE(0x90c, BIT(3)),
> +
> +	[CLK_SPI0]		= GATE(0x940, BIT(31)),
> +	[CLK_SPI1]		= GATE(0x944, BIT(31)),
> +
> +	[CLK_BUS_SPI0]		= GATE(0x96c, BIT(0)),
> +	[CLK_BUS_SPI1]		= GATE(0x96c, BIT(1)),
>  };
>  
>  static struct ccu_reset h6_resets[] = {
> @@ -30,6 +36,9 @@ static struct ccu_reset h6_resets[] = {
>  	[RST_BUS_UART1]		= RESET(0x90c, BIT(17)),
>  	[RST_BUS_UART2]		= RESET(0x90c, BIT(18)),
>  	[RST_BUS_UART3]		= RESET(0x90c, BIT(19)),
> +
> +	[RST_BUS_SPI0]		= RESET(0x96c, BIT(16)),
> +	[RST_BUS_SPI1]		= RESET(0x96c, BIT(17)),
>  };
>  
>  static const struct ccu_desc h6_ccu_desc = {
> diff --git a/drivers/clk/sunxi/clk_r40.c b/drivers/clk/sunxi/clk_r40.c
> index b9457e1971..92907281f1 100644
> --- a/drivers/clk/sunxi/clk_r40.c
> +++ b/drivers/clk/sunxi/clk_r40.c
> @@ -17,6 +17,10 @@ static struct ccu_clk_gate r40_gates[] = {
>  	[CLK_BUS_MMC1]		= GATE(0x060, BIT(9)),
>  	[CLK_BUS_MMC2]		= GATE(0x060, BIT(10)),
>  	[CLK_BUS_MMC3]		= GATE(0x060, BIT(11)),
> +	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
> +	[CLK_BUS_SPI1]		= GATE(0x060, BIT(21)),
> +	[CLK_BUS_SPI2]		= GATE(0x060, BIT(22)),
> +	[CLK_BUS_SPI3]		= GATE(0x060, BIT(23)),
>  	[CLK_BUS_OTG]		= GATE(0x060, BIT(25)),
>  	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(26)),
>  	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(27)),
> @@ -34,6 +38,11 @@ static struct ccu_clk_gate r40_gates[] = {
>  	[CLK_BUS_UART6]		= GATE(0x06c, BIT(22)),
>  	[CLK_BUS_UART7]		= GATE(0x06c, BIT(23)),
>  
> +	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
> +	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
> +	[CLK_SPI2]		= GATE(0x0a8, BIT(31)),
> +	[CLK_SPI3]		= GATE(0x0ac, BIT(31)),
> +
>  	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
>  	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
>  	[CLK_USB_PHY2]		= GATE(0x0cc, BIT(10)),
> @@ -51,6 +60,10 @@ static struct ccu_reset r40_resets[] = {
>  	[RST_BUS_MMC1]		= RESET(0x2c0, BIT(9)),
>  	[RST_BUS_MMC2]		= RESET(0x2c0, BIT(10)),
>  	[RST_BUS_MMC3]		= RESET(0x2c0, BIT(11)),
> +	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
> +	[RST_BUS_SPI1]		= RESET(0x2c0, BIT(21)),
> +	[RST_BUS_SPI2]		= RESET(0x2c0, BIT(22)),
> +	[RST_BUS_SPI3]		= RESET(0x2c0, BIT(23)),
>  	[RST_BUS_OTG]		= RESET(0x2c0, BIT(25)),
>  	[RST_BUS_EHCI0]		= RESET(0x2c0, BIT(26)),
>  	[RST_BUS_EHCI1]		= RESET(0x2c0, BIT(27)),
> diff --git a/drivers/clk/sunxi/clk_v3s.c b/drivers/clk/sunxi/clk_v3s.c
> index c8a9027889..789ac72026 100644
> --- a/drivers/clk/sunxi/clk_v3s.c
> +++ b/drivers/clk/sunxi/clk_v3s.c
> @@ -16,12 +16,15 @@ static struct ccu_clk_gate v3s_gates[] = {
>  	[CLK_BUS_MMC0]		= GATE(0x060, BIT(8)),
>  	[CLK_BUS_MMC1]		= GATE(0x060, BIT(9)),
>  	[CLK_BUS_MMC2]		= GATE(0x060, BIT(10)),
> +	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
>  	[CLK_BUS_OTG]		= GATE(0x060, BIT(24)),
>  
>  	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
>  	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
>  	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
>  
> +	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
> +
>  	[CLK_USB_PHY0]          = GATE(0x0cc, BIT(8)),
>  };
>  
> @@ -31,6 +34,7 @@ static struct ccu_reset v3s_resets[] = {
>  	[RST_BUS_MMC0]		= RESET(0x2c0, BIT(8)),
>  	[RST_BUS_MMC1]		= RESET(0x2c0, BIT(9)),
>  	[RST_BUS_MMC2]		= RESET(0x2c0, BIT(10)),
> +	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
>  	[RST_BUS_OTG]		= RESET(0x2c0, BIT(24)),
>  
>  	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
> 

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

* [U-Boot] [PATCH 03/10] spi: sun4i: Simplify reg writes using set/clrbits_le32
  2019-02-09 13:14 ` [U-Boot] [PATCH 03/10] spi: sun4i: Simplify reg writes using set/clrbits_le32 Jagan Teki
@ 2019-02-13  1:14   ` André Przywara
  2019-02-13 10:24     ` Jagan Teki
  0 siblings, 1 reply; 27+ messages in thread
From: André Przywara @ 2019-02-13  1:14 UTC (permalink / raw)
  To: u-boot

On 09/02/2019 13:14, Jagan Teki wrote:
> Update the existing register writes using setbits_le32 and
> clrbits_le32 in required places.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  drivers/spi/sun4i_spi.c | 21 ++++++++-------------
>  1 file changed, 8 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
> index 87b396a96e..5446cebe7c 100644
> --- a/drivers/spi/sun4i_spi.c
> +++ b/drivers/spi/sun4i_spi.c
> @@ -283,20 +283,18 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
>  {
>  	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
>  
> -	writel(SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER | SUN4I_CTL_TP |
> -	       SUN4I_CTL_CS_MANUAL | SUN4I_CTL_CS_ACTIVE_LOW,
> -	       &priv->regs->ctl);
> +	setbits_le32(&priv->regs->ctl, SUN4I_CTL_ENABLE |
> +		     SUN4I_CTL_MASTER | SUN4I_CTL_TP |
> +		     SUN4I_CTL_CS_MANUAL | SUN4I_CTL_CS_ACTIVE_LOW);
> +

Careful, this changes semantics. The original call explicitly cleared
all the remaining bits, which is important for the setup (some bits are
default 1).
And besides I am not sure what this change would improve anyway, as it
isn't shorter. If at all, I'd use clrsetbits_le32(), to mask off the
reserved bits 31:21.

Rest is fine.

Cheers,
Andre.


>  	return 0;
>  }
>  
>  static int sun4i_spi_release_bus(struct udevice *dev)
>  {
>  	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
> -	u32 reg;
>  
> -	reg = readl(&priv->regs->ctl);
> -	reg &= ~SUN4I_CTL_ENABLE;
> -	writel(reg, &priv->regs->ctl);
> +	clrbits_le32(&priv->regs->ctl, SUN4I_CTL_ENABLE);
>  
>  	return 0;
>  }
> @@ -309,7 +307,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
>  	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
>  
>  	u32 len = bitlen / 8;
> -	u32 reg, rx_fifocnt;
> +	u32 rx_fifocnt;
>  	u8 nbytes;
>  	int ret;
>  
> @@ -324,10 +322,8 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
>  	if (flags & SPI_XFER_BEGIN)
>  		sun4i_spi_set_cs(bus, slave_plat->cs, true);
>  
> -	reg = readl(&priv->regs->ctl);
> -
>  	/* Reset FIFOs */
> -	writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->ctl);
> +	setbits_le32(&priv->regs->ctl, SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST);
>  
>  	while (len) {
>  		/* Setup the transfer now... */
> @@ -341,8 +337,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
>  		sun4i_spi_fill_fifo(priv, nbytes);
>  
>  		/* Start the transfer */
> -		reg = readl(&priv->regs->ctl);
> -		writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);
> +		setbits_le32(&priv->regs->ctl, SUN4I_CTL_XCH);
>  
>  		/* Wait till RX FIFO to be empty */
>  		ret = readl_poll_timeout(&priv->regs->ctl, rx_fifocnt,
> 

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

* [U-Boot] [PATCH 04/10] spi: sun4i: Access registers and bits via enum offsets
  2019-02-09 13:14 ` [U-Boot] [PATCH 04/10] spi: sun4i: Access registers and bits via enum offsets Jagan Teki
@ 2019-02-13  1:15   ` André Przywara
  0 siblings, 0 replies; 27+ messages in thread
From: André Przywara @ 2019-02-13  1:15 UTC (permalink / raw)
  To: u-boot

On 09/02/2019 13:14, Jagan Teki wrote:
> Allwinner support two different SPI controllers one for A10 and
> another for A31 with minimal changes in register offsets and
> respective register bits, but the logic for accessing the SPI
> master via SPI slave remains nearly similar.
> 
> Add enum offsets for register set and register bits, so-that
> it can access both classes of SPI controllers.
> 
> Assign same control register for global, transfer and fifo control
> registers to make the same code compatible with A31 SPI controller.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  drivers/spi/sun4i_spi.c | 162 +++++++++++++++++++++++++++++-----------
>  1 file changed, 120 insertions(+), 42 deletions(-)
> 
> diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
> index 5446cebe7c..c06028890b 100644
> --- a/drivers/spi/sun4i_spi.c
> +++ b/drivers/spi/sun4i_spi.c
> @@ -83,7 +83,6 @@
>  #define SUN4I_XMIT_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
>  
>  #define SUN4I_FIFO_STA_REG	0x28
> -#define SUN4I_FIFO_STA_RF_CNT_MASK	0x7f
>  #define SUN4I_FIFO_STA_RF_CNT_BITS	0
>  #define SUN4I_FIFO_STA_TF_CNT_MASK	0x7f
>  #define SUN4I_FIFO_STA_TF_CNT_BITS	16
> @@ -93,28 +92,49 @@
>  #define SUN4I_SPI_DEFAULT_RATE	1000000
>  #define SUN4I_SPI_TIMEOUT_US	1000000
>  
> -/* sun4i spi register set */
> -struct sun4i_spi_regs {
> -	u32 rxdata;
> -	u32 txdata;
> -	u32 ctl;
> -	u32 intctl;
> -	u32 st;
> -	u32 dmactl;
> -	u32 wait;
> -	u32 cctl;
> -	u32 bc;
> -	u32 tc;
> -	u32 fifo_sta;
> +/* sun spi register set */
> +enum sun4i_spi_regs {
> +	SPI_GCR,
> +	SPI_TCR,
> +	SPI_FCR,
> +	SPI_FSR,
> +	SPI_CCR,
> +	SPI_BC,
> +	SPI_TC,
> +	SPI_BCTL,
> +	SPI_TXD,
> +	SPI_RXD,
> +};
> +
> +/* sun spi register bits */
> +enum sun4i_spi_bits {
> +	SPI_GCR_TP,
> +	SPI_TCR_CPHA,
> +	SPI_TCR_CPOL,
> +	SPI_TCR_CS_ACTIVE_LOW,
> +	SPI_TCR_CS_SEL,
> +	SPI_TCR_CS_MASK,
> +	SPI_TCR_XCH,
> +	SPI_TCR_CS_MANUAL,
> +	SPI_TCR_CS_LEVEL,
> +	SPI_FCR_TF_RST,
> +	SPI_FCR_RF_RST,
> +	SPI_FSR_RF_CNT_MASK,
> +};
> +
> +struct sun4i_spi_variant {
> +	const unsigned long *regs, *bits;
>  };
>  
>  struct sun4i_spi_platdata {
> +	struct sun4i_spi_variant *variant;
>  	u32 base_addr;
>  	u32 max_hz;
>  };
>  
>  struct sun4i_spi_priv {
> -	struct sun4i_spi_regs *regs;
> +	struct sun4i_spi_variant *variant;
> +	u32 base_addr;
>  	u32 freq;
>  	u32 mode;
>  
> @@ -126,10 +146,11 @@ DECLARE_GLOBAL_DATA_PTR;
>  
>  static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
>  {
> +	struct sun4i_spi_variant *variant = priv->variant;
>  	u8 byte;
>  
>  	while (len--) {
> -		byte = readb(&priv->regs->rxdata);
> +		byte = readb(priv->base_addr + variant->regs[SPI_RXD]);

What about making this register address calculation a macro? That would
also allow you to save the variant variable everywhere.

#define SPI_REG(priv, reg) ((priv)->base_addr + \
			    (priv)->variant->regs[reg])

Cheers,
Andre.


>  		if (priv->rx_buf)
>  			*priv->rx_buf++ = byte;
>  	}
> @@ -137,30 +158,33 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
>  
>  static inline void sun4i_spi_fill_fifo(struct sun4i_spi_priv *priv, int len)
>  {
> +	struct sun4i_spi_variant *variant = priv->variant;
>  	u8 byte;
>  
>  	while (len--) {
>  		byte = priv->tx_buf ? *priv->tx_buf++ : 0;
> -		writeb(byte, &priv->regs->txdata);
> +		writeb(byte, priv->base_addr + variant->regs[SPI_TXD]);
>  	}
>  }
>  
>  static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
>  {
>  	struct sun4i_spi_priv *priv = dev_get_priv(bus);
> +	struct sun4i_spi_variant *variant = priv->variant;
>  	u32 reg;
>  
> -	reg = readl(&priv->regs->ctl);
> +	reg = readl(priv->base_addr + variant->regs[SPI_TCR]);
>  
> -	reg &= ~SUN4I_CTL_CS_MASK;
> -	reg |= SUN4I_CTL_CS(cs);
> +	reg &= ~variant->bits[SPI_TCR_CS_MASK];
> +	reg |= ((cs << variant->bits[SPI_TCR_CS_SEL]) &
> +		variant->bits[SPI_TCR_CS_MASK]);
>  
>  	if (enable)
> -		reg &= ~SUN4I_CTL_CS_LEVEL;
> +		reg &= ~variant->bits[SPI_TCR_CS_LEVEL];
>  	else
> -		reg |= SUN4I_CTL_CS_LEVEL;
> +		reg |= variant->bits[SPI_TCR_CS_LEVEL];
>  
> -	writel(reg, &priv->regs->ctl);
> +	writel(reg, priv->base_addr + variant->regs[SPI_TCR]);
>  }
>  
>  static int sun4i_spi_parse_pins(struct udevice *dev)
> @@ -255,6 +279,7 @@ static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
>  	int node = dev_of_offset(bus);
>  
>  	plat->base_addr = devfdt_get_addr(bus);
> +	plat->variant = (struct sun4i_spi_variant *)dev_get_driver_data(bus);
>  	plat->max_hz = fdtdec_get_int(gd->fdt_blob, node,
>  				      "spi-max-frequency",
>  				      SUN4I_SPI_DEFAULT_RATE);
> @@ -273,7 +298,8 @@ static int sun4i_spi_probe(struct udevice *bus)
>  	sun4i_spi_enable_clock();
>  	sun4i_spi_parse_pins(bus);
>  
> -	priv->regs = (struct sun4i_spi_regs *)(uintptr_t)plat->base_addr;
> +	priv->variant = plat->variant;
> +	priv->base_addr = plat->base_addr;
>  	priv->freq = plat->max_hz;
>  
>  	return 0;
> @@ -282,10 +308,15 @@ static int sun4i_spi_probe(struct udevice *bus)
>  static int sun4i_spi_claim_bus(struct udevice *dev)
>  {
>  	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
> +	struct sun4i_spi_variant *variant = priv->variant;
> +
> +	setbits_le32(priv->base_addr + variant->regs[SPI_GCR],
> +		     SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER |
> +		     variant->bits[SPI_GCR_TP]);
>  
> -	setbits_le32(&priv->regs->ctl, SUN4I_CTL_ENABLE |
> -		     SUN4I_CTL_MASTER | SUN4I_CTL_TP |
> -		     SUN4I_CTL_CS_MANUAL | SUN4I_CTL_CS_ACTIVE_LOW);
> +	setbits_le32(priv->base_addr + variant->regs[SPI_TCR],
> +		     variant->bits[SPI_TCR_CS_MANUAL] |
> +		     variant->bits[SPI_TCR_CS_ACTIVE_LOW]);
>  
>  	return 0;
>  }
> @@ -293,8 +324,10 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
>  static int sun4i_spi_release_bus(struct udevice *dev)
>  {
>  	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
> +	struct sun4i_spi_variant *variant = priv->variant;
>  
> -	clrbits_le32(&priv->regs->ctl, SUN4I_CTL_ENABLE);
> +	clrbits_le32(priv->base_addr + variant->regs[SPI_GCR],
> +		     SUN4I_CTL_ENABLE);
>  
>  	return 0;
>  }
> @@ -304,6 +337,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
>  {
>  	struct udevice *bus = dev->parent;
>  	struct sun4i_spi_priv *priv = dev_get_priv(bus);
> +	struct sun4i_spi_variant *variant = priv->variant;
>  	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
>  
>  	u32 len = bitlen / 8;
> @@ -323,25 +357,32 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
>  		sun4i_spi_set_cs(bus, slave_plat->cs, true);
>  
>  	/* Reset FIFOs */
> -	setbits_le32(&priv->regs->ctl, SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST);
> +	setbits_le32(priv->base_addr + variant->regs[SPI_FCR],
> +		     variant->bits[SPI_FCR_RF_RST] |
> +		     variant->bits[SPI_FCR_TF_RST]);
>  
>  	while (len) {
>  		/* Setup the transfer now... */
>  		nbytes = min(len, (u32)(SUN4I_FIFO_DEPTH - 1));
>  
>  		/* Setup the counters */
> -		writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bc);
> -		writel(SUN4I_XMIT_CNT(nbytes), &priv->regs->tc);
> +		writel(SUN4I_BURST_CNT(nbytes),
> +		       priv->base_addr + variant->regs[SPI_BC]);
> +		writel(SUN4I_XMIT_CNT(nbytes),
> +		       priv->base_addr + variant->regs[SPI_TC]);
>  
>  		/* Fill the TX FIFO */
>  		sun4i_spi_fill_fifo(priv, nbytes);
>  
>  		/* Start the transfer */
> -		setbits_le32(&priv->regs->ctl, SUN4I_CTL_XCH);
> +		setbits_le32(priv->base_addr + variant->regs[SPI_TCR],
> +			     variant->bits[SPI_TCR_XCH]);
>  
>  		/* Wait till RX FIFO to be empty */
> -		ret = readl_poll_timeout(&priv->regs->ctl, rx_fifocnt,
> -					 !(((rx_fifocnt & SUN4I_FIFO_STA_RF_CNT_MASK) >>
> +		ret = readl_poll_timeout(priv->base_addr + variant->regs[SPI_FSR],
> +					 rx_fifocnt,
> +					 !(((rx_fifocnt &
> +					 variant->bits[SPI_FSR_RF_CNT_MASK]) >>
>  					 SUN4I_FIFO_STA_RF_CNT_BITS) < nbytes),
>  					 SUN4I_SPI_TIMEOUT_US);
>  		if (ret < 0) {
> @@ -366,6 +407,7 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
>  {
>  	struct sun4i_spi_platdata *plat = dev_get_platdata(dev);
>  	struct sun4i_spi_priv *priv = dev_get_priv(dev);
> +	struct sun4i_spi_variant *variant = priv->variant;
>  	unsigned int div;
>  	u32 reg;
>  
> @@ -390,7 +432,7 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
>  	 */
>  
>  	div = SUN4I_SPI_MAX_RATE / (2 * speed);
> -	reg = readl(&priv->regs->cctl);
> +	reg = readl(priv->base_addr + variant->regs[SPI_CCR]);
>  
>  	if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
>  		if (div > 0)
> @@ -405,7 +447,7 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
>  	}
>  
>  	priv->freq = speed;
> -	writel(reg, &priv->regs->cctl);
> +	writel(reg, priv->base_addr + variant->regs[SPI_CCR]);
>  
>  	return 0;
>  }
> @@ -413,19 +455,20 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
>  static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
>  {
>  	struct sun4i_spi_priv *priv = dev_get_priv(dev);
> +	struct sun4i_spi_variant *variant = priv->variant;
>  	u32 reg;
>  
> -	reg = readl(&priv->regs->ctl);
> -	reg &= ~(SUN4I_CTL_CPOL | SUN4I_CTL_CPHA);
> +	reg = readl(priv->base_addr + variant->regs[SPI_TCR]);
> +	reg &= ~(variant->bits[SPI_TCR_CPOL] | variant->bits[SPI_TCR_CPHA]);
>  
>  	if (mode & SPI_CPOL)
> -		reg |= SUN4I_CTL_CPOL;
> +		reg |= variant->bits[SPI_TCR_CPOL];
>  
>  	if (mode & SPI_CPHA)
> -		reg |= SUN4I_CTL_CPHA;
> +		reg |= variant->bits[SPI_TCR_CPHA];
>  
>  	priv->mode = mode;
> -	writel(reg, &priv->regs->ctl);
> +	writel(reg, priv->base_addr + variant->regs[SPI_TCR]);
>  
>  	return 0;
>  }
> @@ -438,8 +481,43 @@ static const struct dm_spi_ops sun4i_spi_ops = {
>  	.set_mode		= sun4i_spi_set_mode,
>  };
>  
> +static const unsigned long sun4i_spi_regs[] = {
> +	[SPI_GCR]		= SUN4I_CTL_REG,
> +	[SPI_TCR]		= SUN4I_CTL_REG,
> +	[SPI_FCR]		= SUN4I_CTL_REG,
> +	[SPI_FSR]		= SUN4I_FIFO_STA_REG,
> +	[SPI_CCR]		= SUN4I_CLK_CTL_REG,
> +	[SPI_BC]		= SUN4I_BURST_CNT_REG,
> +	[SPI_TC]		= SUN4I_XMIT_CNT_REG,
> +	[SPI_TXD]		= SUN4I_TXDATA_REG,
> +	[SPI_RXD]		= SUN4I_RXDATA_REG,
> +};
> +
> +static const unsigned long sun4i_spi_bits[] = {
> +	[SPI_GCR_TP]		= BIT(18),
> +	[SPI_TCR_CPHA]		= BIT(2),
> +	[SPI_TCR_CPOL]		= BIT(3),
> +	[SPI_TCR_CS_ACTIVE_LOW] = BIT(4),
> +	[SPI_TCR_XCH]		= BIT(10),
> +	[SPI_TCR_CS_SEL]	= 12,
> +	[SPI_TCR_CS_MASK]	= 0x3000,
> +	[SPI_TCR_CS_MANUAL]	= BIT(16),
> +	[SPI_TCR_CS_LEVEL]	= BIT(17),
> +	[SPI_FCR_TF_RST]	= BIT(8),
> +	[SPI_FCR_RF_RST]	= BIT(9),
> +	[SPI_FSR_RF_CNT_MASK]	= GENMASK(6, 0),
> +};
> +
> +static const struct sun4i_spi_variant sun4i_a10_spi_variant = {
> +	.regs			= sun4i_spi_regs,
> +	.bits			= sun4i_spi_bits,
> +};
> +
>  static const struct udevice_id sun4i_spi_ids[] = {
> -	{ .compatible = "allwinner,sun4i-a10-spi"  },
> +	{
> +	  .compatible = "allwinner,sun4i-a10-spi",
> +	  .data = (ulong)&sun4i_a10_spi_variant,
> +	},
>  	{ }
>  };
>  
> 

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

* [U-Boot] [PATCH 05/10] spi: sun4i: Support fifo_depth via drvdata
  2019-02-09 13:14 ` [U-Boot] [PATCH 05/10] spi: sun4i: Support fifo_depth via drvdata Jagan Teki
@ 2019-02-13  1:16   ` André Przywara
  0 siblings, 0 replies; 27+ messages in thread
From: André Przywara @ 2019-02-13  1:16 UTC (permalink / raw)
  To: u-boot

On 09/02/2019 13:14, Jagan Teki wrote:
> Support fifo_depth via drvdata instead of macro definition, this would
> eventually reduce another macro definition for new SPI controller fifo
> depth support addition.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>

Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Cheers,
Andre

> ---
>  drivers/spi/sun4i_spi.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
> index c06028890b..d3cf25db6f 100644
> --- a/drivers/spi/sun4i_spi.c
> +++ b/drivers/spi/sun4i_spi.c
> @@ -33,8 +33,6 @@
>  
>  #include <linux/iopoll.h>
>  
> -#define SUN4I_FIFO_DEPTH	64
> -
>  #define SUN4I_RXDATA_REG	0x00
>  
>  #define SUN4I_TXDATA_REG	0x04
> @@ -124,6 +122,7 @@ enum sun4i_spi_bits {
>  
>  struct sun4i_spi_variant {
>  	const unsigned long *regs, *bits;
> +	u32 fifo_depth;
>  };
>  
>  struct sun4i_spi_platdata {
> @@ -363,7 +362,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
>  
>  	while (len) {
>  		/* Setup the transfer now... */
> -		nbytes = min(len, (u32)(SUN4I_FIFO_DEPTH - 1));
> +		nbytes = min(len, (priv->variant->fifo_depth - 1));
>  
>  		/* Setup the counters */
>  		writel(SUN4I_BURST_CNT(nbytes),
> @@ -511,6 +510,7 @@ static const unsigned long sun4i_spi_bits[] = {
>  static const struct sun4i_spi_variant sun4i_a10_spi_variant = {
>  	.regs			= sun4i_spi_regs,
>  	.bits			= sun4i_spi_bits,
> +	.fifo_depth		= 64,
>  };
>  
>  static const struct udevice_id sun4i_spi_ids[] = {
> 

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

* [U-Boot] [PATCH 06/10] spi: sun4i: Add CLK support
  2019-02-09 13:14 ` [U-Boot] [PATCH 06/10] spi: sun4i: Add CLK support Jagan Teki
@ 2019-02-13  1:19   ` André Przywara
  2019-02-13 11:41     ` Jagan Teki
  0 siblings, 1 reply; 27+ messages in thread
From: André Przywara @ 2019-02-13  1:19 UTC (permalink / raw)
  To: u-boot

On 09/02/2019 13:14, Jagan Teki wrote:
> Add CLK support to enable AHB and MOD SPI clocks on sun4i_spi driver.
> 
> Note, that the code will enable and disable clock in claim and release
> calls to make proper clock and reset handling between claiming and
> releasing SPI bus.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>

That looks alright to me, but I wonder if you should introduce the reset
support here as well. Since it's optional, it shouldn't hurt to have it
in already, even though the SUN4I generation doesn't need it.

Cheers,
Andre.

> ---
>  drivers/spi/sun4i_spi.c | 56 +++++++++++++++++++++++++++++++++++------
>  1 file changed, 48 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
> index d3cf25db6f..aeed68764c 100644
> --- a/drivers/spi/sun4i_spi.c
> +++ b/drivers/spi/sun4i_spi.c
> @@ -19,6 +19,7 @@
>   */
>  
>  #include <common.h>
> +#include <clk.h>
>  #include <dm.h>
>  #include <spi.h>
>  #include <errno.h>
> @@ -29,8 +30,6 @@
>  #include <asm/gpio.h>
>  #include <asm/io.h>
>  
> -#include <asm/arch/clock.h>
> -
>  #include <linux/iopoll.h>
>  
>  #define SUN4I_RXDATA_REG	0x00
> @@ -133,6 +132,7 @@ struct sun4i_spi_platdata {
>  
>  struct sun4i_spi_priv {
>  	struct sun4i_spi_variant *variant;
> +	struct clk clk_ahb, clk_mod;
>  	u32 base_addr;
>  	u32 freq;
>  	u32 mode;
> @@ -263,13 +263,34 @@ static int sun4i_spi_parse_pins(struct udevice *dev)
>  	return 0;
>  }
>  
> -static inline void sun4i_spi_enable_clock(void)
> +static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
>  {
> -	struct sunxi_ccm_reg *const ccm =
> -		(struct sunxi_ccm_reg *const)SUNXI_CCM_BASE;
> +	struct sun4i_spi_priv *priv = dev_get_priv(dev);
> +	int ret;
> +
> +	if (!enable) {
> +		clk_disable(&priv->clk_ahb);
> +		clk_disable(&priv->clk_mod);
> +		return 0;
> +	}
>  
> -	setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_SPI0));
> -	writel((1 << 31), &ccm->spi0_clk_cfg);
> +	ret = clk_enable(&priv->clk_ahb);
> +	if (ret) {
> +		dev_err(dev, "failed to enable ahb clock (ret=%d)\n", ret);
> +		return ret;
> +	}
> +
> +	ret = clk_enable(&priv->clk_mod);
> +	if (ret) {
> +		dev_err(dev, "failed to enable mod clock (ret=%d)\n", ret);
> +		goto err_ahb;
> +	}
> +
> +	return 0;
> +
> +err_ahb:
> +	clk_disable(&priv->clk_ahb);
> +	return ret;
>  }
>  
>  static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
> @@ -293,8 +314,20 @@ static int sun4i_spi_probe(struct udevice *bus)
>  {
>  	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
>  	struct sun4i_spi_priv *priv = dev_get_priv(bus);
> +	int ret;
> +
> +	ret = clk_get_by_name(bus, "ahb", &priv->clk_ahb);
> +	if (ret) {
> +		dev_err(dev, "failed to get ahb clock\n");
> +		return ret;
> +	}
> +
> +	ret = clk_get_by_name(bus, "mod", &priv->clk_mod);
> +	if (ret) {
> +		dev_err(dev, "failed to get mod clock\n");
> +		return ret;
> +	}
>  
> -	sun4i_spi_enable_clock();
>  	sun4i_spi_parse_pins(bus);
>  
>  	priv->variant = plat->variant;
> @@ -308,6 +341,11 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
>  {
>  	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
>  	struct sun4i_spi_variant *variant = priv->variant;
> +	int ret;
> +
> +	ret = sun4i_spi_set_clock(dev->parent, true);
> +	if (ret)
> +		return ret;
>  
>  	setbits_le32(priv->base_addr + variant->regs[SPI_GCR],
>  		     SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER |
> @@ -328,6 +366,8 @@ static int sun4i_spi_release_bus(struct udevice *dev)
>  	clrbits_le32(priv->base_addr + variant->regs[SPI_GCR],
>  		     SUN4I_CTL_ENABLE);
>  
> +	sun4i_spi_set_clock(dev->parent, false);
> +
>  	return 0;
>  }
>  
> 

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

* [U-Boot] [PATCH 07/10] spi: sun4: Add A31 spi controller support
  2019-02-09 13:14 ` [U-Boot] [PATCH 07/10] spi: sun4: Add A31 spi controller support Jagan Teki
@ 2019-02-13  1:19   ` André Przywara
  2019-02-13  3:20     ` Chen-Yu Tsai
  2019-02-13 12:17     ` Jagan Teki
  0 siblings, 2 replies; 27+ messages in thread
From: André Przywara @ 2019-02-13  1:19 UTC (permalink / raw)
  To: u-boot

On 09/02/2019 13:14, Jagan Teki wrote:
> Add A31 spi controller support for existing sun4i_spi driver via driver
> data, this would simply add A31 register along with proper register bits
> via enum sets.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  drivers/spi/Kconfig     |  4 +-
>  drivers/spi/sun4i_spi.c | 84 ++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 85 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index ac7fbab841..15207d23c1 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -223,9 +223,9 @@ config STM32_QSPI
>  	  this ST IP core.
>  
>  config SUN4I_SPI
> -	bool "Allwinner A10 SoCs SPI controller"
> +	bool "Allwinner A10/A31 SoCs SPI controller"
>  	help
> -	  SPI driver for Allwinner sun4i, sun5i and sun7i SoCs
> +	  This enables using the SPI controller on the Allwinner A10/A31 SoCs.
>  
>  config TEGRA114_SPI
>  	bool "nVidia Tegra114 SPI driver"
> diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
> index aeed68764c..36f2215f7d 100644
> --- a/drivers/spi/sun4i_spi.c
> +++ b/drivers/spi/sun4i_spi.c
> @@ -24,6 +24,7 @@
>  #include <spi.h>
>  #include <errno.h>
>  #include <fdt_support.h>
> +#include <reset.h>
>  #include <wait_bit.h>
>  
>  #include <asm/bitops.h>
> @@ -84,6 +85,18 @@
>  #define SUN4I_FIFO_STA_TF_CNT_MASK	0x7f
>  #define SUN4I_FIFO_STA_TF_CNT_BITS	16
>  
> +/* sun6i spi registers */
> +#define SUN6I_GBL_CTL_REG		0x04
> +#define SUN6I_TFR_CTL_REG		0x08
> +#define SUN6I_FIFO_CTL_REG		0x18
> +#define SUN6I_FIFO_STA_REG		0x1c
> +#define SUN6I_CLK_CTL_REG		0x24
> +#define SUN6I_BURST_CNT_REG		0x30
> +#define SUN6I_XMIT_CNT_REG		0x34
> +#define SUN6I_BURST_CTL_REG		0x38
> +#define SUN6I_TXDATA_REG		0x200
> +#define SUN6I_RXDATA_REG		0x300
> +
>  #define SUN4I_SPI_MAX_RATE	24000000
>  #define SUN4I_SPI_MIN_RATE	3000
>  #define SUN4I_SPI_DEFAULT_RATE	1000000
> @@ -106,6 +119,7 @@ enum sun4i_spi_regs {
>  /* sun spi register bits */
>  enum sun4i_spi_bits {
>  	SPI_GCR_TP,
> +	SPI_GCR_SRST,
>  	SPI_TCR_CPHA,
>  	SPI_TCR_CPOL,
>  	SPI_TCR_CS_ACTIVE_LOW,
> @@ -133,6 +147,7 @@ struct sun4i_spi_platdata {
>  struct sun4i_spi_priv {
>  	struct sun4i_spi_variant *variant;
>  	struct clk clk_ahb, clk_mod;
> +	struct reset_ctl reset;
>  	u32 base_addr;
>  	u32 freq;
>  	u32 mode;
> @@ -255,7 +270,10 @@ static int sun4i_spi_parse_pins(struct udevice *dev)
>  			if (pin < 0)
>  				break;
>  
> -			sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
> +			if (IS_ENABLED(CONFIG_MACH_SUN50I))
> +				sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0);
> +			else
> +				sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
>  			sunxi_gpio_set_drv(pin, drive);
>  			sunxi_gpio_set_pull(pin, pull);
>  		}
> @@ -271,6 +289,8 @@ static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
>  	if (!enable) {
>  		clk_disable(&priv->clk_ahb);
>  		clk_disable(&priv->clk_mod);
> +		if (reset_valid(&priv->reset))
> +			reset_assert(&priv->reset);
>  		return 0;
>  	}
>  
> @@ -286,8 +306,18 @@ static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
>  		goto err_ahb;
>  	}
>  
> +	if (reset_valid(&priv->reset)) {
> +		ret = reset_deassert(&priv->reset);
> +		if (ret) {
> +			dev_err(dev, "failed to deassert reset\n");
> +			goto err_mod;
> +		}
> +	}
> +
>  	return 0;
>  
> +err_mod:
> +	clk_disable(&priv->clk_mod);
>  err_ahb:
>  	clk_disable(&priv->clk_ahb);
>  	return ret;
> @@ -328,6 +358,12 @@ static int sun4i_spi_probe(struct udevice *bus)
>  		return ret;
>  	}
>  
> +	ret = reset_get_by_index(bus, 0, &priv->reset);
> +	if (ret && ret != -ENOENT) {
> +		dev_err(dev, "failed to get reset\n");
> +		return ret;
> +	}
> +
>  	sun4i_spi_parse_pins(bus);
>  
>  	priv->variant = plat->variant;
> @@ -351,6 +387,10 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
>  		     SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER |
>  		     variant->bits[SPI_GCR_TP]);
>  
> +	if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
> +		setbits_le32(priv->base_addr + variant->regs[SPI_GCR],
> +			     variant->bits[SPI_GCR_SRST]);
> +

Just a note: This makes the driver only support one class of device, set
at compile time. Which means we could have used an #ifdef approach from
the beginning ....
Can you make this dependent on some bits in variant? That should solve it.

>  	setbits_le32(priv->base_addr + variant->regs[SPI_TCR],
>  		     variant->bits[SPI_TCR_CS_MANUAL] |
>  		     variant->bits[SPI_TCR_CS_ACTIVE_LOW]);
> @@ -409,6 +449,9 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
>  		       priv->base_addr + variant->regs[SPI_BC]);
>  		writel(SUN4I_XMIT_CNT(nbytes),
>  		       priv->base_addr + variant->regs[SPI_TC]);
> +		if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
> +			writel(SUN4I_BURST_CNT(nbytes),
> +			       priv->base_addr + variant->regs[SPI_BCTL]);
>  
>  		/* Fill the TX FIFO */
>  		sun4i_spi_fill_fifo(priv, nbytes);
> @@ -547,17 +590,56 @@ static const unsigned long sun4i_spi_bits[] = {
>  	[SPI_FSR_RF_CNT_MASK]	= GENMASK(6, 0),
>  };
>  
> +static const unsigned long sun8i_spi_regs[] = {
> +	[SPI_GCR]		= SUN6I_GBL_CTL_REG,
> +	[SPI_TCR]		= SUN6I_TFR_CTL_REG,
> +	[SPI_FCR]		= SUN6I_FIFO_CTL_REG,
> +	[SPI_FSR]		= SUN6I_FIFO_STA_REG,
> +	[SPI_CCR]		= SUN6I_CLK_CTL_REG,
> +	[SPI_BC]		= SUN6I_BURST_CNT_REG,
> +	[SPI_TC]		= SUN6I_XMIT_CNT_REG,
> +	[SPI_BCTL]		= SUN6I_BURST_CTL_REG,
> +	[SPI_TXD]		= SUN6I_TXDATA_REG,
> +	[SPI_RXD]		= SUN6I_RXDATA_REG,
> +};
> +
> +static const unsigned long sun8i_spi_bits[] = {
> +	[SPI_GCR_TP]		= BIT(7),
> +	[SPI_GCR_SRST]		= BIT(31),
> +	[SPI_TCR_CPHA]		= BIT(0),
> +	[SPI_TCR_CPOL]		= BIT(1),
> +	[SPI_TCR_CS_ACTIVE_LOW] = BIT(2),
> +	[SPI_TCR_CS_SEL]	= 4,
> +	[SPI_TCR_CS_MASK]	= 0x30,
> +	[SPI_TCR_CS_MANUAL]	= BIT(6),
> +	[SPI_TCR_CS_LEVEL]	= BIT(7),
> +	[SPI_TCR_XCH]		= BIT(31),
> +	[SPI_FCR_RF_RST]	= BIT(15),
> +	[SPI_FCR_TF_RST]	= BIT(31),
> +	[SPI_FSR_RF_CNT_MASK]	= GENMASK(7, 0),
> +};
> +
>  static const struct sun4i_spi_variant sun4i_a10_spi_variant = {
>  	.regs			= sun4i_spi_regs,
>  	.bits			= sun4i_spi_bits,
>  	.fifo_depth		= 64,
>  };
>  
> +static const struct sun4i_spi_variant sun8i_h3_spi_variant = {
> +	.regs			= sun8i_spi_regs,
> +	.bits			= sun8i_spi_bits,
> +	.fifo_depth		= 64,
> +};
> +
>  static const struct udevice_id sun4i_spi_ids[] = {
>  	{
>  	  .compatible = "allwinner,sun4i-a10-spi",
>  	  .data = (ulong)&sun4i_a10_spi_variant,
>  	},
> +	{
> +	  .compatible = "allwinner,sun8i-h3-spi",
> +	  .data = (ulong)&sun8i_h3_spi_variant,
> +	},

Please add the allwinner,sun6i-a31-spi compatible as well.

Cheers,
Andre

>  	{ }
>  };
>  
> 

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

* [U-Boot] [PATCH 08/10] spi: sun4i: Driver cleanup
  2019-02-09 13:14 ` [U-Boot] [PATCH 08/10] spi: sun4i: Driver cleanup Jagan Teki
@ 2019-02-13  1:20   ` André Przywara
  0 siblings, 0 replies; 27+ messages in thread
From: André Przywara @ 2019-02-13  1:20 UTC (permalink / raw)
  To: u-boot

On 09/02/2019 13:14, Jagan Teki wrote:
> - drop unused macros.
> - use base instead of base_addr, for better code readability
> - move .probe and .ofdata_to_platdata functions in required
>   places to add platdata support in future.
> - use sentinel sun4i_spi_ids.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  drivers/spi/sun4i_spi.c | 224 +++++++++++++++++-----------------------
>  1 file changed, 97 insertions(+), 127 deletions(-)
> 
> diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
> index 36f2215f7d..a32f511245 100644
> --- a/drivers/spi/sun4i_spi.c
> +++ b/drivers/spi/sun4i_spi.c
> @@ -33,57 +33,16 @@
>  
>  #include <linux/iopoll.h>
>  
> -#define SUN4I_RXDATA_REG	0x00
> -
> -#define SUN4I_TXDATA_REG	0x04
> -
> -#define SUN4I_CTL_REG		0x08
> -#define SUN4I_CTL_ENABLE		BIT(0)
> -#define SUN4I_CTL_MASTER		BIT(1)
> -#define SUN4I_CTL_CPHA			BIT(2)
> -#define SUN4I_CTL_CPOL			BIT(3)
> -#define SUN4I_CTL_CS_ACTIVE_LOW		BIT(4)
> -#define SUN4I_CTL_LMTF			BIT(6)
> -#define SUN4I_CTL_TF_RST		BIT(8)
> -#define SUN4I_CTL_RF_RST		BIT(9)
> -#define SUN4I_CTL_XCH			BIT(10)
> -#define SUN4I_CTL_CS_MASK		0x3000
> -#define SUN4I_CTL_CS(cs)		(((cs) << 12) & SUN4I_CTL_CS_MASK)
> -#define SUN4I_CTL_DHB			BIT(15)
> -#define SUN4I_CTL_CS_MANUAL		BIT(16)
> -#define SUN4I_CTL_CS_LEVEL		BIT(17)
> -#define SUN4I_CTL_TP			BIT(18)
> -
> -#define SUN4I_INT_CTL_REG	0x0c
> -#define SUN4I_INT_CTL_RF_F34		BIT(4)
> -#define SUN4I_INT_CTL_TF_E34		BIT(12)
> -#define SUN4I_INT_CTL_TC		BIT(16)
> -
> -#define SUN4I_INT_STA_REG	0x10
> -
> -#define SUN4I_DMA_CTL_REG	0x14
> -
> -#define SUN4I_WAIT_REG		0x18
> -
> -#define SUN4I_CLK_CTL_REG	0x1c
> -#define SUN4I_CLK_CTL_CDR2_MASK		0xff
> -#define SUN4I_CLK_CTL_CDR2(div)		((div) & SUN4I_CLK_CTL_CDR2_MASK)
> -#define SUN4I_CLK_CTL_CDR1_MASK		0xf
> -#define SUN4I_CLK_CTL_CDR1(div)		(((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8)
> -#define SUN4I_CLK_CTL_DRS		BIT(12)
> -
> -#define SUN4I_MAX_XFER_SIZE		0xffffff
> -
> -#define SUN4I_BURST_CNT_REG	0x20
> -#define SUN4I_BURST_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
> -
> -#define SUN4I_XMIT_CNT_REG	0x24
> -#define SUN4I_XMIT_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
> +DECLARE_GLOBAL_DATA_PTR;
>  
> -#define SUN4I_FIFO_STA_REG	0x28
> -#define SUN4I_FIFO_STA_RF_CNT_BITS	0
> -#define SUN4I_FIFO_STA_TF_CNT_MASK	0x7f
> -#define SUN4I_FIFO_STA_TF_CNT_BITS	16
> +/* sun4i spi registers */
> +#define SUN4I_RXDATA_REG		0x00
> +#define SUN4I_TXDATA_REG		0x04
> +#define SUN4I_CTL_REG			0x08
> +#define SUN4I_CLK_CTL_REG		0x1c
> +#define SUN4I_BURST_CNT_REG		0x20
> +#define SUN4I_XMIT_CNT_REG		0x24
> +#define SUN4I_FIFO_STA_REG		0x28
>  
>  /* sun6i spi registers */
>  #define SUN6I_GBL_CTL_REG		0x04
> @@ -97,10 +56,23 @@
>  #define SUN6I_TXDATA_REG		0x200
>  #define SUN6I_RXDATA_REG		0x300
>  
> -#define SUN4I_SPI_MAX_RATE	24000000
> -#define SUN4I_SPI_MIN_RATE	3000
> -#define SUN4I_SPI_DEFAULT_RATE	1000000
> -#define SUN4I_SPI_TIMEOUT_US	1000000
> +/* sun spi bits */
> +#define SUN4I_CTL_ENABLE		BIT(0)
> +#define SUN4I_CTL_MASTER		BIT(1)
> +#define SUN4I_CLK_CTL_CDR2_MASK		0xff
> +#define SUN4I_CLK_CTL_CDR2(div)		((div) & SUN4I_CLK_CTL_CDR2_MASK)
> +#define SUN4I_CLK_CTL_CDR1_MASK		0xf
> +#define SUN4I_CLK_CTL_CDR1(div)		(((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8)
> +#define SUN4I_CLK_CTL_DRS		BIT(12)
> +#define SUN4I_MAX_XFER_SIZE		0xffffff
> +#define SUN4I_BURST_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
> +#define SUN4I_XMIT_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
> +#define SUN4I_FIFO_STA_RF_CNT_BITS	0
> +
> +#define SUN4I_SPI_MAX_RATE		24000000
> +#define SUN4I_SPI_MIN_RATE		3000
> +#define SUN4I_SPI_DEFAULT_RATE		1000000
> +#define SUN4I_SPI_TIMEOUT_US		1000000
>  
>  /* sun spi register set */
>  enum sun4i_spi_regs {
> @@ -140,7 +112,7 @@ struct sun4i_spi_variant {
>  
>  struct sun4i_spi_platdata {
>  	struct sun4i_spi_variant *variant;
> -	u32 base_addr;
> +	u32 base;
>  	u32 max_hz;
>  };
>  
> @@ -148,7 +120,7 @@ struct sun4i_spi_priv {
>  	struct sun4i_spi_variant *variant;
>  	struct clk clk_ahb, clk_mod;
>  	struct reset_ctl reset;
> -	u32 base_addr;
> +	u32 base;
>  	u32 freq;
>  	u32 mode;
>  
> @@ -156,15 +128,13 @@ struct sun4i_spi_priv {
>  	u8 *rx_buf;
>  };
>  
> -DECLARE_GLOBAL_DATA_PTR;
> -
>  static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
>  {
>  	struct sun4i_spi_variant *variant = priv->variant;
>  	u8 byte;
>  
>  	while (len--) {
> -		byte = readb(priv->base_addr + variant->regs[SPI_RXD]);
> +		byte = readb(priv->base + variant->regs[SPI_RXD]);

Those parts of this patch would go away when hiding the address
calculation in a macro. Or you do the rename already in patch 04/10,
where you would just need to rename it in three existing places.

Cheers,
Andre.


>  		if (priv->rx_buf)
>  			*priv->rx_buf++ = byte;
>  	}
> @@ -177,7 +147,7 @@ static inline void sun4i_spi_fill_fifo(struct sun4i_spi_priv *priv, int len)
>  
>  	while (len--) {
>  		byte = priv->tx_buf ? *priv->tx_buf++ : 0;
> -		writeb(byte, priv->base_addr + variant->regs[SPI_TXD]);
> +		writeb(byte, priv->base + variant->regs[SPI_TXD]);
>  	}
>  }
>  
> @@ -187,7 +157,7 @@ static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
>  	struct sun4i_spi_variant *variant = priv->variant;
>  	u32 reg;
>  
> -	reg = readl(priv->base_addr + variant->regs[SPI_TCR]);
> +	reg = readl(priv->base + variant->regs[SPI_TCR]);
>  
>  	reg &= ~variant->bits[SPI_TCR_CS_MASK];
>  	reg |= ((cs << variant->bits[SPI_TCR_CS_SEL]) &
> @@ -198,7 +168,7 @@ static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
>  	else
>  		reg |= variant->bits[SPI_TCR_CS_LEVEL];
>  
> -	writel(reg, priv->base_addr + variant->regs[SPI_TCR]);
> +	writel(reg, priv->base + variant->regs[SPI_TCR]);
>  }
>  
>  static int sun4i_spi_parse_pins(struct udevice *dev)
> @@ -323,56 +293,6 @@ err_ahb:
>  	return ret;
>  }
>  
> -static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
> -{
> -	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
> -	int node = dev_of_offset(bus);
> -
> -	plat->base_addr = devfdt_get_addr(bus);
> -	plat->variant = (struct sun4i_spi_variant *)dev_get_driver_data(bus);
> -	plat->max_hz = fdtdec_get_int(gd->fdt_blob, node,
> -				      "spi-max-frequency",
> -				      SUN4I_SPI_DEFAULT_RATE);
> -
> -	if (plat->max_hz > SUN4I_SPI_MAX_RATE)
> -		plat->max_hz = SUN4I_SPI_MAX_RATE;
> -
> -	return 0;
> -}
> -
> -static int sun4i_spi_probe(struct udevice *bus)
> -{
> -	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
> -	struct sun4i_spi_priv *priv = dev_get_priv(bus);
> -	int ret;
> -
> -	ret = clk_get_by_name(bus, "ahb", &priv->clk_ahb);
> -	if (ret) {
> -		dev_err(dev, "failed to get ahb clock\n");
> -		return ret;
> -	}
> -
> -	ret = clk_get_by_name(bus, "mod", &priv->clk_mod);
> -	if (ret) {
> -		dev_err(dev, "failed to get mod clock\n");
> -		return ret;
> -	}
> -
> -	ret = reset_get_by_index(bus, 0, &priv->reset);
> -	if (ret && ret != -ENOENT) {
> -		dev_err(dev, "failed to get reset\n");
> -		return ret;
> -	}
> -
> -	sun4i_spi_parse_pins(bus);
> -
> -	priv->variant = plat->variant;
> -	priv->base_addr = plat->base_addr;
> -	priv->freq = plat->max_hz;
> -
> -	return 0;
> -}
> -
>  static int sun4i_spi_claim_bus(struct udevice *dev)
>  {
>  	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
> @@ -383,15 +303,15 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
>  	if (ret)
>  		return ret;
>  
> -	setbits_le32(priv->base_addr + variant->regs[SPI_GCR],
> +	setbits_le32(priv->base + variant->regs[SPI_GCR],
>  		     SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER |
>  		     variant->bits[SPI_GCR_TP]);
>  
>  	if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
> -		setbits_le32(priv->base_addr + variant->regs[SPI_GCR],
> +		setbits_le32(priv->base + variant->regs[SPI_GCR],
>  			     variant->bits[SPI_GCR_SRST]);
>  
> -	setbits_le32(priv->base_addr + variant->regs[SPI_TCR],
> +	setbits_le32(priv->base + variant->regs[SPI_TCR],
>  		     variant->bits[SPI_TCR_CS_MANUAL] |
>  		     variant->bits[SPI_TCR_CS_ACTIVE_LOW]);
>  
> @@ -403,7 +323,7 @@ static int sun4i_spi_release_bus(struct udevice *dev)
>  	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
>  	struct sun4i_spi_variant *variant = priv->variant;
>  
> -	clrbits_le32(priv->base_addr + variant->regs[SPI_GCR],
> +	clrbits_le32(priv->base + variant->regs[SPI_GCR],
>  		     SUN4I_CTL_ENABLE);
>  
>  	sun4i_spi_set_clock(dev->parent, false);
> @@ -436,7 +356,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
>  		sun4i_spi_set_cs(bus, slave_plat->cs, true);
>  
>  	/* Reset FIFOs */
> -	setbits_le32(priv->base_addr + variant->regs[SPI_FCR],
> +	setbits_le32(priv->base + variant->regs[SPI_FCR],
>  		     variant->bits[SPI_FCR_RF_RST] |
>  		     variant->bits[SPI_FCR_TF_RST]);
>  
> @@ -446,22 +366,22 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
>  
>  		/* Setup the counters */
>  		writel(SUN4I_BURST_CNT(nbytes),
> -		       priv->base_addr + variant->regs[SPI_BC]);
> +		       priv->base + variant->regs[SPI_BC]);
>  		writel(SUN4I_XMIT_CNT(nbytes),
> -		       priv->base_addr + variant->regs[SPI_TC]);
> +		       priv->base + variant->regs[SPI_TC]);
>  		if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
>  			writel(SUN4I_BURST_CNT(nbytes),
> -			       priv->base_addr + variant->regs[SPI_BCTL]);
> +			       priv->base + variant->regs[SPI_BCTL]);
>  
>  		/* Fill the TX FIFO */
>  		sun4i_spi_fill_fifo(priv, nbytes);
>  
>  		/* Start the transfer */
> -		setbits_le32(priv->base_addr + variant->regs[SPI_TCR],
> +		setbits_le32(priv->base + variant->regs[SPI_TCR],
>  			     variant->bits[SPI_TCR_XCH]);
>  
>  		/* Wait till RX FIFO to be empty */
> -		ret = readl_poll_timeout(priv->base_addr + variant->regs[SPI_FSR],
> +		ret = readl_poll_timeout(priv->base + variant->regs[SPI_FSR],
>  					 rx_fifocnt,
>  					 !(((rx_fifocnt &
>  					 variant->bits[SPI_FSR_RF_CNT_MASK]) >>
> @@ -514,7 +434,7 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
>  	 */
>  
>  	div = SUN4I_SPI_MAX_RATE / (2 * speed);
> -	reg = readl(priv->base_addr + variant->regs[SPI_CCR]);
> +	reg = readl(priv->base + variant->regs[SPI_CCR]);
>  
>  	if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
>  		if (div > 0)
> @@ -529,7 +449,7 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
>  	}
>  
>  	priv->freq = speed;
> -	writel(reg, priv->base_addr + variant->regs[SPI_CCR]);
> +	writel(reg, priv->base + variant->regs[SPI_CCR]);
>  
>  	return 0;
>  }
> @@ -540,7 +460,7 @@ static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
>  	struct sun4i_spi_variant *variant = priv->variant;
>  	u32 reg;
>  
> -	reg = readl(priv->base_addr + variant->regs[SPI_TCR]);
> +	reg = readl(priv->base + variant->regs[SPI_TCR]);
>  	reg &= ~(variant->bits[SPI_TCR_CPOL] | variant->bits[SPI_TCR_CPHA]);
>  
>  	if (mode & SPI_CPOL)
> @@ -550,7 +470,7 @@ static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
>  		reg |= variant->bits[SPI_TCR_CPHA];
>  
>  	priv->mode = mode;
> -	writel(reg, priv->base_addr + variant->regs[SPI_TCR]);
> +	writel(reg, priv->base + variant->regs[SPI_TCR]);
>  
>  	return 0;
>  }
> @@ -563,6 +483,56 @@ static const struct dm_spi_ops sun4i_spi_ops = {
>  	.set_mode		= sun4i_spi_set_mode,
>  };
>  
> +static int sun4i_spi_probe(struct udevice *bus)
> +{
> +	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
> +	struct sun4i_spi_priv *priv = dev_get_priv(bus);
> +	int ret;
> +
> +	ret = clk_get_by_name(bus, "ahb", &priv->clk_ahb);
> +	if (ret) {
> +		dev_err(dev, "failed to get ahb clock\n");
> +		return ret;
> +	}
> +
> +	ret = clk_get_by_name(bus, "mod", &priv->clk_mod);
> +	if (ret) {
> +		dev_err(dev, "failed to get mod clock\n");
> +		return ret;
> +	}
> +
> +	ret = reset_get_by_index(bus, 0, &priv->reset);
> +	if (ret && ret != -ENOENT) {
> +		dev_err(dev, "failed to get reset\n");
> +		return ret;
> +	}
> +
> +	sun4i_spi_parse_pins(bus);
> +
> +	priv->variant = plat->variant;
> +	priv->base = plat->base;
> +	priv->freq = plat->max_hz;
> +
> +	return 0;
> +}
> +
> +static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
> +{
> +	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
> +	int node = dev_of_offset(bus);
> +
> +	plat->base = devfdt_get_addr(bus);
> +	plat->variant = (struct sun4i_spi_variant *)dev_get_driver_data(bus);
> +	plat->max_hz = fdtdec_get_int(gd->fdt_blob, node,
> +				      "spi-max-frequency",
> +				      SUN4I_SPI_DEFAULT_RATE);
> +
> +	if (plat->max_hz > SUN4I_SPI_MAX_RATE)
> +		plat->max_hz = SUN4I_SPI_MAX_RATE;
> +
> +	return 0;
> +}
> +
>  static const unsigned long sun4i_spi_regs[] = {
>  	[SPI_GCR]		= SUN4I_CTL_REG,
>  	[SPI_TCR]		= SUN4I_CTL_REG,
> @@ -640,7 +610,7 @@ static const struct udevice_id sun4i_spi_ids[] = {
>  	  .compatible = "allwinner,sun8i-h3-spi",
>  	  .data = (ulong)&sun8i_h3_spi_variant,
>  	},
> -	{ }
> +	{ /* sentinel */ }
>  };
>  
>  U_BOOT_DRIVER(sun4i_spi) = {
> 

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

* [U-Boot] [PATCH 09/10] spi: kconfig: Enable SUN4I_SPI by default if ARCH_SUNXI
  2019-02-09 13:14 ` [U-Boot] [PATCH 09/10] spi: kconfig: Enable SUN4I_SPI by default if ARCH_SUNXI Jagan Teki
@ 2019-02-13  1:21   ` André Przywara
  0 siblings, 0 replies; 27+ messages in thread
From: André Przywara @ 2019-02-13  1:21 UTC (permalink / raw)
  To: u-boot

On 09/02/2019 13:14, Jagan Teki wrote:
> Enable SUN4I_SPI by default for ARCH_SUNXI, so that board
> that would require to enable DM_SPI that eventually enable
> the SUN4I_SPI driver.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  drivers/spi/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 15207d23c1..2fb4862c4a 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -224,6 +224,7 @@ config STM32_QSPI
>  
>  config SUN4I_SPI
>  	bool "Allwinner A10/A31 SoCs SPI controller"
> +	default ARCH_SUNXI

I don't think that's justified, only a few boards have SPI flash,
really, also it's a new driver that nobody desperately needed so far.

What about:
	default y if ARCH_SUNXI && SPI

That would mean to just define CONFIG_SPI=y in a defconfig to enable SPI
(flash) support for a board.
Similar we should add
	select DM_SPI if SPI
	select DM_SPI_FLASH if SPI
to the ARCH_SUNXI stanza in arch/arm/Kconfig

Cheers,
Andre.


>  	help
>  	  This enables using the SPI controller on the Allwinner A10/A31 SoCs.
>  
> 

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

* [U-Boot] [PATCH 10/10] board: sopine: Enable SPI/SPI-FLASH
  2019-02-09 13:15 ` [U-Boot] [PATCH 10/10] board: sopine: Enable SPI/SPI-FLASH Jagan Teki
@ 2019-02-13  1:21   ` André Przywara
  2019-02-13 10:27     ` Jagan Teki
  0 siblings, 1 reply; 27+ messages in thread
From: André Przywara @ 2019-02-13  1:21 UTC (permalink / raw)
  To: u-boot

On 09/02/2019 13:15, Jagan Teki wrote:
> Sopine has Winbond SPI flash, so enable the same to use
> flash on Sopine board.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi | 12 ++++++++++++
>  configs/sopine_baseboard_defconfig                   |  4 ++++
>  2 files changed, 16 insertions(+)
>  create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> 
> diff --git a/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> new file mode 100644
> index 0000000000..02b1ae046e
> --- /dev/null
> +++ b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> @@ -0,0 +1,12 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2018 Jagan Teki <jagan@amarulasolutions.com>
> + */
> +
> +#include "sunxi-u-boot.dtsi"
> +
> +/ {
> +	aliases {
> +		spi0 = &spi0;
> +	};
> +};
> diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig
> index 9d7e3a2b6c..a94e3c21fd 100644
> --- a/configs/sopine_baseboard_defconfig
> +++ b/configs/sopine_baseboard_defconfig
> @@ -10,11 +10,15 @@ CONFIG_MMC0_CD_PIN=""
>  CONFIG_MMC_SUNXI_SLOT_EXTRA=2
>  CONFIG_SPL_SPI_SUNXI=y
>  CONFIG_NR_DRAM_BANKS=1
> +CONFIG_CMD_SF=y
>  # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
>  # CONFIG_CMD_FLASH is not set
>  # CONFIG_SPL_DOS_PARTITION is not set
>  # CONFIG_SPL_EFI_PARTITION is not set
>  CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-sopine-baseboard"
> +CONFIG_DM_SPI=y
> +CONFIG_DM_SPI_FLASH=y
> +CONFIG_SPI_FLASH_WINBOND=y

That isn't enough, you need CONFIG_SPI=y as well, otherwise the build fails.
I'd suggest to move DM_SPI=y and DM_SPI_FLASH=y to arch/arm/Kconfig (as
mentioned in the previous mail) and keep CONFIG_SPI=y here, to enable
SPI support for a particular board. Then keep ..._WINBOND here to set
the flash chip. For which you need CONFIG_SPI_FLASH, I believe. Which
sounds somewhat weird.

Cheers,
Andre.

>  CONFIG_SUN8I_EMAC=y
>  CONFIG_USB_EHCI_HCD=y
>  CONFIG_USB_OHCI_HCD=y
> 

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

* [U-Boot] [PATCH 07/10] spi: sun4: Add A31 spi controller support
  2019-02-13  1:19   ` André Przywara
@ 2019-02-13  3:20     ` Chen-Yu Tsai
  2019-02-13 10:14       ` Andre Przywara
  2019-02-13 12:17     ` Jagan Teki
  1 sibling, 1 reply; 27+ messages in thread
From: Chen-Yu Tsai @ 2019-02-13  3:20 UTC (permalink / raw)
  To: u-boot

On Wed, Feb 13, 2019 at 9:21 AM André Przywara <andre.przywara@arm.com> wrote:
>
> On 09/02/2019 13:14, Jagan Teki wrote:
> > Add A31 spi controller support for existing sun4i_spi driver via driver
> > data, this would simply add A31 register along with proper register bits
> > via enum sets.
> >
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > ---
> >  drivers/spi/Kconfig     |  4 +-
> >  drivers/spi/sun4i_spi.c | 84 ++++++++++++++++++++++++++++++++++++++++-
> >  2 files changed, 85 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> > index ac7fbab841..15207d23c1 100644
> > --- a/drivers/spi/Kconfig
> > +++ b/drivers/spi/Kconfig
> > @@ -223,9 +223,9 @@ config STM32_QSPI
> >         this ST IP core.
> >
> >  config SUN4I_SPI
> > -     bool "Allwinner A10 SoCs SPI controller"
> > +     bool "Allwinner A10/A31 SoCs SPI controller"
> >       help
> > -       SPI driver for Allwinner sun4i, sun5i and sun7i SoCs
> > +       This enables using the SPI controller on the Allwinner A10/A31 SoCs.
> >
> >  config TEGRA114_SPI
> >       bool "nVidia Tegra114 SPI driver"
> > diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
> > index aeed68764c..36f2215f7d 100644
> > --- a/drivers/spi/sun4i_spi.c
> > +++ b/drivers/spi/sun4i_spi.c
> > @@ -24,6 +24,7 @@
> >  #include <spi.h>
> >  #include <errno.h>
> >  #include <fdt_support.h>
> > +#include <reset.h>
> >  #include <wait_bit.h>
> >
> >  #include <asm/bitops.h>
> > @@ -84,6 +85,18 @@
> >  #define SUN4I_FIFO_STA_TF_CNT_MASK   0x7f
> >  #define SUN4I_FIFO_STA_TF_CNT_BITS   16
> >
> > +/* sun6i spi registers */
> > +#define SUN6I_GBL_CTL_REG            0x04
> > +#define SUN6I_TFR_CTL_REG            0x08
> > +#define SUN6I_FIFO_CTL_REG           0x18
> > +#define SUN6I_FIFO_STA_REG           0x1c
> > +#define SUN6I_CLK_CTL_REG            0x24
> > +#define SUN6I_BURST_CNT_REG          0x30
> > +#define SUN6I_XMIT_CNT_REG           0x34
> > +#define SUN6I_BURST_CTL_REG          0x38
> > +#define SUN6I_TXDATA_REG             0x200
> > +#define SUN6I_RXDATA_REG             0x300
> > +
> >  #define SUN4I_SPI_MAX_RATE   24000000
> >  #define SUN4I_SPI_MIN_RATE   3000
> >  #define SUN4I_SPI_DEFAULT_RATE       1000000
> > @@ -106,6 +119,7 @@ enum sun4i_spi_regs {
> >  /* sun spi register bits */
> >  enum sun4i_spi_bits {
> >       SPI_GCR_TP,
> > +     SPI_GCR_SRST,
> >       SPI_TCR_CPHA,
> >       SPI_TCR_CPOL,
> >       SPI_TCR_CS_ACTIVE_LOW,
> > @@ -133,6 +147,7 @@ struct sun4i_spi_platdata {
> >  struct sun4i_spi_priv {
> >       struct sun4i_spi_variant *variant;
> >       struct clk clk_ahb, clk_mod;
> > +     struct reset_ctl reset;
> >       u32 base_addr;
> >       u32 freq;
> >       u32 mode;
> > @@ -255,7 +270,10 @@ static int sun4i_spi_parse_pins(struct udevice *dev)
> >                       if (pin < 0)
> >                               break;
> >
> > -                     sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
> > +                     if (IS_ENABLED(CONFIG_MACH_SUN50I))
> > +                             sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0);
> > +                     else
> > +                             sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
> >                       sunxi_gpio_set_drv(pin, drive);
> >                       sunxi_gpio_set_pull(pin, pull);
> >               }
> > @@ -271,6 +289,8 @@ static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
> >       if (!enable) {
> >               clk_disable(&priv->clk_ahb);
> >               clk_disable(&priv->clk_mod);
> > +             if (reset_valid(&priv->reset))
> > +                     reset_assert(&priv->reset);
> >               return 0;
> >       }
> >
> > @@ -286,8 +306,18 @@ static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
> >               goto err_ahb;
> >       }
> >
> > +     if (reset_valid(&priv->reset)) {
> > +             ret = reset_deassert(&priv->reset);
> > +             if (ret) {
> > +                     dev_err(dev, "failed to deassert reset\n");
> > +                     goto err_mod;
> > +             }
> > +     }
> > +
> >       return 0;
> >
> > +err_mod:
> > +     clk_disable(&priv->clk_mod);
> >  err_ahb:
> >       clk_disable(&priv->clk_ahb);
> >       return ret;
> > @@ -328,6 +358,12 @@ static int sun4i_spi_probe(struct udevice *bus)
> >               return ret;
> >       }
> >
> > +     ret = reset_get_by_index(bus, 0, &priv->reset);
> > +     if (ret && ret != -ENOENT) {
> > +             dev_err(dev, "failed to get reset\n");
> > +             return ret;
> > +     }
> > +
> >       sun4i_spi_parse_pins(bus);
> >
> >       priv->variant = plat->variant;
> > @@ -351,6 +387,10 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
> >                    SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER |
> >                    variant->bits[SPI_GCR_TP]);
> >
> > +     if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
> > +             setbits_le32(priv->base_addr + variant->regs[SPI_GCR],
> > +                          variant->bits[SPI_GCR_SRST]);
> > +
>
> Just a note: This makes the driver only support one class of device, set
> at compile time. Which means we could have used an #ifdef approach from
> the beginning ....
> Can you make this dependent on some bits in variant? That should solve it.

I believe the argument for IS_ENABLED from working in the kernel is that
it still gives you compile-time checks, whereas #ifdef doesn't.

Though I believe your ultimate goal is to have one image for all? In that
case checking against the variants at runtime is better.

ChenYu

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

* [U-Boot] [PATCH 07/10] spi: sun4: Add A31 spi controller support
  2019-02-13  3:20     ` Chen-Yu Tsai
@ 2019-02-13 10:14       ` Andre Przywara
  0 siblings, 0 replies; 27+ messages in thread
From: Andre Przywara @ 2019-02-13 10:14 UTC (permalink / raw)
  To: u-boot

On Wed, 13 Feb 2019 11:20:11 +0800
Chen-Yu Tsai <wens@csie.org> wrote:

Hi Chen-Yu,

> On Wed, Feb 13, 2019 at 9:21 AM André Przywara <andre.przywara@arm.com> wrote:
> >
> > On 09/02/2019 13:14, Jagan Teki wrote:  
> > > Add A31 spi controller support for existing sun4i_spi driver via driver
> > > data, this would simply add A31 register along with proper register bits
> > > via enum sets.
> > >
> > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > > ---
> > >  drivers/spi/Kconfig     |  4 +-
> > >  drivers/spi/sun4i_spi.c | 84 ++++++++++++++++++++++++++++++++++++++++-
> > >  2 files changed, 85 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> > > index ac7fbab841..15207d23c1 100644
> > > --- a/drivers/spi/Kconfig
> > > +++ b/drivers/spi/Kconfig
> > > @@ -223,9 +223,9 @@ config STM32_QSPI
> > >         this ST IP core.
> > >
> > >  config SUN4I_SPI
> > > -     bool "Allwinner A10 SoCs SPI controller"
> > > +     bool "Allwinner A10/A31 SoCs SPI controller"
> > >       help
> > > -       SPI driver for Allwinner sun4i, sun5i and sun7i SoCs
> > > +       This enables using the SPI controller on the Allwinner A10/A31 SoCs.
> > >
> > >  config TEGRA114_SPI
> > >       bool "nVidia Tegra114 SPI driver"
> > > diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
> > > index aeed68764c..36f2215f7d 100644
> > > --- a/drivers/spi/sun4i_spi.c
> > > +++ b/drivers/spi/sun4i_spi.c
> > > @@ -24,6 +24,7 @@
> > >  #include <spi.h>
> > >  #include <errno.h>
> > >  #include <fdt_support.h>
> > > +#include <reset.h>
> > >  #include <wait_bit.h>
> > >
> > >  #include <asm/bitops.h>
> > > @@ -84,6 +85,18 @@
> > >  #define SUN4I_FIFO_STA_TF_CNT_MASK   0x7f
> > >  #define SUN4I_FIFO_STA_TF_CNT_BITS   16
> > >
> > > +/* sun6i spi registers */
> > > +#define SUN6I_GBL_CTL_REG            0x04
> > > +#define SUN6I_TFR_CTL_REG            0x08
> > > +#define SUN6I_FIFO_CTL_REG           0x18
> > > +#define SUN6I_FIFO_STA_REG           0x1c
> > > +#define SUN6I_CLK_CTL_REG            0x24
> > > +#define SUN6I_BURST_CNT_REG          0x30
> > > +#define SUN6I_XMIT_CNT_REG           0x34
> > > +#define SUN6I_BURST_CTL_REG          0x38
> > > +#define SUN6I_TXDATA_REG             0x200
> > > +#define SUN6I_RXDATA_REG             0x300
> > > +
> > >  #define SUN4I_SPI_MAX_RATE   24000000
> > >  #define SUN4I_SPI_MIN_RATE   3000
> > >  #define SUN4I_SPI_DEFAULT_RATE       1000000
> > > @@ -106,6 +119,7 @@ enum sun4i_spi_regs {
> > >  /* sun spi register bits */
> > >  enum sun4i_spi_bits {
> > >       SPI_GCR_TP,
> > > +     SPI_GCR_SRST,
> > >       SPI_TCR_CPHA,
> > >       SPI_TCR_CPOL,
> > >       SPI_TCR_CS_ACTIVE_LOW,
> > > @@ -133,6 +147,7 @@ struct sun4i_spi_platdata {
> > >  struct sun4i_spi_priv {
> > >       struct sun4i_spi_variant *variant;
> > >       struct clk clk_ahb, clk_mod;
> > > +     struct reset_ctl reset;
> > >       u32 base_addr;
> > >       u32 freq;
> > >       u32 mode;
> > > @@ -255,7 +270,10 @@ static int sun4i_spi_parse_pins(struct udevice *dev)
> > >                       if (pin < 0)
> > >                               break;
> > >
> > > -                     sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
> > > +                     if (IS_ENABLED(CONFIG_MACH_SUN50I))
> > > +                             sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0);
> > > +                     else
> > > +                             sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
> > >                       sunxi_gpio_set_drv(pin, drive);
> > >                       sunxi_gpio_set_pull(pin, pull);
> > >               }
> > > @@ -271,6 +289,8 @@ static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
> > >       if (!enable) {
> > >               clk_disable(&priv->clk_ahb);
> > >               clk_disable(&priv->clk_mod);
> > > +             if (reset_valid(&priv->reset))
> > > +                     reset_assert(&priv->reset);
> > >               return 0;
> > >       }
> > >
> > > @@ -286,8 +306,18 @@ static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
> > >               goto err_ahb;
> > >       }
> > >
> > > +     if (reset_valid(&priv->reset)) {
> > > +             ret = reset_deassert(&priv->reset);
> > > +             if (ret) {
> > > +                     dev_err(dev, "failed to deassert reset\n");
> > > +                     goto err_mod;
> > > +             }
> > > +     }
> > > +
> > >       return 0;
> > >
> > > +err_mod:
> > > +     clk_disable(&priv->clk_mod);
> > >  err_ahb:
> > >       clk_disable(&priv->clk_ahb);
> > >       return ret;
> > > @@ -328,6 +358,12 @@ static int sun4i_spi_probe(struct udevice *bus)
> > >               return ret;
> > >       }
> > >
> > > +     ret = reset_get_by_index(bus, 0, &priv->reset);
> > > +     if (ret && ret != -ENOENT) {
> > > +             dev_err(dev, "failed to get reset\n");
> > > +             return ret;
> > > +     }
> > > +
> > >       sun4i_spi_parse_pins(bus);
> > >
> > >       priv->variant = plat->variant;
> > > @@ -351,6 +387,10 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
> > >                    SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER |
> > >                    variant->bits[SPI_GCR_TP]);
> > >
> > > +     if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
> > > +             setbits_le32(priv->base_addr + variant->regs[SPI_GCR],
> > > +                          variant->bits[SPI_GCR_SRST]);
> > > +  
> >
> > Just a note: This makes the driver only support one class of device, set
> > at compile time. Which means we could have used an #ifdef approach from
> > the beginning ....
> > Can you make this dependent on some bits in variant? That should solve it.  
> 
> I believe the argument for IS_ENABLED from working in the kernel is that
> it still gives you compile-time checks, whereas #ifdef doesn't.

I see that, but my point was that this series is more complicated than the simple one I sent yesterday, using compile time decisions[1].
And the #ifdefs there were not guarding any *code* as well, only defines.
So I am not against this approach here, I just wanted to point out that despite the extra effort of doing runtime choices we will actually fail in doing so anyway.
But if I am not mistaken, this is the only place where this is critical, and it can be fixed.

> Though I believe your ultimate goal is to have one image for all? In that
> case checking against the variants at runtime is better.

I am not sure we really want to cover *every* Allwinner board with a single U-Boot image. For my part I am fine if we can cover all 64-bit boards, maybe an extra build for newer (>= SUN6I) 32-bit boards. But to be honest those drivers are the least of our problems then ;-)

Cheers,
Andre.

[1] https://lists.denx.de/pipermail/u-boot/2019-February/358502.html

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

* [U-Boot] [PATCH 03/10] spi: sun4i: Simplify reg writes using set/clrbits_le32
  2019-02-13  1:14   ` André Przywara
@ 2019-02-13 10:24     ` Jagan Teki
  0 siblings, 0 replies; 27+ messages in thread
From: Jagan Teki @ 2019-02-13 10:24 UTC (permalink / raw)
  To: u-boot

On Wed, Feb 13, 2019 at 6:46 AM André Przywara <andre.przywara@arm.com> wrote:
>
> On 09/02/2019 13:14, Jagan Teki wrote:
> > Update the existing register writes using setbits_le32 and
> > clrbits_le32 in required places.
> >
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > ---
> >  drivers/spi/sun4i_spi.c | 21 ++++++++-------------
> >  1 file changed, 8 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
> > index 87b396a96e..5446cebe7c 100644
> > --- a/drivers/spi/sun4i_spi.c
> > +++ b/drivers/spi/sun4i_spi.c
> > @@ -283,20 +283,18 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
> >  {
> >       struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
> >
> > -     writel(SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER | SUN4I_CTL_TP |
> > -            SUN4I_CTL_CS_MANUAL | SUN4I_CTL_CS_ACTIVE_LOW,
> > -            &priv->regs->ctl);
> > +     setbits_le32(&priv->regs->ctl, SUN4I_CTL_ENABLE |
> > +                  SUN4I_CTL_MASTER | SUN4I_CTL_TP |
> > +                  SUN4I_CTL_CS_MANUAL | SUN4I_CTL_CS_ACTIVE_LOW);
> > +
>
> Careful, this changes semantics. The original call explicitly cleared
> all the remaining bits, which is important for the setup (some bits are
> default 1).

Usually claiming would need to setup require bits, on that case
setbits is safer rather than complete writel

> And besides I am not sure what this change would improve anyway, as it
> isn't shorter. If at all, I'd use clrsetbits_le32(), to mask off the
> reserved bits 31:21.

It's not about the shorter and just enable require bits which is
usually do any claim call in SPI.

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

* [U-Boot] [PATCH 10/10] board: sopine: Enable SPI/SPI-FLASH
  2019-02-13  1:21   ` André Przywara
@ 2019-02-13 10:27     ` Jagan Teki
  0 siblings, 0 replies; 27+ messages in thread
From: Jagan Teki @ 2019-02-13 10:27 UTC (permalink / raw)
  To: u-boot

On Wed, Feb 13, 2019 at 6:53 AM André Przywara <andre.przywara@arm.com> wrote:
>
> On 09/02/2019 13:15, Jagan Teki wrote:
> > Sopine has Winbond SPI flash, so enable the same to use
> > flash on Sopine board.
> >
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > ---
> >  arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi | 12 ++++++++++++
> >  configs/sopine_baseboard_defconfig                   |  4 ++++
> >  2 files changed, 16 insertions(+)
> >  create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> >
> > diff --git a/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> > new file mode 100644
> > index 0000000000..02b1ae046e
> > --- /dev/null
> > +++ b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> > @@ -0,0 +1,12 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (C) 2018 Jagan Teki <jagan@amarulasolutions.com>
> > + */
> > +
> > +#include "sunxi-u-boot.dtsi"
> > +
> > +/ {
> > +     aliases {
> > +             spi0 = &spi0;
> > +     };
> > +};
> > diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig
> > index 9d7e3a2b6c..a94e3c21fd 100644
> > --- a/configs/sopine_baseboard_defconfig
> > +++ b/configs/sopine_baseboard_defconfig
> > @@ -10,11 +10,15 @@ CONFIG_MMC0_CD_PIN=""
> >  CONFIG_MMC_SUNXI_SLOT_EXTRA=2
> >  CONFIG_SPL_SPI_SUNXI=y
> >  CONFIG_NR_DRAM_BANKS=1
> > +CONFIG_CMD_SF=y
> >  # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
> >  # CONFIG_CMD_FLASH is not set
> >  # CONFIG_SPL_DOS_PARTITION is not set
> >  # CONFIG_SPL_EFI_PARTITION is not set
> >  CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-sopine-baseboard"
> > +CONFIG_DM_SPI=y
> > +CONFIG_DM_SPI_FLASH=y
> > +CONFIG_SPI_FLASH_WINBOND=y
>
> That isn't enough, you need CONFIG_SPI=y as well, otherwise the build fails.
> I'd suggest to move DM_SPI=y and DM_SPI_FLASH=y to arch/arm/Kconfig (as
> mentioned in the previous mail) and keep CONFIG_SPI=y here, to enable
> SPI support for a particular board. Then keep ..._WINBOND here to set
> the flash chip. For which you need CONFIG_SPI_FLASH, I believe. Which
> sounds somewhat weird.

Did the similar work already[1], plan to use these on top of these set.

[1] https://patchwork.ozlabs.org/patch/1039175/

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

* [U-Boot] [PATCH 06/10] spi: sun4i: Add CLK support
  2019-02-13  1:19   ` André Przywara
@ 2019-02-13 11:41     ` Jagan Teki
  0 siblings, 0 replies; 27+ messages in thread
From: Jagan Teki @ 2019-02-13 11:41 UTC (permalink / raw)
  To: u-boot

On Wed, Feb 13, 2019 at 6:51 AM André Przywara <andre.przywara@arm.com> wrote:
>
> On 09/02/2019 13:14, Jagan Teki wrote:
> > Add CLK support to enable AHB and MOD SPI clocks on sun4i_spi driver.
> >
> > Note, that the code will enable and disable clock in claim and release
> > calls to make proper clock and reset handling between claiming and
> > releasing SPI bus.
> >
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
>
> That looks alright to me, but I wonder if you should introduce the reset
> support here as well. Since it's optional, it shouldn't hurt to have it
> in already, even though the SUN4I generation doesn't need it.

OK, but I see the point of adding reset during A31 support patch since
it has reset control on it and it's becoming optional since we are
trying to use same driver even for A10.

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

* [U-Boot] [PATCH 07/10] spi: sun4: Add A31 spi controller support
  2019-02-13  1:19   ` André Przywara
  2019-02-13  3:20     ` Chen-Yu Tsai
@ 2019-02-13 12:17     ` Jagan Teki
  1 sibling, 0 replies; 27+ messages in thread
From: Jagan Teki @ 2019-02-13 12:17 UTC (permalink / raw)
  To: u-boot

On Wed, Feb 13, 2019 at 6:51 AM André Przywara <andre.przywara@arm.com> wrote:
>
> On 09/02/2019 13:14, Jagan Teki wrote:
> > Add A31 spi controller support for existing sun4i_spi driver via driver
> > data, this would simply add A31 register along with proper register bits
> > via enum sets.
> >
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > ---
> >  drivers/spi/Kconfig     |  4 +-
> >  drivers/spi/sun4i_spi.c | 84 ++++++++++++++++++++++++++++++++++++++++-
> >  2 files changed, 85 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> > index ac7fbab841..15207d23c1 100644
> > --- a/drivers/spi/Kconfig
> > +++ b/drivers/spi/Kconfig
> > @@ -223,9 +223,9 @@ config STM32_QSPI
> >         this ST IP core.
> >
> >  config SUN4I_SPI
> > -     bool "Allwinner A10 SoCs SPI controller"
> > +     bool "Allwinner A10/A31 SoCs SPI controller"
> >       help
> > -       SPI driver for Allwinner sun4i, sun5i and sun7i SoCs
> > +       This enables using the SPI controller on the Allwinner A10/A31 SoCs.
> >
> >  config TEGRA114_SPI
> >       bool "nVidia Tegra114 SPI driver"
> > diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
> > index aeed68764c..36f2215f7d 100644
> > --- a/drivers/spi/sun4i_spi.c
> > +++ b/drivers/spi/sun4i_spi.c
> > @@ -24,6 +24,7 @@
> >  #include <spi.h>
> >  #include <errno.h>
> >  #include <fdt_support.h>
> > +#include <reset.h>
> >  #include <wait_bit.h>
> >
> >  #include <asm/bitops.h>
> > @@ -84,6 +85,18 @@
> >  #define SUN4I_FIFO_STA_TF_CNT_MASK   0x7f
> >  #define SUN4I_FIFO_STA_TF_CNT_BITS   16
> >
> > +/* sun6i spi registers */
> > +#define SUN6I_GBL_CTL_REG            0x04
> > +#define SUN6I_TFR_CTL_REG            0x08
> > +#define SUN6I_FIFO_CTL_REG           0x18
> > +#define SUN6I_FIFO_STA_REG           0x1c
> > +#define SUN6I_CLK_CTL_REG            0x24
> > +#define SUN6I_BURST_CNT_REG          0x30
> > +#define SUN6I_XMIT_CNT_REG           0x34
> > +#define SUN6I_BURST_CTL_REG          0x38
> > +#define SUN6I_TXDATA_REG             0x200
> > +#define SUN6I_RXDATA_REG             0x300
> > +
> >  #define SUN4I_SPI_MAX_RATE   24000000
> >  #define SUN4I_SPI_MIN_RATE   3000
> >  #define SUN4I_SPI_DEFAULT_RATE       1000000
> > @@ -106,6 +119,7 @@ enum sun4i_spi_regs {
> >  /* sun spi register bits */
> >  enum sun4i_spi_bits {
> >       SPI_GCR_TP,
> > +     SPI_GCR_SRST,
> >       SPI_TCR_CPHA,
> >       SPI_TCR_CPOL,
> >       SPI_TCR_CS_ACTIVE_LOW,
> > @@ -133,6 +147,7 @@ struct sun4i_spi_platdata {
> >  struct sun4i_spi_priv {
> >       struct sun4i_spi_variant *variant;
> >       struct clk clk_ahb, clk_mod;
> > +     struct reset_ctl reset;
> >       u32 base_addr;
> >       u32 freq;
> >       u32 mode;
> > @@ -255,7 +270,10 @@ static int sun4i_spi_parse_pins(struct udevice *dev)
> >                       if (pin < 0)
> >                               break;
> >
> > -                     sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
> > +                     if (IS_ENABLED(CONFIG_MACH_SUN50I))
> > +                             sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0);
> > +                     else
> > +                             sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
> >                       sunxi_gpio_set_drv(pin, drive);
> >                       sunxi_gpio_set_pull(pin, pull);
> >               }
> > @@ -271,6 +289,8 @@ static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
> >       if (!enable) {
> >               clk_disable(&priv->clk_ahb);
> >               clk_disable(&priv->clk_mod);
> > +             if (reset_valid(&priv->reset))
> > +                     reset_assert(&priv->reset);
> >               return 0;
> >       }
> >
> > @@ -286,8 +306,18 @@ static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
> >               goto err_ahb;
> >       }
> >
> > +     if (reset_valid(&priv->reset)) {
> > +             ret = reset_deassert(&priv->reset);
> > +             if (ret) {
> > +                     dev_err(dev, "failed to deassert reset\n");
> > +                     goto err_mod;
> > +             }
> > +     }
> > +
> >       return 0;
> >
> > +err_mod:
> > +     clk_disable(&priv->clk_mod);
> >  err_ahb:
> >       clk_disable(&priv->clk_ahb);
> >       return ret;
> > @@ -328,6 +358,12 @@ static int sun4i_spi_probe(struct udevice *bus)
> >               return ret;
> >       }
> >
> > +     ret = reset_get_by_index(bus, 0, &priv->reset);
> > +     if (ret && ret != -ENOENT) {
> > +             dev_err(dev, "failed to get reset\n");
> > +             return ret;
> > +     }
> > +
> >       sun4i_spi_parse_pins(bus);
> >
> >       priv->variant = plat->variant;
> > @@ -351,6 +387,10 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
> >                    SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER |
> >                    variant->bits[SPI_GCR_TP]);
> >
> > +     if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
> > +             setbits_le32(priv->base_addr + variant->regs[SPI_GCR],
> > +                          variant->bits[SPI_GCR_SRST]);
> > +
>
> Just a note: This makes the driver only support one class of device, set
> at compile time. Which means we could have used an #ifdef approach from
> the beginning ....
> Can you make this dependent on some bits in variant? That should solve it.

Yes, we can do this meaningfully via driverdata or compatible check.

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

end of thread, other threads:[~2019-02-13 12:17 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-09 13:14 [U-Boot] [PATCH 00/10] spi: Add Allwinner A31 SPI driver Jagan Teki
2019-02-09 13:14 ` [U-Boot] [PATCH 01/10] spi: sun4i: Poll for rxfifo empty Jagan Teki
2019-02-13  1:11   ` André Przywara
2019-02-09 13:14 ` [U-Boot] [PATCH 02/10] clk: sunxi: Implement SPI clocks, resets Jagan Teki
2019-02-13  1:13   ` André Przywara
2019-02-09 13:14 ` [U-Boot] [PATCH 03/10] spi: sun4i: Simplify reg writes using set/clrbits_le32 Jagan Teki
2019-02-13  1:14   ` André Przywara
2019-02-13 10:24     ` Jagan Teki
2019-02-09 13:14 ` [U-Boot] [PATCH 04/10] spi: sun4i: Access registers and bits via enum offsets Jagan Teki
2019-02-13  1:15   ` André Przywara
2019-02-09 13:14 ` [U-Boot] [PATCH 05/10] spi: sun4i: Support fifo_depth via drvdata Jagan Teki
2019-02-13  1:16   ` André Przywara
2019-02-09 13:14 ` [U-Boot] [PATCH 06/10] spi: sun4i: Add CLK support Jagan Teki
2019-02-13  1:19   ` André Przywara
2019-02-13 11:41     ` Jagan Teki
2019-02-09 13:14 ` [U-Boot] [PATCH 07/10] spi: sun4: Add A31 spi controller support Jagan Teki
2019-02-13  1:19   ` André Przywara
2019-02-13  3:20     ` Chen-Yu Tsai
2019-02-13 10:14       ` Andre Przywara
2019-02-13 12:17     ` Jagan Teki
2019-02-09 13:14 ` [U-Boot] [PATCH 08/10] spi: sun4i: Driver cleanup Jagan Teki
2019-02-13  1:20   ` André Przywara
2019-02-09 13:14 ` [U-Boot] [PATCH 09/10] spi: kconfig: Enable SUN4I_SPI by default if ARCH_SUNXI Jagan Teki
2019-02-13  1:21   ` André Przywara
2019-02-09 13:15 ` [U-Boot] [PATCH 10/10] board: sopine: Enable SPI/SPI-FLASH Jagan Teki
2019-02-13  1:21   ` André Przywara
2019-02-13 10:27     ` 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.