All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 00/14] tegra114 SPI driver
@ 2013-02-13  3:23 Allen Martin
  2013-02-13  3:23 ` [U-Boot] [PATCH 01/14] tegra: spi: rename tegra SPI drivers Allen Martin
                   ` (13 more replies)
  0 siblings, 14 replies; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

This series pulls fdt functionality from the existing tegra20 and
tegra30 SPI drivers into a new common fdt SPI driver front end,
then adds a new tegra114 SPI driver as an additional client of
the fdt SPI driver.

Allen Martin (14):
  tegra: spi: rename tegra SPI drivers
  tegra: spi: remove non fdt support
  tegra: spi: pull register structs out of headers
  tegra20: spi: move fdt probe to spi_init
  spi: add common fdt SPI driver interface
  sf: winbond: add W25Q32DW
  tegra114: dalmore: add SPI pinmux config
  tegra114: fdt: add compatible string for tegra114 SPI ctrl
  tegra114: fdt: add CAR block
  tegra114: fdt: add apbdma block
  tegra114: fdt: add SPI blocks
  tegra114: dalmore: fdt: enable dalmore SPI controller
  tegra114: add SPI driver
  tegra114: dalmore: config: enable SPI

 arch/arm/dts/tegra114.dtsi                        |  115 +++++++
 arch/arm/include/asm/arch-tegra/tegra_slink.h     |   84 -----
 arch/arm/include/asm/arch-tegra/tegra_spi.h       |   75 -----
 arch/arm/include/asm/arch-tegra114/tegra114_spi.h |   91 ++++++
 arch/arm/include/asm/arch-tegra20/tegra20_spi.h   |   73 +++++
 arch/arm/include/asm/arch-tegra30/tegra30_spi.h   |   77 +++++
 board/nvidia/common/board.c                       |    2 +-
 board/nvidia/common/uart-spi-switch.c             |    2 +-
 board/nvidia/dalmore/pinmux-config-dalmore.h      |    9 +-
 board/nvidia/dts/tegra114-dalmore.dts             |    5 +
 drivers/mtd/spi/winbond.c                         |    5 +
 drivers/spi/Makefile                              |    6 +-
 drivers/spi/fdt_spi.c                             |  187 +++++++++++
 drivers/spi/tegra114_spi.c                        |  355 +++++++++++++++++++++
 drivers/spi/tegra20_spi.c                         |  350 ++++++++++++++++++++
 drivers/spi/tegra30_spi.c                         |  325 +++++++++++++++++++
 drivers/spi/tegra_slink.c                         |  343 --------------------
 drivers/spi/tegra_spi.c                           |  330 -------------------
 include/configs/cardhu.h                          |    4 +-
 include/configs/dalmore.h                         |   11 +
 include/configs/tegra-common-post.h               |    4 +
 include/configs/trimslice.h                       |    2 +-
 include/fdtdec.h                                  |    1 +
 lib/fdtdec.c                                      |    1 +
 24 files changed, 1615 insertions(+), 842 deletions(-)
 delete mode 100644 arch/arm/include/asm/arch-tegra/tegra_slink.h
 delete mode 100644 arch/arm/include/asm/arch-tegra/tegra_spi.h
 create mode 100644 arch/arm/include/asm/arch-tegra114/tegra114_spi.h
 create mode 100644 arch/arm/include/asm/arch-tegra20/tegra20_spi.h
 create mode 100644 arch/arm/include/asm/arch-tegra30/tegra30_spi.h
 create mode 100644 drivers/spi/fdt_spi.c
 create mode 100644 drivers/spi/tegra114_spi.c
 create mode 100644 drivers/spi/tegra20_spi.c
 create mode 100644 drivers/spi/tegra30_spi.c
 delete mode 100644 drivers/spi/tegra_slink.c
 delete mode 100644 drivers/spi/tegra_spi.c

-- 
1.7.10.4

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

* [U-Boot] [PATCH 01/14] tegra: spi: rename tegra SPI drivers
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  2013-02-13 22:30   ` Stephen Warren
  2013-02-13 22:36   ` Stephen Warren
  2013-02-13  3:23 ` [U-Boot] [PATCH 02/14] tegra: spi: remove non fdt support Allen Martin
                   ` (12 subsequent siblings)
  13 siblings, 2 replies; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Rename tegra SPI drivers to tegra20_spi and tegra30_spi in preparation
for commonization and addition of tegra114_spi.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 arch/arm/include/asm/arch-tegra/tegra_slink.h   |   84 ------
 arch/arm/include/asm/arch-tegra/tegra_spi.h     |   75 -----
 arch/arm/include/asm/arch-tegra20/tegra20_spi.h |   75 +++++
 arch/arm/include/asm/arch-tegra30/tegra30_spi.h |   84 ++++++
 board/nvidia/common/board.c                     |    2 +-
 board/nvidia/common/uart-spi-switch.c           |    2 +-
 drivers/spi/Makefile                            |    4 +-
 drivers/spi/tegra20_spi.c                       |  330 ++++++++++++++++++++++
 drivers/spi/tegra30_spi.c                       |  343 +++++++++++++++++++++++
 drivers/spi/tegra_slink.c                       |  343 -----------------------
 drivers/spi/tegra_spi.c                         |  330 ----------------------
 include/configs/cardhu.h                        |    2 +-
 include/configs/trimslice.h                     |    2 +-
 13 files changed, 838 insertions(+), 838 deletions(-)
 delete mode 100644 arch/arm/include/asm/arch-tegra/tegra_slink.h
 delete mode 100644 arch/arm/include/asm/arch-tegra/tegra_spi.h
 create mode 100644 arch/arm/include/asm/arch-tegra20/tegra20_spi.h
 create mode 100644 arch/arm/include/asm/arch-tegra30/tegra30_spi.h
 create mode 100644 drivers/spi/tegra20_spi.c
 create mode 100644 drivers/spi/tegra30_spi.c
 delete mode 100644 drivers/spi/tegra_slink.c
 delete mode 100644 drivers/spi/tegra_spi.c

diff --git a/arch/arm/include/asm/arch-tegra/tegra_slink.h b/arch/arm/include/asm/arch-tegra/tegra_slink.h
deleted file mode 100644
index 74804b5..0000000
--- a/arch/arm/include/asm/arch-tegra/tegra_slink.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * NVIDIA Tegra SPI-SLINK controller
- *
- * Copyright 2010-2013 NVIDIA Corporation
- *
- * This software may be used and distributed according to the
- * terms of the GNU Public License, Version 2, incorporated
- * herein by reference.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * Version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#ifndef _TEGRA_SLINK_H_
-#define _TEGRA_SLINK_H_
-
-#include <asm/types.h>
-
-struct slink_tegra {
-	u32 command;	/* SLINK_COMMAND_0 register  */
-	u32 command2;	/* SLINK_COMMAND2_0 reg */
-	u32 status;	/* SLINK_STATUS_0 register */
-	u32 reserved;	/* Reserved offset 0C */
-	u32 mas_data;	/* SLINK_MAS_DATA_0 reg */
-	u32 slav_data;	/* SLINK_SLAVE_DATA_0 reg */
-	u32 dma_ctl;	/* SLINK_DMA_CTL_0 register */
-	u32 status2;	/* SLINK_STATUS2_0 reg */
-	u32 rsvd[56];	/* 0x20 to 0xFF reserved */
-	u32 tx_fifo;	/* SLINK_TX_FIFO_0 reg off 100h */
-	u32 rsvd2[31];	/* 0x104 to 0x17F reserved */
-	u32 rx_fifo;	/* SLINK_RX_FIFO_0 reg off 180h */
-};
-
-/* COMMAND */
-#define SLINK_CMD_ENB			(1 << 31)
-#define SLINK_CMD_GO			(1 << 30)
-#define SLINK_CMD_M_S			(1 << 28)
-#define SLINK_CMD_CK_SDA		(1 << 21)
-#define SLINK_CMD_CS_POL		(1 << 13)
-#define SLINK_CMD_CS_VAL		(1 << 12)
-#define SLINK_CMD_CS_SOFT		(1 << 11)
-#define SLINK_CMD_BIT_LENGTH		(1 << 4)
-#define SLINK_CMD_BIT_LENGTH_MASK	0x0000001F
-/* COMMAND2 */
-#define SLINK_CMD2_TXEN			(1 << 30)
-#define SLINK_CMD2_RXEN			(1 << 31)
-#define SLINK_CMD2_SS_EN		(1 << 18)
-#define SLINK_CMD2_SS_EN_SHIFT		18
-#define SLINK_CMD2_SS_EN_MASK		0x000C0000
-#define SLINK_CMD2_CS_ACTIVE_BETWEEN	(1 << 17)
-/* STATUS */
-#define SLINK_STAT_BSY			(1 << 31)
-#define SLINK_STAT_RDY			(1 << 30)
-#define SLINK_STAT_ERR			(1 << 29)
-#define SLINK_STAT_RXF_FLUSH		(1 << 27)
-#define SLINK_STAT_TXF_FLUSH		(1 << 26)
-#define SLINK_STAT_RXF_OVF		(1 << 25)
-#define SLINK_STAT_TXF_UNR		(1 << 24)
-#define SLINK_STAT_RXF_EMPTY		(1 << 23)
-#define SLINK_STAT_RXF_FULL		(1 << 22)
-#define SLINK_STAT_TXF_EMPTY		(1 << 21)
-#define SLINK_STAT_TXF_FULL		(1 << 20)
-#define SLINK_STAT_TXF_OVF		(1 << 19)
-#define SLINK_STAT_RXF_UNR		(1 << 18)
-#define SLINK_STAT_CUR_BLKCNT		(1 << 15)
-/* STATUS2 */
-#define SLINK_STAT2_RXF_FULL_CNT	(1 << 16)
-#define SLINK_STAT2_TXF_FULL_CNT	(1 << 0)
-
-#define SPI_TIMEOUT		1000
-#define TEGRA_SPI_MAX_FREQ	52000000
-
-#endif	/* _TEGRA_SLINK_H_ */
diff --git a/arch/arm/include/asm/arch-tegra/tegra_spi.h b/arch/arm/include/asm/arch-tegra/tegra_spi.h
deleted file mode 100644
index d53a93f..0000000
--- a/arch/arm/include/asm/arch-tegra/tegra_spi.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * NVIDIA Tegra20 SPI-FLASH controller
- *
- * Copyright 2010-2012 NVIDIA Corporation
- *
- * This software may be used and distributed according to the
- * terms of the GNU Public License, Version 2, incorporated
- * herein by reference.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * Version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#ifndef _TEGRA_SPI_H_
-#define _TEGRA_SPI_H_
-
-#include <asm/types.h>
-
-struct spi_tegra {
-	u32 command;	/* SPI_COMMAND_0 register  */
-	u32 status;	/* SPI_STATUS_0 register */
-	u32 rx_cmp;	/* SPI_RX_CMP_0 register  */
-	u32 dma_ctl;	/* SPI_DMA_CTL_0 register */
-	u32 tx_fifo;	/* SPI_TX_FIFO_0 register */
-	u32 rsvd[3];	/* offsets 0x14 to 0x1F reserved */
-	u32 rx_fifo;	/* SPI_RX_FIFO_0 register */
-};
-
-#define SPI_CMD_GO			(1 << 30)
-#define SPI_CMD_ACTIVE_SCLK_SHIFT	26
-#define SPI_CMD_ACTIVE_SCLK_MASK	(3 << SPI_CMD_ACTIVE_SCLK_SHIFT)
-#define SPI_CMD_CK_SDA			(1 << 21)
-#define SPI_CMD_ACTIVE_SDA_SHIFT	18
-#define SPI_CMD_ACTIVE_SDA_MASK		(3 << SPI_CMD_ACTIVE_SDA_SHIFT)
-#define SPI_CMD_CS_POL			(1 << 16)
-#define SPI_CMD_TXEN			(1 << 15)
-#define SPI_CMD_RXEN			(1 << 14)
-#define SPI_CMD_CS_VAL			(1 << 13)
-#define SPI_CMD_CS_SOFT			(1 << 12)
-#define SPI_CMD_CS_DELAY		(1 << 9)
-#define SPI_CMD_CS3_EN			(1 << 8)
-#define SPI_CMD_CS2_EN			(1 << 7)
-#define SPI_CMD_CS1_EN			(1 << 6)
-#define SPI_CMD_CS0_EN			(1 << 5)
-#define SPI_CMD_BIT_LENGTH		(1 << 4)
-#define SPI_CMD_BIT_LENGTH_MASK		0x0000001F
-
-#define SPI_STAT_BSY			(1 << 31)
-#define SPI_STAT_RDY			(1 << 30)
-#define SPI_STAT_RXF_FLUSH		(1 << 29)
-#define SPI_STAT_TXF_FLUSH		(1 << 28)
-#define SPI_STAT_RXF_UNR		(1 << 27)
-#define SPI_STAT_TXF_OVF		(1 << 26)
-#define SPI_STAT_RXF_EMPTY		(1 << 25)
-#define SPI_STAT_RXF_FULL		(1 << 24)
-#define SPI_STAT_TXF_EMPTY		(1 << 23)
-#define SPI_STAT_TXF_FULL		(1 << 22)
-#define SPI_STAT_SEL_TXRX_N		(1 << 16)
-#define SPI_STAT_CUR_BLKCNT		(1 << 15)
-
-#define SPI_TIMEOUT		1000
-#define TEGRA_SPI_MAX_FREQ	52000000
-
-#endif	/* _TEGRA_SPI_H_ */
diff --git a/arch/arm/include/asm/arch-tegra20/tegra20_spi.h b/arch/arm/include/asm/arch-tegra20/tegra20_spi.h
new file mode 100644
index 0000000..26a8402
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra20/tegra20_spi.h
@@ -0,0 +1,75 @@
+/*
+ * NVIDIA Tegra20 SPI-FLASH controller
+ *
+ * Copyright 2010-2012 NVIDIA Corporation
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _TEGRA20_SPI_H_
+#define _TEGRA20_SPI_H_
+
+#include <asm/types.h>
+
+struct spi_tegra {
+	u32 command;	/* SPI_COMMAND_0 register  */
+	u32 status;	/* SPI_STATUS_0 register */
+	u32 rx_cmp;	/* SPI_RX_CMP_0 register  */
+	u32 dma_ctl;	/* SPI_DMA_CTL_0 register */
+	u32 tx_fifo;	/* SPI_TX_FIFO_0 register */
+	u32 rsvd[3];	/* offsets 0x14 to 0x1F reserved */
+	u32 rx_fifo;	/* SPI_RX_FIFO_0 register */
+};
+
+#define SPI_CMD_GO			(1 << 30)
+#define SPI_CMD_ACTIVE_SCLK_SHIFT	26
+#define SPI_CMD_ACTIVE_SCLK_MASK	(3 << SPI_CMD_ACTIVE_SCLK_SHIFT)
+#define SPI_CMD_CK_SDA			(1 << 21)
+#define SPI_CMD_ACTIVE_SDA_SHIFT	18
+#define SPI_CMD_ACTIVE_SDA_MASK		(3 << SPI_CMD_ACTIVE_SDA_SHIFT)
+#define SPI_CMD_CS_POL			(1 << 16)
+#define SPI_CMD_TXEN			(1 << 15)
+#define SPI_CMD_RXEN			(1 << 14)
+#define SPI_CMD_CS_VAL			(1 << 13)
+#define SPI_CMD_CS_SOFT			(1 << 12)
+#define SPI_CMD_CS_DELAY		(1 << 9)
+#define SPI_CMD_CS3_EN			(1 << 8)
+#define SPI_CMD_CS2_EN			(1 << 7)
+#define SPI_CMD_CS1_EN			(1 << 6)
+#define SPI_CMD_CS0_EN			(1 << 5)
+#define SPI_CMD_BIT_LENGTH		(1 << 4)
+#define SPI_CMD_BIT_LENGTH_MASK		0x0000001F
+
+#define SPI_STAT_BSY			(1 << 31)
+#define SPI_STAT_RDY			(1 << 30)
+#define SPI_STAT_RXF_FLUSH		(1 << 29)
+#define SPI_STAT_TXF_FLUSH		(1 << 28)
+#define SPI_STAT_RXF_UNR		(1 << 27)
+#define SPI_STAT_TXF_OVF		(1 << 26)
+#define SPI_STAT_RXF_EMPTY		(1 << 25)
+#define SPI_STAT_RXF_FULL		(1 << 24)
+#define SPI_STAT_TXF_EMPTY		(1 << 23)
+#define SPI_STAT_TXF_FULL		(1 << 22)
+#define SPI_STAT_SEL_TXRX_N		(1 << 16)
+#define SPI_STAT_CUR_BLKCNT		(1 << 15)
+
+#define SPI_TIMEOUT		1000
+#define TEGRA_SPI_MAX_FREQ	52000000
+
+#endif	/* _TEGRA20_SPI_H_ */
diff --git a/arch/arm/include/asm/arch-tegra30/tegra30_spi.h b/arch/arm/include/asm/arch-tegra30/tegra30_spi.h
new file mode 100644
index 0000000..afa9b36
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra30/tegra30_spi.h
@@ -0,0 +1,84 @@
+/*
+ * NVIDIA Tegra SPI-SLINK controller
+ *
+ * Copyright 2010-2013 NVIDIA Corporation
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _TEGRA30_SPI_H_
+#define _TEGRA30_SPI_H_
+
+#include <asm/types.h>
+
+struct slink_tegra {
+	u32 command;	/* SLINK_COMMAND_0 register  */
+	u32 command2;	/* SLINK_COMMAND2_0 reg */
+	u32 status;	/* SLINK_STATUS_0 register */
+	u32 reserved;	/* Reserved offset 0C */
+	u32 mas_data;	/* SLINK_MAS_DATA_0 reg */
+	u32 slav_data;	/* SLINK_SLAVE_DATA_0 reg */
+	u32 dma_ctl;	/* SLINK_DMA_CTL_0 register */
+	u32 status2;	/* SLINK_STATUS2_0 reg */
+	u32 rsvd[56];	/* 0x20 to 0xFF reserved */
+	u32 tx_fifo;	/* SLINK_TX_FIFO_0 reg off 100h */
+	u32 rsvd2[31];	/* 0x104 to 0x17F reserved */
+	u32 rx_fifo;	/* SLINK_RX_FIFO_0 reg off 180h */
+};
+
+/* COMMAND */
+#define SLINK_CMD_ENB			(1 << 31)
+#define SLINK_CMD_GO			(1 << 30)
+#define SLINK_CMD_M_S			(1 << 28)
+#define SLINK_CMD_CK_SDA		(1 << 21)
+#define SLINK_CMD_CS_POL		(1 << 13)
+#define SLINK_CMD_CS_VAL		(1 << 12)
+#define SLINK_CMD_CS_SOFT		(1 << 11)
+#define SLINK_CMD_BIT_LENGTH		(1 << 4)
+#define SLINK_CMD_BIT_LENGTH_MASK	0x0000001F
+/* COMMAND2 */
+#define SLINK_CMD2_TXEN			(1 << 30)
+#define SLINK_CMD2_RXEN			(1 << 31)
+#define SLINK_CMD2_SS_EN		(1 << 18)
+#define SLINK_CMD2_SS_EN_SHIFT		18
+#define SLINK_CMD2_SS_EN_MASK		0x000C0000
+#define SLINK_CMD2_CS_ACTIVE_BETWEEN	(1 << 17)
+/* STATUS */
+#define SLINK_STAT_BSY			(1 << 31)
+#define SLINK_STAT_RDY			(1 << 30)
+#define SLINK_STAT_ERR			(1 << 29)
+#define SLINK_STAT_RXF_FLUSH		(1 << 27)
+#define SLINK_STAT_TXF_FLUSH		(1 << 26)
+#define SLINK_STAT_RXF_OVF		(1 << 25)
+#define SLINK_STAT_TXF_UNR		(1 << 24)
+#define SLINK_STAT_RXF_EMPTY		(1 << 23)
+#define SLINK_STAT_RXF_FULL		(1 << 22)
+#define SLINK_STAT_TXF_EMPTY		(1 << 21)
+#define SLINK_STAT_TXF_FULL		(1 << 20)
+#define SLINK_STAT_TXF_OVF		(1 << 19)
+#define SLINK_STAT_RXF_UNR		(1 << 18)
+#define SLINK_STAT_CUR_BLKCNT		(1 << 15)
+/* STATUS2 */
+#define SLINK_STAT2_RXF_FULL_CNT	(1 << 16)
+#define SLINK_STAT2_TXF_FULL_CNT	(1 << 0)
+
+#define SPI_TIMEOUT		1000
+#define TEGRA_SPI_MAX_FREQ	52000000
+
+#endif	/* _TEGRA30_SPI_H_ */
diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index d1d8a29..18e6420 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -131,7 +131,7 @@ int board_init(void)
 #ifdef CONFIG_SPI_UART_SWITCH
 	gpio_config_uart();
 #endif
-#if defined(CONFIG_TEGRA_SPI) || defined(CONFIG_TEGRA_SLINK)
+#if defined(CONFIG_TEGRA20_SPI) || defined(CONFIG_TEGRA30_SPI)
 	pin_mux_spi();
 	spi_init();
 #endif
