Skip to contentSkip to conversation

tegra: SPI drivers

PATCH Superseded Allen Martin 2 participants 18 messages Jan 11, 2013 – Jan 12, 2013

Subsystems (4)

v1 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

cover tegra: SPI drivers

This series updates the tegra20 SPI driver to add fdt support and adds a new tegra30 SPI driver. This series depends on the following patches:

Allen Martin:
fdt: fix dts preprocessor options
tegra: remove IRDA pinmux synonym

Testing was done on seaboard (tegra20) and cardhu (tegra30).

Allen Martin (7):
tegra: fdt: add apbdma node
tegra: spi: add fdt support to tegra SPI SFLASH driver
tegra30: add SBC1 to periph id mapping table
tegra30: fdt: add SPI SLINK nodes
tegra: add addresses of SPI SLINK controllers
tegra: add SPI SLINK driver
tegra: cardhu: config: enable SPI

 arch/arm/cpu/tegra30-common/clock.c           |    2 +-
 arch/arm/dts/tegra20.dtsi                     |   34 +++
 arch/arm/dts/tegra30.dtsi                     |  114 +++++++++
 arch/arm/include/asm/arch-tegra/tegra.h       |    6 +
 arch/arm/include/asm/arch-tegra/tegra_slink.h |   84 +++++++
 board/nvidia/common/board.c                   |    3 +-
 drivers/spi/Makefile                          |    1 +
 drivers/spi/tegra_slink.c                     |  333 +++++++++++++++++++++++++
 drivers/spi/tegra_spi.c                       |   42 +++-
 include/configs/cardhu.h                      |   11 +
 include/fdtdec.h                              |    2 +
 lib/fdtdec.c                                  |    2 +
 12 files changed, 631 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-tegra/tegra_slink.h
 create mode 100644 drivers/spi/tegra_slink.c
Signature · 1 line
1.7.10.4
#1 lore raw

PATCH 1/7 tegra: fdt: add apbdma node

Add apbdma node for tegra20 and tegra30, copied directly from tegra Linux dtsi files.

---
 arch/arm/dts/tegra20.dtsi |   21 +++++++++++++++++++++
 arch/arm/dts/tegra30.dtsi |   37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)
arch/arm/dts/tegra20.dtsi +21 -0
index 636ec2c..707975c 100644
@@ -20,6 +20,27 @@
 		};
 	};
 
+	apbdma: dma {
+		compatible = "nvidia,tegra20-apbdma";
+		reg = <0x6000a000 0x1200>;
+		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>;
+	};
+
 	intc: interrupt-controller at 50041000 {
 		compatible = "nvidia,tegra20-gic";
 		interrupt-controller;
arch/arm/dts/tegra30.dtsi +37 -0
index 664c397..d5f761e 100644
@@ -19,6 +19,43 @@
 		};
 	};
 
+	apbdma: dma {
+		compatible = "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>;
+	};
+
 	i2c at 7000c000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
Signature · 1 line
1.7.10.4
#2 lore raw

PATCH 1/7 tegra: fdt: add apbdma node

Quoted 8 lines · Allen Martin

Add apbdma node for tegra20 and tegra30, copied directly from tegra Linux dtsi files.

arch/arm/dts/tegra20.dtsi +3 -0
 
