All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Shiyan <shc_work@mail.ru>
To: linux-spi@vger.kernel.org
Cc: Mark Brown <broonie@kernel.org>,
	Alexander Shiyan <shc_work@mail.ru>,
	linux-arm-kernel@lists.infradead.org
Subject: [PATCH 1/2] spi: clps711x: Driver refactor
Date: Wed,  1 Jan 2014 10:09:28 +0400	[thread overview]
Message-ID: <1388556568-10973-1-git-send-email-shc_work@mail.ru> (raw)

This is a complex patch for refactoring CLPS711X SPI driver.
Major changes:
- Eliminate <mach/hardware.h> usage.
- Devicetree support.

Since we do not have any platform users of this driver,
non-DT support is removed. DT users will be introduced later
once DT support for this platform will be completed.

Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
---
 drivers/spi/Kconfig                        |   2 +-
 drivers/spi/spi-clps711x.c                 | 233 ++++++++++-------------------
 include/linux/platform_data/spi-clps711x.h |  21 ---
 3 files changed, 84 insertions(+), 172 deletions(-)
 delete mode 100644 include/linux/platform_data/spi-clps711x.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 81b96e5..54c7bb2a 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -150,7 +150,7 @@ config SPI_BUTTERFLY
 
 config SPI_CLPS711X
 	tristate "CLPS711X host SPI controller"
-	depends on ARCH_CLPS711X
+	depends on OF && (ARCH_CLPS711X || COMPILE_TEST)
 	help
 	  This enables dedicated general purpose SPI/Microwire1-compatible
 	  master mode interface (SSI1) for CLPS711X-based CPUs.
diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c
index 6f03d7e..9d8eb39 100644
--- a/drivers/spi/spi-clps711x.c
+++ b/drivers/spi/spi-clps711x.c
@@ -1,7 +1,7 @@
 /*
  *  CLPS711X SPI bus driver
  *
- *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *  Copyright (C) 2012-2014 Alexander Shiyan <shc_work@mail.ru>
  *
  * 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
@@ -9,113 +9,77 @@
  * (at your option) any later version.
  */
 
-#include <linux/io.h>
 #include <linux/clk.h>
-#include <linux/init.h>
-#include <linux/gpio.h>
 #include <linux/delay.h>
-#include <linux/module.h>
+#include <linux/gpio.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/clps711x.h>
 #include <linux/spi/spi.h>
-#include <linux/platform_data/spi-clps711x.h>
-
-#include <mach/hardware.h>
 
-#define DRIVER_NAME	"spi-clps711x"
+#define SYNCIO_FRMLEN(x)	(((x) & 0x1f) << 8)
+#define SYNCIO_SMCKEN		(1 << 13)
+#define SYNCIO_TXFRMEN		(1 << 14)
 
 struct spi_clps711x_data {
 	struct completion	done;
-
+	void __iomem		*syncio;
+	struct regmap		*syscon3;
 	struct clk		*spi_clk;
-	u32			max_speed_hz;
-
 	u8			*tx_buf;
 	u8			*rx_buf;
-	int			count;
+	unsigned int		bpw;
 	int			len;
-
-	int			chipselect[0];
 };
 
 static int spi_clps711x_setup(struct spi_device *spi)
 {
-	struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master);
+	if (!spi->controller_state) {
+		int ret;
 
-	/* We are expect that SPI-device is not selected */
-	gpio_direction_output(hw->chipselect[spi->chip_select],
-			      !(spi->mode & SPI_CS_HIGH));
+		ret = devm_gpio_request(&spi->master->dev, spi->cs_gpio, NULL);
+		if (ret)
+			return ret;
 
-	return 0;
-}
-
-static void spi_clps711x_setup_mode(struct spi_device *spi)
-{
-	/* Setup edge for transfer */
-	if (spi->mode & SPI_CPHA)
-		clps_writew(clps_readw(SYSCON3) | SYSCON3_ADCCKNSEN, SYSCON3);
-	else
-		clps_writew(clps_readw(SYSCON3) & ~SYSCON3_ADCCKNSEN, SYSCON3);
-}
-
-static int spi_clps711x_setup_xfer(struct spi_device *spi,
-				   struct spi_transfer *xfer)
-{
-	u32 speed = xfer->speed_hz ? : spi->max_speed_hz;
-	u8 bpw = xfer->bits_per_word;
-	struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master);
-
-	if (bpw != 8) {
-		dev_err(&spi->dev, "Unsupported master bus width %i\n", bpw);
-		return -EINVAL;
+		spi->controller_state = spi;
 	}
 