diff --git a/board/nvidia/common/uart-spi-switch.c b/board/nvidia/common/uart-spi-switch.c
index e9d445d..3252250 100644
--- a/board/nvidia/common/uart-spi-switch.c
+++ b/board/nvidia/common/uart-spi-switch.c
@@ -25,7 +25,7 @@
 #include <asm/arch/pinmux.h>
 #include <asm/arch/uart-spi-switch.h>
 #include <asm/arch/tegra.h>
-#include <asm/arch-tegra/tegra_spi.h>
+#include <asm/arch-tegra20/tegra20_spi.h>
 #include <asm/arch-tegra/board.h>
 
 /* position of the UART/SPI select switch */
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 83abcbd..e9fccb5 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -45,8 +45,8 @@ COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o
 COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
 COBJS-$(CONFIG_SH_SPI) += sh_spi.o
 COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o
-COBJS-$(CONFIG_TEGRA_SPI) += tegra_spi.o
-COBJS-$(CONFIG_TEGRA_SLINK) += tegra_slink.o
+COBJS-$(CONFIG_TEGRA20_SPI) += tegra20_spi.o
+COBJS-$(CONFIG_TEGRA30_SPI) += tegra30_spi.o
 COBJS-$(CONFIG_XILINX_SPI) += xilinx_spi.o
 
 COBJS	:= $(COBJS-y)