+	apbdma: dma {
+		compatible = "nvidia,tegra20-apbdma";
+		reg = <0x6000a000 0x1200>;

...

Quoted 1 line

intc: interrupt-controller at 50041000 {

Can the nodes be kept sorted by address?

#3 lore raw

PATCH 1/7 tegra: fdt: add apbdma node

Quoted 6 lines · Stephen Warren
Quoted 4 lines · Allen Martin

Add apbdma node for tegra20 and tegra30, copied directly from tegra Linux dtsi files.

arch/arm/dts/tegra20.dtsi +0 -0
Quoted 8 lines
Quoted 3 lines
arch/arm/dts/tegra20.dtsi +3 -0
+	apbdma: dma {
+		compatible = "nvidia,tegra20-apbdma";
+		reg = <0x6000a000 0x1200>;

...

Quoted 1 line

intc: interrupt-controller at 50041000 {

Can the nodes be kept sorted by address?

They're already unsorted. I'll add a new patch to sort them, then add this one on top.

-Allen

Signature · 1 line
nvpublic
#4 lore raw

PATCH 1/7 tegra: fdt: add apbdma node

Quoted 11 lines · Allen Martin
Quoted 10 lines · Stephen Warren
Quoted 8 lines · Allen Martin

Add apbdma node for tegra20 and tegra30, copied directly from tegra Linux dtsi files.

arch/arm/dts/tegra20.dtsi +3 -0
 
+	apbdma: dma {
+		compatible = "nvidia,tegra20-apbdma";
+		reg = <0x6000a000 0x1200>;

...

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

intc: interrupt-controller at 50041000 {

Can the nodes be kept sorted by address?

They're already unsorted. I'll add a new patch to sort them, then add this one on top.

Ah yes.

You can use the kernel as a reference, but FYI the order I have attempted to impose there is:

1) Any nodes that already exist in any /include/d file, in the order they appear in the /include/d file.

2) Any nodes with a reg property, in order of their address.

3) Any nodes without a reg property, alphabetically by node name.

If U-Boot follows the same rules, diff'ing the .dts files between U-Boot and the kernel should be easy.

#5 lore raw

PATCH 1/7 tegra: fdt: add apbdma node

Quoted 28 lines · Stephen Warren
Quoted 11 lines · Allen Martin
Quoted 10 lines · Stephen Warren
Quoted 8 lines · Allen Martin

Add apbdma node for tegra20 and tegra30, copied directly from tegra Linux dtsi files.

arch/arm/dts/tegra20.dtsi +3 -0
 
+	apbdma: dma {
+		compatible = "nvidia,tegra20-apbdma";
+		reg = <0x6000a000 0x1200>;

...

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

intc: interrupt-controller at 50041000 {

Can the nodes be kept sorted by address?

They're already unsorted. I'll add a new patch to sort them, then add this one on top.

Ah yes.

You can use the kernel as a reference, but FYI the order I have attempted to impose there is:

1) Any nodes that already exist in any /include/d file, in the order they appear in the /include/d file.

Quoted 6 lines

2) Any nodes with a reg property, in order of their address.

3) Any nodes without a reg property, alphabetically by node name.

If U-Boot follows the same rules, diff'ing the .dts files between U-Boot and the kernel should be easy.

Ok, thanks, I'll try to follow the same rules.

BTW: cache-controller and interrupt-controller are out of order in the kernel dtsi files.

-Allen

Signature · 1 line
nvpublic
#6 lore raw

PATCH 2/7 tegra: spi: add fdt support to tegra SPI SFLASH driver

In reply to Allen Martin

Add support for configuring tegra SPI driver from devicetree. Support is keyed off CONFIG_OF_CONTROL. Add entry in seaboard dts file for spi controller to describe seaboard spi.

---
 arch/arm/dts/tegra20.dtsi |   13 +++++++++++++
 drivers/spi/tegra_spi.c   |   42 +++++++++++++++++++++++++++++++++++++++++-
 include/fdtdec.h          |    1 +
 lib/fdtdec.c              |    1 +
 4 files changed, 56 insertions(+), 1 deletion(-)
arch/arm/dts/tegra20.dtsi +13 -0
index 707975c..8d4c7ec 100644
@@ -337,4 +337,17 @@
 		};
 	};
 
+	spi at 7000c380 {
+		compatible = "nvidia,tegra20-sflash";
+		reg = <0x7000c380 0x80>;
+		interrupts = <0 39 0x04>;
+		nvidia,dma-request-selector = <&apbdma 11>;
+		spi-max-frequency = <25000000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SPI1, PLLP_OUT0 */
+		clocks = <&tegra_car 43>;
+	};
+
 };
drivers/spi/tegra_spi.c +41 -1

67 lines not on this page · raw message

