From 5de6baef9b5d9e3a84e0c3752cfb7eaef2eb1a0f Mon Sep 17 00:00:00 2001
From: notro <notro@tronnes.org>
Date: Sun, 27 Jul 2014 20:12:58 +0200
Subject: [PATCH 052/114] spi: bcm2708: add device tree support

Add DT support to driver and add to .dtsi file.
Setup pins and spidev in .dts file.
SPI is disabled by default.

Signed-off-by: Noralf Tronnes <notro@tronnes.org>

BCM2708: don't register SPI controller when using DT

The device for the SPI controller is in the Device Tree.
Only register the device when not using DT.

Signed-off-by: Noralf Tronnes <notro@tronnes.org>

spi: bcm2835: make driver available on ARCH_BCM2708

Make this driver available on ARCH_BCM2708

Signed-off-by: Noralf Tronnes <notro@tronnes.org>

bcm2708: Remove the prohibition on mixing SPIDEV and DT
---
 arch/arm/boot/dts/bcm2708-rpi-b.dts | 32 ++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/bcm2708.dtsi      | 18 ++++++++++++++++++
 arch/arm/mach-bcm2708/bcm2708.c     | 19 ++++++++++++++++---
 drivers/spi/Kconfig                 |  2 +-
 drivers/spi/spi-bcm2708.c           |  8 ++++++++
 5 files changed, 75 insertions(+), 4 deletions(-)

--- a/arch/arm/boot/dts/bcm2708-rpi-b.dts
+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts
@@ -5,4 +5,36 @@
 / {
 	compatible = "brcm,bcm2708";
 	model = "Raspberry Pi";
+
+	aliases {
+		spi0 = &spi0;
+	};
+};
+
+&gpio {
+	spi0_pins: spi0_pins {
+		brcm,pins = <7 8 9 10 11>;
+		brcm,function = <4>; /* alt0 */
+	};
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_pins>;
+
+	spidev@0{
+		compatible = "spidev";
+		reg = <0>;	/* CE0 */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		spi-max-frequency = <500000>;
+	};
+
+	spidev@1{
+		compatible = "spidev";
+		reg = <1>;	/* CE1 */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		spi-max-frequency = <500000>;
+	};
 };
--- a/arch/arm/boot/dts/bcm2708.dtsi
+++ b/arch/arm/boot/dts/bcm2708.dtsi
@@ -38,11 +38,29 @@
 			interrupt-controller;
 			#interrupt-cells = <2>;
 		};
+
+		spi0: spi@7e204000 {
+			compatible = "brcm,bcm2708-spi";
+			reg = <0x7e204000 0x1000>;
+			interrupts = <2 22>;
+			clocks = <&clk_spi>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
 	};
 
 	clocks {
 		compatible = "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <0>;
+
+		clk_spi: clock@2 {
+			compatible = "fixed-clock";
+			reg = <2>;
+			#clock-cells = <0>;
+			clock-output-names = "spi";
+			clock-frequency = <250000000>;
+		};
 	};
 };
--- a/arch/arm/mach-bcm2708/bcm2708.c
+++ b/arch/arm/mach-bcm2708/bcm2708.c
@@ -486,6 +486,7 @@ static struct platform_device bcm2708_al
 	       },
 };
 
+#ifndef CONFIG_OF
 static struct resource bcm2708_spi_resources[] = {
 	{
 		.start = SPI0_BASE,
@@ -509,6 +510,7 @@ static struct platform_device bcm2708_sp
 		.dma_mask = &bcm2708_spi_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON)},
 };
+#endif
 
 #ifdef CONFIG_BCM2708_SPIDEV
 static struct spi_board_info bcm2708_spi_devices[] = {
@@ -670,6 +672,16 @@ int __init bcm_register_device(struct pl
 	return ret;
 }
 
+/*
+ * Use this macro for platform devices that are present in the Device Tree.
+ * This way the device is only added on non-DT builds.
+ */
+#ifdef CONFIG_OF
+#define bcm_register_device_dt(pdev)
+#else
+#define bcm_register_device_dt(pdev) bcm_register_device(pdev)
+#endif
+
 int calc_rsts(int partition)
 {
 	return PM_PASSWORD |
@@ -784,7 +796,7 @@ void __init bcm2708_init(void)
 	for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++)
 		bcm_register_device(&bcm2708_alsa_devices[i]);
 
-	bcm_register_device(&bcm2708_spi_device);
+	bcm_register_device_dt(&bcm2708_spi_device);
 	bcm_register_device(&bcm2708_bsc0_device);
 	bcm_register_device(&bcm2708_bsc1_device);
 
@@ -824,8 +836,9 @@ void __init bcm2708_init(void)
 	system_serial_low = serial;
 
 #ifdef CONFIG_BCM2708_SPIDEV
-	spi_register_board_info(bcm2708_spi_devices,
-			ARRAY_SIZE(bcm2708_spi_devices));
+	if (!use_dt)
+	    spi_register_board_info(bcm2708_spi_devices,
+				    ARRAY_SIZE(bcm2708_spi_devices));
 #endif
 }
 
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -77,7 +77,7 @@ config SPI_ATMEL
 
 config SPI_BCM2835
 	tristate "BCM2835 SPI controller"
-	depends on ARCH_BCM2835 || COMPILE_TEST
+	depends on ARCH_BCM2835 || ARCH_BCM2708 || COMPILE_TEST
 	help
 	  This selects a driver for the Broadcom BCM2835 SPI master.
 
--- a/drivers/spi/spi-bcm2708.c
+++ b/drivers/spi/spi-bcm2708.c
@@ -512,6 +512,7 @@ static int bcm2708_spi_probe(struct plat
 	master->setup = bcm2708_spi_setup;
 	master->transfer = bcm2708_spi_transfer;
 	master->cleanup = bcm2708_spi_cleanup;
+	master->dev.of_node = pdev->dev.of_node;
 	platform_set_drvdata(pdev, master);
 
 	bs = spi_master_get_devdata(master);
@@ -596,10 +597,17 @@ static int bcm2708_spi_remove(struct pla
 	return 0;
 }
 
+static const struct of_device_id bcm2708_spi_match[] = {
+	{ .compatible = "brcm,bcm2708-spi", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, bcm2708_spi_match);
+
 static struct platform_driver bcm2708_spi_driver = {
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = bcm2708_spi_match,
 	},
 	.probe		= bcm2708_spi_probe,
 	.remove		= bcm2708_spi_remove,