diff --git a/drivers/spi/tegra20_spi.c b/drivers/spi/tegra20_spi.c
new file mode 100644
index 0000000..8cc3e5d
--- /dev/null
+++ b/drivers/spi/tegra20_spi.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2010-2012 NVIDIA Corporation
+ * With help from the mpc8xxx SPI driver
+ * With more help from omap3_spi SPI driver
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/uart-spi-switch.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra20/tegra20_spi.h>
+#include <spi.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_SPI_CORRUPTS_UART)
+ #define corrupt_delay()	udelay(CONFIG_SPI_CORRUPTS_UART_DLY);
+#else
+ #define corrupt_delay()
+#endif
+
+struct tegra_spi_slave {
+	struct spi_slave slave;
+	struct spi_tegra *regs;
+	unsigned int freq;
+	unsigned int mode;
+	int periph_id;
+};
+
+static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
+{
+	return container_of(slave, struct tegra_spi_slave, slave);
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+	/* Tegra20 SPI-Flash - only 1 device ('bus/cs') */
+	if (bus != 0 || cs != 0)
+		return 0;
+	else
+		return 1;
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+		unsigned int max_hz, unsigned int mode)
+{
+	struct tegra_spi_slave *spi;
+
+	if (!spi_cs_is_valid(bus, cs)) {
+		printf("SPI error: unsupported bus %d / chip select %d\n",
+		       bus, cs);
+		return NULL;
+	}
+
+	if (max_hz > TEGRA_SPI_MAX_FREQ) {
+		printf("SPI error: unsupported frequency %d Hz. Max frequency"
+			" is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ);
+		return NULL;
+	}
+
+	spi = malloc(sizeof(struct tegra_spi_slave));
+	if (!spi) {
+		printf("SPI error: malloc of SPI structure failed\n");
+		return NULL;
+	}
+	spi->slave.bus = bus;
+	spi->slave.cs = cs;
+#ifdef CONFIG_OF_CONTROL
+	int node = fdtdec_next_compatible(gd->fdt_blob, 0,
+					  COMPAT_NVIDIA_TEGRA20_SFLASH);
+	if (node < 0) {
+		debug("%s: cannot locate sflash node\n", __func__);
+		return NULL;
+	}
+	if (!fdtdec_get_is_enabled(gd->fdt_blob, node)) {
+		debug("%s: sflash is disabled\n", __func__);
+		return NULL;
+	}
+	spi->regs = (struct spi_tegra *)fdtdec_get_addr(gd->fdt_blob,
+							node, "reg");
+	if ((fdt_addr_t)spi->regs == FDT_ADDR_T_NONE) {
+		debug("%s: no sflash register found\n", __func__);
+		return NULL;
+	}
+	spi->freq = fdtdec_get_int(gd->fdt_blob, node, "spi-max-frequency", 0);
+	if (!spi->freq) {
+		debug("%s: no sflash max frequency found\n", __func__);
+		return NULL;
+	}
+	spi->periph_id = clock_decode_periph_id(gd->fdt_blob, node);
+	if (spi->periph_id == PERIPH_ID_NONE) {
+		debug("%s: could not decode periph id\n", __func__);
+		return NULL;
+	}
+#else
+	spi->regs = (struct spi_tegra *)NV_PA_SPI_BASE;
+	spi->freq = TEGRA_SPI_MAX_FREQ;
+	spi->periph_id = PERIPH_ID_SPI1;
+#endif
+	if (max_hz < spi->freq) {
+		debug("%s: limiting frequency from %u to %u\n", __func__,
+		      spi->freq, max_hz);
+		spi->freq = max_hz;
+	}
+	debug("%s: controller initialized at %p, freq = %u, periph_id = %d\n",
+	      __func__, spi->regs, spi->freq, spi->periph_id);
+	spi->mode = mode;
+
+	return &spi->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+
+	free(spi);
+}
+
+void spi_init(void)
+{
+	/* do nothing */
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+	struct spi_tegra *regs = spi->regs;
+	u32 reg;
+
+	/* Change SPI clock to correct frequency, PLLP_OUT0 source */
+	clock_start_periph_pll(spi->periph_id, CLOCK_ID_PERIPH, spi->freq);
+
+	/* Clear stale status here */
+	reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \
+		SPI_STAT_RXF_UNR | SPI_STAT_TXF_OVF;
+	writel(reg, &regs->status);
+	debug("spi_init: STATUS = %08x\n", readl(&regs->status));
+
+	/*
+	 * Use sw-controlled CS, so we can clock in data after ReadID, etc.
+	 */
+	reg = (spi->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT;
+	if (spi->mode & 2)
+		reg |= 1 << SPI_CMD_ACTIVE_SCLK_SHIFT;
+	clrsetbits_le32(&regs->command, SPI_CMD_ACTIVE_SCLK_MASK |
+		SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg);
+	debug("spi_init: COMMAND = %08x\n", readl(&regs->command));
+
+	/*
+	 * SPI pins on Tegra20 are muxed - change pinmux later due to UART
+	 * issue.
+	 */
+	pinmux_set_func(PINGRP_GMD, PMUX_FUNC_SFLASH);
+	pinmux_tristate_disable(PINGRP_LSPI);
+
+#ifndef CONFIG_SPI_UART_SWITCH
+	/*
+	 * NOTE:
+	 * Only set PinMux bits 3:2 to SPI here on boards that don't have the
+	 * SPI UART switch or subsequent UART data won't go out!  See
+	 * spi_uart_switch().
+	 */
+	/* TODO: pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH); */
+#endif
+	return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+	/*
+	 * We can't release UART_DISABLE and set pinmux to UART4 here since
+	 * some code (e,g, spi_flash_probe) uses printf() while the SPI
+	 * bus is held. That is arguably bad, but it has the advantage of
+	 * already being in the source tree.
+	 */
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+
+	pinmux_select_spi();
+
+	/* CS is negated on Tegra, so drive a 1 to get a 0 */
+	setbits_le32(&spi->regs->command, SPI_CMD_CS_VAL);
+
+	corrupt_delay();		/* Let UART settle */
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+
+	pinmux_select_uart();
+
+	/* CS is negated on Tegra, so drive a 0 to get a 1 */
+	clrbits_le32(&spi->regs->command, SPI_CMD_CS_VAL);
+
+	corrupt_delay();		/* Let SPI settle */
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+		const void *data_out, void *data_in, unsigned long flags)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+	struct spi_tegra *regs = spi->regs;
+	u32 reg, tmpdout, tmpdin = 0;
+	const u8 *dout = data_out;
+	u8 *din = data_in;
+	int num_bytes;
+	int ret;
+
+	debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
+	      slave->bus, slave->cs, *(u8 *)dout, *(u8 *)din, bitlen);
+	if (bitlen % 8)
+		return -1;
+	num_bytes = bitlen / 8;
+
+	ret = 0;
+
+	reg = readl(&regs->status);
+	writel(reg, &regs->status);	/* Clear all SPI events via R/W */
+	debug("spi_xfer entry: STATUS = %08x\n", reg);
+
+	reg = readl(&regs->command);
+	reg |= SPI_CMD_TXEN | SPI_CMD_RXEN;
+	writel(reg, &regs->command);
+	debug("spi_xfer: COMMAND = %08x\n", readl(&regs->command));
+
+	if (flags & SPI_XFER_BEGIN)
+		spi_cs_activate(slave);
+
+	/* handle data in 32-bit chunks */
+	while (num_bytes > 0) {
+		int bytes;
+		int is_read = 0;
+		int tm, i;
+
+		tmpdout = 0;
+		bytes = (num_bytes > 4) ?  4 : num_bytes;
+
+		if (dout != NULL) {
+			for (i = 0; i < bytes; ++i)
+				tmpdout = (tmpdout << 8) | dout[i];
+		}
+
+		num_bytes -= bytes;
+		if (dout)
+			dout += bytes;
+
+		clrsetbits_le32(&regs->command, SPI_CMD_BIT_LENGTH_MASK,
+				bytes * 8 - 1);
+		writel(tmpdout, &regs->tx_fifo);
+		setbits_le32(&regs->command, SPI_CMD_GO);
+
+		/*
+		 * Wait for SPI transmit FIFO to empty, or to time out.
+		 * The RX FIFO status will be read and cleared last
+		 */
+		for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) {
+			u32 status;
+
+			status = readl(&regs->status);
+
+			/* We can exit when we've had both RX and TX activity */
+			if (is_read && (status & SPI_STAT_TXF_EMPTY))
+				break;
+
+			if ((status & (SPI_STAT_BSY | SPI_STAT_RDY)) !=
+					SPI_STAT_RDY)
+				tm++;
+
+			else if (!(status & SPI_STAT_RXF_EMPTY)) {
+				tmpdin = readl(&regs->rx_fifo);
+				is_read = 1;
+
+				/* swap bytes read in */
+				if (din != NULL) {
+					for (i = bytes - 1; i >= 0; --i) {
+						din[i] = tmpdin & 0xff;
+						tmpdin >>= 8;
+					}
+					din += bytes;
+				}
+			}
+		}
+
+		if (tm >= SPI_TIMEOUT)
+			ret = tm;
+
+		/* clear ACK RDY, etc. bits */
+		writel(readl(&regs->status), &regs->status);
+	}
+
+	if (flags & SPI_XFER_END)
+		spi_cs_deactivate(slave);
+
+	debug("spi_xfer: transfer ended. Value=%08x, status = %08x\n",
+		tmpdin, readl(&regs->status));
+
+	if (ret) {
+		printf("spi_xfer: timeout during SPI transfer, tm %d\n", ret);
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/drivers/spi/tegra30_spi.c b/drivers/spi/tegra30_spi.c
new file mode 100644
index 0000000..b475090
--- /dev/null
+++ b/drivers/spi/tegra30_spi.c
@@ -0,0 +1,343 @@
+/*
+ * NVIDIA Tegra SPI-SLINK controller
+ *
+ * Copyright (c) 2010-2013 NVIDIA Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/clock.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra30/tegra30_spi.h>
+#include <spi.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct tegra_spi_ctrl {
+	struct slink_tegra *regs;
+	unsigned int freq;
+	unsigned int mode;
+	int periph_id;
+	int valid;
+};
+
+struct tegra_spi_slave {
+	struct spi_slave slave;
+	struct tegra_spi_ctrl *ctrl;
+};
+
+static struct tegra_spi_ctrl spi_ctrls[CONFIG_TEGRA_SLINK_CTRLS];
+
+static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
+{
+	return container_of(slave, struct tegra_spi_slave, slave);
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+	if (bus >= CONFIG_TEGRA_SLINK_CTRLS || cs > 3 || !spi_ctrls[bus].valid)
+		return 0;
+	else
+		return 1;
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+		unsigned int max_hz, unsigned int mode)
+{
+	struct tegra_spi_slave *spi;
+
+	debug("%s: bus: %u, cs: %u, max_hz: %u, mode: %u\n", __func__,
+		bus, cs, max_hz, mode);
+
+	if (!spi_cs_is_valid(bus, cs)) {
+		printf("SPI error: unsupported bus %d / chip select %d\n",
+		       bus, cs);
+		return NULL;
+	}
+
+	if (max_hz > TEGRA_SPI_MAX_FREQ) {
+		printf("SPI error: unsupported frequency %d Hz. Max frequency"
+			" is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ);
+		return NULL;
+	}
+
+	spi = malloc(sizeof(struct tegra_spi_slave));
+	if (!spi) {
+		printf("SPI error: malloc of SPI structure failed\n");
+		return NULL;
+	}
+	spi->slave.bus = bus;
+	spi->slave.cs = cs;
+	spi->ctrl = &spi_ctrls[bus];
+	if (!spi->ctrl) {
+		printf("SPI error: could not find controller for bus %d\n",
+		       bus);
+		return NULL;
+	}
+
+	if (max_hz < spi->ctrl->freq) {
+		debug("%s: limiting frequency from %u to %u\n", __func__,
+		      spi->ctrl->freq, max_hz);
+		spi->ctrl->freq = max_hz;
+	}
+	spi->ctrl->mode = mode;
+
+	return &spi->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+
+	free(spi);
+}
+
+void spi_init(void)
+{
+	struct tegra_spi_ctrl *ctrl;
+	int i;
+#ifdef CONFIG_OF_CONTROL
+	int node = 0;
+	int count;
+	int node_list[CONFIG_TEGRA_SLINK_CTRLS];
+
+	count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi",
+					   COMPAT_NVIDIA_TEGRA20_SLINK,
+					   node_list,
+					   CONFIG_TEGRA_SLINK_CTRLS);
+	for (i = 0; i < count; i++) {
+		ctrl = &spi_ctrls[i];
+		node = node_list[i];
+
+		ctrl->regs = (struct slink_tegra *)fdtdec_get_addr(gd->fdt_blob,
+								   node, "reg");
+		if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) {
+			debug("%s: no slink register found\n", __func__);
+			continue;
+		}
+		ctrl->freq = fdtdec_get_int(gd->fdt_blob, node,
+					    "spi-max-frequency", 0);
+		if (!ctrl->freq) {
+			debug("%s: no slink max frequency found\n", __func__);
+			continue;
+		}
+
+		ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node);
+		if (ctrl->periph_id == PERIPH_ID_NONE) {
+			debug("%s: could not decode periph id\n", __func__);
+			continue;
+		}
+		ctrl->valid = 1;
+
+		debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
+		      __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
+	}
+#else
+	for (i = 0; i < CONFIG_TEGRA_SLINK_CTRLS; i++) {
+		ctrl = &spi_ctrls[i];
+		u32 base_regs[] = {
+			NV_PA_SLINK1_BASE,
+			NV_PA_SLINK2_BASE,
+			NV_PA_SLINK3_BASE,
+			NV_PA_SLINK4_BASE,
+			NV_PA_SLINK5_BASE,
+			NV_PA_SLINK6_BASE,
+		};
+		int periph_ids[] = {
+			PERIPH_ID_SBC1,
+			PERIPH_ID_SBC2,
+			PERIPH_ID_SBC3,
+			PERIPH_ID_SBC4,
+			PERIPH_ID_SBC5,
+			PERIPH_ID_SBC6,
+		};
+		ctrl->regs = (struct slink_tegra *)base_regs[i];
+		ctrl->freq = TEGRA_SPI_MAX_FREQ;
+		ctrl->periph_id = periph_ids[i];
+		ctrl->valid = 1;
+
+		debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
+		      __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
+	}
+#endif
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+	struct slink_tegra *regs = spi->ctrl->regs;
+	u32 reg;
+
+	/* Change SPI clock to correct frequency, PLLP_OUT0 source */
+	clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH,
+			       spi->ctrl->freq);
+
+	/* Clear stale status here */
+	reg = SLINK_STAT_RDY | SLINK_STAT_RXF_FLUSH | SLINK_STAT_TXF_FLUSH | \
+		SLINK_STAT_RXF_UNR | SLINK_STAT_TXF_OVF;
+	writel(reg, &regs->status);
+	debug("%s: STATUS = %08x\n", __func__, readl(&regs->status));
+
+	/* Set master mode and sw controlled CS */
+	reg = readl(&regs->command);
+	reg |= SLINK_CMD_M_S | SLINK_CMD_CS_SOFT;
+	writel(reg, &regs->command);
+	debug("%s: COMMAND = %08x\n", __func__, readl(&regs->command));
+
+	return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+	struct slink_tegra *regs = spi->ctrl->regs;
+
+	/* CS is negated on Tegra, so drive a 1 to get a 0 */
+	setbits_le32(&regs->command, SLINK_CMD_CS_VAL);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+	struct slink_tegra *regs = spi->ctrl->regs;
+
+	/* CS is negated on Tegra, so drive a 0 to get a 1 */
+	clrbits_le32(&regs->command, SLINK_CMD_CS_VAL);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+		const void *data_out, void *data_in, unsigned long flags)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+	struct slink_tegra *regs = spi->ctrl->regs;
+	u32 reg, tmpdout, tmpdin = 0;
+	const u8 *dout = data_out;
+	u8 *din = data_in;
+	int num_bytes;
+	int ret;
+
+	debug("%s: slave %u:%u dout %p din %p bitlen %u\n",
+	      __func__, slave->bus, slave->cs, dout, din, bitlen);
+	if (bitlen % 8)
+		return -1;
+	num_bytes = bitlen / 8;
+
+	ret = 0;
+
+	reg = readl(&regs->status);
+	writel(reg, &regs->status);	/* Clear all SPI events via R/W */
+	debug("%s entry: STATUS = %08x\n", __func__, reg);
+
+	reg = readl(&regs->status2);
+	writel(reg, &regs->status2);	/* Clear all STATUS2 events via R/W */
+	debug("%s entry: STATUS2 = %08x\n", __func__, reg);
+
+	debug("%s entry: COMMAND = %08x\n", __func__, readl(&regs->command));
+
+	clrsetbits_le32(&regs->command2, SLINK_CMD2_SS_EN_MASK,
+			SLINK_CMD2_TXEN | SLINK_CMD2_RXEN |
+			(slave->cs << SLINK_CMD2_SS_EN_SHIFT));
+	debug("%s entry: COMMAND2 = %08x\n", __func__, readl(&regs->command2));
+
+	if (flags & SPI_XFER_BEGIN)
+		spi_cs_activate(slave);
+
+	/* handle data in 32-bit chunks */
+	while (num_bytes > 0) {
+		int bytes;
+		int is_read = 0;
+		int tm, i;
+
+		tmpdout = 0;
+		bytes = (num_bytes > 4) ?  4 : num_bytes;
+
+		if (dout != NULL) {
+			for (i = 0; i < bytes; ++i)
+				tmpdout = (tmpdout << 8) | dout[i];
+			dout += bytes;
+		}
+
+		num_bytes -= bytes;
+
+		clrsetbits_le32(&regs->command, SLINK_CMD_BIT_LENGTH_MASK,
+				bytes * 8 - 1);
+		writel(tmpdout, &regs->tx_fifo);
+		setbits_le32(&regs->command, SLINK_CMD_GO);
+
+		/*
+		 * Wait for SPI transmit FIFO to empty, or to time out.
+		 * The RX FIFO status will be read and cleared last
+		 */
+		for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) {
+			u32 status;
+
+			status = readl(&regs->status);
+
+			/* We can exit when we've had both RX and TX activity */
+			if (is_read && (status & SLINK_STAT_TXF_EMPTY))
+				break;
+
+			if ((status & (SLINK_STAT_BSY | SLINK_STAT_RDY)) !=
+					SLINK_STAT_RDY)
+				tm++;
+
+			else if (!(status & SLINK_STAT_RXF_EMPTY)) {
+				tmpdin = readl(&regs->rx_fifo);
+				is_read = 1;
+
+				/* swap bytes read in */
+				if (din != NULL) {
+					for (i = bytes - 1; i >= 0; --i) {
+						din[i] = tmpdin & 0xff;
+						tmpdin >>= 8;
+					}
+					din += bytes;
+				}
+			}
+		}
+
+		if (tm >= SPI_TIMEOUT)
+			ret = tm;
+
+		/* clear ACK RDY, etc. bits */
+		writel(readl(&regs->status), &regs->status);
+	}
+
+	if (flags & SPI_XFER_END)
+		spi_cs_deactivate(slave);
+
+	debug("%s: transfer ended. Value=%08x, status = %08x\n",
+	      __func__, tmpdin, readl(&regs->status));
+
+	if (ret) {
+		printf("%s: timeout during SPI transfer, tm %d\n",
+		       __func__, ret);
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/drivers/spi/tegra_slink.c b/drivers/spi/tegra_slink.c
deleted file mode 100644
index 2c41fab..0000000
--- a/drivers/spi/tegra_slink.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * NVIDIA Tegra SPI-SLINK controller
- *
- * Copyright (c) 2010-2013 NVIDIA Corporation
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <asm/io.h>
-#include <asm/gpio.h>
-#include <asm/arch/clock.h>
-#include <asm/arch-tegra/clk_rst.h>
-#include <asm/arch-tegra/tegra_slink.h>
-#include <spi.h>
-#include <fdtdec.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-struct tegra_spi_ctrl {
-	struct slink_tegra *regs;
-	unsigned int freq;
-	unsigned int mode;
-	int periph_id;
-	int valid;
-};
-
-struct tegra_spi_slave {
-	struct spi_slave slave;
-	struct tegra_spi_ctrl *ctrl;
-};
-
-static struct tegra_spi_ctrl spi_ctrls[CONFIG_TEGRA_SLINK_CTRLS];
-
-static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
-{
-	return container_of(slave, struct tegra_spi_slave, slave);
-}
-
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-	if (bus >= CONFIG_TEGRA_SLINK_CTRLS || cs > 3 || !spi_ctrls[bus].valid)
-		return 0;
-	else
-		return 1;
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-		unsigned int max_hz, unsigned int mode)
-{
-	struct tegra_spi_slave *spi;
-
-	debug("%s: bus: %u, cs: %u, max_hz: %u, mode: %u\n", __func__,
-		bus, cs, max_hz, mode);
-
-	if (!spi_cs_is_valid(bus, cs)) {
-		printf("SPI error: unsupported bus %d / chip select %d\n",
-		       bus, cs);
-		return NULL;
-	}
-
-	if (max_hz > TEGRA_SPI_MAX_FREQ) {
-		printf("SPI error: unsupported frequency %d Hz. Max frequency"
-			" is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ);
-		return NULL;
-	}
-
-	spi = malloc(sizeof(struct tegra_spi_slave));
-	if (!spi) {
-		printf("SPI error: malloc of SPI structure failed\n");
-		return NULL;
-	}
-	spi->slave.bus = bus;
-	spi->slave.cs = cs;
-	spi->ctrl = &spi_ctrls[bus];
-	if (!spi->ctrl) {
-		printf("SPI error: could not find controller for bus %d\n",
-		       bus);
-		return NULL;
-	}
-
-	if (max_hz < spi->ctrl->freq) {
-		debug("%s: limiting frequency from %u to %u\n", __func__,
-		      spi->ctrl->freq, max_hz);
-		spi->ctrl->freq = max_hz;
-	}
-	spi->ctrl->mode = mode;
-
-	return &spi->slave;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
-	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-
-	free(spi);
-}
-
-void spi_init(void)
-{
-	struct tegra_spi_ctrl *ctrl;
-	int i;
-#ifdef CONFIG_OF_CONTROL
-	int node = 0;
-	int count;
-	int node_list[CONFIG_TEGRA_SLINK_CTRLS];
-
-	count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi",
-					   COMPAT_NVIDIA_TEGRA20_SLINK,
-					   node_list,
-					   CONFIG_TEGRA_SLINK_CTRLS);
-	for (i = 0; i < count; i++) {
-		ctrl = &spi_ctrls[i];
-		node = node_list[i];
-
-		ctrl->regs = (struct slink_tegra *)fdtdec_get_addr(gd->fdt_blob,
-								   node, "reg");
-		if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) {
-			debug("%s: no slink register found\n", __func__);
-			continue;
-		}
-		ctrl->freq = fdtdec_get_int(gd->fdt_blob, node,
-					    "spi-max-frequency", 0);
-		if (!ctrl->freq) {
-			debug("%s: no slink max frequency found\n", __func__);
-			continue;
-		}
-
-		ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node);
-		if (ctrl->periph_id == PERIPH_ID_NONE) {
-			debug("%s: could not decode periph id\n", __func__);
-			continue;
-		}
-		ctrl->valid = 1;
-
-		debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
-		      __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
-	}
-#else
-	for (i = 0; i < CONFIG_TEGRA_SLINK_CTRLS; i++) {
-		ctrl = &spi_ctrls[i];
-		u32 base_regs[] = {
-			NV_PA_SLINK1_BASE,
-			NV_PA_SLINK2_BASE,
-			NV_PA_SLINK3_BASE,
-			NV_PA_SLINK4_BASE,
-			NV_PA_SLINK5_BASE,
-			NV_PA_SLINK6_BASE,
-		};
-		int periph_ids[] = {
-			PERIPH_ID_SBC1,
-			PERIPH_ID_SBC2,
-			PERIPH_ID_SBC3,
-			PERIPH_ID_SBC4,
-			PERIPH_ID_SBC5,
-			PERIPH_ID_SBC6,
-		};
-		ctrl->regs = (struct slink_tegra *)base_regs[i];
-		ctrl->freq = TEGRA_SPI_MAX_FREQ;
-		ctrl->periph_id = periph_ids[i];
-		ctrl->valid = 1;
-
-		debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
-		      __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
-	}
-#endif
-}
-
-int spi_claim_bus(struct spi_slave *slave)
-{
-	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct slink_tegra *regs = spi->ctrl->regs;
-	u32 reg;
-
-	/* Change SPI clock to correct frequency, PLLP_OUT0 source */
-	clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH,
-			       spi->ctrl->freq);
-
-	/* Clear stale status here */
-	reg = SLINK_STAT_RDY | SLINK_STAT_RXF_FLUSH | SLINK_STAT_TXF_FLUSH | \
-		SLINK_STAT_RXF_UNR | SLINK_STAT_TXF_OVF;
-	writel(reg, &regs->status);
-	debug("%s: STATUS = %08x\n", __func__, readl(&regs->status));
-
-	/* Set master mode and sw controlled CS */
-	reg = readl(&regs->command);
-	reg |= SLINK_CMD_M_S | SLINK_CMD_CS_SOFT;
-	writel(reg, &regs->command);
-	debug("%s: COMMAND = %08x\n", __func__, readl(&regs->command));
-
-	return 0;
-}
-
-void spi_release_bus(struct spi_slave *slave)
-{
-}
-
-void spi_cs_activate(struct spi_slave *slave)
-{
-	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct slink_tegra *regs = spi->ctrl->regs;
-
-	/* CS is negated on Tegra, so drive a 1 to get a 0 */
-	setbits_le32(&regs->command, SLINK_CMD_CS_VAL);
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
-	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct slink_tegra *regs = spi->ctrl->regs;
-
-	/* CS is negated on Tegra, so drive a 0 to get a 1 */
-	clrbits_le32(&regs->command, SLINK_CMD_CS_VAL);
-}
-
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-		const void *data_out, void *data_in, unsigned long flags)
-{
-	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct slink_tegra *regs = spi->ctrl->regs;
-	u32 reg, tmpdout, tmpdin = 0;
-	const u8 *dout = data_out;
-	u8 *din = data_in;
-	int num_bytes;
-	int ret;
-
-	debug("%s: slave %u:%u dout %p din %p bitlen %u\n",
-	      __func__, slave->bus, slave->cs, dout, din, bitlen);
-	if (bitlen % 8)
-		return -1;
-	num_bytes = bitlen / 8;
-
-	ret = 0;
-
-	reg = readl(&regs->status);
-	writel(reg, &regs->status);	/* Clear all SPI events via R/W */
-	debug("%s entry: STATUS = %08x\n", __func__, reg);
-
-	reg = readl(&regs->status2);
-	writel(reg, &regs->status2);	/* Clear all STATUS2 events via R/W */
-	debug("%s entry: STATUS2 = %08x\n", __func__, reg);
-
-	debug("%s entry: COMMAND = %08x\n", __func__, readl(&regs->command));
-
-	clrsetbits_le32(&regs->command2, SLINK_CMD2_SS_EN_MASK,
-			SLINK_CMD2_TXEN | SLINK_CMD2_RXEN |
-			(slave->cs << SLINK_CMD2_SS_EN_SHIFT));
-	debug("%s entry: COMMAND2 = %08x\n", __func__, readl(&regs->command2));
-
-	if (flags & SPI_XFER_BEGIN)
-		spi_cs_activate(slave);
-
-	/* handle data in 32-bit chunks */
-	while (num_bytes > 0) {
-		int bytes;
-		int is_read = 0;
-		int tm, i;
-
-		tmpdout = 0;
-		bytes = (num_bytes > 4) ?  4 : num_bytes;
-
-		if (dout != NULL) {
-			for (i = 0; i < bytes; ++i)
-				tmpdout = (tmpdout << 8) | dout[i];
-			dout += bytes;
-		}
-
-		num_bytes -= bytes;
-
-		clrsetbits_le32(&regs->command, SLINK_CMD_BIT_LENGTH_MASK,
-				bytes * 8 - 1);
-		writel(tmpdout, &regs->tx_fifo);
-		setbits_le32(&regs->command, SLINK_CMD_GO);
-
-		/*
-		 * Wait for SPI transmit FIFO to empty, or to time out.
-		 * The RX FIFO status will be read and cleared last
-		 */
-		for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) {
-			u32 status;
-
-			status = readl(&regs->status);
-
-			/* We can exit when we've had both RX and TX activity */
-			if (is_read && (status & SLINK_STAT_TXF_EMPTY))
-				break;
-
-			if ((status & (SLINK_STAT_BSY | SLINK_STAT_RDY)) !=
-					SLINK_STAT_RDY)
-				tm++;
-
-			else if (!(status & SLINK_STAT_RXF_EMPTY)) {
-				tmpdin = readl(&regs->rx_fifo);
-				is_read = 1;
-
-				/* swap bytes read in */
-				if (din != NULL) {
-					for (i = bytes - 1; i >= 0; --i) {
-						din[i] = tmpdin & 0xff;
-						tmpdin >>= 8;
-					}
-					din += bytes;
-				}
-			}
-		}
-
-		if (tm >= SPI_TIMEOUT)
-			ret = tm;
-
-		/* clear ACK RDY, etc. bits */
-		writel(readl(&regs->status), &regs->status);
-	}
-
-	if (flags & SPI_XFER_END)
-		spi_cs_deactivate(slave);
-
-	debug("%s: transfer ended. Value=%08x, status = %08x\n",
-	      __func__, tmpdin, readl(&regs->status));
-
-	if (ret) {
-		printf("%s: timeout during SPI transfer, tm %d\n",
-		       __func__, ret);
-		return -1;
-	}
-
-	return 0;
-}
diff --git a/drivers/spi/tegra_spi.c b/drivers/spi/tegra_spi.c
deleted file mode 100644
index ce19095..0000000
--- a/drivers/spi/tegra_spi.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Copyright (c) 2010-2012 NVIDIA Corporation
- * With help from the mpc8xxx SPI driver
- * With more help from omap3_spi SPI driver
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <asm/io.h>
-#include <asm/gpio.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/pinmux.h>
-#include <asm/arch/uart-spi-switch.h>
-#include <asm/arch-tegra/clk_rst.h>
-#include <asm/arch-tegra/tegra_spi.h>
-#include <spi.h>
-#include <fdtdec.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#if defined(CONFIG_SPI_CORRUPTS_UART)
- #define corrupt_delay()	udelay(CONFIG_SPI_CORRUPTS_UART_DLY);
-#else
- #define corrupt_delay()
-#endif
-
-struct tegra_spi_slave {
-	struct spi_slave slave;
-	struct spi_tegra *regs;
-	unsigned int freq;
-	unsigned int mode;
-	int periph_id;
-};
-
-static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
-{
-	return container_of(slave, struct tegra_spi_slave, slave);
-}
-
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-	/* Tegra20 SPI-Flash - only 1 device ('bus/cs') */
-	if (bus != 0 || cs != 0)
-		return 0;
-	else
-		return 1;
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-		unsigned int max_hz, unsigned int mode)
-{
-	struct tegra_spi_slave *spi;
-
-	if (!spi_cs_is_valid(bus, cs)) {
-		printf("SPI error: unsupported bus %d / chip select %d\n",
-		       bus, cs);
-		return NULL;
-	}
-
-	if (max_hz > TEGRA_SPI_MAX_FREQ) {
-		printf("SPI error: unsupported frequency %d Hz. Max frequency"
-			" is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ);
-		return NULL;
-	}
-
-	spi = malloc(sizeof(struct tegra_spi_slave));
-	if (!spi) {
-		printf("SPI error: malloc of SPI structure failed\n");
-		return NULL;
-	}
-	spi->slave.bus = bus;
-	spi->slave.cs = cs;
-#ifdef CONFIG_OF_CONTROL
-	int node = fdtdec_next_compatible(gd->fdt_blob, 0,
-					  COMPAT_NVIDIA_TEGRA20_SFLASH);
-	if (node < 0) {
-		debug("%s: cannot locate sflash node\n", __func__);
-		return NULL;
-	}
-	if (!fdtdec_get_is_enabled(gd->fdt_blob, node)) {
-		debug("%s: sflash is disabled\n", __func__);
-		return NULL;
-	}
-	spi->regs = (struct spi_tegra *)fdtdec_get_addr(gd->fdt_blob,
-							node, "reg");
-	if ((fdt_addr_t)spi->regs == FDT_ADDR_T_NONE) {
-		debug("%s: no sflash register found\n", __func__);
-		return NULL;
-	}
-	spi->freq = fdtdec_get_int(gd->fdt_blob, node, "spi-max-frequency", 0);
-	if (!spi->freq) {
-		debug("%s: no sflash max frequency found\n", __func__);
-		return NULL;
-	}
-	spi->periph_id = clock_decode_periph_id(gd->fdt_blob, node);
-	if (spi->periph_id == PERIPH_ID_NONE) {
-		debug("%s: could not decode periph id\n", __func__);
-		return NULL;
-	}
-#else
-	spi->regs = (struct spi_tegra *)NV_PA_SPI_BASE;
-	spi->freq = TEGRA_SPI_MAX_FREQ;
-	spi->periph_id = PERIPH_ID_SPI1;
-#endif
-	if (max_hz < spi->freq) {
-		debug("%s: limiting frequency from %u to %u\n", __func__,
-		      spi->freq, max_hz);
-		spi->freq = max_hz;
-	}
-	debug("%s: controller initialized at %p, freq = %u, periph_id = %d\n",
-	      __func__, spi->regs, spi->freq, spi->periph_id);
-	spi->mode = mode;
-
-	return &spi->slave;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
-	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-
-	free(spi);
-}
-
-void spi_init(void)
-{
-	/* do nothing */
-}
-
-int spi_claim_bus(struct spi_slave *slave)
-{
-	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct spi_tegra *regs = spi->regs;
-	u32 reg;
-
-	/* Change SPI clock to correct frequency, PLLP_OUT0 source */
-	clock_start_periph_pll(spi->periph_id, CLOCK_ID_PERIPH, spi->freq);
-
-	/* Clear stale status here */
-	reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \
-		SPI_STAT_RXF_UNR | SPI_STAT_TXF_OVF;
-	writel(reg, &regs->status);
-	debug("spi_init: STATUS = %08x\n", readl(&regs->status));
-
-	/*
-	 * Use sw-controlled CS, so we can clock in data after ReadID, etc.
-	 */
-	reg = (spi->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT;
-	if (spi->mode & 2)
-		reg |= 1 << SPI_CMD_ACTIVE_SCLK_SHIFT;
-	clrsetbits_le32(&regs->command, SPI_CMD_ACTIVE_SCLK_MASK |
-		SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg);
-	debug("spi_init: COMMAND = %08x\n", readl(&regs->command));
-
-	/*
-	 * SPI pins on Tegra20 are muxed - change pinmux later due to UART
-	 * issue.
-	 */
-	pinmux_set_func(PINGRP_GMD, PMUX_FUNC_SFLASH);
-	pinmux_tristate_disable(PINGRP_LSPI);
-
-#ifndef CONFIG_SPI_UART_SWITCH
-	/*
-	 * NOTE:
-	 * Only set PinMux bits 3:2 to SPI here on boards that don't have the
-	 * SPI UART switch or subsequent UART data won't go out!  See
-	 * spi_uart_switch().
-	 */
-	/* TODO: pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH); */
-#endif
-	return 0;
-}
-
-void spi_release_bus(struct spi_slave *slave)
-{
-	/*
-	 * We can't release UART_DISABLE and set pinmux to UART4 here since
-	 * some code (e,g, spi_flash_probe) uses printf() while the SPI
-	 * bus is held. That is arguably bad, but it has the advantage of
-	 * already being in the source tree.
-	 */
-}
-
-void spi_cs_activate(struct spi_slave *slave)
-{
-	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-
-	pinmux_select_spi();
-
-	/* CS is negated on Tegra, so drive a 1 to get a 0 */
-	setbits_le32(&spi->regs->command, SPI_CMD_CS_VAL);
-
-	corrupt_delay();		/* Let UART settle */
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
-	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-
-	pinmux_select_uart();
-
-	/* CS is negated on Tegra, so drive a 0 to get a 1 */
-	clrbits_le32(&spi->regs->command, SPI_CMD_CS_VAL);
-
-	corrupt_delay();		/* Let SPI settle */
-}
-
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-		const void *data_out, void *data_in, unsigned long flags)
-{
-	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct spi_tegra *regs = spi->regs;
-	u32 reg, tmpdout, tmpdin = 0;
-	const u8 *dout = data_out;
-	u8 *din = data_in;
-	int num_bytes;
-	int ret;
-
-	debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
-	      slave->bus, slave->cs, *(u8 *)dout, *(u8 *)din, bitlen);
-	if (bitlen % 8)
-		return -1;
-	num_bytes = bitlen / 8;
-
-	ret = 0;
-
-	reg = readl(&regs->status);
-	writel(reg, &regs->status);	/* Clear all SPI events via R/W */
-	debug("spi_xfer entry: STATUS = %08x\n", reg);
-
-	reg = readl(&regs->command);
-	reg |= SPI_CMD_TXEN | SPI_CMD_RXEN;
-	writel(reg, &regs->command);
-	debug("spi_xfer: COMMAND = %08x\n", readl(&regs->command));
-
-	if (flags & SPI_XFER_BEGIN)
-		spi_cs_activate(slave);
-
-	/* handle data in 32-bit chunks */
-	while (num_bytes > 0) {
-		int bytes;
-		int is_read = 0;
-		int tm, i;
-
-		tmpdout = 0;
-		bytes = (num_bytes > 4) ?  4 : num_bytes;
-
-		if (dout != NULL) {
-			for (i = 0; i < bytes; ++i)
-				tmpdout = (tmpdout << 8) | dout[i];
-		}
-
-		num_bytes -= bytes;
-		if (dout)
-			dout += bytes;
-
-		clrsetbits_le32(&regs->command, SPI_CMD_BIT_LENGTH_MASK,
-				bytes * 8 - 1);
-		writel(tmpdout, &regs->tx_fifo);
-		setbits_le32(&regs->command, SPI_CMD_GO);
-
-		/*
-		 * Wait for SPI transmit FIFO to empty, or to time out.
-		 * The RX FIFO status will be read and cleared last
-		 */
-		for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) {
-			u32 status;
-
-			status = readl(&regs->status);
-
-			/* We can exit when we've had both RX and TX activity */
-			if (is_read && (status & SPI_STAT_TXF_EMPTY))
-				break;
-
-			if ((status & (SPI_STAT_BSY | SPI_STAT_RDY)) !=
-					SPI_STAT_RDY)
-				tm++;
-
-			else if (!(status & SPI_STAT_RXF_EMPTY)) {
-				tmpdin = readl(&regs->rx_fifo);
-				is_read = 1;
-
-				/* swap bytes read in */
-				if (din != NULL) {
-					for (i = bytes - 1; i >= 0; --i) {
-						din[i] = tmpdin & 0xff;
-						tmpdin >>= 8;
-					}
-					din += bytes;
-				}
-			}
-		}
-
-		if (tm >= SPI_TIMEOUT)
-			ret = tm;
-
-		/* clear ACK RDY, etc. bits */
-		writel(readl(&regs->status), &regs->status);
-	}
-
-	if (flags & SPI_XFER_END)
-		spi_cs_deactivate(slave);
-
-	debug("spi_xfer: transfer ended. Value=%08x, status = %08x\n",
-		tmpdin, readl(&regs->status));
-
-	if (ret) {
-		printf("spi_xfer: timeout during SPI transfer, tm %d\n", ret);
-		return -1;
-	}
-
-	return 0;
-}
diff --git a/include/configs/cardhu.h b/include/configs/cardhu.h
index 1616b39..e7274f8 100644
--- a/include/configs/cardhu.h
+++ b/include/configs/cardhu.h
@@ -50,7 +50,7 @@
 #define CONFIG_ENV_IS_NOWHERE
 
 /* SPI */
-#define CONFIG_TEGRA_SLINK
+#define CONFIG_TEGRA30_SPI
 #define CONFIG_TEGRA_SLINK_CTRLS       6
 #define CONFIG_SPI_FLASH
 #define CONFIG_SPI_FLASH_WINBOND
diff --git a/include/configs/trimslice.h b/include/configs/trimslice.h
index 334d3a3..0aa6305 100644
--- a/include/configs/trimslice.h
+++ b/include/configs/trimslice.h
@@ -46,7 +46,7 @@
 #define CONFIG_BOARD_EARLY_INIT_F
 
 /* SPI */