include/fdtdec.h +1 -0
index 70d0e97..1504336 100644
@@ -70,6 +70,7 @@ enum fdt_compat_id {
 	COMPAT_NVIDIA_TEGRA20_NAND,	/* Tegra2 NAND controller */
 	COMPAT_NVIDIA_TEGRA20_PWM,	/* Tegra 2 PWM controller */
 	COMPAT_NVIDIA_TEGRA20_DC,	/* Tegra 2 Display controller */
+	COMPAT_NVIDIA_TEGRA20_SFLASH,	/* Tegra 2 SPI flash controller */
 
 	COMPAT_COUNT,
 };
lib/fdtdec.c +1 -0
index 6dba438..6779278 100644
@@ -45,6 +45,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),
 	COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"),
 	COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"),
+	COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
Signature · 1 line
1.7.10.4
#7 lore raw

PATCH 2/7 tegra: spi: add fdt support to tegra SPI SFLASH driver

arch/arm/dts/tegra20.dtsi

Quoted 5 lines · Allen Martin

Add support for configuring tegra SPI driver from devicetree. Support is keyed off CONFIG_OF_CONTROL. Add entry in seaboard dts file for spi controller to describe seaboard spi.

arch/arm/dts/tegra20.dtsi +0 -0

.dtsi changes would typically be in a separate patch.

arch/arm/dts/tegra20.dtsi line 345

