[OpenWrt-Devel] [PATCH 7/8] ramips: use transfer_one instead of transfer_one_message on rt2880 spi

Michael Lee igvtee at gmail.com
Thu Oct 8 10:16:07 EDT 2015


* use kernel buildin transfer_one_message. we only need to implement
transfer_one and set_cs function
* should support use gpio as cs pin
* deselected the spi device when setup and add debug info
* only reset device when first driver probe

Signed-off-by: Michael Lee <igvtee at gmail.com>
---
 ...0050-SPI-ralink-add-Ralink-SoC-spi-driver.patch | 127 ++++++++++-----------
 1 file changed, 62 insertions(+), 65 deletions(-)

diff --git a/target/linux/ramips/patches-3.18/0050-SPI-ralink-add-Ralink-SoC-spi-driver.patch b/target/linux/ramips/patches-3.18/0050-SPI-ralink-add-Ralink-SoC-spi-driver.patch
index 862e24c..57986d3 100644
--- a/target/linux/ramips/patches-3.18/0050-SPI-ralink-add-Ralink-SoC-spi-driver.patch
+++ b/target/linux/ramips/patches-3.18/0050-SPI-ralink-add-Ralink-SoC-spi-driver.patch
@@ -41,7 +41,7 @@ Acked-by: John Crispin <blogic at openwrt.org>
  spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
 --- /dev/null
 +++ b/drivers/spi/spi-rt2880.c
-@@ -0,0 +1,533 @@
+@@ -0,0 +1,530 @@
 +/*
 + * spi-rt2880.c -- Ralink RT288x/RT305x SPI controller driver
 + *
@@ -66,10 +66,9 @@ Acked-by: John Crispin <blogic at openwrt.org>
 +#include <linux/reset.h>
 +#include <linux/spi/spi.h>
 +#include <linux/platform_device.h>
++#include <linux/gpio.h>
 +
 +#define DRIVER_NAME			"spi-rt2880"
-+/* only one slave is supported*/
-+#define RALINK_NUM_CHIPSELECTS		1
 +
 +#define RAMIPS_SPI_STAT			0x00
 +#define RAMIPS_SPI_CFG			0x10
@@ -169,6 +168,8 @@ Acked-by: John Crispin <blogic at openwrt.org>
 +#define RT2880_SPI_MODE_BITS	(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | \
 +		SPI_CS_HIGH)
 +
++static atomic_t hw_reset_count = ATOMIC_INIT(0);
++
 +struct rt2880_spi {
 +	struct spi_master	*master;
 +	void __iomem		*base;
@@ -248,12 +249,14 @@ Acked-by: John Crispin <blogic at openwrt.org>
 +	return offset;
 +}
 +
-+static void rt2880_spi_set_cs(struct rt2880_spi *rs, int enable)
++static void rt2880_spi_set_cs(struct spi_device *spi, bool enable)
 +{
++	struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
++
 +	if (enable)
-+		rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
-+	else
 +		rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
++	else
++		rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
 +}
 +
 +static int rt2880_spi_wait_ready(struct rt2880_spi *rs, int len)
@@ -269,22 +272,41 @@ Acked-by: John Crispin <blogic at openwrt.org>
 +	return -ETIMEDOUT;
 +}
 +
-+static unsigned int
-+rt2880_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
++static void rt2880_dump_reg(struct spi_master *master)
 +{
-+	struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
-+	unsigned count = 0;
-+	u8 *rx = xfer->rx_buf;
-+	const u8 *tx = xfer->tx_buf;
-+	int err;
++	struct rt2880_spi *rs = spi_master_get_devdata(master);
 +
-+	dev_dbg(&spi->dev, "read (%d): %s %s\n", xfer->len,
-+		  (tx != NULL) ? "tx" : "  ",
-+		  (rx != NULL) ? "rx" : "  ");
++	dev_dbg(&master->dev, "stat: %08x, cfg: %08x, ctl: %08x, " \
++			"data: %08x, arb: %08x\n",
++			rt2880_spi_read(rs, RAMIPS_SPI_STAT),
++			rt2880_spi_read(rs, RAMIPS_SPI_CFG),
++			rt2880_spi_read(rs, RAMIPS_SPI_CTL),
++			rt2880_spi_read(rs, RAMIPS_SPI_DATA),
++			rt2880_spi_read(rs, get_arbiter_offset(master)));
++}
++
++static int rt2880_spi_transfer_one(struct spi_master *master,
++		struct spi_device *spi, struct spi_transfer *xfer)
++{
++	struct rt2880_spi *rs = spi_master_get_devdata(master);
++	unsigned len;
++	const u8 *tx = xfer->tx_buf;
++	u8 *rx = xfer->rx_buf;
++	int err = 0;
++
++	/* change clock speed  */
++	if (unlikely(rs->speed != xfer->speed_hz)) {
++		u32 reg;
++		reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG);
++		reg &= ~SPICFG_SPICLK_PRESCALE_MASK;
++		reg |= rt2880_spi_baudrate_get(spi, xfer->speed_hz);
++		rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg);
++	}
 +
 +	if (tx) {
-+		for (count = 0; count < xfer->len; count++) {
-+			rt2880_spi_write(rs, RAMIPS_SPI_DATA, tx[count]);
++		len = xfer->len;
++		while (len-- > 0) {
++			rt2880_spi_write(rs, RAMIPS_SPI_DATA, *tx++);
 +			rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR);
 +			err = rt2880_spi_wait_ready(rs, 1);
 +			if (err) {
@@ -295,63 +317,32 @@ Acked-by: John Crispin <blogic at openwrt.org>
 +	}
 +
 +	if (rx) {
-+		for (count = 0; count < xfer->len; count++) {
++		len = xfer->len;
++		while (len-- > 0) {
 +			rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD);
 +			err = rt2880_spi_wait_ready(rs, 1);
 +			if (err) {
 +				dev_err(&spi->dev, "RX failed, err=%d\n", err);
 +				goto out;
 +			}
-+			rx[count] = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA);
++			*rx++ = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA);
 +		}
 +	}
 +
 +out:
