From 3353228a04a004ec67073871f40cf58dc4e209aa Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Mon, 7 Sep 2015 21:01:38 +0200
Subject: [PATCH 4/8] spi/bcm63xx: add support for probing through devicetree

Add required binding support to probe through device tree.

Use the compatible instead of the resource size for identifiying the
block type, and allow reducing the number of cs lines through OF.

Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
 drivers/spi/spi-bcm63xx.c | 42 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 36 insertions(+), 6 deletions(-)

--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -26,6 +26,7 @@
 #include <linux/completion.h>
 #include <linux/err.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
 
 /* BCM 6338/6348 SPI core */
 #define SPI_6348_RSET_SIZE		64
@@ -484,21 +485,48 @@ static const struct platform_device_id b
 	},
 };
 
+static const struct of_device_id bcm63xx_spi_of_match[] = {
+	{ .compatible = "brcm,bcm6348-spi", .data = &bcm6348_spi_reg_offsets },
+	{ .compatible = "brcm,bcm6358-spi", .data = &bcm6358_spi_reg_offsets },
+	{ },
+};
+
 static int bcm63xx_spi_probe(struct platform_device *pdev)
 {
 	struct resource *r;
 	const unsigned long *bcm63xx_spireg;
 	struct device *dev = &pdev->dev;
-	int irq;
+	int irq, bus_num;
 	struct spi_master *master;
 	struct clk *clk;
 	struct bcm63xx_spi *bs;
 	int ret;
+	u32 num_cs = BCM63XX_SPI_MAX_CS;
 
-	if (!pdev->id_entry->driver_data)
-		return -EINVAL;
+	if (dev->of_node) {
+		const struct of_device_id *match;
 
-	bcm63xx_spireg = (const unsigned long *)pdev->id_entry->driver_data;
+		match = of_match_node(bcm63xx_spi_of_match, dev->of_node);
+		if (!match)
+			return -EINVAL;
+		bcm63xx_spireg = match->data;
+
+		of_property_read_u32(dev->of_node, "num-cs", &num_cs);
+		if (num_cs > BCM63XX_SPI_MAX_CS) {
+			dev_warn(dev, "unsupported number of cs (%i), reducing to 8\n",
+				 num_cs);
+			num_cs = BCM63XX_SPI_MAX_CS;
+		}
+
+		bus_num = -1;
+	} else if (pdev->id_entry->driver_data) {
+		const struct platform_device_id *match = pdev->id_entry;
+
+		bcm63xx_spireg = (const unsigned long *)match->driver_data;
+		bus_num = BCM63XX_SPI_BUS_NUM;
+	} else {
+		return -EINVAL;
+	}
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
@@ -543,8 +571,9 @@ static int bcm63xx_spi_probe(struct plat
 		goto out_err;
 	}
 
-	master->bus_num = BCM63XX_SPI_BUS_NUM;
-	master->num_chipselect = BCM63XX_SPI_MAX_CS;
+	master->dev.of_node = dev->of_node;
+	master->bus_num = bus_num;
+	master->num_chipselect = num_cs;
 	master->transfer_one_message = bcm63xx_spi_transfer_one;
 	master->mode_bits = MODEBITS;
 	master->bits_per_word_mask = SPI_BPW_MASK(8);
@@ -633,6 +662,7 @@ static struct platform_driver bcm63xx_sp
 	.driver = {
 		.name	= "bcm63xx-spi",
 		.pm	= &bcm63xx_spi_pm_ops,
+		.of_match_table = bcm63xx_spi_of_match,
 	},
 	.id_table	= bcm63xx_spi_dev_match,
 	.probe		= bcm63xx_spi_probe,