Quoted 7 lines
arch/arm/dts/tegra20.dtsi +6 -0
+	spi at 7000c380 {
+		compatible = "nvidia,tegra20-sflash";
+		reg = <0x7000c380 0x80>;
+		interrupts = <0 39 0x04>;
+		nvidia,dma-request-selector = <&apbdma 11>;
 
+		spi-max-frequency = <25000000>;

spi-max-frequency is board-specific; it should appear in the board .dts file not the SoC .dtsi file.

drivers/spi/tegra_spi.c struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, · line 96

Quoted 9 lines
drivers/spi/tegra_spi.c +3 -0
@@ -85,7 +91,41 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 	spi->slave.bus = bus;
 	spi->slave.cs = cs;
 	spi->freq = max_hz;
+#ifdef CONFIG_OF_CONTROL
+	int node = fdtdec_next_compatible(gd->fdt_blob, 0,
+					  COMPAT_NVIDIA_TEGRA20_SFLASH);

I assume this function gets called once, and hence the line above simply finds the first sflash node in the device tree. What if there's more than one node? There certainly can be more than one SPI controller, although perhaps the sflash controller only has one instance on any current chip and it's the other IP block ("SPI") that has multiple instances in practice.

#8 lore raw

PATCH 2/7 tegra: spi: add fdt support to tegra SPI SFLASH driver

Quoted 8 lines · Stephen Warren

arch/arm/dts/tegra20.dtsi

Quoted 5 lines · Allen Martin

Add support for configuring tegra SPI driver from devicetree. Support is keyed off CONFIG_OF_CONTROL. Add entry in seaboard dts file for spi controller to describe seaboard spi.

arch/arm/dts/tegra20.dtsi +0 -0

.dtsi changes would typically be in a separate patch.

ok

Quoted 11 lines

arch/arm/dts/tegra20.dtsi line 345

Quoted 8 lines
arch/arm/dts/tegra20.dtsi +6 -0
+	spi at 7000c380 {
+		compatible = "nvidia,tegra20-sflash";
+		reg = <0x7000c380 0x80>;
+		interrupts = <0 39 0x04>;
+		nvidia,dma-request-selector = <&apbdma 11>;
 
+		spi-max-frequency = <25000000>;

spi-max-frequency is board-specific; it should appear in the board .dts file not the SoC .dtsi file.

ok

Quoted 17 lines

drivers/spi/tegra_spi.c struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, · line 96

Quoted 10 lines
drivers/spi/tegra_spi.c +3 -0
@@ -85,7 +91,41 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 	spi->slave.bus = bus;
 	spi->slave.cs = cs;
 	spi->freq = max_hz;
+#ifdef CONFIG_OF_CONTROL
+	int node = fdtdec_next_compatible(gd->fdt_blob, 0,
+					  COMPAT_NVIDIA_TEGRA20_SFLASH);

I assume this function gets called once, and hence the line above simply finds the first sflash node in the device tree. What if there's more than one node? There certainly can be more than one SPI controller, although perhaps the sflash controller only has one instance on any current chip and it's the other IP block ("SPI") that has multiple instances in practice.

SFLASH only exists in tegra20, and there is only one. This driver can only handle a single controller anyway. I highly doubt there will ever be another chip with an SFLASH controller, never mind more than one, but if there is, this driver will need lots of modification to support multiple. All newer chips have SLINK controllers only.

This function can be called more than once, like if you type "sf probe" multiple times, but it passes in 0 as the initial node offset, so it will always return the first compatible node. So theoretically if there ever is a tegra with more than one SFLASH controller, with this patch the driver will operate like it did before this patch, it will support the first controller only.

-Allen

Signature · 1 line
nvpublic
#9 lore raw

PATCH 3/7 tegra30: add SBC1 to periph id mapping table

In reply to Allen Martin

SBC1 is SPI controller 1 on tegra30

---
 arch/arm/cpu/tegra30-common/clock.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/cpu/tegra30-common/clock.c +1 -1
index c67a2e1..db5ac1e 100644
@@ -318,7 +318,7 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
 
 	/* 40 */
 	NONE(KFUSE),
-	NONE(SBC1),	/* SBC1, 0x34, is this SPI1? */
+	PERIPHC_SBC1,
 	PERIPHC_NOR,
 	NONE(RESERVED43),
 	PERIPHC_SBC2,
Signature · 1 line
1.7.10.4
#10 lore raw

PATCH 4/7 tegra30: fdt: add SPI SLINK nodes

In reply to Allen Martin

Add tegra30 SPI SLINK nodes to fdt.

---
 arch/arm/dts/tegra30.dtsi |   77 +++++++++++++++++++++++++++++++++++++++++++++
 include/fdtdec.h          |    1 +
 lib/fdtdec.c              |    1 +
 3 files changed, 79 insertions(+)
arch/arm/dts/tegra30.dtsi +77 -0
index d5f761e..e58e112 100644
@@ -100,4 +100,81 @@
 		/* PERIPH_ID_I2C_DVC, CLK_M */
 		clocks = <&tegra_car 47>;
 	};
+	spi at 7000d400 {
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000d400 0x200>;
+		interrupts = <0 59 0x04>;
+		nvidia,dma-request-selector = <&apbdma 15>;
+		spi-max-frequency = <25000000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC1, PLLP_OUT0 */
+		clocks = <&tegra_car 41>;
+	};
+
+	spi at 7000d600 {
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000d600 0x200>;
+		interrupts = <0 82 0x04>;
+		nvidia,dma-request-selector = <&apbdma 16>;
+		spi-max-frequency = <25000000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC2, PLLP_OUT0 */
+		clocks = <&tegra_car 44>;
+	};
+
+	spi at 7000d800 {
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000d480 0x200>;
+		interrupts = <0 83 0x04>;
+		nvidia,dma-request-selector = <&apbdma 17>;
+		spi-max-frequency = <25000000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC3, PLLP_OUT0 */
+		clocks = <&tegra_car 46>;
+	};
+
+	spi at 7000da00 {
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000da00 0x200>;
+		interrupts = <0 93 0x04>;
+		nvidia,dma-request-selector = <&apbdma 18>;
+		spi-max-frequency = <25000000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC4, PLLP_OUT0 */
+		clocks = <&tegra_car 68>;
+	};
+
+	spi at 7000dc00 {
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000dc00 0x200>;
+		interrupts = <0 94 0x04>;
+		nvidia,dma-request-selector = <&apbdma 27>;
+		spi-max-frequency = <25000000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC5, PLLP_OUT0 */
+		clocks = <&tegra_car 104>;
+	};
+
+	spi at 7000de00 {
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000de00 0x200>;
+		interrupts = <0 79 0x04>;
+		nvidia,dma-request-selector = <&apbdma 28>;
+		spi-max-frequency = <25000000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC6, PLLP_OUT0 */
+		clocks = <&tegra_car 105>;
+	};
 };