-+	return count;
++	return err;
 +}
 +
-+static int rt2880_spi_transfer_one_message(struct spi_master *master,
-+					   struct spi_message *m)
++/* copy from spi.c */
++static void spi_set_cs(struct spi_device *spi, bool enable)
 +{
-+	struct rt2880_spi *rs = spi_master_get_devdata(master);
-+	struct spi_device *spi = m->spi;
-+	struct spi_transfer *t = NULL;
-+	int status = 0;
-+	int cs_active = 0;
-+
-+	list_for_each_entry(t, &m->transfers, transfer_list) {
-+		if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
-+			dev_err(&spi->dev,
-+				"message rejected: invalid transfer data buffers\n");
-+			status = -EIO;
-+			goto msg_done;
-+		}
-+
-+		if (!cs_active) {
-+			rt2880_spi_set_cs(rs, 1);
-+			cs_active = 1;
-+		}
-+
-+		if (t->len)
-+			m->actual_length += rt2880_spi_write_read(spi, t);
-+
-+		if (t->delay_usecs)
-+			udelay(t->delay_usecs);
-+
-+		if (t->cs_change) {
-+			rt2880_spi_set_cs(rs, 0);
-+			cs_active = 0;
-+		}
-+	}
-+
-+msg_done:
-+	if (cs_active)
-+		rt2880_spi_set_cs(rs, 0);
-+
-+	m->status = status;
-+	spi_finalize_current_message(master);
++	if (spi->mode & SPI_CS_HIGH)
++		enable = !enable;
 +
-+	return 0;
++	if (spi->cs_gpio >= 0)
++		gpio_set_value(spi->cs_gpio, !enable);
++	else if (spi->master->set_cs)
++		spi->master->set_cs(spi, !enable);
 +}
 +
 +static int rt2880_spi_setup(struct spi_device *spi)
@@ -410,6 +401,11 @@ Acked-by: John Crispin <blogic at openwrt.org>
 +	if (reg != old_reg)
 +		rt2880_spi_write(rs, arbit_off, reg);
 +
++	/* deselected the spi device */
++	spi_set_cs(spi, false);
++
++	rt2880_dump_reg(master);
++
 +	return 0;
 +}
 +
@@ -508,8 +504,8 @@ Acked-by: John Crispin <blogic at openwrt.org>
 +	master->flags = SPI_MASTER_HALF_DUPLEX;
 +	master->setup = rt2880_spi_setup;
 +	master->prepare_message = rt2880_spi_prepare_message;
-+	master->transfer_one_message = rt2880_spi_transfer_one_message;
-+	master->num_chipselect = RALINK_NUM_CHIPSELECTS;
++	master->set_cs = rt2880_spi_set_cs;
++	master->transfer_one = rt2880_spi_transfer_one,
 +
 +	dev_set_drvdata(&pdev->dev, master);
 +
@@ -518,8 +514,8 @@ Acked-by: John Crispin <blogic at openwrt.org>
 +	rs->base = base;
 +	rs->clk = clk;
 +
-+	device_reset(&pdev->dev);
-+
++	if (atomic_inc_return(&hw_reset_count) == 1)
++		device_reset(&pdev->dev);
 +
 +	ret = devm_spi_register_master(&pdev->dev, master);
 +	if (ret < 0) {
@@ -547,6 +543,7 @@ Acked-by: John Crispin <blogic at openwrt.org>
 +	rs = spi_master_get_devdata(master);
 +
 +	clk_disable_unprepare(rs->clk);
++	atomic_dec(&hw_reset_count);
 +
 +	return 0;
 +}
-- 
2.3.6
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list