-#define CONFIG_TEGRA_SPI
+#define CONFIG_TEGRA20_SPI
 #define CONFIG_SPI_FLASH
 #define CONFIG_SPI_FLASH_WINBOND
 #define CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
-- 
1.7.10.4

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

* [U-Boot] [PATCH 02/14] tegra: spi: remove non fdt support
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
  2013-02-13  3:23 ` [U-Boot] [PATCH 01/14] tegra: spi: rename tegra SPI drivers Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  2013-02-13  3:23 ` [U-Boot] [PATCH 03/14] tegra: spi: pull register structs out of headers Allen Martin
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Remove non fdt support from tegra20 and tegra30 SPI drivers in
preparation of new common fdt based SPI driver front end.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 drivers/spi/tegra20_spi.c |   12 ++++--------
 drivers/spi/tegra30_spi.c |   29 -----------------------------
 2 files changed, 4 insertions(+), 37 deletions(-)

diff --git a/drivers/spi/tegra20_spi.c b/drivers/spi/tegra20_spi.c
index 8cc3e5d..9e5de68 100644
--- a/drivers/spi/tegra20_spi.c
+++ b/drivers/spi/tegra20_spi.c
@@ -68,6 +68,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 		unsigned int max_hz, unsigned int mode)
 {
 	struct tegra_spi_slave *spi;
+	int node;
 
 	if (!spi_cs_is_valid(bus, cs)) {
 		printf("SPI error: unsupported bus %d / chip select %d\n",
@@ -88,9 +89,9 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 	}
 	spi->slave.bus = bus;
 	spi->slave.cs = cs;
-#ifdef CONFIG_OF_CONTROL
-	int node = fdtdec_next_compatible(gd->fdt_blob, 0,
-					  COMPAT_NVIDIA_TEGRA20_SFLASH);
+
+	node = fdtdec_next_compatible(gd->fdt_blob, 0,
+				      COMPAT_NVIDIA_TEGRA20_SFLASH);
 	if (node < 0) {
 		debug("%s: cannot locate sflash node\n", __func__);
 		return NULL;
@@ -115,11 +116,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 		debug("%s: could not decode periph id\n", __func__);
 		return NULL;
 	}
-#else
-	spi->regs = (struct spi_tegra *)NV_PA_SPI_BASE;
-	spi->freq = TEGRA_SPI_MAX_FREQ;
-	spi->periph_id = PERIPH_ID_SPI1;
-#endif
 	if (max_hz < spi->freq) {
 		debug("%s: limiting frequency from %u to %u\n", __func__,
 		      spi->freq, max_hz);
diff --git a/drivers/spi/tegra30_spi.c b/drivers/spi/tegra30_spi.c
index b475090..2d788e6 100644
--- a/drivers/spi/tegra30_spi.c
+++ b/drivers/spi/tegra30_spi.c
@@ -116,7 +116,6 @@ void spi_init(void)
 {
 	struct tegra_spi_ctrl *ctrl;
 	int i;
-#ifdef CONFIG_OF_CONTROL
 	int node = 0;
 	int count;
 	int node_list[CONFIG_TEGRA_SLINK_CTRLS];
@@ -152,34 +151,6 @@ void spi_init(void)
 		debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
 		      __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
 	}
-#else
-	for (i = 0; i < CONFIG_TEGRA_SLINK_CTRLS; i++) {
-		ctrl = &spi_ctrls[i];
-		u32 base_regs[] = {
-			NV_PA_SLINK1_BASE,
-			NV_PA_SLINK2_BASE,
-			NV_PA_SLINK3_BASE,
-			NV_PA_SLINK4_BASE,
-			NV_PA_SLINK5_BASE,
-			NV_PA_SLINK6_BASE,
-		};
-		int periph_ids[] = {
-			PERIPH_ID_SBC1,
-			PERIPH_ID_SBC2,
-			PERIPH_ID_SBC3,
-			PERIPH_ID_SBC4,
-			PERIPH_ID_SBC5,
-			PERIPH_ID_SBC6,
-		};
-		ctrl->regs = (struct slink_tegra *)base_regs[i];
-		ctrl->freq = TEGRA_SPI_MAX_FREQ;
-		ctrl->periph_id = periph_ids[i];
-		ctrl->valid = 1;
-
-		debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
-		      __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
-	}
-#endif
 }
 
 int spi_claim_bus(struct spi_slave *slave)
-- 
1.7.10.4

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

* [U-Boot] [PATCH 03/14] tegra: spi: pull register structs out of headers
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
  2013-02-13  3:23 ` [U-Boot] [PATCH 01/14] tegra: spi: rename tegra SPI drivers Allen Martin
  2013-02-13  3:23 ` [U-Boot] [PATCH 02/14] tegra: spi: remove non fdt support Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  2013-02-13 22:32   ` Stephen Warren
  2013-02-13  3:23 ` [U-Boot] [PATCH 04/14] tegra20: spi: move fdt probe to spi_init Allen Martin
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Move register structs from headers into .c files and use common name.
This is in preparation of making common fdt front end for SPI
drivers.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 arch/arm/include/asm/arch-tegra20/tegra20_spi.h |   13 ---------
 arch/arm/include/asm/arch-tegra30/tegra30_spi.h |   18 -------------
 drivers/spi/tegra20_spi.c                       |   21 ++++++++++++---
 drivers/spi/tegra30_spi.c                       |   32 ++++++++++++++++++-----
 4 files changed, 42 insertions(+), 42 deletions(-)

diff --git a/arch/arm/include/asm/arch-tegra20/tegra20_spi.h b/arch/arm/include/asm/arch-tegra20/tegra20_spi.h
index 26a8402..6789881 100644
--- a/arch/arm/include/asm/arch-tegra20/tegra20_spi.h
+++ b/arch/arm/include/asm/arch-tegra20/tegra20_spi.h
@@ -27,16 +27,6 @@
 
 #include <asm/types.h>
 
-struct spi_tegra {
-	u32 command;	/* SPI_COMMAND_0 register  */
-	u32 status;	/* SPI_STATUS_0 register */
-	u32 rx_cmp;	/* SPI_RX_CMP_0 register  */
-	u32 dma_ctl;	/* SPI_DMA_CTL_0 register */
-	u32 tx_fifo;	/* SPI_TX_FIFO_0 register */
-	u32 rsvd[3];	/* offsets 0x14 to 0x1F reserved */
-	u32 rx_fifo;	/* SPI_RX_FIFO_0 register */
-};
-
 #define SPI_CMD_GO			(1 << 30)
 #define SPI_CMD_ACTIVE_SCLK_SHIFT	26
 #define SPI_CMD_ACTIVE_SCLK_MASK	(3 << SPI_CMD_ACTIVE_SCLK_SHIFT)
@@ -69,7 +59,4 @@ struct spi_tegra {
 #define SPI_STAT_SEL_TXRX_N		(1 << 16)
 #define SPI_STAT_CUR_BLKCNT		(1 << 15)
 
-#define SPI_TIMEOUT		1000
-#define TEGRA_SPI_MAX_FREQ	52000000
-
 #endif	/* _TEGRA20_SPI_H_ */
diff --git a/arch/arm/include/asm/arch-tegra30/tegra30_spi.h b/arch/arm/include/asm/arch-tegra30/tegra30_spi.h
index afa9b36..87a8169 100644
--- a/arch/arm/include/asm/arch-tegra30/tegra30_spi.h
+++ b/arch/arm/include/asm/arch-tegra30/tegra30_spi.h
@@ -27,21 +27,6 @@
 
 #include <asm/types.h>
 
-struct slink_tegra {
-	u32 command;	/* SLINK_COMMAND_0 register  */
-	u32 command2;	/* SLINK_COMMAND2_0 reg */
-	u32 status;	/* SLINK_STATUS_0 register */
-	u32 reserved;	/* Reserved offset 0C */
-	u32 mas_data;	/* SLINK_MAS_DATA_0 reg */
-	u32 slav_data;	/* SLINK_SLAVE_DATA_0 reg */
-	u32 dma_ctl;	/* SLINK_DMA_CTL_0 register */
-	u32 status2;	/* SLINK_STATUS2_0 reg */
-	u32 rsvd[56];	/* 0x20 to 0xFF reserved */
-	u32 tx_fifo;	/* SLINK_TX_FIFO_0 reg off 100h */
-	u32 rsvd2[31];	/* 0x104 to 0x17F reserved */
-	u32 rx_fifo;	/* SLINK_RX_FIFO_0 reg off 180h */
-};
-
 /* COMMAND */
 #define SLINK_CMD_ENB			(1 << 31)
 #define SLINK_CMD_GO			(1 << 30)
@@ -78,7 +63,4 @@ struct slink_tegra {
 #define SLINK_STAT2_RXF_FULL_CNT	(1 << 16)
 #define SLINK_STAT2_TXF_FULL_CNT	(1 << 0)
 
-#define SPI_TIMEOUT		1000
-#define TEGRA_SPI_MAX_FREQ	52000000
-
 #endif	/* _TEGRA30_SPI_H_ */
diff --git a/drivers/spi/tegra20_spi.c b/drivers/spi/tegra20_spi.c
index 9e5de68..d6567f8 100644
--- a/drivers/spi/tegra20_spi.c
+++ b/drivers/spi/tegra20_spi.c
@@ -36,15 +36,28 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define SPI_TIMEOUT		1000
+#define TEGRA_SPI_MAX_FREQ	52000000
+
 #if defined(CONFIG_SPI_CORRUPTS_UART)
  #define corrupt_delay()	udelay(CONFIG_SPI_CORRUPTS_UART_DLY);
 #else
  #define corrupt_delay()
 #endif
 
+struct spi_regs {
+	u32 command;	/* SPI_COMMAND_0 register  */
+	u32 status;	/* SPI_STATUS_0 register */
+	u32 rx_cmp;	/* SPI_RX_CMP_0 register  */
+	u32 dma_ctl;	/* SPI_DMA_CTL_0 register */
+	u32 tx_fifo;	/* SPI_TX_FIFO_0 register */
+	u32 rsvd[3];	/* offsets 0x14 to 0x1F reserved */
+	u32 rx_fifo;	/* SPI_RX_FIFO_0 register */
+};
+
 struct tegra_spi_slave {
 	struct spi_slave slave;
-	struct spi_tegra *regs;
+	struct spi_regs *regs;
 	unsigned int freq;
 	unsigned int mode;
 	int periph_id;
@@ -100,7 +113,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 		debug("%s: sflash is disabled\n", __func__);
 		return NULL;
 	}
-	spi->regs = (struct spi_tegra *)fdtdec_get_addr(gd->fdt_blob,
+	spi->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob,
 							node, "reg");
 	if ((fdt_addr_t)spi->regs == FDT_ADDR_T_NONE) {
 		debug("%s: no sflash register found\n", __func__);
@@ -143,7 +156,7 @@ void spi_init(void)
 int spi_claim_bus(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct spi_tegra *regs = spi->regs;
+	struct spi_regs *regs = spi->regs;
 	u32 reg;
 
 	/* Change SPI clock to correct frequency, PLLP_OUT0 source */
@@ -222,7 +235,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 		const void *data_out, void *data_in, unsigned long flags)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct spi_tegra *regs = spi->regs;
+	struct spi_regs *regs = spi->regs;
 	u32 reg, tmpdout, tmpdin = 0;
 	const u8 *dout = data_out;
 	u8 *din = data_in;
diff --git a/drivers/spi/tegra30_spi.c b/drivers/spi/tegra30_spi.c
index 2d788e6..8f3dc8f 100644
--- a/drivers/spi/tegra30_spi.c
+++ b/drivers/spi/tegra30_spi.c
@@ -33,8 +33,26 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define SPI_TIMEOUT		1000
+#define TEGRA_SPI_MAX_FREQ	52000000
+
+struct spi_regs {
+	u32 command;	/* SLINK_COMMAND_0 register  */
+	u32 command2;	/* SLINK_COMMAND2_0 reg */
+	u32 status;	/* SLINK_STATUS_0 register */
+	u32 reserved;	/* Reserved offset 0C */
+	u32 mas_data;	/* SLINK_MAS_DATA_0 reg */
+	u32 slav_data;	/* SLINK_SLAVE_DATA_0 reg */
+	u32 dma_ctl;	/* SLINK_DMA_CTL_0 register */
+	u32 status2;	/* SLINK_STATUS2_0 reg */
+	u32 rsvd[56];	/* 0x20 to 0xFF reserved */
+	u32 tx_fifo;	/* SLINK_TX_FIFO_0 reg off 100h */
+	u32 rsvd2[31];	/* 0x104 to 0x17F reserved */
+	u32 rx_fifo;	/* SLINK_RX_FIFO_0 reg off 180h */
+};
+
 struct tegra_spi_ctrl {
-	struct slink_tegra *regs;
+	struct spi_regs *regs;
 	unsigned int freq;
 	unsigned int mode;
 	int periph_id;
@@ -128,8 +146,8 @@ void spi_init(void)
 		ctrl = &spi_ctrls[i];
 		node = node_list[i];
 
-		ctrl->regs = (struct slink_tegra *)fdtdec_get_addr(gd->fdt_blob,
-								   node, "reg");
+		ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob,
+								node, "reg");
 		if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) {
 			debug("%s: no slink register found\n", __func__);
 			continue;
@@ -156,7 +174,7 @@ void spi_init(void)
 int spi_claim_bus(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct slink_tegra *regs = spi->ctrl->regs;
+	struct spi_regs *regs = spi->ctrl->regs;
 	u32 reg;
 
 	/* Change SPI clock to correct frequency, PLLP_OUT0 source */
@@ -185,7 +203,7 @@ void spi_release_bus(struct spi_slave *slave)
 void spi_cs_activate(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct slink_tegra *regs = spi->ctrl->regs;
+	struct spi_regs *regs = spi->ctrl->regs;
 
 	/* CS is negated on Tegra, so drive a 1 to get a 0 */
 	setbits_le32(&regs->command, SLINK_CMD_CS_VAL);
@@ -194,7 +212,7 @@ void spi_cs_activate(struct spi_slave *slave)
 void spi_cs_deactivate(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct slink_tegra *regs = spi->ctrl->regs;
+	struct spi_regs *regs = spi->ctrl->regs;
 
 	/* CS is negated on Tegra, so drive a 0 to get a 1 */
 	clrbits_le32(&regs->command, SLINK_CMD_CS_VAL);
@@ -204,7 +222,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 		const void *data_out, void *data_in, unsigned long flags)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct slink_tegra *regs = spi->ctrl->regs;
+	struct spi_regs *regs = spi->ctrl->regs;
 	u32 reg, tmpdout, tmpdin = 0;
 	const u8 *dout = data_out;
 	u8 *din = data_in;
-- 
1.7.10.4

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

* [U-Boot] [PATCH 04/14] tegra20: spi: move fdt probe to spi_init
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
                   ` (2 preceding siblings ...)
  2013-02-13  3:23 ` [U-Boot] [PATCH 03/14] tegra: spi: pull register structs out of headers Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  2013-02-13  3:23 ` [U-Boot] [PATCH 05/14] spi: add common fdt SPI driver interface Allen Martin
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Make the tegra20 SPI driver similar to the tegra30 (and soon to be
tegra114) SPI drivers in preparation of common fdt SPI driver front
end.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 drivers/spi/tegra20_spi.c |  110 +++++++++++++++++++++++++++------------------
 1 file changed, 67 insertions(+), 43 deletions(-)

diff --git a/drivers/spi/tegra20_spi.c b/drivers/spi/tegra20_spi.c
index d6567f8..f3985f2 100644
--- a/drivers/spi/tegra20_spi.c
+++ b/drivers/spi/tegra20_spi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012 NVIDIA Corporation
+ * Copyright (c) 2010-2013 NVIDIA Corporation
  * With help from the mpc8xxx SPI driver
  * With more help from omap3_spi SPI driver
  *
@@ -55,14 +55,22 @@ struct spi_regs {
 	u32 rx_fifo;	/* SPI_RX_FIFO_0 register */
 };
 
-struct tegra_spi_slave {
-	struct spi_slave slave;
+struct tegra_spi_ctrl {
 	struct spi_regs *regs;
 	unsigned int freq;
 	unsigned int mode;
 	int periph_id;
+	int valid;
+};
+
+struct tegra_spi_slave {
+	struct spi_slave slave;
+	struct tegra_spi_ctrl *ctrl;
 };
 
+/* tegra20 only supports one SFLASH controller */
+static struct tegra_spi_ctrl spi_ctrls[1];
+
 static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
 {
 	return container_of(slave, struct tegra_spi_slave, slave);
@@ -81,7 +89,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 		unsigned int max_hz, unsigned int mode)
 {
 	struct tegra_spi_slave *spi;
-	int node;
 
 	if (!spi_cs_is_valid(bus, cs)) {
 		printf("SPI error: unsupported bus %d / chip select %d\n",
@@ -102,41 +109,19 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 	}
 	spi->slave.bus = bus;
 	spi->slave.cs = cs;
-
-	node = fdtdec_next_compatible(gd->fdt_blob, 0,
-				      COMPAT_NVIDIA_TEGRA20_SFLASH);
-	if (node < 0) {
-		debug("%s: cannot locate sflash node\n", __func__);
-		return NULL;
-	}
-	if (!fdtdec_get_is_enabled(gd->fdt_blob, node)) {
-		debug("%s: sflash is disabled\n", __func__);
-		return NULL;
-	}
-	spi->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob,
-							node, "reg");
-	if ((fdt_addr_t)spi->regs == FDT_ADDR_T_NONE) {
-		debug("%s: no sflash register found\n", __func__);
+	spi->ctrl = &spi_ctrls[bus];
+	if (!spi->ctrl) {
+		printf("SPI error: could not find controller for bus %d\n",
+		       bus);
 		return NULL;
 	}
-	spi->freq = fdtdec_get_int(gd->fdt_blob, node, "spi-max-frequency", 0);
-	if (!spi->freq) {
-		debug("%s: no sflash max frequency found\n", __func__);
-		return NULL;
-	}
-	spi->periph_id = clock_decode_periph_id(gd->fdt_blob, node);
-	if (spi->periph_id == PERIPH_ID_NONE) {
-		debug("%s: could not decode periph id\n", __func__);
-		return NULL;
-	}
-	if (max_hz < spi->freq) {
+
+	if (max_hz < spi->ctrl->freq) {
 		debug("%s: limiting frequency from %u to %u\n", __func__,
-		      spi->freq, max_hz);
-		spi->freq = max_hz;
+		      spi->ctrl->freq, max_hz);
+		spi->ctrl->freq = max_hz;
 	}
-	debug("%s: controller initialized at %p, freq = %u, periph_id = %d\n",
-	      __func__, spi->regs, spi->freq, spi->periph_id);
-	spi->mode = mode;
+	spi->ctrl->mode = mode;
 
 	return &spi->slave;
 }
@@ -150,17 +135,54 @@ void spi_free_slave(struct spi_slave *slave)
 
 void spi_init(void)
 {
-	/* do nothing */
+	struct tegra_spi_ctrl *ctrl;
+	int i;
+	int node = 0;
+	int count;
+	int node_list[1];
+
+	count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi",
+					   COMPAT_NVIDIA_TEGRA20_SFLASH,
+					   node_list,
+					   1);
+	for (i = 0; i < count; i++) {
+		ctrl = &spi_ctrls[i];
+		node = node_list[i];
+
+		ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob,
+								node, "reg");
+		if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) {
+			debug("%s: no slink register found\n", __func__);
+			continue;
+		}
+		ctrl->freq = fdtdec_get_int(gd->fdt_blob, node,
+					    "spi-max-frequency", 0);
+		if (!ctrl->freq) {
+			debug("%s: no slink max frequency found\n", __func__);
+			continue;
+		}
+
+		ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node);
+		if (ctrl->periph_id == PERIPH_ID_NONE) {
+			debug("%s: could not decode periph id\n", __func__);
+			continue;
+		}
+		ctrl->valid = 1;
+
+		debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
+		      __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
+	}
 }
 
 int spi_claim_bus(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct spi_regs *regs = spi->regs;
+	struct spi_regs *regs = spi->ctrl->regs;
 	u32 reg;
 
 	/* Change SPI clock to correct frequency, PLLP_OUT0 source */
-	clock_start_periph_pll(spi->periph_id, CLOCK_ID_PERIPH, spi->freq);
+	clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH,
+			       spi->ctrl->freq);
 
 	/* Clear stale status here */
 	reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \
@@ -171,8 +193,8 @@ int spi_claim_bus(struct spi_slave *slave)
 	/*
 	 * Use sw-controlled CS, so we can clock in data after ReadID, etc.
 	 */
-	reg = (spi->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT;
-	if (spi->mode & 2)
+	reg = (spi->ctrl->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT;
+	if (spi->ctrl->mode & 2)
 		reg |= 1 << SPI_CMD_ACTIVE_SCLK_SHIFT;
 	clrsetbits_le32(&regs->command, SPI_CMD_ACTIVE_SCLK_MASK |
 		SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg);
@@ -210,11 +232,12 @@ void spi_release_bus(struct spi_slave *slave)
 void spi_cs_activate(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+	struct spi_regs *regs = spi->ctrl->regs;
 
 	pinmux_select_spi();
 
 	/* CS is negated on Tegra, so drive a 1 to get a 0 */
-	setbits_le32(&spi->regs->command, SPI_CMD_CS_VAL);
+	setbits_le32(&regs->command, SPI_CMD_CS_VAL);
 
 	corrupt_delay();		/* Let UART settle */
 }
@@ -222,11 +245,12 @@ void spi_cs_activate(struct spi_slave *slave)
 void spi_cs_deactivate(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+	struct spi_regs *regs = spi->ctrl->regs;
 
 	pinmux_select_uart();
 
 	/* CS is negated on Tegra, so drive a 0 to get a 1 */
-	clrbits_le32(&spi->regs->command, SPI_CMD_CS_VAL);
+	clrbits_le32(&regs->command, SPI_CMD_CS_VAL);
 
 	corrupt_delay();		/* Let SPI settle */
 }
@@ -235,7 +259,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 		const void *data_out, void *data_in, unsigned long flags)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
-	struct spi_regs *regs = spi->regs;
+	struct spi_regs *regs = spi->ctrl->regs;
 	u32 reg, tmpdout, tmpdin = 0;
 	const u8 *dout = data_out;
 	u8 *din = data_in;
-- 
1.7.10.4

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

* [U-Boot] [PATCH 05/14] spi: add common fdt SPI driver interface
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
                   ` (3 preceding siblings ...)
  2013-02-13  3:23 ` [U-Boot] [PATCH 04/14] tegra20: spi: move fdt probe to spi_init Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  2013-02-13 22:40   ` Stephen Warren
  2013-02-13  3:23 ` [U-Boot] [PATCH 06/14] sf: winbond: add W25Q32DW Allen Martin
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Add a common interface to fdt based SPI drivers.  Each driver is
represented by a table entry in fdt_spi_drivers[].  If there are
multiple SPI drivers in the table, the first driver to return success
from spi_init() will be registered as the SPI driver.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 arch/arm/include/asm/arch-tegra20/tegra20_spi.h |   11 ++
 arch/arm/include/asm/arch-tegra30/tegra30_spi.h |   11 ++
 board/nvidia/common/board.c                     |    2 +-
 drivers/spi/Makefile                            |    1 +
 drivers/spi/fdt_spi.c                           |  172 +++++++++++++++++++++++
 drivers/spi/tegra20_spi.c                       |   41 ++----
 drivers/spi/tegra30_spi.c                       |   33 ++---
 include/configs/cardhu.h                        |    2 +-
 include/configs/tegra-common-post.h             |    4 +
 9 files changed, 228 insertions(+), 49 deletions(-)
 create mode 100644 drivers/spi/fdt_spi.c

diff --git a/arch/arm/include/asm/arch-tegra20/tegra20_spi.h b/arch/arm/include/asm/arch-tegra20/tegra20_spi.h
index 6789881..b272fc5 100644
--- a/arch/arm/include/asm/arch-tegra20/tegra20_spi.h
+++ b/arch/arm/include/asm/arch-tegra20/tegra20_spi.h
@@ -59,4 +59,15 @@
 #define SPI_STAT_SEL_TXRX_N		(1 << 16)
 #define SPI_STAT_CUR_BLKCNT		(1 << 15)
 
+int tegra20_spi_cs_is_valid(unsigned int bus, unsigned int cs);
+struct spi_slave *tegra20_spi_setup_slave(unsigned int bus, unsigned int cs,
+				  unsigned int max_hz, unsigned int mode);
+void tegra20_spi_free_slave(struct spi_slave *slave);
+int tegra20_spi_init(int *node_list, int count);
+int tegra20_spi_claim_bus(struct spi_slave *slave);
+void tegra20_spi_cs_activate(struct spi_slave *slave);
+void tegra20_spi_cs_deactivate(struct spi_slave *slave);
+int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+	     const void *data_out, void *data_in, unsigned long flags);
+
 #endif	/* _TEGRA20_SPI_H_ */
diff --git a/arch/arm/include/asm/arch-tegra30/tegra30_spi.h b/arch/arm/include/asm/arch-tegra30/tegra30_spi.h
index 87a8169..234a468 100644
--- a/arch/arm/include/asm/arch-tegra30/tegra30_spi.h
+++ b/arch/arm/include/asm/arch-tegra30/tegra30_spi.h
@@ -63,4 +63,15 @@
 #define SLINK_STAT2_RXF_FULL_CNT	(1 << 16)
 #define SLINK_STAT2_TXF_FULL_CNT	(1 << 0)
 
+int tegra30_spi_init(int *node_list, int count);
+int tegra30_spi_cs_is_valid(unsigned int bus, unsigned int cs);
+struct spi_slave *tegra30_spi_setup_slave(unsigned int bus, unsigned int cs,
+				  unsigned int max_hz, unsigned int mode);
+void tegra30_spi_free_slave(struct spi_slave *slave);
+int tegra30_spi_claim_bus(struct spi_slave *slave);
+void tegra30_spi_cs_activate(struct spi_slave *slave);
+void tegra30_spi_cs_deactivate(struct spi_slave *slave);
+int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+		     const void *data_out, void *data_in, unsigned long flags);
+
 #endif	/* _TEGRA30_SPI_H_ */
diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index 18e6420..30e71a6 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -131,7 +131,7 @@ int board_init(void)
 #ifdef CONFIG_SPI_UART_SWITCH
 	gpio_config_uart();
 #endif
-#if defined(CONFIG_TEGRA20_SPI) || defined(CONFIG_TEGRA30_SPI)
+#ifdef CONFIG_FDT_SPI
 	pin_mux_spi();
 	spi_init();
 #endif
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e9fccb5..5551d01 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -45,6 +45,7 @@ COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o
 COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
 COBJS-$(CONFIG_SH_SPI) += sh_spi.o
 COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o
+COBJS-$(CONFIG_FDT_SPI) += fdt_spi.o
 COBJS-$(CONFIG_TEGRA20_SPI) += tegra20_spi.o
 COBJS-$(CONFIG_TEGRA30_SPI) += tegra30_spi.o
 COBJS-$(CONFIG_XILINX_SPI) += xilinx_spi.o
diff --git a/drivers/spi/fdt_spi.c b/drivers/spi/fdt_spi.c
new file mode 100644
index 0000000..1a3937a
--- /dev/null
+++ b/drivers/spi/fdt_spi.c
@@ -0,0 +1,172 @@
+/*
+ * Common fdt based SPI driver front end
+ *
+ * Copyright (c) 2013 NVIDIA Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/clock.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra20/tegra20_spi.h>
+#include <asm/arch-tegra30/tegra30_spi.h>
+#include <spi.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct fdt_spi_driver {
+	int compat;
+	int max_ctrls;
+	int (*init)(int *node_list, int count);
+	int (*claim_bus)(struct spi_slave *slave);
+	int (*release_bus)(struct spi_slave *slave);
+	int (*cs_is_valid)(unsigned int bus, unsigned int cs);
+	struct spi_slave *(*setup_slave)(unsigned int bus, unsigned int cs,
+					unsigned int max_hz, unsigned int mode);
+	void (*free_slave)(struct spi_slave *slave);
+	void (*cs_activate)(struct spi_slave *slave);
+	void (*cs_deactivate)(struct spi_slave *slave);
+	int (*xfer)(struct spi_slave *slave, unsigned int bitlen,
+		    const void *data_out, void *data_in, unsigned long flags);
+};
+
+static struct fdt_spi_driver fdt_spi_drivers[] = {
+#ifdef CONFIG_TEGRA20_SPI
+	{
+		.compat		= COMPAT_NVIDIA_TEGRA20_SFLASH,
+		.max_ctrls	= 1,
+		.init		= tegra20_spi_init,
+		.claim_bus	= tegra20_spi_claim_bus,
+		.cs_is_valid	= tegra20_spi_cs_is_valid,
+		.setup_slave	= tegra20_spi_setup_slave,
+		.free_slave	= tegra20_spi_free_slave,
+		.cs_activate	= tegra20_spi_cs_activate,
+		.cs_deactivate	= tegra20_spi_cs_deactivate,
+		.xfer		= tegra20_spi_xfer,
+	},
+#endif
+#ifdef CONFIG_TEGRA30_SPI
+	{
+		.compat		= COMPAT_NVIDIA_TEGRA20_SLINK,
+		.max_ctrls	= CONFIG_TEGRA30_SPI_CTRLS,
+		.init		= tegra30_spi_init,
+		.claim_bus	= tegra30_spi_claim_bus,
+		.cs_is_valid	= tegra30_spi_cs_is_valid,
+		.setup_slave	= tegra30_spi_setup_slave,
+		.free_slave	= tegra30_spi_free_slave,
+		.cs_activate	= tegra30_spi_cs_activate,
+		.cs_deactivate	= tegra30_spi_cs_deactivate,
+		.xfer		= tegra30_spi_xfer,
+	},
+#endif
+};
+
+static struct fdt_spi_driver *driver;
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+	if (!driver)
+		return 0;
+	else if (!driver->cs_is_valid)
+		return 1;
+	else
+		return driver->cs_is_valid(bus, cs);
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+		unsigned int max_hz, unsigned int mode)
+{
+	if (!driver || !driver->setup_slave)
+		return NULL;
+
+	return driver->setup_slave(bus, cs, max_hz, mode);
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	if (driver && driver->free_slave)
+		return driver->free_slave(slave);
+}
+
+static int spi_init_driver(struct fdt_spi_driver *driver)
+{
+	int count;
+	int node_list[driver->max_ctrls];
+
+	count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi",
+					   driver->compat,
+					   node_list,
+					   driver->max_ctrls);
+	return driver->init(node_list, count);
+}
+
+void spi_init(void)
+{
+	int i;
+	int num_drivers = sizeof(fdt_spi_drivers) /
+		sizeof(struct fdt_spi_driver);
+	for (i = 0; i < num_drivers; i++) {
+		driver = &fdt_spi_drivers[i];
+		if (!spi_init_driver(driver))
+			break;
+	}
+	if (i == num_drivers)
+		driver = NULL;
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	if (!driver)
+		return 1;
+	if (!driver->claim_bus)
+		return 0;
+
+	return driver->claim_bus(slave);
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+	if (driver && driver->release_bus)
+		driver->release_bus(slave);
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+	if (driver && driver->cs_activate)
+		driver->cs_activate(slave);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+	if (driver && driver->cs_deactivate)
+		driver->cs_deactivate(slave);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+	     const void *data_out, void *data_in, unsigned long flags)
+{
+	if (!driver || !driver->xfer)
+		return -1;
+
+	return driver->xfer(slave, bitlen, data_out, data_in, flags);
+}
diff --git a/drivers/spi/tegra20_spi.c b/drivers/spi/tegra20_spi.c
index f3985f2..df481cb 100644
--- a/drivers/spi/tegra20_spi.c
+++ b/drivers/spi/tegra20_spi.c
@@ -76,7 +76,7 @@ static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
 	return container_of(slave, struct tegra_spi_slave, slave);
 }
 
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+int tegra20_spi_cs_is_valid(unsigned int bus, unsigned int cs)
 {
 	/* Tegra20 SPI-Flash - only 1 device ('bus/cs') */
 	if (bus != 0 || cs != 0)
@@ -85,8 +85,8 @@ int spi_cs_is_valid(unsigned int bus, unsigned int cs)
 		return 1;
 }
 
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-		unsigned int max_hz, unsigned int mode)
+struct spi_slave *tegra20_spi_setup_slave(unsigned int bus, unsigned int cs,
+				  unsigned int max_hz, unsigned int mode)
 {
 	struct tegra_spi_slave *spi;
 
@@ -126,25 +126,20 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 	return &spi->slave;
 }
 
-void spi_free_slave(struct spi_slave *slave)
+void tegra20_spi_free_slave(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
 
 	free(spi);
 }
 
-void spi_init(void)
+int tegra20_spi_init(int *node_list, int count)
 {
 	struct tegra_spi_ctrl *ctrl;
 	int i;
 	int node = 0;
-	int count;
-	int node_list[1];
+	int found = 0;
 
-	count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi",
-					   COMPAT_NVIDIA_TEGRA20_SFLASH,
-					   node_list,
-					   1);
 	for (i = 0; i < count; i++) {
 		ctrl = &spi_ctrls[i];
 		node = node_list[i];
@@ -168,13 +163,15 @@ void spi_init(void)
 			continue;
 		}
 		ctrl->valid = 1;
+		found = 1;
 
 		debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
 		      __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
 	}
+	return !found;
 }
 
-int spi_claim_bus(struct spi_slave *slave)
+int tegra20_spi_claim_bus(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
 	struct spi_regs *regs = spi->ctrl->regs;
@@ -188,7 +185,7 @@ int spi_claim_bus(struct spi_slave *slave)
 	reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \
 		SPI_STAT_RXF_UNR | SPI_STAT_TXF_OVF;
 	writel(reg, &regs->status);
-	debug("spi_init: STATUS = %08x\n", readl(&regs->status));
+	debug("%s: STATUS = %08x\n", __func__, readl(&regs->status));
 
 	/*
 	 * Use sw-controlled CS, so we can clock in data after ReadID, etc.
@@ -198,7 +195,7 @@ int spi_claim_bus(struct spi_slave *slave)
 		reg |= 1 << SPI_CMD_ACTIVE_SCLK_SHIFT;
 	clrsetbits_le32(&regs->command, SPI_CMD_ACTIVE_SCLK_MASK |
 		SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg);
-	debug("spi_init: COMMAND = %08x\n", readl(&regs->command));
+	debug("%s: COMMAND = %08x\n", __func__, readl(&regs->command));
 
 	/*
 	 * SPI pins on Tegra20 are muxed - change pinmux later due to UART
@@ -219,17 +216,7 @@ int spi_claim_bus(struct spi_slave *slave)
 	return 0;
 }
 
-void spi_release_bus(struct spi_slave *slave)
-{
-	/*
-	 * We can't release UART_DISABLE and set pinmux to UART4 here since
-	 * some code (e,g, spi_flash_probe) uses printf() while the SPI
-	 * bus is held. That is arguably bad, but it has the advantage of
-	 * already being in the source tree.
-	 */
-}
-
-void spi_cs_activate(struct spi_slave *slave)
+void tegra20_spi_cs_activate(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
 	struct spi_regs *regs = spi->ctrl->regs;
@@ -242,7 +229,7 @@ void spi_cs_activate(struct spi_slave *slave)
 	corrupt_delay();		/* Let UART settle */
 }
 
-void spi_cs_deactivate(struct spi_slave *slave)
+void tegra20_spi_cs_deactivate(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
 	struct spi_regs *regs = spi->ctrl->regs;
@@ -255,7 +242,7 @@ void spi_cs_deactivate(struct spi_slave *slave)
 	corrupt_delay();		/* Let SPI settle */
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 		const void *data_out, void *data_in, unsigned long flags)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
diff --git a/drivers/spi/tegra30_spi.c b/drivers/spi/tegra30_spi.c
index 8f3dc8f..e94848d 100644
--- a/drivers/spi/tegra30_spi.c
+++ b/drivers/spi/tegra30_spi.c
@@ -64,22 +64,22 @@ struct tegra_spi_slave {
 	struct tegra_spi_ctrl *ctrl;
 };
 
-static struct tegra_spi_ctrl spi_ctrls[CONFIG_TEGRA_SLINK_CTRLS];
+static struct tegra_spi_ctrl spi_ctrls[CONFIG_TEGRA30_SPI_CTRLS];
 
 static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
 {
 	return container_of(slave, struct tegra_spi_slave, slave);
 }
 
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+int tegra30_spi_cs_is_valid(unsigned int bus, unsigned int cs)
 {
-	if (bus >= CONFIG_TEGRA_SLINK_CTRLS || cs > 3 || !spi_ctrls[bus].valid)
+	if (bus >= CONFIG_TEGRA30_SPI_CTRLS || cs > 3 || !spi_ctrls[bus].valid)
 		return 0;
 	else
 		return 1;
 }
 
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+struct spi_slave *tegra30_spi_setup_slave(unsigned int bus, unsigned int cs,
 		unsigned int max_hz, unsigned int mode)
 {
 	struct tegra_spi_slave *spi;
@@ -123,25 +123,20 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 	return &spi->slave;
 }
 
-void spi_free_slave(struct spi_slave *slave)
+void tegra30_spi_free_slave(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
 
 	free(spi);
 }
 
-void spi_init(void)
+int tegra30_spi_init(int *node_list, int count)
 {
 	struct tegra_spi_ctrl *ctrl;
 	int i;
 	int node = 0;
-	int count;
-	int node_list[CONFIG_TEGRA_SLINK_CTRLS];
+	int found = 0;
 
-	count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi",
-					   COMPAT_NVIDIA_TEGRA20_SLINK,
-					   node_list,
-					   CONFIG_TEGRA_SLINK_CTRLS);
 	for (i = 0; i < count; i++) {
 		ctrl = &spi_ctrls[i];
 		node = node_list[i];
@@ -165,13 +160,15 @@ void spi_init(void)
 			continue;
 		}
 		ctrl->valid = 1;
+		found = 1;
 
 		debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
 		      __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
 	}
+	return !found;
 }
 
-int spi_claim_bus(struct spi_slave *slave)
+int tegra30_spi_claim_bus(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
 	struct spi_regs *regs = spi->ctrl->regs;
@@ -196,11 +193,7 @@ int spi_claim_bus(struct spi_slave *slave)
 	return 0;
 }
 
-void spi_release_bus(struct spi_slave *slave)
-{
-}
-
-void spi_cs_activate(struct spi_slave *slave)
+void tegra30_spi_cs_activate(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
 	struct spi_regs *regs = spi->ctrl->regs;
@@ -209,7 +202,7 @@ void spi_cs_activate(struct spi_slave *slave)
 	setbits_le32(&regs->command, SLINK_CMD_CS_VAL);
 }
 
-void spi_cs_deactivate(struct spi_slave *slave)
+void tegra30_spi_cs_deactivate(struct spi_slave *slave)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
 	struct spi_regs *regs = spi->ctrl->regs;
@@ -218,7 +211,7 @@ void spi_cs_deactivate(struct spi_slave *slave)
 	clrbits_le32(&regs->command, SLINK_CMD_CS_VAL);
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 		const void *data_out, void *data_in, unsigned long flags)
 {
 	struct tegra_spi_slave *spi = to_tegra_spi(slave);
diff --git a/include/configs/cardhu.h b/include/configs/cardhu.h
index e7274f8..247bbaa 100644
--- a/include/configs/cardhu.h
+++ b/include/configs/cardhu.h
@@ -51,7 +51,7 @@
 
 /* SPI */
 #define CONFIG_TEGRA30_SPI
-#define CONFIG_TEGRA_SLINK_CTRLS       6
+#define CONFIG_TEGRA30_SPI_CTRLS       6
 #define CONFIG_SPI_FLASH
 #define CONFIG_SPI_FLASH_WINBOND
 #define CONFIG_SF_DEFAULT_MODE         SPI_MODE_0
diff --git a/include/configs/tegra-common-post.h b/include/configs/tegra-common-post.h
index f2a70b1..9e8b407 100644
--- a/include/configs/tegra-common-post.h
+++ b/include/configs/tegra-common-post.h
@@ -150,6 +150,10 @@
 	MEM_LAYOUT_ENV_SETTINGS \
 	BOOTCMDS_COMMON
 
+#if defined(CONFIG_TEGRA20_SPI) || defined(CONFIG_TEGRA30_SPI)
+#define CONFIG_FDT_SPI
+#endif
+
 /* overrides for SPL build here */
 #ifdef CONFIG_SPL_BUILD
 
-- 
1.7.10.4

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

* [U-Boot] [PATCH 06/14] sf: winbond: add W25Q32DW
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
                   ` (4 preceding siblings ...)
  2013-02-13  3:23 ` [U-Boot] [PATCH 05/14] spi: add common fdt SPI driver interface Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  2013-02-13  3:23 ` [U-Boot] [PATCH 07/14] tegra114: dalmore: add SPI pinmux config Allen Martin
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Add support for Winbond W25Q32DW 32Mbit part

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 drivers/mtd/spi/winbond.c |    5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c
index f6aab3d..9156957 100644
--- a/drivers/mtd/spi/winbond.c
+++ b/drivers/mtd/spi/winbond.c
@@ -67,6 +67,11 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {
 		.nr_blocks		= 128,
 		.name			= "W25Q80",
 	},
+	{
+		.id			= 0x6016,
+		.nr_blocks		= 512,
+		.name			= "W25Q32DW",
+	},
 };
 
 struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
-- 
1.7.10.4

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

* [U-Boot] [PATCH 07/14] tegra114: dalmore: add SPI pinmux config
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
                   ` (5 preceding siblings ...)
  2013-02-13  3:23 ` [U-Boot] [PATCH 06/14] sf: winbond: add W25Q32DW Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  2013-02-13  3:23 ` [U-Boot] [PATCH 08/14] tegra114: fdt: add compatible string for tegra114 SPI ctrl Allen Martin
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Configure pinmux for SPI4 controller.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 board/nvidia/dalmore/pinmux-config-dalmore.h |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/board/nvidia/dalmore/pinmux-config-dalmore.h b/board/nvidia/dalmore/pinmux-config-dalmore.h
index 3dd47da..b337119 100644
--- a/board/nvidia/dalmore/pinmux-config-dalmore.h
+++ b/board/nvidia/dalmore/pinmux-config-dalmore.h
@@ -225,6 +225,12 @@ static struct pingroup_config tegra114_pinmux_common[] = {
 	DEFAULT_PINMUX(SPI2_SCK,	GMI,      NORMAL, NORMAL,   INPUT),
 	DEFAULT_PINMUX(GPIO_PBB4,       VGP4,     NORMAL, NORMAL,   INPUT),
 	DEFAULT_PINMUX(KB_ROW8,	        KBC,      UP,     NORMAL,   INPUT),
+
+	/* SPI */
+	DEFAULT_PINMUX(GMI_AD5,	        SPI4,     NORMAL, NORMAL,   OUTPUT),
+	DEFAULT_PINMUX(GMI_AD6,	        SPI4,     NORMAL, NORMAL,   OUTPUT),
+	DEFAULT_PINMUX(GMI_AD7,	        SPI4,     NORMAL, NORMAL,   INPUT),
+	DEFAULT_PINMUX(GMI_CS6_N,       SPI4,     NORMAL, NORMAL,   OUTPUT),
 };
 
 static struct pingroup_config unused_pins_lowpower[] = {
@@ -237,9 +243,6 @@ static struct pingroup_config unused_pins_lowpower[] = {
 	DEFAULT_PINMUX(GMI_AD2,	        NAND,     NORMAL, TRISTATE, INPUT),
 	DEFAULT_PINMUX(GMI_AD3,	        NAND,     NORMAL, TRISTATE, INPUT),
 	DEFAULT_PINMUX(GMI_AD4,	        NAND,     NORMAL, TRISTATE, INPUT),
-	DEFAULT_PINMUX(GMI_AD5,	        NAND,     NORMAL, TRISTATE, INPUT),
-	DEFAULT_PINMUX(GMI_AD6,	        NAND,     NORMAL, TRISTATE, INPUT),
-	DEFAULT_PINMUX(GMI_AD7,	        NAND,     NORMAL, TRISTATE, INPUT),
 	DEFAULT_PINMUX(GMI_AD9,	        PWM1,     NORMAL, TRISTATE, OUTPUT),
 	DEFAULT_PINMUX(GMI_AD11,	NAND,     NORMAL, TRISTATE, OUTPUT),
 	DEFAULT_PINMUX(GMI_AD13,	NAND,     UP,	  NORMAL,   INPUT),
-- 
1.7.10.4

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

* [U-Boot] [PATCH 08/14] tegra114: fdt: add compatible string for tegra114 SPI ctrl
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
                   ` (6 preceding siblings ...)
  2013-02-13  3:23 ` [U-Boot] [PATCH 07/14] tegra114: dalmore: add SPI pinmux config Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  2013-02-13 22:51   ` Stephen Warren
  2013-02-13  3:23 ` [U-Boot] [PATCH 09/14] tegra114: fdt: add CAR block Allen Martin
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Add "nvidia,tegra114-spi" to represent t114 SPI controller hardware.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 include/fdtdec.h |    1 +
 lib/fdtdec.c     |    1 +
 2 files changed, 2 insertions(+)

diff --git a/include/fdtdec.h b/include/fdtdec.h
index 77f244f..1b20f72 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -72,6 +72,7 @@ enum fdt_compat_id {
 	COMPAT_NVIDIA_TEGRA20_DC,	/* Tegra 2 Display controller */
 	COMPAT_NVIDIA_TEGRA20_SFLASH,	/* Tegra 2 SPI flash controller */
 	COMPAT_NVIDIA_TEGRA20_SLINK,	/* Tegra 2 SPI SLINK controller */
+	COMPAT_NVIDIA_TEGRA114_SPI,	/* Tegra 114 SPI controller */
 	COMPAT_SMSC_LAN9215,		/* SMSC 10/100 Ethernet LAN9215 */
 	COMPAT_SAMSUNG_EXYNOS5_SROMC,	/* Exynos5 SROMC */
 	COMPAT_SAMSUNG_S3C2440_I2C,	/* Exynos I2C Controller */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 3ae348d..c68d05b 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -47,6 +47,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"),
 	COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"),
 	COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"),
+	COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"),
 	COMPAT(SMSC_LAN9215, "smsc,lan9215"),
 	COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"),
 	COMPAT(SAMSUNG_S3C2440_I2C, "samsung,s3c2440-i2c"),
-- 
1.7.10.4

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

* [U-Boot] [PATCH 09/14] tegra114: fdt: add CAR block
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
                   ` (7 preceding siblings ...)
  2013-02-13  3:23 ` [U-Boot] [PATCH 08/14] tegra114: fdt: add compatible string for tegra114 SPI ctrl Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  2013-02-13 22:46   ` Stephen Warren
  2013-02-13  3:23 ` [U-Boot] [PATCH 10/14] tegra114: fdt: add apbdma block Allen Martin
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Add node for clock and reset controller hardware.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 arch/arm/dts/tegra114.dtsi |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi
index d06cd12..bd969aa 100644
--- a/arch/arm/dts/tegra114.dtsi
+++ b/arch/arm/dts/tegra114.dtsi
@@ -2,4 +2,10 @@
 
 / {
 	compatible = "nvidia,tegra114";
+
+	tegra_car: clock at 60006000 {
+		compatible = "nvidia,tegra114-car", "nvidia,tegra30-car", "nvidia,tegra20-car";
+		reg = <0x60006000 0x1000>;
+		#clock-cells = <1>;
+	};
 };
-- 
1.7.10.4

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

* [U-Boot] [PATCH 10/14] tegra114: fdt: add apbdma block
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
                   ` (8 preceding siblings ...)
  2013-02-13  3:23 ` [U-Boot] [PATCH 09/14] tegra114: fdt: add CAR block Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  2013-02-13 22:48   ` Stephen Warren
  2013-02-13  3:23 ` [U-Boot] [PATCH 11/14] tegra114: fdt: add SPI blocks Allen Martin
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Add node for apbdma controller hardware.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 arch/arm/dts/tegra114.dtsi |   37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi
index bd969aa..f8b4605 100644
--- a/arch/arm/dts/tegra114.dtsi
+++ b/arch/arm/dts/tegra114.dtsi
@@ -8,4 +8,41 @@
 		reg = <0x60006000 0x1000>;
 		#clock-cells = <1>;
 	};
+
+	apbdma: dma {
+		compatible = "nvidia,tegra114-apbdma", "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma";
+		reg = <0x6000a000 0x1400>;
+		interrupts = <0 104 0x04
+			      0 105 0x04
+			      0 106 0x04
+			      0 107 0x04
+			      0 108 0x04
+			      0 109 0x04
+			      0 110 0x04
+			      0 111 0x04
+			      0 112 0x04
+			      0 113 0x04
+			      0 114 0x04
+			      0 115 0x04
+			      0 116 0x04
+			      0 117 0x04
+			      0 118 0x04
+			      0 119 0x04
+			      0 128 0x04
+			      0 129 0x04
+			      0 130 0x04
+			      0 131 0x04
+			      0 132 0x04
+			      0 133 0x04
+			      0 134 0x04
+			      0 135 0x04
+			      0 136 0x04
+			      0 137 0x04
+			      0 138 0x04
+			      0 139 0x04
+			      0 140 0x04
+			      0 141 0x04
+			      0 142 0x04
+			      0 143 0x04>;
+	};
 };
-- 
1.7.10.4

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

* [U-Boot] [PATCH 11/14] tegra114: fdt: add SPI blocks
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
                   ` (9 preceding siblings ...)
  2013-02-13  3:23 ` [U-Boot] [PATCH 10/14] tegra114: fdt: add apbdma block Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  2013-02-13 22:52   ` Stephen Warren
  2013-02-13  3:23 ` [U-Boot] [PATCH 12/14] tegra114: dalmore: fdt: enable dalmore SPI controller Allen Martin
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Add nodes for t114 SPI controller hardware

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 arch/arm/dts/tegra114.dtsi |   72 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi
index f8b4605..a7bd3ca 100644
--- a/arch/arm/dts/tegra114.dtsi
+++ b/arch/arm/dts/tegra114.dtsi
@@ -45,4 +45,76 @@
 			      0 142 0x04
 			      0 143 0x04>;
 	};
+
+	spi at 7000d400 {
+		compatible = "nvidia,tegra114-spi";
+		reg = <0x7000d400 0x200>;
+		interrupts = <0 59 0x04>;
+		nvidia,dma-request-selector = <&apbdma 15>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC1, PLLP_OUT0 */
+		clocks = <&tegra_car 41>;
+	};
+
+	spi at 7000d600 {
+		compatible = "nvidia,tegra114-spi";
+		reg = <0x7000d600 0x200>;
+		interrupts = <0 82 0x04>;
+		nvidia,dma-request-selector = <&apbdma 16>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC2, PLLP_OUT0 */
+		clocks = <&tegra_car 44>;
+	};
+
+	spi at 7000d800 {
+		compatible = "nvidia,tegra114-spi";
+		reg = <0x7000d480 0x200>;
+		interrupts = <0 83 0x04>;
+		nvidia,dma-request-selector = <&apbdma 17>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC3, PLLP_OUT0 */
+		clocks = <&tegra_car 46>;
+	};
+
+	spi at 7000da00 {
+		compatible = "nvidia,tegra114-spi";
+		reg = <0x7000da00 0x200>;
+		interrupts = <0 93 0x04>;
+		nvidia,dma-request-selector = <&apbdma 18>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC4, PLLP_OUT0 */
+		clocks = <&tegra_car 68>;
+	};
+
+	spi at 7000dc00 {
+		compatible = "nvidia,tegra114-spi";
+		reg = <0x7000dc00 0x200>;
+		interrupts = <0 94 0x04>;
+		nvidia,dma-request-selector = <&apbdma 27>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC5, PLLP_OUT0 */
+		clocks = <&tegra_car 104>;
+	};
+
+	spi at 7000de00 {
+		compatible = "nvidia,tegra114-spi";
+		reg = <0x7000de00 0x200>;
+		interrupts = <0 79 0x04>;
+		nvidia,dma-request-selector = <&apbdma 28>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC6, PLLP_OUT0 */
+		clocks = <&tegra_car 105>;
+	};
 };
-- 
1.7.10.4

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

* [U-Boot] [PATCH 12/14] tegra114: dalmore: fdt: enable dalmore SPI controller
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
                   ` (10 preceding siblings ...)
  2013-02-13  3:23 ` [U-Boot] [PATCH 11/14] tegra114: fdt: add SPI blocks Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  2013-02-13  3:23 ` [U-Boot] [PATCH 13/14] tegra114: add SPI driver Allen Martin
  2013-02-13  3:23 ` [U-Boot] [PATCH 14/14] tegra114: dalmore: config: enable SPI Allen Martin
  13 siblings, 0 replies; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Dalmore has a SPI flash part attached to controller 4, so enable
controller 4 and set to 25MHz.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 board/nvidia/dts/tegra114-dalmore.dts |    5 +++++
 1 file changed, 5 insertions(+)

diff --git a/board/nvidia/dts/tegra114-dalmore.dts b/board/nvidia/dts/tegra114-dalmore.dts
index 7315577..af50aed 100644
--- a/board/nvidia/dts/tegra114-dalmore.dts
+++ b/board/nvidia/dts/tegra114-dalmore.dts
@@ -10,4 +10,9 @@
 		device_type = "memory";
 		reg = <0x80000000 0x80000000>;
 	};
+
+	spi at 7000da00 {
+		status = "okay";
+		spi-max-frequency = <25000000>;
+	};
 };
-- 
1.7.10.4

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

* [U-Boot] [PATCH 13/14] tegra114: add SPI driver
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
                   ` (11 preceding siblings ...)
  2013-02-13  3:23 ` [U-Boot] [PATCH 12/14] tegra114: dalmore: fdt: enable dalmore SPI controller Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  2013-02-13 22:59   ` Stephen Warren
  2013-02-13  3:23 ` [U-Boot] [PATCH 14/14] tegra114: dalmore: config: enable SPI Allen Martin
  13 siblings, 1 reply; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Add driver for tegra114 SPI controller.  This controller is not
compatible with either the tegra20 or tegra30 controllers, so it
requires a new driver.

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 arch/arm/include/asm/arch-tegra114/tegra114_spi.h |   91 ++++++
 drivers/spi/Makefile                              |    1 +
 drivers/spi/fdt_spi.c                             |   15 +
 drivers/spi/tegra114_spi.c                        |  355 +++++++++++++++++++++
 include/configs/tegra-common-post.h               |    2 +-
 5 files changed, 463 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/include/asm/arch-tegra114/tegra114_spi.h
 create mode 100644 drivers/spi/tegra114_spi.c

diff --git a/arch/arm/include/asm/arch-tegra114/tegra114_spi.h b/arch/arm/include/asm/arch-tegra114/tegra114_spi.h
new file mode 100644
index 0000000..bfbfa21
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra114/tegra114_spi.h
@@ -0,0 +1,91 @@
+/*
+ * NVIDIA Tegra SPI controller
+ *
+ * Copyright 2010-2013 NVIDIA Corporation
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _TEGRA114_SPI_H_
+#define _TEGRA114_SPI_H_
+
+#include <asm/types.h>
+
+/* COMMAND1 */
+#define SPI_CMD1_GO			(1 << 31)
+#define SPI_CMD1_M_S			(1 << 30)
+#define SPI_CMD1_MODE_MASK		0x3
+#define SPI_CMD1_MODE_SHIFT		28
+#define SPI_CMD1_CS_SEL_MASK		0x3
+#define SPI_CMD1_CS_SEL_SHIFT		26
+#define SPI_CMD1_CS_POL_INACTIVE3	(1 << 25)
+#define SPI_CMD1_CS_POL_INACTIVE2	(1 << 24)
+#define SPI_CMD1_CS_POL_INACTIVE1	(1 << 23)
+#define SPI_CMD1_CS_POL_INACTIVE0	(1 << 22)
+#define SPI_CMD1_CS_SW_HW		(1 << 21)
+#define SPI_CMD1_CS_SW_VAL		(1 << 20)
+#define SPI_CMD1_IDLE_SDA_MASK		0x3
+#define SPI_CMD1_IDLE_SDA_SHIFT		18
+#define SPI_CMD1_BIDIR			(1 << 17)
+#define SPI_CMD1_LSBI_FE		(1 << 16)
+#define SPI_CMD1_LSBY_FE		(1 << 15)
+#define SPI_CMD1_BOTH_EN_BIT		(1 << 14)
+#define SPI_CMD1_BOTH_EN_BYTE		(1 << 13)
+#define SPI_CMD1_RX_EN			(1 << 12)
+#define SPI_CMD1_TX_EN			(1 << 11)
+#define SPI_CMD1_PACKED			(1 << 5)
+#define SPI_CMD1_BIT_LEN_MASK		0x1F
+#define SPI_CMD1_BIT_LEN_SHIFT		0
+
+/* COMMAND2 */
+#define SPI_CMD2_TX_CLK_TAP_DELAY	(1 << 6)
+#define SPI_CMD2_TX_CLK_TAP_DELAY_MASK	(0x3F << 6)
+#define SPI_CMD2_RX_CLK_TAP_DELAY	(1 << 0)
+#define SPI_CMD2_RX_CLK_TAP_DELAY_MASK	(0x3F << 0)
+
+/* TRANSFER STATUS */
+#define SPI_XFER_STS_RDY		(1 << 30)
+
+/* FIFO STATUS */
+#define SPI_FIFO_STS_CS_INACTIVE	(1 << 31)
+#define SPI_FIFO_STS_FRAME_END		(1 << 30)
+#define SPI_FIFO_STS_RX_FIFO_FLUSH	(1 << 15)
+#define SPI_FIFO_STS_TX_FIFO_FLUSH	(1 << 14)
+#define SPI_FIFO_STS_ERR		(1 << 8)
+#define SPI_FIFO_STS_TX_FIFO_OVF	(1 << 7)
+#define SPI_FIFO_STS_TX_FIFO_UNR	(1 << 6)
+#define SPI_FIFO_STS_RX_FIFO_OVF	(1 << 5)
+#define SPI_FIFO_STS_RX_FIFO_UNR	(1 << 4)
+#define SPI_FIFO_STS_TX_FIFO_FULL	(1 << 3)
+#define SPI_FIFO_STS_TX_FIFO_EMPTY	(1 << 2)
+#define SPI_FIFO_STS_RX_FIFO_FULL	(1 << 1)
+#define SPI_FIFO_STS_RX_FIFO_EMPTY	(1 << 0)
+
+int tegra114_spi_init(int *node_list, int count);
+int tegra114_spi_cs_is_valid(unsigned int bus, unsigned int cs);
+struct spi_slave *tegra114_spi_setup_slave(unsigned int bus, unsigned int cs,
+				  unsigned int max_hz, unsigned int mode);
+void tegra114_spi_free_slave(struct spi_slave *slave);
+int tegra114_spi_claim_bus(struct spi_slave *slave);
+void tegra114_spi_cs_activate(struct spi_slave *slave);
+void tegra114_spi_cs_deactivate(struct spi_slave *slave);
+int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+		     const void *data_out, void *data_in, unsigned long flags);
+
+#endif	/* _TEGRA114_SPI_H_ */
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 5551d01..275b70f 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -48,6 +48,7 @@ COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o
 COBJS-$(CONFIG_FDT_SPI) += fdt_spi.o
 COBJS-$(CONFIG_TEGRA20_SPI) += tegra20_spi.o
 COBJS-$(CONFIG_TEGRA30_SPI) += tegra30_spi.o
+COBJS-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
 COBJS-$(CONFIG_XILINX_SPI) += xilinx_spi.o
 
 COBJS	:= $(COBJS-y)
diff --git a/drivers/spi/fdt_spi.c b/drivers/spi/fdt_spi.c
index 1a3937a..bddebaa 100644
--- a/drivers/spi/fdt_spi.c
+++ b/drivers/spi/fdt_spi.c
@@ -29,6 +29,7 @@
 #include <asm/arch-tegra/clk_rst.h>
 #include <asm/arch-tegra20/tegra20_spi.h>
 #include <asm/arch-tegra30/tegra30_spi.h>
+#include <asm/arch-tegra114/tegra114_spi.h>
 #include <spi.h>
 #include <fdtdec.h>
 
@@ -79,6 +80,20 @@ static struct fdt_spi_driver fdt_spi_drivers[] = {
 		.xfer		= tegra30_spi_xfer,
 	},
 #endif
+#ifdef CONFIG_TEGRA114_SPI
+	{
+		.compat		= COMPAT_NVIDIA_TEGRA114_SPI,
+		.max_ctrls	= CONFIG_TEGRA114_SPI_CTRLS,
+		.init		= tegra114_spi_init,
+		.claim_bus	= tegra114_spi_claim_bus,
+		.cs_is_valid	= tegra114_spi_cs_is_valid,
+		.setup_slave	= tegra114_spi_setup_slave,
+		.free_slave	= tegra114_spi_free_slave,
+		.cs_activate	= tegra114_spi_cs_activate,
+		.cs_deactivate	= tegra114_spi_cs_deactivate,
+		.xfer		= tegra114_spi_xfer,
+	},
+#endif
 };
 
 static struct fdt_spi_driver *driver;
diff --git a/drivers/spi/tegra114_spi.c b/drivers/spi/tegra114_spi.c
new file mode 100644
index 0000000..2f1891f
--- /dev/null
+++ b/drivers/spi/tegra114_spi.c
@@ -0,0 +1,355 @@
+/*
+ * NVIDIA Tegra SPI controller (T114 and later)
+ *
+ * Copyright (c) 2010-2013 NVIDIA Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/clock.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra114/tegra114_spi.h>
+#include <spi.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SPI_TIMEOUT		1000
+#define TEGRA_SPI_MAX_FREQ	52000000
+
+struct spi_regs {
+	u32 command1;	/* SPI_COMMAND1 register  0x000 */
+	u32 command2;	/* SPI_COMMAND2 register 0x004 */
+	u32 timing1;	/* SPI_CS_TIM1 register 0x008 */
+	u32 timing2;	/* SPI_CS_TIM2 register 0x00c */
+	u32 xfer_status;/* SPI_TRANS_STATUS register 0x010 */
+	u32 fifo_status;/* SPI_FIFO_STATUS register 0x014 */
+	u32 tx_data;	/* SPI_TX_DATA register 0x018 */
+	u32 rx_data;	/* SPI_RX_DATA register 0x01c */
+	u32 dma_ctl;	/* SPI_DMA_CTL register 0x020 */
+	u32 dma_blk;	/* SPI_DMA_BLK register 0x024 */
+	u32 rsvd[56];	/* 0x28 to 0x107 reserved */
+	u32 tx_fifo;	/* SPI_FIFO1 reg off 108h */
+	u32 rsvd2[31];	/* 0x10c to 0x187 reserved */
+	u32 rx_fifo;	/* SPI_FIFO2 reg off 188h */
+	u32 spare_ctl;	/* SPI_SPARE_CTRL register */
+};
+
+struct tegra_spi_ctrl {
+	struct spi_regs *regs;
+	unsigned int freq;
+	unsigned int mode;
+	int periph_id;
+	int valid;
+};
+
+struct tegra_spi_slave {
+	struct spi_slave slave;
+	struct tegra_spi_ctrl *ctrl;
+};
+
+static struct tegra_spi_ctrl spi_ctrls[CONFIG_TEGRA114_SPI_CTRLS];
+
+static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
+{
+	return container_of(slave, struct tegra_spi_slave, slave);
+}
+
+int tegra114_spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+	if (bus >= CONFIG_TEGRA114_SPI_CTRLS || cs > 3 || !spi_ctrls[bus].valid)
+		return 0;
+	else
+		return 1;
+}
+
+struct spi_slave *tegra114_spi_setup_slave(unsigned int bus, unsigned int cs,
+		unsigned int max_hz, unsigned int mode)
+{
+	struct tegra_spi_slave *spi;
+
+	debug("%s: bus: %u, cs: %u, max_hz: %u, mode: %u\n", __func__,
+		bus, cs, max_hz, mode);
+
+	if (!spi_cs_is_valid(bus, cs)) {
+		printf("SPI error: unsupported bus %d / chip select %d\n",
+		       bus, cs);
+		return NULL;
+	}
+
+	if (max_hz > TEGRA_SPI_MAX_FREQ) {
+		printf("SPI error: unsupported frequency %d Hz. Max frequency"
+			" is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ);
+		return NULL;
+	}
+
+	spi = malloc(sizeof(struct tegra_spi_slave));
+	if (!spi) {
+		printf("SPI error: malloc of SPI structure failed\n");
+		return NULL;
+	}
+	spi->slave.bus = bus;
+	spi->slave.cs = cs;
+	spi->ctrl = &spi_ctrls[bus];
+	if (!spi->ctrl) {
+		printf("SPI error: could not find controller for bus %d\n",
+		       bus);
+		return NULL;
+	}
+
+	if (max_hz < spi->ctrl->freq) {
+		debug("%s: limiting frequency from %u to %u\n", __func__,
+		      spi->ctrl->freq, max_hz);
+		spi->ctrl->freq = max_hz;
+	}
+	spi->ctrl->mode = mode;
+
+	return &spi->slave;
+}
+
+void tegra114_spi_free_slave(struct spi_slave *slave)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+
+	free(spi);
+}
+
+int tegra114_spi_init(int *node_list, int count)
+{
+	struct tegra_spi_ctrl *ctrl;
+	int i;
+	int node = 0;
+	int found = 0;
+
+	for (i = 0; i < count; i++) {
+		ctrl = &spi_ctrls[i];
+		node = node_list[i];
+
+		ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob,
+								 node, "reg");
+		if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) {
+			debug("%s: no spi register found\n", __func__);
+			continue;
+		}
+		ctrl->freq = fdtdec_get_int(gd->fdt_blob, node,
+					    "spi-max-frequency", 0);
+		if (!ctrl->freq) {
+			debug("%s: no spi max frequency found\n", __func__);
+			continue;
+		}
+
+		ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node);
+		if (ctrl->periph_id == PERIPH_ID_NONE) {
+			debug("%s: could not decode periph id\n", __func__);
+			continue;
+		}
+		ctrl->valid = 1;
+		found = 1;
+
+		debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
+		      __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
+	}
+
+	return !found;
+}
+
+int tegra114_spi_claim_bus(struct spi_slave *slave)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+	struct spi_regs *regs = spi->ctrl->regs;
+
+	/* Change SPI clock to correct frequency, PLLP_OUT0 source */
+	clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH,
+			       spi->ctrl->freq);
+
+	/* Clear stale status here */
+	setbits_le32(&regs->fifo_status,
+		     SPI_FIFO_STS_ERR		|
+		     SPI_FIFO_STS_TX_FIFO_OVF	|
+		     SPI_FIFO_STS_TX_FIFO_UNR	|
+		     SPI_FIFO_STS_RX_FIFO_OVF	|
+		     SPI_FIFO_STS_RX_FIFO_UNR	|
+		     SPI_FIFO_STS_TX_FIFO_FULL	|
+		     SPI_FIFO_STS_TX_FIFO_EMPTY	|
+		     SPI_FIFO_STS_RX_FIFO_FULL	|
+		     SPI_FIFO_STS_RX_FIFO_EMPTY);
+	debug("%s: FIFO STATUS = %08x\n", __func__, readl(&regs->fifo_status));
+
+	/* Set master mode and sw controlled CS */
+	setbits_le32(&regs->command1, SPI_CMD1_M_S | SPI_CMD1_CS_SW_HW |
+		     (spi->ctrl->mode << SPI_CMD1_MODE_SHIFT));
+	debug("%s: COMMAND1 = %08x\n", __func__, readl(&regs->command1));
+
+	return 0;
+}
+
+void tegra114_spi_cs_activate(struct spi_slave *slave)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+	struct spi_regs *regs = spi->ctrl->regs;
+
+	clrbits_le32(&regs->command1, SPI_CMD1_CS_SW_VAL);
+}
+
+void tegra114_spi_cs_deactivate(struct spi_slave *slave)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+	struct spi_regs *regs = spi->ctrl->regs;
+
+	setbits_le32(&regs->command1, SPI_CMD1_CS_SW_VAL);
+}
+
+int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+		const void *data_out, void *data_in, unsigned long flags)
+{
+	struct tegra_spi_slave *spi = to_tegra_spi(slave);
+	struct spi_regs *regs = spi->ctrl->regs;
+	u32 reg, tmpdout, tmpdin = 0;
+	const u8 *dout = data_out;
+	u8 *din = data_in;
+	int num_bytes;
+	int ret;
+
+	debug("%s: slave %u:%u dout %p din %p bitlen %u\n",
+	      __func__, slave->bus, slave->cs, dout, din, bitlen);
+	if (bitlen % 8)
+		return -1;
+	num_bytes = bitlen / 8;
+
+	ret = 0;
+
+	/* clear all error status bits */
+	reg = readl(&regs->fifo_status);
+	writel(reg, &regs->fifo_status);
+
+	/* clear ready bit */
+	setbits_le32(&regs->xfer_status, SPI_XFER_STS_RDY);
+
+	clrsetbits_le32(&regs->command1, SPI_CMD1_CS_SW_VAL,
+			SPI_CMD1_RX_EN | SPI_CMD1_TX_EN | SPI_CMD1_LSBY_FE |
+			(slave->cs << SPI_CMD1_CS_SEL_SHIFT));
+
+	/* set xfer size to 1 block (32 bits) */
+	writel(0, &regs->dma_blk);
+
+	if (flags & SPI_XFER_BEGIN)
+		spi_cs_activate(slave);
+
+	/* handle data in 32-bit chunks */
+	while (num_bytes > 0) {
+		int bytes;
+		int is_read = 0;
+		int tm, i;
+
+		tmpdout = 0;
+		bytes = (num_bytes > 4) ?  4 : num_bytes;
+
+		if (dout != NULL) {
+			for (i = 0; i < bytes; ++i)
+				tmpdout = (tmpdout << 8) | dout[i];
+			dout += bytes;
+		}
+
+		num_bytes -= bytes;
+
+		clrsetbits_le32(&regs->command1,
+				SPI_CMD1_BIT_LEN_MASK << SPI_CMD1_BIT_LEN_SHIFT,
+				(bytes * 8 - 1) << SPI_CMD1_BIT_LEN_SHIFT);
+		writel(tmpdout, &regs->tx_fifo);
+		setbits_le32(&regs->command1, SPI_CMD1_GO);
+
+		/*
+		 * Wait for SPI transmit FIFO to empty, or to time out.
+		 * The RX FIFO status will be read and cleared last
+		 */
+		for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) {
+			u32 fifo_status, xfer_status;
+
+			fifo_status = readl(&regs->fifo_status);
+
+			/* We can exit when we've had both RX and TX activity */
+			if (is_read &&
+			    (fifo_status & SPI_FIFO_STS_TX_FIFO_EMPTY))
+				break;
+
+			xfer_status = readl(&regs->xfer_status);
+			if (!(xfer_status & SPI_XFER_STS_RDY))
+				continue;
+
+			if (fifo_status & SPI_FIFO_STS_ERR) {
+				debug("%s: got a fifo error: ", __func__);
+				if (fifo_status & SPI_FIFO_STS_TX_FIFO_OVF)
+					debug("tx FIFO overflow ");
+				if (fifo_status & SPI_FIFO_STS_TX_FIFO_UNR)
+					debug("tx FIFO underrun ");
+				if (fifo_status & SPI_FIFO_STS_RX_FIFO_OVF)
+					debug("rx FIFO overflow ");
+				if (fifo_status & SPI_FIFO_STS_RX_FIFO_UNR)
+					debug("rx FIFO underrun ");
+				if (fifo_status & SPI_FIFO_STS_TX_FIFO_FULL)
+					debug("tx FIFO full ");
+				if (fifo_status & SPI_FIFO_STS_TX_FIFO_EMPTY)
+					debug("tx FIFO empty ");
+				if (fifo_status & SPI_FIFO_STS_RX_FIFO_FULL)
+					debug("rx FIFO full ");
+				if (fifo_status & SPI_FIFO_STS_RX_FIFO_EMPTY)
+					debug("rx FIFO empty ");
+				debug("\n");
+				break;
+			}
+
+			if (!(fifo_status & SPI_FIFO_STS_RX_FIFO_EMPTY)) {
+				tmpdin = readl(&regs->rx_fifo);
+				is_read = 1;
+
+				/* swap bytes read in */
+				if (din != NULL) {
+					for (i = bytes - 1; i >= 0; --i) {
+						din[i] = tmpdin & 0xff;
+						tmpdin >>= 8;
+					}
+					din += bytes;
+				}
+			}
+		}
+
+		if (tm >= SPI_TIMEOUT)
+			ret = tm;
+
+		/* clear ACK RDY, etc. bits */
+		writel(readl(&regs->fifo_status), &regs->fifo_status);
+	}
+
+	if (flags & SPI_XFER_END)
+		spi_cs_deactivate(slave);
+
+	debug("%s: transfer ended. Value=%08x, fifo_status = %08x\n",
+	      __func__, tmpdin, readl(&regs->fifo_status));
+
+	if (ret) {
+		printf("%s: timeout during SPI transfer, tm %d\n",
+		       __func__, ret);
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/include/configs/tegra-common-post.h b/include/configs/tegra-common-post.h
index 9e8b407..83cb4fc 100644
--- a/include/configs/tegra-common-post.h
+++ b/include/configs/tegra-common-post.h
@@ -150,7 +150,7 @@
 	MEM_LAYOUT_ENV_SETTINGS \
 	BOOTCMDS_COMMON
 
-#if defined(CONFIG_TEGRA20_SPI) || defined(CONFIG_TEGRA30_SPI)
+#if defined(CONFIG_TEGRA20_SPI) || defined(CONFIG_TEGRA30_SPI) || defined(CONFIG_TEGRA114_SPI)
 #define CONFIG_FDT_SPI
 #endif
 
-- 
1.7.10.4

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

* [U-Boot] [PATCH 14/14] tegra114: dalmore: config: enable SPI
  2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
                   ` (12 preceding siblings ...)
  2013-02-13  3:23 ` [U-Boot] [PATCH 13/14] tegra114: add SPI driver Allen Martin
@ 2013-02-13  3:23 ` Allen Martin
  13 siblings, 0 replies; 33+ messages in thread
From: Allen Martin @ 2013-02-13  3:23 UTC (permalink / raw)
  To: u-boot

Turn on SPI in dalmore config file

Signed-off-by: Allen Martin <amartin@nvidia.com>
---
 include/configs/dalmore.h |   11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/configs/dalmore.h b/include/configs/dalmore.h
index ce32c80..e7df60b 100644
--- a/include/configs/dalmore.h
+++ b/include/configs/dalmore.h
@@ -45,6 +45,17 @@
 
 #define MACH_TYPE_DALMORE	4304	/* not yet in mach-types.h */
 
+/* SPI */
+#define CONFIG_TEGRA114_SPI
+#define CONFIG_TEGRA114_SPI_CTRLS	6
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_WINBOND
+#define CONFIG_SF_DEFAULT_MODE         SPI_MODE_0
+#define CONFIG_SF_DEFAULT_SPEED        24000000
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_SF
+#define CONFIG_SPI_FLASH_SIZE          (4 << 20)
+
 #include "tegra-common-post.h"
 
 #endif /* __CONFIG_H */
-- 
1.7.10.4

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

* [U-Boot] [PATCH 01/14] tegra: spi: rename tegra SPI drivers
  2013-02-13  3:23 ` [U-Boot] [PATCH 01/14] tegra: spi: rename tegra SPI drivers Allen Martin
@ 2013-02-13 22:30   ` Stephen Warren
  2013-02-14 19:58     ` Allen Martin
  2013-02-13 22:36   ` Stephen Warren
  1 sibling, 1 reply; 33+ messages in thread
From: Stephen Warren @ 2013-02-13 22:30 UTC (permalink / raw)
  To: u-boot

On 02/12/2013 08:23 PM, Allen Martin wrote:
> Rename tegra SPI drivers to tegra20_spi and tegra30_spi in preparation
> for commonization and addition of tegra114_spi.

This isn't logically quite right. Both types (sflash, slink) of SPI
controller actually exist on Tegra20, so it isn't right to name them
after the different chips. It is true that only one is kept for Tegra30
(slink). As such, it might make sense to simply drop this patch.

>  arch/arm/include/asm/arch-tegra/tegra_slink.h   |   84 ------
>  arch/arm/include/asm/arch-tegra/tegra_spi.h     |   75 -----
>  arch/arm/include/asm/arch-tegra20/tegra20_spi.h |   75 +++++
>  arch/arm/include/asm/arch-tegra30/tegra30_spi.h |   84 ++++++
>  board/nvidia/common/board.c                     |    2 +-
>  board/nvidia/common/uart-spi-switch.c           |    2 +-
>  drivers/spi/Makefile                            |    4 +-
>  drivers/spi/tegra20_spi.c                       |  330 ++++++++++++++++++++++
>  drivers/spi/tegra30_spi.c                       |  343 +++++++++++++++++++++++
>  drivers/spi/tegra_slink.c                       |  343 -----------------------
>  drivers/spi/tegra_spi.c                         |  330 ----------------------
>  include/configs/cardhu.h                        |    2 +-
>  include/configs/trimslice.h                     |    2 +-
>  13 files changed, 838 insertions(+), 838 deletions(-)
>  delete mode 100644 arch/arm/include/asm/arch-tegra/tegra_slink.h
>  delete mode 100644 arch/arm/include/asm/arch-tegra/tegra_spi.h
>  create mode 100644 arch/arm/include/asm/arch-tegra20/tegra20_spi.h
>  create mode 100644 arch/arm/include/asm/arch-tegra30/tegra30_spi.h
>  create mode 100644 drivers/spi/tegra20_spi.c
>  create mode 100644 drivers/spi/tegra30_spi.c
>  delete mode 100644 drivers/spi/tegra_slink.c
>  delete mode 100644 drivers/spi/tegra_spi.c

"git format-patch -M" might have made this easier to spot the changes
during the renames, assuming there weren't too many edits to make it
worthwhile.

I didn't actually review the diffs, since I assume it was just a simple
rename.

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

* [U-Boot] [PATCH 03/14] tegra: spi: pull register structs out of headers
  2013-02-13  3:23 ` [U-Boot] [PATCH 03/14] tegra: spi: pull register structs out of headers Allen Martin
@ 2013-02-13 22:32   ` Stephen Warren
  2013-02-14 19:20     ` Allen Martin
  0 siblings, 1 reply; 33+ messages in thread
From: Stephen Warren @ 2013-02-13 22:32 UTC (permalink / raw)
  To: u-boot

On 02/12/2013 08:23 PM, Allen Martin wrote:
> Move register structs from headers into .c files and use common name.
> This is in preparation of making common fdt front end for SPI
> drivers.

Why not move all the register defines too?

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

* [U-Boot] [PATCH 01/14] tegra: spi: rename tegra SPI drivers
  2013-02-13  3:23 ` [U-Boot] [PATCH 01/14] tegra: spi: rename tegra SPI drivers Allen Martin
  2013-02-13 22:30   ` Stephen Warren
@ 2013-02-13 22:36   ` Stephen Warren
  2013-02-14 20:01     ` Allen Martin
  1 sibling, 1 reply; 33+ messages in thread
From: Stephen Warren @ 2013-02-13 22:36 UTC (permalink / raw)
  To: u-boot

On 02/12/2013 08:23 PM, Allen Martin wrote:
> Rename tegra SPI drivers to tegra20_spi and tegra30_spi in preparation
> for commonization and addition of tegra114_spi.

>  board/nvidia/common/uart-spi-switch.c           |    2 +-

I tend to think we should just rip out the UART/SPI switch cruft; it's
just not that useful.

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

* [U-Boot] [PATCH 05/14] spi: add common fdt SPI driver interface
  2013-02-13  3:23 ` [U-Boot] [PATCH 05/14] spi: add common fdt SPI driver interface Allen Martin
@ 2013-02-13 22:40   ` Stephen Warren
  2013-02-14 20:07     ` Allen Martin
  0 siblings, 1 reply; 33+ messages in thread
From: Stephen Warren @ 2013-02-13 22:40 UTC (permalink / raw)
  To: u-boot

On 02/12/2013 08:23 PM, Allen Martin wrote:
> Add a common interface to fdt based SPI drivers.  Each driver is
> represented by a table entry in fdt_spi_drivers[].  If there are
> multiple SPI drivers in the table, the first driver to return success
> from spi_init() will be registered as the SPI driver.

I don't think there should be a global concept of "the" SPI driver;
instances of both SPI blocks exist on Tegra20, so they should be able to
co-exist, using the SFLASH driver for 1 SPI port, and the SLINK driver
for the other 4 ports.

How does this patch interact with any SPI-related device manager work?

> +void spi_init(void)
> +{
> +	int i;
> +	int num_drivers = sizeof(fdt_spi_drivers) /
> +		sizeof(struct fdt_spi_driver);

U-Boot doesn't have an ARSIZE/ARRAY_SIZE macro?

> diff --git a/include/configs/cardhu.h b/include/configs/cardhu.h

>  /* SPI */
>  #define CONFIG_TEGRA30_SPI
> -#define CONFIG_TEGRA_SLINK_CTRLS       6
> +#define CONFIG_TEGRA30_SPI_CTRLS       6

Should that be in one of the other patches?

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

* [U-Boot] [PATCH 09/14] tegra114: fdt: add CAR block
  2013-02-13  3:23 ` [U-Boot] [PATCH 09/14] tegra114: fdt: add CAR block Allen Martin
@ 2013-02-13 22:46   ` Stephen Warren
  0 siblings, 0 replies; 33+ messages in thread
From: Stephen Warren @ 2013-02-13 22:46 UTC (permalink / raw)
  To: u-boot

On 02/12/2013 08:23 PM, Allen Martin wrote:
> Add node for clock and reset controller hardware.

> diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi

> +	tegra_car: clock at 60006000 {
> +		compatible = "nvidia,tegra114-car", "nvidia,tegra30-car", "nvidia,tegra20-car";

The Tegra114 CAR isn't 100% backwards-compatible with either the Tegra20
nor Tegra30 CAR, so shouldn't include those compatible values.

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

* [U-Boot] [PATCH 10/14] tegra114: fdt: add apbdma block
  2013-02-13  3:23 ` [U-Boot] [PATCH 10/14] tegra114: fdt: add apbdma block Allen Martin
@ 2013-02-13 22:48   ` Stephen Warren
  0 siblings, 0 replies; 33+ messages in thread
From: Stephen Warren @ 2013-02-13 22:48 UTC (permalink / raw)
  To: u-boot

On 02/12/2013 08:23 PM, Allen Martin wrote:
> Add node for apbdma controller hardware.

> diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi

> +	apbdma: dma {
> +		compatible = "nvidia,tegra114-apbdma", "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma";

Sam here; the HW isn't 100% backwards-compatible with any previous
generation, so only include the Tegra114 compatible value.

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

* [U-Boot] [PATCH 08/14] tegra114: fdt: add compatible string for tegra114 SPI ctrl
  2013-02-13  3:23 ` [U-Boot] [PATCH 08/14] tegra114: fdt: add compatible string for tegra114 SPI ctrl Allen Martin
@ 2013-02-13 22:51   ` Stephen Warren
  0 siblings, 0 replies; 33+ messages in thread
From: Stephen Warren @ 2013-02-13 22:51 UTC (permalink / raw)
  To: u-boot

On 02/12/2013 08:23 PM, Allen Martin wrote:
> Add "nvidia,tegra114-spi" to represent t114 SPI controller hardware.

> +	COMPAT_NVIDIA_TEGRA114_SPI,	/* Tegra 114 SPI controller */

Should probably be called TEGRA114_SLINK to match the actual value.

> +	COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"),

The value is nvidia,tegra114-slink.

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

* [U-Boot] [PATCH 11/14] tegra114: fdt: add SPI blocks
  2013-02-13  3:23 ` [U-Boot] [PATCH 11/14] tegra114: fdt: add SPI blocks Allen Martin
@ 2013-02-13 22:52   ` Stephen Warren
  0 siblings, 0 replies; 33+ messages in thread
From: Stephen Warren @ 2013-02-13 22:52 UTC (permalink / raw)
  To: u-boot

On 02/12/2013 08:23 PM, Allen Martin wrote:
> Add nodes for t114 SPI controller hardware

s/t114/Tegra114/. Similar in patch 8/14 subject.

> diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi

> +	spi at 7000d400 {
> +		compatible = "nvidia,tegra114-spi";
> +		reg = <0x7000d400 0x200>;
> +		interrupts = <0 59 0x04>;
> +		nvidia,dma-request-selector = <&apbdma 15>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		status = "disabled";
> +		/* PERIPH_ID_SBC1, PLLP_OUT0 */
> +		clocks = <&tegra_car 41>;
> +	};

The status property should be last to match the kernel's device tree.

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

* [U-Boot] [PATCH 13/14] tegra114: add SPI driver
  2013-02-13  3:23 ` [U-Boot] [PATCH 13/14] tegra114: add SPI driver Allen Martin
@ 2013-02-13 22:59   ` Stephen Warren
  2013-02-14 14:32     ` Simon Glass
  0 siblings, 1 reply; 33+ messages in thread
From: Stephen Warren @ 2013-02-13 22:59 UTC (permalink / raw)
  To: u-boot

On 02/12/2013 08:23 PM, Allen Martin wrote:
> Subject: tegra114: add SPI driver

This really touches the SPI sub-system more than Tegra, and the Tegra
subsystem is just (and all of) Tegra not Tegra114-specific, so I'd
re-title this:

spi: tegra: add Tegra114 SPI driver

similar s/tegra114:/tegra:/ in other patch subjects, many of which
probably should be "ARM: tegra: ...".

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

* [U-Boot] [PATCH 13/14] tegra114: add SPI driver
  2013-02-13 22:59   ` Stephen Warren
@ 2013-02-14 14:32     ` Simon Glass
  2013-02-14 21:49       ` Allen Martin
  0 siblings, 1 reply; 33+ messages in thread
From: Simon Glass @ 2013-02-14 14:32 UTC (permalink / raw)
  To: u-boot

Hi Allen,

On Wed, Feb 13, 2013 at 2:59 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 02/12/2013 08:23 PM, Allen Martin wrote:
>> Subject: tegra114: add SPI driver
>
> This really touches the SPI sub-system more than Tegra, and the Tegra
> subsystem is just (and all of) Tegra not Tegra114-specific, so I'd
> re-title this:
>
> spi: tegra: add Tegra114 SPI driver
>
> similar s/tegra114:/tegra:/ in other patch subjects, many of which
> probably should be "ARM: tegra: ...".

This driver seems to add a lot of duplication. What prevents using
common code? Is it the register layout, differences in algorithm or
something else?

Regards,
Simon

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

* [U-Boot] [PATCH 03/14] tegra: spi: pull register structs out of headers
  2013-02-13 22:32   ` Stephen Warren
@ 2013-02-14 19:20     ` Allen Martin
  0 siblings, 0 replies; 33+ messages in thread
From: Allen Martin @ 2013-02-14 19:20 UTC (permalink / raw)
  To: u-boot

On Wed, Feb 13, 2013 at 02:32:44PM -0800, Stephen Warren wrote:
> On 02/12/2013 08:23 PM, Allen Martin wrote:
> > Move register structs from headers into .c files and use common name.
> > This is in preparation of making common fdt front end for SPI
> > drivers.
> 
> Why not move all the register defines too?

Sure, makes sense.

-Allen
-- 
nvpublic

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

* [U-Boot] [PATCH 01/14] tegra: spi: rename tegra SPI drivers
  2013-02-13 22:30   ` Stephen Warren
@ 2013-02-14 19:58     ` Allen Martin
  2013-02-14 20:18       ` Stephen Warren
  0 siblings, 1 reply; 33+ messages in thread
From: Allen Martin @ 2013-02-14 19:58 UTC (permalink / raw)
  To: u-boot

On Wed, Feb 13, 2013 at 02:30:26PM -0800, Stephen Warren wrote:
> On 02/12/2013 08:23 PM, Allen Martin wrote:
> > Rename tegra SPI drivers to tegra20_spi and tegra30_spi in preparation
> > for commonization and addition of tegra114_spi.
> 
> This isn't logically quite right. Both types (sflash, slink) of SPI
> controller actually exist on Tegra20, so it isn't right to name them
> after the different chips. It is true that only one is kept for Tegra30
> (slink). As such, it might make sense to simply drop this patch.

Mostly my intention here was to try to make the SPI driver naming less
confusing and to make room for the "new" tegra114 SPI driver.  What do
you think of the following:

tegra_sflash: tegra20 sflash driver
tegra_slink: tegra20 and tegra30 slink driver
tegra_spi: tegra114 and later spi driver

> 
> >  arch/arm/include/asm/arch-tegra/tegra_slink.h   |   84 ------
> >  arch/arm/include/asm/arch-tegra/tegra_spi.h     |   75 -----
> >  arch/arm/include/asm/arch-tegra20/tegra20_spi.h |   75 +++++
> >  arch/arm/include/asm/arch-tegra30/tegra30_spi.h |   84 ++++++
> >  board/nvidia/common/board.c                     |    2 +-
> >  board/nvidia/common/uart-spi-switch.c           |    2 +-
> >  drivers/spi/Makefile                            |    4 +-
> >  drivers/spi/tegra20_spi.c                       |  330 ++++++++++++++++++++++
> >  drivers/spi/tegra30_spi.c                       |  343 +++++++++++++++++++++++
> >  drivers/spi/tegra_slink.c                       |  343 -----------------------
> >  drivers/spi/tegra_spi.c                         |  330 ----------------------
> >  include/configs/cardhu.h                        |    2 +-
> >  include/configs/trimslice.h                     |    2 +-
> >  13 files changed, 838 insertions(+), 838 deletions(-)
> >  delete mode 100644 arch/arm/include/asm/arch-tegra/tegra_slink.h
> >  delete mode 100644 arch/arm/include/asm/arch-tegra/tegra_spi.h
> >  create mode 100644 arch/arm/include/asm/arch-tegra20/tegra20_spi.h
> >  create mode 100644 arch/arm/include/asm/arch-tegra30/tegra30_spi.h
> >  create mode 100644 drivers/spi/tegra20_spi.c
> >  create mode 100644 drivers/spi/tegra30_spi.c
> >  delete mode 100644 drivers/spi/tegra_slink.c
> >  delete mode 100644 drivers/spi/tegra_spi.c
> 
> "git format-patch -M" might have made this easier to spot the changes
> during the renames, assuming there weren't too many edits to make it
> worthwhile.

Yes, sorry, I'll fix for next round.


> 
> I didn't actually review the diffs, since I assume it was just a simple
> rename.

-Allen
-- 
nvpublic

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

* [U-Boot] [PATCH 01/14] tegra: spi: rename tegra SPI drivers
  2013-02-13 22:36   ` Stephen Warren
@ 2013-02-14 20:01     ` Allen Martin
  0 siblings, 0 replies; 33+ messages in thread
From: Allen Martin @ 2013-02-14 20:01 UTC (permalink / raw)
  To: u-boot

On Wed, Feb 13, 2013 at 02:36:10PM -0800, Stephen Warren wrote:
> On 02/12/2013 08:23 PM, Allen Martin wrote:
> > Rename tegra SPI drivers to tegra20_spi and tegra30_spi in preparation
> > for commonization and addition of tegra114_spi.
> 
> >  board/nvidia/common/uart-spi-switch.c           |    2 +-
> 
> I tend to think we should just rip out the UART/SPI switch cruft; it's
> just not that useful.

Ok

-- 
nvpublic

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

* [U-Boot] [PATCH 05/14] spi: add common fdt SPI driver interface
  2013-02-13 22:40   ` Stephen Warren
@ 2013-02-14 20:07     ` Allen Martin
  2013-02-14 20:21       ` Stephen Warren
  0 siblings, 1 reply; 33+ messages in thread
From: Allen Martin @ 2013-02-14 20:07 UTC (permalink / raw)
  To: u-boot

On Wed, Feb 13, 2013 at 02:40:29PM -0800, Stephen Warren wrote:
> On 02/12/2013 08:23 PM, Allen Martin wrote:
> > Add a common interface to fdt based SPI drivers.  Each driver is
> > represented by a table entry in fdt_spi_drivers[].  If there are
> > multiple SPI drivers in the table, the first driver to return success
> > from spi_init() will be registered as the SPI driver.
> 
> I don't think there should be a global concept of "the" SPI driver;
> instances of both SPI blocks exist on Tegra20, so they should be able to
> co-exist, using the SFLASH driver for 1 SPI port, and the SLINK driver
> for the other 4 ports.

I agree, but that's probably beyond the scope of this series, as
that's a more global problem.  Other drivers call directly into the
SPI driver by use of well known function names, so that would need to
be abstracted to fix.

> 
> How does this patch interact with any SPI-related device manager work?

I'm not sure what device manager is in the context of u-boot.  Is that
the same as the unified driver model that's being documented in
doc/driver-model?  If so I think this fits in really well with that.
The "struct ops" described there is almost identical to the callbacks
I added in "struct fdt_spi_driver" 

> 
> > +void spi_init(void)
> > +{
> > +	int i;
> > +	int num_drivers = sizeof(fdt_spi_drivers) /
> > +		sizeof(struct fdt_spi_driver);
> 
> U-Boot doesn't have an ARSIZE/ARRAY_SIZE macro?

Will fix.

> 
> > diff --git a/include/configs/cardhu.h b/include/configs/cardhu.h
> 
> >  /* SPI */
> >  #define CONFIG_TEGRA30_SPI
> > -#define CONFIG_TEGRA_SLINK_CTRLS       6
> > +#define CONFIG_TEGRA30_SPI_CTRLS       6
> 
> Should that be in one of the other patches?

Yes, probably the renaming patch if we decide to keep it.

-- 
nvpublic

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

* [U-Boot] [PATCH 01/14] tegra: spi: rename tegra SPI drivers
  2013-02-14 19:58     ` Allen Martin
@ 2013-02-14 20:18       ` Stephen Warren
  0 siblings, 0 replies; 33+ messages in thread
From: Stephen Warren @ 2013-02-14 20:18 UTC (permalink / raw)
  To: u-boot

On 02/14/2013 12:58 PM, Allen Martin wrote:
> On Wed, Feb 13, 2013 at 02:30:26PM -0800, Stephen Warren wrote:
>> On 02/12/2013 08:23 PM, Allen Martin wrote:
>>> Rename tegra SPI drivers to tegra20_spi and tegra30_spi in preparation
>>> for commonization and addition of tegra114_spi.
>>
>> This isn't logically quite right. Both types (sflash, slink) of SPI
>> controller actually exist on Tegra20, so it isn't right to name them
>> after the different chips. It is true that only one is kept for Tegra30
>> (slink). As such, it might make sense to simply drop this patch.
> 
> Mostly my intention here was to try to make the SPI driver naming less
> confusing and to make room for the "new" tegra114 SPI driver.  What do
> you think of the following:
> 
> tegra_sflash: tegra20 sflash driver
> tegra_slink: tegra20 and tegra30 slink driver

I'd suggest naming those tegra20_*.

> tegra_spi: tegra114 and later spi driver

... and that tegra114_spi. That way, it's obvious when those IP blocks
were introduced, which will help people know which driver they care about.

Looking closer at the Tegra114 TRM, it looks like they did declare
"slink" a deprecated name, so the Tegra114 block really should be called
"SPI" as you have it. So, disregard my comments about the compatible
value; nvidia,tegra114-spi looks like the correct choice now.

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

* [U-Boot] [PATCH 05/14] spi: add common fdt SPI driver interface
  2013-02-14 20:07     ` Allen Martin
@ 2013-02-14 20:21       ` Stephen Warren
  2013-02-14 21:42         ` Allen Martin
  0 siblings, 1 reply; 33+ messages in thread
From: Stephen Warren @ 2013-02-14 20:21 UTC (permalink / raw)
  To: u-boot

On 02/14/2013 01:07 PM, Allen Martin wrote:
> On Wed, Feb 13, 2013 at 02:40:29PM -0800, Stephen Warren wrote:
>> On 02/12/2013 08:23 PM, Allen Martin wrote:
>>> Add a common interface to fdt based SPI drivers.  Each driver is
>>> represented by a table entry in fdt_spi_drivers[].  If there are
>>> multiple SPI drivers in the table, the first driver to return success
>>> from spi_init() will be registered as the SPI driver.
>>
>> I don't think there should be a global concept of "the" SPI driver;
>> instances of both SPI blocks exist on Tegra20, so they should be able to
>> co-exist, using the SFLASH driver for 1 SPI port, and the SLINK driver
>> for the other 4 ports.
> 
> I agree, but that's probably beyond the scope of this series, as
> that's a more global problem.  Other drivers call directly into the
> SPI driver by use of well known function names, so that would need to
> be abstracted to fix.

It should be simple to fix; you already have a table of all known
(DT-based) SPI drivers; simply iterate over all entries in the table
always, rather than stopping when you hit the first one. Also, don't
store /a/ pointer to the driver, but store a pointer per instance. I
think the modifications to your patch series to solve this shouldn't be
large at all.

>> How does this patch interact with any SPI-related device manager work?
> 
> I'm not sure what device manager is in the context of u-boot.  Is that
> the same as the unified driver model that's being documented in
> doc/driver-model?

Yes.

> If so I think this fits in really well with that.
> The "struct ops" described there is almost identical to the callbacks
> I added in "struct fdt_spi_driver" 

The code certainly looks like a move in the right direction. I was
thinking more along the lines of: Is anyone actively working on this
right now, so your patches will conflict.

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

* [U-Boot] [PATCH 05/14] spi: add common fdt SPI driver interface
  2013-02-14 20:21       ` Stephen Warren
@ 2013-02-14 21:42         ` Allen Martin
  0 siblings, 0 replies; 33+ messages in thread
From: Allen Martin @ 2013-02-14 21:42 UTC (permalink / raw)
  To: u-boot

On Thu, Feb 14, 2013 at 12:21:34PM -0800, Stephen Warren wrote:
> On 02/14/2013 01:07 PM, Allen Martin wrote:
> > On Wed, Feb 13, 2013 at 02:40:29PM -0800, Stephen Warren wrote:
> >> On 02/12/2013 08:23 PM, Allen Martin wrote:
> >>> Add a common interface to fdt based SPI drivers.  Each driver is
> >>> represented by a table entry in fdt_spi_drivers[].  If there are
> >>> multiple SPI drivers in the table, the first driver to return success
> >>> from spi_init() will be registered as the SPI driver.
> >>
> >> I don't think there should be a global concept of "the" SPI driver;
> >> instances of both SPI blocks exist on Tegra20, so they should be able to
> >> co-exist, using the SFLASH driver for 1 SPI port, and the SLINK driver
> >> for the other 4 ports.
> > 
> > I agree, but that's probably beyond the scope of this series, as
> > that's a more global problem.  Other drivers call directly into the
> > SPI driver by use of well known function names, so that would need to
> > be abstracted to fix.
> 
> It should be simple to fix; you already have a table of all known
> (DT-based) SPI drivers; simply iterate over all entries in the table
> always, rather than stopping when you hit the first one. Also, don't
> store /a/ pointer to the driver, but store a pointer per instance. I
> think the modifications to your patch series to solve this shouldn't be
> large at all.
> 

I don't think it will be that easy.  The different drivers would have
to coordinate on bus numbering, or there would have to be a new
"adapter number" addressing to differentiate the drivers, which would
be hard to do without impacting all the other non-fdt drivers as well.


> >> How does this patch interact with any SPI-related device manager work?
> > 
> > I'm not sure what device manager is in the context of u-boot.  Is that
> > the same as the unified driver model that's being documented in
> > doc/driver-model?
> 
> Yes.
> 
> > If so I think this fits in really well with that.
> > The "struct ops" described there is almost identical to the callbacks
> > I added in "struct fdt_spi_driver" 
> 
> The code certainly looks like a move in the right direction. I was
> thinking more along the lines of: Is anyone actively working on this
> right now, so your patches will conflict.

I haven't seen any, but I haven't been looking out for those patches
either, I'll look through the list archives and see if anyting turns
up. 

-Allen
-- 
nvpublic

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

* [U-Boot] [PATCH 13/14] tegra114: add SPI driver
  2013-02-14 14:32     ` Simon Glass
@ 2013-02-14 21:49       ` Allen Martin
  0 siblings, 0 replies; 33+ messages in thread
From: Allen Martin @ 2013-02-14 21:49 UTC (permalink / raw)
  To: u-boot

On Thu, Feb 14, 2013 at 06:32:06AM -0800, Simon Glass wrote:
> Hi Allen,
> 
> On Wed, Feb 13, 2013 at 2:59 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> > On 02/12/2013 08:23 PM, Allen Martin wrote:
> >> Subject: tegra114: add SPI driver
> >
> > This really touches the SPI sub-system more than Tegra, and the Tegra
> > subsystem is just (and all of) Tegra not Tegra114-specific, so I'd
> > re-title this:
> >
> > spi: tegra: add Tegra114 SPI driver
> >
> > similar s/tegra114:/tegra:/ in other patch subjects, many of which
> > probably should be "ARM: tegra: ...".
> 
> This driver seems to add a lot of duplication. What prevents using
> common code? Is it the register layout, differences in algorithm or
> something else?

Yes, unfortunately there really are three different SPI controller
hardware blocks.  There's "sflash" which is a tegra20 only block,
"slink" which is present in tegra20 and tegra30, and tegra114 has a
new SPI controller which is functionally equivalent to slink, but the
register interface is different.

The programming model is quite similar, but not exactly the same
between each.  For example, the same function may be one register
write on one chip and two or more register writes on another.  It
could be possible to hide some of those differences in macros or
inline functions, but I'm not sure if that's more or less messy.

-Allen
-- 
nvpublic

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

end of thread, other threads:[~2013-02-14 21:49 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-13  3:23 [U-Boot] [PATCH 00/14] tegra114 SPI driver Allen Martin
2013-02-13  3:23 ` [U-Boot] [PATCH 01/14] tegra: spi: rename tegra SPI drivers Allen Martin
2013-02-13 22:30   ` Stephen Warren
2013-02-14 19:58     ` Allen Martin
2013-02-14 20:18       ` Stephen Warren
2013-02-13 22:36   ` Stephen Warren
2013-02-14 20:01     ` Allen Martin
2013-02-13  3:23 ` [U-Boot] [PATCH 02/14] tegra: spi: remove non fdt support Allen Martin
2013-02-13  3:23 ` [U-Boot] [PATCH 03/14] tegra: spi: pull register structs out of headers Allen Martin
2013-02-13 22:32   ` Stephen Warren
2013-02-14 19:20     ` Allen Martin
2013-02-13  3:23 ` [U-Boot] [PATCH 04/14] tegra20: spi: move fdt probe to spi_init Allen Martin
2013-02-13  3:23 ` [U-Boot] [PATCH 05/14] spi: add common fdt SPI driver interface Allen Martin
2013-02-13 22:40   ` Stephen Warren
2013-02-14 20:07     ` Allen Martin
2013-02-14 20:21       ` Stephen Warren
2013-02-14 21:42         ` Allen Martin
2013-02-13  3:23 ` [U-Boot] [PATCH 06/14] sf: winbond: add W25Q32DW Allen Martin
2013-02-13  3:23 ` [U-Boot] [PATCH 07/14] tegra114: dalmore: add SPI pinmux config Allen Martin
2013-02-13  3:23 ` [U-Boot] [PATCH 08/14] tegra114: fdt: add compatible string for tegra114 SPI ctrl Allen Martin
2013-02-13 22:51   ` Stephen Warren
2013-02-13  3:23 ` [U-Boot] [PATCH 09/14] tegra114: fdt: add CAR block Allen Martin
2013-02-13 22:46   ` Stephen Warren
2013-02-13  3:23 ` [U-Boot] [PATCH 10/14] tegra114: fdt: add apbdma block Allen Martin
2013-02-13 22:48   ` Stephen Warren
2013-02-13  3:23 ` [U-Boot] [PATCH 11/14] tegra114: fdt: add SPI blocks Allen Martin
2013-02-13 22:52   ` Stephen Warren
2013-02-13  3:23 ` [U-Boot] [PATCH 12/14] tegra114: dalmore: fdt: enable dalmore SPI controller Allen Martin
2013-02-13  3:23 ` [U-Boot] [PATCH 13/14] tegra114: add SPI driver Allen Martin
2013-02-13 22:59   ` Stephen Warren
2013-02-14 14:32     ` Simon Glass
2013-02-14 21:49       ` Allen Martin
2013-02-13  3:23 ` [U-Boot] [PATCH 14/14] tegra114: dalmore: config: enable SPI Allen Martin

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.