include/fdtdec.h +1 -0
index 1504336..14aa308 100644
@@ -71,6 +71,7 @@ enum fdt_compat_id {
 	COMPAT_NVIDIA_TEGRA20_PWM,	/* Tegra 2 PWM controller */
 	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_COUNT,
 };
lib/fdtdec.c +1 -0
index 6779278..4fef428 100644
@@ -46,6 +46,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"),
 	COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"),
 	COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"),
+	COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
Signature · 1 line
1.7.10.4
#11 lore raw

PATCH 4/7 tegra30: fdt: add SPI SLINK nodes

arch/arm/dts/tegra30.dtsi line 103

Quoted 8 lines · Allen Martin

Add tegra30 SPI SLINK nodes to fdt.

arch/arm/dts/tegra30.dtsi +1 -0
 
 		/* PERIPH_ID_I2C_DVC, CLK_M */
 		clocks = <&tegra_car 47>;
 	};
+	spi at 7000d400 {

Blank line needed before the new node.

arch/arm/dts/tegra30.dtsi line 105

Quoted 2 lines
arch/arm/dts/tegra30.dtsi +2 -0
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000d400 0x200>;

I can't tell if the sort order is correct here; not enough context in the diff.

arch/arm/dts/tegra30.dtsi line 108

Quoted 3 lines
arch/arm/dts/tegra30.dtsi +3 -0
+		interrupts = <0 59 0x04>;
+		nvidia,dma-request-selector = <&apbdma 15>;
+		spi-max-frequency = <25000000>;

Same comment about that property being board-specific.

Quoted 6 lines
arch/arm/dts/tegra30.dtsi +6 -0
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC1, PLLP_OUT0 */
+		clocks = <&tegra_car 41>;
+	};
#12 lore raw

PATCH 4/7 tegra30: fdt: add SPI SLINK nodes

Quoted 11 lines · Stephen Warren

arch/arm/dts/tegra30.dtsi line 103

Quoted 8 lines · Allen Martin

Add tegra30 SPI SLINK nodes to fdt.

arch/arm/dts/tegra30.dtsi +1 -0
 
 		/* PERIPH_ID_I2C_DVC, CLK_M */
 		clocks = <&tegra_car 47>;
 	};
+	spi at 7000d400 {

Blank line needed before the new node.

ok

Quoted 6 lines

arch/arm/dts/tegra30.dtsi line 105

Quoted 3 lines
arch/arm/dts/tegra30.dtsi +2 -0
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000d400 0x200>;

I can't tell if the sort order is correct here; not enough context in the diff.

It's not, I'll fix.

Quoted 6 lines

arch/arm/dts/tegra30.dtsi line 108

Quoted 4 lines
arch/arm/dts/tegra30.dtsi +3 -0
+		interrupts = <0 59 0x04>;
+		nvidia,dma-request-selector = <&apbdma 15>;
+		spi-max-frequency = <25000000>;

Same comment about that property being board-specific.

ok

Quoted 8 lines

arch/arm/dts/tegra30.dtsi line 114

Quoted 7 lines
arch/arm/dts/tegra30.dtsi +6 -0
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		/* PERIPH_ID_SBC1, PLLP_OUT0 */
+		clocks = <&tegra_car 41>;
+	};

-Allen

Signature · 1 line
nvpublic
#13 lore raw

PATCH 5/7 tegra: add addresses of SPI SLINK controllers

In reply to Allen Martin

Add I/O addresses of SPI SLINK controllers 1-6

---
 arch/arm/include/asm/arch-tegra/tegra.h |    6 ++++++
 1 file changed, 6 insertions(+)
arch/arm/include/asm/arch-tegra/tegra.h +6 -0
index 67e6fd0..d2435c1 100644
@@ -40,6 +40,12 @@
 #define NV_PA_APB_UARTE_BASE	(NV_PA_APB_MISC_BASE + 0x6400)
 #define NV_PA_NAND_BASE		(NV_PA_APB_MISC_BASE + 0x8000)
 #define NV_PA_SPI_BASE		(NV_PA_APB_MISC_BASE + 0xC380)