-	/* Setup SPI frequency divider */
-	if (!speed || (speed >= hw->max_speed_hz))
-		clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
-			    SYSCON1_ADCKSEL(3), SYSCON1);
-	else if (speed >= (hw->max_speed_hz / 2))
-		clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
-			    SYSCON1_ADCKSEL(2), SYSCON1);
-	else if (speed >= (hw->max_speed_hz / 8))
-		clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
-			    SYSCON1_ADCKSEL(1), SYSCON1);
-	else
-		clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
-			    SYSCON1_ADCKSEL(0), SYSCON1);
-
-	return 0;
+	return gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
 }
 
 static int spi_clps711x_transfer_one_message(struct spi_master *master,
 					     struct spi_message *msg)
 {
 	struct spi_clps711x_data *hw = spi_master_get_devdata(master);
+	struct spi_device *spi = msg->spi;
 	struct spi_transfer *xfer;
-	int status = 0, cs = hw->chipselect[msg->spi->chip_select];
-	u32 data;
 
-	spi_clps711x_setup_mode(msg->spi);
+	/* Setup mode for transfer */
+	regmap_update_bits(hw->syscon3, SYSCON_OFFSET, SYSCON3_ADCCKNSEN,
+			   (spi->mode & SPI_CPHA) ? SYSCON3_ADCCKNSEN : 0);
 
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-		if (spi_clps711x_setup_xfer(msg->spi, xfer)) {
-			status = -EINVAL;
-			goto out_xfr;
-		}
+		u8 data;
 
-		gpio_set_value(cs, !!(msg->spi->mode & SPI_CS_HIGH));
+		clk_set_rate(hw->spi_clk, xfer->speed_hz ? : spi->max_speed_hz);
+
+		gpio_set_value(spi->cs_gpio, !!(spi->mode & SPI_CS_HIGH));
 
 		reinit_completion(&hw->done);
 
-		hw->count = 0;
 		hw->len = xfer->len;
+		hw->bpw = xfer->bits_per_word ? : spi->bits_per_word;
 		hw->tx_buf = (u8 *)xfer->tx_buf;
 		hw->rx_buf = (u8 *)xfer->rx_buf;
 
 		/* Initiate transfer */
-		data = hw->tx_buf ? hw->tx_buf[hw->count] : 0;
-		clps_writel(data | SYNCIO_FRMLEN(8) | SYNCIO_TXFRMEN, SYNCIO);
-
+		data = hw->tx_buf ? *hw->tx_buf++ : 0;
+		writel(data | SYNCIO_FRMLEN(hw->bpw) | SYNCIO_TXFRMEN,
+		       hw->syncio);
 		wait_for_completion(&hw->done);
 
 		if (xfer->delay_usecs)
@@ -123,13 +87,13 @@ static int spi_clps711x_transfer_one_message(struct spi_master *master,
 
 		if (xfer->cs_change ||
 		    list_is_last(&xfer->transfer_list, &msg->transfers))
-			gpio_set_value(cs, !(msg->spi->mode & SPI_CS_HIGH));
+			gpio_set_value(spi->cs_gpio,
+				       !(spi->mode & SPI_CS_HIGH));
 
 		msg->actual_length += xfer->len;
 	}
 
-out_xfr:
-	msg->status = status;
+	msg->status = 0;
 	spi_finalize_current_message(master);
 
 	return 0;
@@ -138,19 +102,18 @@ out_xfr:
 static irqreturn_t spi_clps711x_isr(int irq, void *dev_id)
 {
 	struct spi_clps711x_data *hw = (struct spi_clps711x_data *)dev_id;
-	u32 data;
+	u8 data;
 
 	/* Handle RX */
-	data = clps_readb(SYNCIO);
+	data = readb(hw->syncio);
 	if (hw->rx_buf)
-		hw->rx_buf[hw->count] = (u8)data;
-
-	hw->count++;
+		*hw->rx_buf++ = data;
 
 	/* Handle TX */
-	if (hw->count < hw->len) {
-		data = hw->tx_buf ? hw->tx_buf[hw->count] : 0;
-		clps_writel(data | SYNCIO_FRMLEN(8) | SYNCIO_TXFRMEN, SYNCIO);
+	if (--hw->len > 0) {
+		data = hw->tx_buf ? *hw->tx_buf++ : 0;
+		writel(data | SYNCIO_FRMLEN(hw->bpw) | SYNCIO_TXFRMEN,
+		       hw->syncio);
 	} else
 		complete(&hw->done);
 
@@ -159,116 +122,86 @@ static irqreturn_t spi_clps711x_isr(int irq, void *dev_id)
 
 static int spi_clps711x_probe(struct platform_device *pdev)
 {
-	int i, ret;
-	struct spi_master *master;
+	struct device_node *np = pdev->dev.of_node;
 	struct spi_clps711x_data *hw;
-	struct spi_clps711x_pdata *pdata = dev_get_platdata(&pdev->dev);
+	struct spi_master *master;
+	struct resource *res;
+	int irq, ret;
 
-	if (!pdata) {
-		dev_err(&pdev->dev, "No platform data supplied\n");
-		return -EINVAL;
-	}
+	master = spi_alloc_master(&pdev->dev, sizeof(*hw));
+	if (!master)
+		return -ENOMEM;
 
-	if (pdata->num_chipselect < 1) {
-		dev_err(&pdev->dev, "At least one CS must be defined\n");
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
 		return -EINVAL;
-	}
 
-	master = spi_alloc_master(&pdev->dev,
-				  sizeof(struct spi_clps711x_data) +
-				  sizeof(int) * pdata->num_chipselect);
-	if (!master) {
-		dev_err(&pdev->dev, "SPI allocating memory error\n");
-		return -ENOMEM;
+	hw = spi_master_get_devdata(master);
+
+	hw->spi_clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(hw->spi_clk)) {
+		ret = PTR_ERR(hw->spi_clk);
+		goto err_out;
 	}
 
-	master->bus_num = pdev->id;
+	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8);
+	master->bus_num = -1;
+	master->dev.of_node = np;
 	master->mode_bits = SPI_CPHA | SPI_CS_HIGH;
-	master->bits_per_word_mask = SPI_BPW_MASK(8);
-	master->num_chipselect = pdata->num_chipselect;
 	master->setup = spi_clps711x_setup;
 	master->transfer_one_message = spi_clps711x_transfer_one_message;
 
-	hw = spi_master_get_devdata(master);
-
-	for (i = 0; i < master->num_chipselect; i++) {
-		hw->chipselect[i] = pdata->chipselect[i];
-		if (!gpio_is_valid(hw->chipselect[i])) {
-			dev_err(&pdev->dev, "Invalid CS GPIO %i\n", i);
-			ret = -EINVAL;
-			goto err_out;
-		}
-		if (gpio_request(hw->chipselect[i], DRIVER_NAME)) {
-			dev_err(&pdev->dev, "Can't get CS GPIO %i\n", i);
-			ret = -EINVAL;
-			goto err_out;
-		}
+	hw->syscon3 = syscon_regmap_lookup_by_phandle(np, "syscon");
+	if (IS_ERR(hw->syscon3)) {
+		ret = PTR_ERR(hw->syscon3);
+		goto err_out;
 	}
 
-	hw->spi_clk = devm_clk_get(&pdev->dev, "spi");
-	if (IS_ERR(hw->spi_clk)) {
-		dev_err(&pdev->dev, "Can't get clocks\n");
-		ret = PTR_ERR(hw->spi_clk);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hw->syncio = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(hw->syncio)) {
+		ret = PTR_ERR(hw->syncio);
 		goto err_out;
 	}
-	hw->max_speed_hz = clk_get_rate(hw->spi_clk);
 
 	init_completion(&hw->done);
-	platform_set_drvdata(pdev, master);
 
 	/* Disable extended mode due hardware problems */
-	clps_writew(clps_readw(SYSCON3) & ~SYSCON3_ADCCON, SYSCON3);
+	ret = regmap_update_bits(hw->syscon3, SYSCON_OFFSET, SYSCON3_ADCCON, 0);
+	if (ret)
+		goto err_out;
 
 	/* Clear possible pending interrupt */
-	clps_readl(SYNCIO);
+	readl(hw->syncio);
 
-	ret = devm_request_irq(&pdev->dev, IRQ_SSEOTI, spi_clps711x_isr, 0,
+	ret = devm_request_irq(&pdev->dev, irq, spi_clps711x_isr, 0,
 			       dev_name(&pdev->dev), hw);
-	if (ret) {
-		dev_err(&pdev->dev, "Can't request IRQ\n");
+	if (ret)
 		goto err_out;
-	}
 
 	ret = devm_spi_register_master(&pdev->dev, master);
-	if (!ret) {
-		dev_info(&pdev->dev,
-			 "SPI bus driver initialized. Master clock %u Hz\n",
-			 hw->max_speed_hz);
+	if (!ret)
 		return 0;
-	}
-
-	dev_err(&pdev->dev, "Failed to register master\n");
 
 err_out:
-	while (--i >= 0)
-		if (gpio_is_valid(hw->chipselect[i]))
-			gpio_free(hw->chipselect[i]);
-
 	spi_master_put(master);
 
 	return ret;
 }
 
-static int spi_clps711x_remove(struct platform_device *pdev)
-{
-	int i;
-	struct spi_master *master = platform_get_drvdata(pdev);
-	struct spi_clps711x_data *hw = spi_master_get_devdata(master);
-
-	for (i = 0; i < master->num_chipselect; i++)
-		if (gpio_is_valid(hw->chipselect[i]))
-			gpio_free(hw->chipselect[i]);
-
-	return 0;
-}
+static const struct of_device_id clps711x_spi_dt_ids[] = {
+	{ .compatible = "cirrus,clps711x-spi", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, clps711x_spi_dt_ids);
 
 static struct platform_driver clps711x_spi_driver = {
 	.driver	= {
-		.name	= DRIVER_NAME,
-		.owner	= THIS_MODULE,
+		.name		= "clps711x-spi",
+		.owner		= THIS_MODULE,
+		.of_match_table	= clps711x_spi_dt_ids,
 	},
 	.probe	= spi_clps711x_probe,
-	.remove	= spi_clps711x_remove,
 };
 module_platform_driver(clps711x_spi_driver);
 
diff --git a/include/linux/platform_data/spi-clps711x.h b/include/linux/platform_data/spi-clps711x.h
deleted file mode 100644
index 301956e..0000000
--- a/include/linux/platform_data/spi-clps711x.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- *  CLPS711X SPI bus driver definitions
- *
- *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
- *
- * 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.
- */
-
-#ifndef ____LINUX_PLATFORM_DATA_SPI_CLPS711X_H
-#define ____LINUX_PLATFORM_DATA_SPI_CLPS711X_H
-
-/* Board specific platform_data */
-struct spi_clps711x_pdata {
-	int *chipselect;	/* Array of GPIO-numbers */
-	int num_chipselect;	/* Total count of GPIOs */
-};
-
-#endif
-- 
1.8.3.2

WARNING: multiple messages have this Message-ID (diff)
From: shc_work@mail.ru (Alexander Shiyan)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 1/2] spi: clps711x: Driver refactor
Date: Wed,  1 Jan 2014 10:09:28 +0400	[thread overview]
Message-ID: <1388556568-10973-1-git-send-email-shc_work@mail.ru> (raw)

This is a complex patch for refactoring CLPS711X SPI driver.
Major changes:
- Eliminate <mach/hardware.h> usage.
- Devicetree support.

Since we do not have any platform users of this driver,
non-DT support is removed. DT users will be introduced later
once DT support for this platform will be completed.

Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
---
 drivers/spi/Kconfig                        |   2 +-
 drivers/spi/spi-clps711x.c                 | 233 ++++++++++-------------------
 include/linux/platform_data/spi-clps711x.h |  21 ---
 3 files changed, 84 insertions(+), 172 deletions(-)
 delete mode 100644 include/linux/platform_data/spi-clps711x.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 81b96e5..54c7bb2a 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -150,7 +150,7 @@ config SPI_BUTTERFLY
 
 config SPI_CLPS711X
 	tristate "CLPS711X host SPI controller"
-	depends on ARCH_CLPS711X
+	depends on OF && (ARCH_CLPS711X || COMPILE_TEST)
 	help
 	  This enables dedicated general purpose SPI/Microwire1-compatible
 	  master mode interface (SSI1) for CLPS711X-based CPUs.
diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c
index 6f03d7e..9d8eb39 100644
--- a/drivers/spi/spi-clps711x.c
+++ b/drivers/spi/spi-clps711x.c
@@ -1,7 +1,7 @@
 /*
  *  CLPS711X SPI bus driver
  *
- *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *  Copyright (C) 2012-2014 Alexander Shiyan <shc_work@mail.ru>
  *
  * 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
@@ -9,113 +9,77 @@
  * (at your option) any later version.
  */
 
-#include <linux/io.h>
 #include <linux/clk.h>
-#include <linux/init.h>
-#include <linux/gpio.h>
 #include <linux/delay.h>
-#include <linux/module.h>
+#include <linux/gpio.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/clps711x.h>
 #include <linux/spi/spi.h>
-#include <linux/platform_data/spi-clps711x.h>
-
-#include <mach/hardware.h>
 
-#define DRIVER_NAME	"spi-clps711x"
+#define SYNCIO_FRMLEN(x)	(((x) & 0x1f) << 8)
+#define SYNCIO_SMCKEN		(1 << 13)
+#define SYNCIO_TXFRMEN		(1 << 14)
 
 struct spi_clps711x_data {
 	struct completion	done;
-
+	void __iomem		*syncio;
+	struct regmap		*syscon3;
 	struct clk		*spi_clk;
-	u32			max_speed_hz;
-
 	u8			*tx_buf;
 	u8			*rx_buf;
-	int			count;
+	unsigned int		bpw;
 	int			len;
-
-	int			chipselect[0];
 };
 
 static int spi_clps711x_setup(struct spi_device *spi)
 {
-	struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master);
+	if (!spi->controller_state) {
+		int ret;
 
-	/* We are expect that SPI-device is not selected */
-	gpio_direction_output(hw->chipselect[spi->chip_select],
-			      !(spi->mode & SPI_CS_HIGH));
+		ret = devm_gpio_request(&spi->master->dev, spi->cs_gpio, NULL);
+		if (ret)
+			return ret;
 
-	return 0;
-}
-
-static void spi_clps711x_setup_mode(struct spi_device *spi)
-{
-	/* Setup edge for transfer */
-	if (spi->mode & SPI_CPHA)
-		clps_writew(clps_readw(SYSCON3) | SYSCON3_ADCCKNSEN, SYSCON3);
-	else
-		clps_writew(clps_readw(SYSCON3) & ~SYSCON3_ADCCKNSEN, SYSCON3);
-}
-
-static int spi_clps711x_setup_xfer(struct spi_device *spi,
-				   struct spi_transfer *xfer)
-{
-	u32 speed = xfer->speed_hz ? : spi->max_speed_hz;
-	u8 bpw = xfer->bits_per_word;
-	struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master);
-
-	if (bpw != 8) {
-		dev_err(&spi->dev, "Unsupported master bus width %i\n", bpw);
-		return -EINVAL;
+		spi->controller_state = spi;
 	}
 
-	/* Setup SPI frequency divider */
-	if (!speed || (speed >= hw->max_speed_hz))
-		clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
-			    SYSCON1_ADCKSEL(3), SYSCON1);
-	else if (speed >= (hw->max_speed_hz / 2))
-		clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
-			    SYSCON1_ADCKSEL(2), SYSCON1);
-	else if (speed >= (hw->max_speed_hz / 8))
-		clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
-			    SYSCON1_ADCKSEL(1), SYSCON1);
-	else
-		clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
-			    SYSCON1_ADCKSEL(0), SYSCON1);
-
-	return 0;
+	return gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
 }
 
 static int spi_clps711x_transfer_one_message(struct spi_master *master,
 					     struct spi_message *msg)
 {
 	struct spi_clps711x_data *hw = spi_master_get_devdata(master);
+	struct spi_device *spi = msg->spi;
 	struct spi_transfer *xfer;
-	int status = 0, cs = hw->chipselect[msg->spi->chip_select];
-	u32 data;
 
-	spi_clps711x_setup_mode(msg->spi);
+	/* Setup mode for transfer */
+	regmap_update_bits(hw->syscon3, SYSCON_OFFSET, SYSCON3_ADCCKNSEN,
+			   (spi->mode & SPI_CPHA) ? SYSCON3_ADCCKNSEN : 0);
 
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-		if (spi_clps711x_setup_xfer(msg->spi, xfer)) {
-			status = -EINVAL;
-			goto out_xfr;
-		}
+		u8 data;
 
-		gpio_set_value(cs, !!(msg->spi->mode & SPI_CS_HIGH));
+		clk_set_rate(hw->spi_clk, xfer->speed_hz ? : spi->max_speed_hz);
+
+		gpio_set_value(spi->cs_gpio, !!(spi->mode & SPI_CS_HIGH));
 
 		reinit_completion(&hw->done);
 
-		hw->count = 0;
 		hw->len = xfer->len;
+		hw->bpw = xfer->bits_per_word ? : spi->bits_per_word;
 		hw->tx_buf = (u8 *)xfer->tx_buf;
 		hw->rx_buf = (u8 *)xfer->rx_buf;
 
 		/* Initiate transfer */
-		data = hw->tx_buf ? hw->tx_buf[hw->count] : 0;
-		clps_writel(data | SYNCIO_FRMLEN(8) | SYNCIO_TXFRMEN, SYNCIO);
-
+		data = hw->tx_buf ? *hw->tx_buf++ : 0;
+		writel(data | SYNCIO_FRMLEN(hw->bpw) | SYNCIO_TXFRMEN,
+		       hw->syncio);
 		wait_for_completion(&hw->done);
 
 		if (xfer->delay_usecs)
@@ -123,13 +87,13 @@ static int spi_clps711x_transfer_one_message(struct spi_master *master,
 
 		if (xfer->cs_change ||
 		    list_is_last(&xfer->transfer_list, &msg->transfers))
-			gpio_set_value(cs, !(msg->spi->mode & SPI_CS_HIGH));
+			gpio_set_value(spi->cs_gpio,
+				       !(spi->mode & SPI_CS_HIGH));
 
 		msg->actual_length += xfer->len;
 	}
 
-out_xfr:
-	msg->status = status;
+	msg->status = 0;
 	spi_finalize_current_message(master);
 
 	return 0;
@@ -138,19 +102,18 @@ out_xfr:
 static irqreturn_t spi_clps711x_isr(int irq, void *dev_id)
 {
 	struct spi_clps711x_data *hw = (struct spi_clps711x_data *)dev_id;
-	u32 data;
+	u8 data;
 
 	/* Handle RX */
-	data = clps_readb(SYNCIO);
+	data = readb(hw->syncio);
 	if (hw->rx_buf)
-		hw->rx_buf[hw->count] = (u8)data;
-
-	hw->count++;
+		*hw->rx_buf++ = data;
 
 	/* Handle TX */
-	if (hw->count < hw->len) {
-		data = hw->tx_buf ? hw->tx_buf[hw->count] : 0;
-		clps_writel(data | SYNCIO_FRMLEN(8) | SYNCIO_TXFRMEN, SYNCIO);
+	if (--hw->len > 0) {
+		data = hw->tx_buf ? *hw->tx_buf++ : 0;
+		writel(data | SYNCIO_FRMLEN(hw->bpw) | SYNCIO_TXFRMEN,
+		       hw->syncio);
 	} else
 		complete(&hw->done);
 
@@ -159,116 +122,86 @@ static irqreturn_t spi_clps711x_isr(int irq, void *dev_id)
 
 static int spi_clps711x_probe(struct platform_device *pdev)
 {
-	int i, ret;
-	struct spi_master *master;
+	struct device_node *np = pdev->dev.of_node;
 	struct spi_clps711x_data *hw;
-	struct spi_clps711x_pdata *pdata = dev_get_platdata(&pdev->dev);
+	struct spi_master *master;
+	struct resource *res;
+	int irq, ret;
 
-	if (!pdata) {
-		dev_err(&pdev->dev, "No platform data supplied\n");
-		return -EINVAL;
-	}
+	master = spi_alloc_master(&pdev->dev, sizeof(*hw));
+	if (!master)
+		return -ENOMEM;
 
-	if (pdata->num_chipselect < 1) {
-		dev_err(&pdev->dev, "At least one CS must be defined\n");
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
 		return -EINVAL;
-	}
 
-	master = spi_alloc_master(&pdev->dev,
-				  sizeof(struct spi_clps711x_data) +
-				  sizeof(int) * pdata->num_chipselect);
-	if (!master) {
-		dev_err(&pdev->dev, "SPI allocating memory error\n");
-		return -ENOMEM;
+	hw = spi_master_get_devdata(master);
+
+	hw->spi_clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(hw->spi_clk)) {
+		ret = PTR_ERR(hw->spi_clk);
+		goto err_out;
 	}
 
-	master->bus_num = pdev->id;
+	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8);
+	master->bus_num = -1;
+	master->dev.of_node = np;
 	master->mode_bits = SPI_CPHA | SPI_CS_HIGH;
-	master->bits_per_word_mask = SPI_BPW_MASK(8);
-	master->num_chipselect = pdata->num_chipselect;
 	master->setup = spi_clps711x_setup;
 	master->transfer_one_message = spi_clps711x_transfer_one_message;
 
-	hw = spi_master_get_devdata(master);
-
-	for (i = 0; i < master->num_chipselect; i++) {
-		hw->chipselect[i] = pdata->chipselect[i];
-		if (!gpio_is_valid(hw->chipselect[i])) {
-			dev_err(&pdev->dev, "Invalid CS GPIO %i\n", i);
-			ret = -EINVAL;
-			goto err_out;
-		}
-		if (gpio_request(hw->chipselect[i], DRIVER_NAME)) {
-			dev_err(&pdev->dev, "Can't get CS GPIO %i\n", i);
-			ret = -EINVAL;
-			goto err_out;
-		}
+	hw->syscon3 = syscon_regmap_lookup_by_phandle(np, "syscon");
+	if (IS_ERR(hw->syscon3)) {
+		ret = PTR_ERR(hw->syscon3);
+		goto err_out;
 	}
 
-	hw->spi_clk = devm_clk_get(&pdev->dev, "spi");
-	if (IS_ERR(hw->spi_clk)) {
-		dev_err(&pdev->dev, "Can't get clocks\n");
-		ret = PTR_ERR(hw->spi_clk);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hw->syncio = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(hw->syncio)) {
+		ret = PTR_ERR(hw->syncio);
 		goto err_out;
 	}
-	hw->max_speed_hz = clk_get_rate(hw->spi_clk);
 
 	init_completion(&hw->done);
-	platform_set_drvdata(pdev, master);
 
 	/* Disable extended mode due hardware problems */
-	clps_writew(clps_readw(SYSCON3) & ~SYSCON3_ADCCON, SYSCON3);
+	ret = regmap_update_bits(hw->syscon3, SYSCON_OFFSET, SYSCON3_ADCCON, 0);
+	if (ret)
+		goto err_out;
 
 	/* Clear possible pending interrupt */
-	clps_readl(SYNCIO);
+	readl(hw->syncio);
 
-	ret = devm_request_irq(&pdev->dev, IRQ_SSEOTI, spi_clps711x_isr, 0,
+	ret = devm_request_irq(&pdev->dev, irq, spi_clps711x_isr, 0,
 			       dev_name(&pdev->dev), hw);
-	if (ret) {
-		dev_err(&pdev->dev, "Can't request IRQ\n");
+	if (ret)
 		goto err_out;
-	}
 
 	ret = devm_spi_register_master(&pdev->dev, master);
-	if (!ret) {
-		dev_info(&pdev->dev,
-			 "SPI bus driver initialized. Master clock %u Hz\n",
-			 hw->max_speed_hz);
+	if (!ret)
 		return 0;
-	}
-
-	dev_err(&pdev->dev, "Failed to register master\n");
 
 err_out:
-	while (--i >= 0)
-		if (gpio_is_valid(hw->chipselect[i]))
-			gpio_free(hw->chipselect[i]);
-
 	spi_master_put(master);
 
 	return ret;
 }
 
-static int spi_clps711x_remove(struct platform_device *pdev)
-{
-	int i;
-	struct spi_master *master = platform_get_drvdata(pdev);
-	struct spi_clps711x_data *hw = spi_master_get_devdata(master);
-
-	for (i = 0; i < master->num_chipselect; i++)
-		if (gpio_is_valid(hw->chipselect[i]))
-			gpio_free(hw->chipselect[i]);
-
-	return 0;
-}
+static const struct of_device_id clps711x_spi_dt_ids[] = {
+	{ .compatible = "cirrus,clps711x-spi", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, clps711x_spi_dt_ids);
 
 static struct platform_driver clps711x_spi_driver = {
 	.driver	= {
-		.name	= DRIVER_NAME,
-		.owner	= THIS_MODULE,
+		.name		= "clps711x-spi",
+		.owner		= THIS_MODULE,
+		.of_match_table	= clps711x_spi_dt_ids,
 	},
 	.probe	= spi_clps711x_probe,
-	.remove	= spi_clps711x_remove,
 };
 module_platform_driver(clps711x_spi_driver);
 
diff --git a/include/linux/platform_data/spi-clps711x.h b/include/linux/platform_data/spi-clps711x.h
deleted file mode 100644
index 301956e..0000000
--- a/include/linux/platform_data/spi-clps711x.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- *  CLPS711X SPI bus driver definitions
- *
- *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
- *
- * 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.
- */
-
-#ifndef ____LINUX_PLATFORM_DATA_SPI_CLPS711X_H
-#define ____LINUX_PLATFORM_DATA_SPI_CLPS711X_H
-
-/* Board specific platform_data */
-struct spi_clps711x_pdata {
-	int *chipselect;	/* Array of GPIO-numbers */
-	int num_chipselect;	/* Total count of GPIOs */
-};
-
-#endif
-- 
1.8.3.2

             reply	other threads:[~2014-01-01  6:09 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-01  6:09 Alexander Shiyan [this message]
2014-01-01  6:09 ` [PATCH 1/2] spi: clps711x: Driver refactor Alexander Shiyan
     [not found] ` <1388556568-10973-1-git-send-email-shc_work-JGs/UdohzUI@public.gmane.org>
2014-01-01 13:23   ` Mark Brown
2014-01-01 13:23     ` Mark Brown
     [not found]     ` <20140101132334.GP31886-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2014-01-01 13:44       ` Alexander Shiyan
2014-01-01 13:44         ` Alexander Shiyan
     [not found]         ` <1388583851.810843204-7YUp6uTCZANsdVUOrk1QfQ@public.gmane.org>
2014-01-01 15:07           ` Mark Brown
2014-01-01 15:07             ` Mark Brown
     [not found]             ` <20140101150737.GR31886-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2014-01-02 17:46               ` Arnd Bergmann
2014-01-02 17:46                 ` Arnd Bergmann
2014-01-02 18:20                 ` Alexander Shiyan
2014-01-02 18:20                   ` Alexander Shiyan
     [not found]                 ` <201401021846.23488.arnd-r2nGTMty4D4@public.gmane.org>
2014-01-02 18:25                   ` Mark Brown
2014-01-02 18:25                     ` Mark Brown
     [not found]                     ` <20140102182549.GF31886-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2014-01-02 19:03                       ` Arnd Bergmann
2014-01-02 19:03                         ` Arnd Bergmann
2016-07-06 14:53 Arnd Bergmann
2016-07-06 14:53 ` Arnd Bergmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1388556568-10973-1-git-send-email-shc_work@mail.ru \
    --to=shc_work@mail.ru \
    --cc=broonie@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-spi@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.