+#define NV_PA_SLINK1_BASE	(NV_PA_APB_MISC_BASE + 0xD400)
+#define NV_PA_SLINK2_BASE	(NV_PA_APB_MISC_BASE + 0xD600)
+#define NV_PA_SLINK3_BASE	(NV_PA_APB_MISC_BASE + 0xD800)
+#define NV_PA_SLINK4_BASE	(NV_PA_APB_MISC_BASE + 0xDA00)
+#define NV_PA_SLINK5_BASE	(NV_PA_APB_MISC_BASE + 0xDC00)
+#define NV_PA_SLINK6_BASE	(NV_PA_APB_MISC_BASE + 0xDE00)
 #define TEGRA_DVC_BASE		(NV_PA_APB_MISC_BASE + 0xD000)
 #define NV_PA_PMC_BASE		(NV_PA_APB_MISC_BASE + 0xE400)
 #define NV_PA_EMC_BASE		(NV_PA_APB_MISC_BASE + 0xF400)
Signature · 1 line
1.7.10.4
#14 lore raw

PATCH 6/7 tegra: add SPI SLINK driver

In reply to Allen Martin

Add driver for tegra SPI "SLINK" style driver. This controller is similar to the tegra20 SPI "SFLASH" controller. The difference is that the SLINK controller is a genernal purpose SPI controller and the SFLASH controller is special purpose and can only talk to FLASH devices. In addition there are potentially many instances of an SLINK controller on tegra and only a single instance of SFLASH. Tegra20 is currently ths only version of tegra that instantiates an SFLASH controller.

This driver supports basic PIO mode of operation and is configurable (CONFIG_OF_CONTROL) to be driven off devicetree bindings. Up to 4 devices per controller may be attached, although typically only a single chip select line is exposed from tegra per controller so in reality this is usually limited to 1.

To enable this driver, use CONFIG_TEGRA_SLINK

---
 arch/arm/include/asm/arch-tegra/tegra_slink.h |   84 +++++++
 board/nvidia/common/board.c                   |    3 +-
 drivers/spi/Makefile                          |    1 +
 drivers/spi/tegra_slink.c                     |  333 +++++++++++++++++++++++++
 4 files changed, 420 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/include/asm/arch-tegra/tegra_slink.h
 create mode 100644 drivers/spi/tegra_slink.c
arch/arm/include/asm/arch-tegra/tegra_slink.h new file +84 -0
new file mode 100644
index 0000000..74804b5
@@ -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 _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_ */
board/nvidia/common/board.c +2 -1
index a4af539..63a7fcb 100644
@@ -131,10 +131,11 @@ int board_init(void)
 #ifdef CONFIG_SPI_UART_SWITCH
 	gpio_config_uart();
 #endif
-#ifdef CONFIG_TEGRA_SPI
+#if defined(CONFIG_TEGRA_SPI) || defined(CONFIG_TEGRA_SLINK)
 	pin_mux_spi();
 	spi_init();
 #endif
+
 #ifdef CONFIG_PWM_TEGRA
 	if (pwm_init(gd->fdt_blob))
 		debug("%s: Failed to init pwm\n", __func__);
drivers/spi/Makefile +1 -0
index 824d357..83abcbd 100644
@@ -46,6 +46,7 @@ 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_XILINX_SPI) += xilinx_spi.o
 
 COBJS	:= $(COBJS-y)
drivers/spi/tegra_slink.c new file +333 -0

333 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#15 lore raw

PATCH 6/7 tegra: add SPI SLINK driver

Quoted 18 lines · Allen Martin

Add driver for tegra SPI "SLINK" style driver. This controller is similar to the tegra20 SPI "SFLASH" controller. The difference is that the SLINK controller is a genernal purpose SPI controller and the SFLASH controller is special purpose and can only talk to FLASH devices. In addition there are potentially many instances of an SLINK controller on tegra and only a single instance of SFLASH. Tegra20 is currently ths only version of tegra that instantiates an SFLASH controller.

This driver supports basic PIO mode of operation and is configurable (CONFIG_OF_CONTROL) to be driven off devicetree bindings. Up to 4 devices per controller may be attached, although typically only a single chip select line is exposed from tegra per controller so in reality this is usually limited to 1.

To enable this driver, use CONFIG_TEGRA_SLINK

drivers/spi/tegra_slink.c line 123

Quoted 8 lines
drivers/spi/tegra_slink.c +7 -0
 
+void spi_init(void)
+{
+	int node = 0, i;
+	struct tegra_spi_ctrl *ctrl;
+	for (i = 0; i < CONFIG_TEGRA_SLINK_CTRLS; i++) {
+		ctrl = &spi_ctrls[i];
+#ifdef CONFIG_OF_CONTROL

Is this ever false for Tegra upstream? I don't think so.

drivers/spi/tegra_slink.c line 132

Quoted 9 lines
drivers/spi/tegra_slink.c +9 -0
+		node = fdtdec_next_compatible(gd->fdt_blob, node,
+					      COMPAT_NVIDIA_TEGRA20_SLINK);
+		if (!node)
+			break;
+		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__);
+			break;

Shouldn't most of the "break"s in this loop be "continue"s, so that any other nodes can be parsed? After all, this loop is trying to initialize all SLINK controllers in the DT right?

#16 lore raw

PATCH 6/7 tegra: add SPI SLINK driver

Quoted 20 lines · Stephen Warren
Quoted 18 lines · Allen Martin

Add driver for tegra SPI "SLINK" style driver. This controller is similar to the tegra20 SPI "SFLASH" controller. The difference is that the SLINK controller is a genernal purpose SPI controller and the SFLASH controller is special purpose and can only talk to FLASH devices. In addition there are potentially many instances of an SLINK controller on tegra and only a single instance of SFLASH. Tegra20 is currently ths only version of tegra that instantiates an SFLASH controller.

This driver supports basic PIO mode of operation and is configurable (CONFIG_OF_CONTROL) to be driven off devicetree bindings. Up to 4 devices per controller may be attached, although typically only a single chip select line is exposed from tegra per controller so in reality this is usually limited to 1.

To enable this driver, use CONFIG_TEGRA_SLINK

drivers/spi/tegra_slink.c +0 -0
Quoted 9 lines

drivers/spi/tegra_slink.c line 123

Quoted 7 lines
drivers/spi/tegra_slink.c +7 -0
+void spi_init(void)
+{
+	int node = 0, i;
+	struct tegra_spi_ctrl *ctrl;
+	for (i = 0; i < CONFIG_TEGRA_SLINK_CTRLS; i++) {
+		ctrl = &spi_ctrls[i];
+#ifdef CONFIG_OF_CONTROL

Is this ever false for Tegra upstream? I don't think so.

No, but I think it's worthwhile to keep it under #ifdef so this driver could be used from the SPL if the need ever comes up. I tested by forcing it off for this driver and it works.

Quoted 14 lines

drivers/spi/tegra_slink.c line 132

Quoted 10 lines
drivers/spi/tegra_slink.c +9 -0
+		node = fdtdec_next_compatible(gd->fdt_blob, node,
+					      COMPAT_NVIDIA_TEGRA20_SLINK);
+		if (!node)
+			break;
+		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__);
+			break;

Shouldn't most of the "break"s in this loop be "continue"s, so that any other nodes can be parsed? After all, this loop is trying to initialize all SLINK controllers in the DT right?

True, and looking at this code I think the driver is going to do something bad if any of the controllers are not fully specified and you go to use it later. I think the controller structure needs a "valid" flag.

-Allen

Signature · 1 line
nvpublic
#17 lore raw

PATCH 7/7 tegra: cardhu: config: enable SPI

In reply to Allen Martin

Turn on SPI in cardhu config file

---
 include/configs/cardhu.h |   11 +++++++++++
 1 file changed, 11 insertions(+)
include/configs/cardhu.h +11 -0
index aa725ba..1616b39 100644
@@ -49,6 +49,17 @@
 
 #define CONFIG_ENV_IS_NOWHERE
 
+/* SPI */
+#define CONFIG_TEGRA_SLINK
+#define CONFIG_TEGRA_SLINK_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 */
Signature · 1 line
1.7.10.4