linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2/2] SPI: make the moved loopback test work
@ 2010-07-11  0:43 Linus Walleij
  2010-07-19  5:51 ` Grant Likely
  0 siblings, 1 reply; 9+ messages in thread
From: Linus Walleij @ 2010-07-11  0:43 UTC (permalink / raw)
  To: spi-devel-general, Grant Likely; +Cc: Linus Walleij, linux-arm-kernel

This completes the move of the SPI test chip out of the U300
architecture by modifying the loopback test to register itself on
every PL022 master if it is compiled in. Also updates some minor
things like naming to make the code stricter.

Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
---
 arch/arm/mach-u300/Kconfig        |   12 ----
 arch/arm/mach-u300/Makefile       |    1 -
 arch/arm/mach-u300/spi.c          |   61 -------------------
 drivers/spi/Kconfig               |   13 ++++
 drivers/spi/Makefile              |    1 +
 drivers/spi/amba-pl022-looptest.c |  120 +++++++++++++++++++++++++++++-------
 drivers/spi/amba-pl022-looptest.h |   11 ++++
 drivers/spi/amba-pl022.c          |    6 ++
 8 files changed, 127 insertions(+), 98 deletions(-)
 create mode 100644 drivers/spi/amba-pl022-looptest.h

diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig
index 801b21e..337b9aa 100644
--- a/arch/arm/mach-u300/Kconfig
+++ b/arch/arm/mach-u300/Kconfig
@@ -81,18 +81,6 @@ config MACH_U300_SEMI_IS_SHARED
 		Memory Interface) from both from access and application
 		side.
 
-config MACH_U300_SPIDUMMY
-	bool "SSP/SPI dummy chip"
-	select SPI
-	select SPI_MASTER
-	select SPI_PL022
-	help
-		This creates a small kernel module that creates a dummy
-		SPI device to be used for loopback tests. Regularly used
-		to test reference designs. If you're not testing SPI,
-		you don't need it. Selecting this will activate the
-		SPI framework and ARM PL022 support.
-
 comment "All the settings below must match the bootloader's settings"
 
 config MACH_U300_ACCESS_MEM_SIZE
diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile
index fab46fe..1f0f4b8 100644
--- a/arch/arm/mach-u300/Makefile
+++ b/arch/arm/mach-u300/Makefile
@@ -10,6 +10,5 @@ obj-		:=
 obj-$(CONFIG_ARCH_U300)	          += u300.o
 obj-$(CONFIG_MMC)                 += mmc.o
 obj-$(CONFIG_SPI_PL022)           += spi.o
-obj-$(CONFIG_MACH_U300_SPIDUMMY)  += dummyspichip.o
 obj-$(CONFIG_I2C_STU300)          += i2c.o
 obj-$(CONFIG_REGULATOR_AB3100)    += regulator.o
diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c
index f0e887b..0790cce 100644
--- a/arch/arm/mach-u300/spi.c
+++ b/arch/arm/mach-u300/spi.c
@@ -16,68 +16,8 @@
 /*
  * The following is for the actual devices on the SSP/SPI bus
  */
-#ifdef CONFIG_MACH_U300_SPIDUMMY
-static void select_dummy_chip(u32 chipselect)
-{
-	pr_debug("CORE: %s called with CS=0x%x (%s)\n",
-		 __func__,
-		 chipselect,
-		 chipselect ? "unselect chip" : "select chip");
-	/*
-	 * Here you would write the chip select value to the GPIO pins if
-	 * this was a real chip (but this is a loopback dummy).
-	 */
-}
-
-struct pl022_config_chip dummy_chip_info = {
-	/* Nominally this is LOOPBACK_DISABLED, but this is our dummy chip! */
-	.lbm = LOOPBACK_ENABLED,
-	/*
-	 * available POLLING_TRANSFER and INTERRUPT_TRANSFER,
-	 * DMA_TRANSFER does not work
-	 */
-	.com_mode = INTERRUPT_TRANSFER,
-	.iface = SSP_INTERFACE_MOTOROLA_SPI,
-	/* We can only act as master but SSP_SLAVE is possible in theory */
-	.hierarchy = SSP_MASTER,
-	/* 0 = drive TX even as slave, 1 = do not drive TX as slave */
-	.slave_tx_disable = 0,
-	/* LSB first */
-	.endian_tx = SSP_TX_LSB,
-	.endian_rx = SSP_RX_LSB,
-	.data_size = SSP_DATA_BITS_8, /* used to be 12 in some default */
-	.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
-	.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
-	.clk_phase = SSP_CLK_SECOND_EDGE,
-	.clk_pol = SSP_CLK_POL_IDLE_LOW,
-	.ctrl_len = SSP_BITS_12,
-	.wait_state = SSP_MWIRE_WAIT_ZERO,
-	.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
-	/*
-	 * This is where you insert a call to a function to enable CS
-	 * (usually GPIO) for a certain chip.
-	 */
-	.cs_control = select_dummy_chip,
-};
-#endif
 
 static struct spi_board_info u300_spi_devices[] = {
-#ifdef CONFIG_MACH_U300_SPIDUMMY
-	{
-		/* A dummy chip used for loopback tests */
-		.modalias       = "spi-dummy",
-		/* Really dummy, pass in additional chip config here */
-		.platform_data  = NULL,
-		/* This defines how the controller shall handle the device */
-		.controller_data = &dummy_chip_info,
-		/* .irq - no external IRQ routed from this device */
-		.max_speed_hz   = 1000000,
-		.bus_num        = 0, /* Only one bus on this chip */
-		.chip_select    = 0,
-		/* Means SPI_CS_HIGH, change if e.g low CS */
-		.mode           = 0,
-	},
-#endif
 };
 
 static struct pl022_ssp_controller ssp_platform_data = {
@@ -94,7 +34,6 @@ static struct pl022_ssp_controller ssp_platform_data = {
 	.num_chipselect = 3,
 };
 
-
 void __init u300_spi_init(struct amba_device *adev)
 {
 	struct pmx *pmx;
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 91c2f4f..9e584dc 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -227,6 +227,19 @@ config SPI_PL022
 	  controller. If you have an embedded system with an AMBA(R)
 	  bus and a PL022 controller, say Y or M here.
 
+config SPI_PL022_LOOPTEST
+	bool "PL022 loopback chip"
+	depends on SPI_PL022
+	help
+	  The PL022 supports a loopback mode where the output is
+	  looped back to the input for testing.
+
+	  This creates a small kernel module that creates a dummy
+	  SPI device on each PL022 SPI bus to be used for loopback
+	  tests. You find the device in the /sys filesystem, e.g.
+	  /sys/bus/spi/devices/spi0.0/looptest and the test is run by
+	  issuing cat <looptest>.
+
 config SPI_PPC4xx
 	tristate "PPC4xx SPI Controller"
 	depends on PPC32 && 4xx && SPI_MASTER
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e9cbd18..9ac8e95 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_SPI_OMAP24XX)		+= omap2_mcspi.o
 obj-$(CONFIG_SPI_OMAP_100K)		+= omap_spi_100k.o
 obj-$(CONFIG_SPI_ORION)			+= orion_spi.o
 obj-$(CONFIG_SPI_PL022)			+= amba-pl022.o
+obj-$(CONFIG_SPI_PL022_LOOPTEST)	+= amba-pl022-looptest.o
 obj-$(CONFIG_SPI_MPC512x_PSC)		+= mpc512x_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx)		+= mpc52xx_spi.o
diff --git a/drivers/spi/amba-pl022-looptest.c b/drivers/spi/amba-pl022-looptest.c
index 5f55012..561886a 100644
--- a/drivers/spi/amba-pl022-looptest.c
+++ b/drivers/spi/amba-pl022-looptest.c
@@ -1,7 +1,5 @@
 /*
- * arch/arm/mach-u300/dummyspichip.c
- *
- * Copyright (C) 2007-2009 ST-Ericsson AB
+ * Copyright (C) 2007-2010 ST-Ericsson SA
  * License terms: GNU General Public License (GPL) version 2
  * This is a dummy loopback SPI "chip" used for testing SPI.
  * Author: Linus Walleij <linus.walleij@stericsson.com>
@@ -25,19 +23,93 @@
  */
 #include <linux/amba/pl022.h>
 
-struct dummy {
+struct pl022_loopback {
 	struct device *dev;
 	struct mutex lock;
 };
 
 #define DMA_TEST_SIZE 2048
 
-/* When we cat /sys/bus/spi/devices/spi0.0/looptest this will be triggered */
-static ssize_t dummy_looptest(struct device *dev,
+/*
+ * The following code self-registers the PL022 loopback
+ * chip on each PL022 SPI bus.
+ */
+
+static void pl022_select_loopback_chip(u32 chipselect)
+{
+	pr_debug("PL022 loopback chip: %s called with CS=0x%x (%s)\n",
+		 __func__,
+		 chipselect,
+		 chipselect ? "unselect chip" : "select chip");
+	/*
+	 * Here you would write the chip select value to the GPIO pins if
+	 * this was a real chip (but this is a loopback dummy).
+	 */
+}
+
+struct pl022_config_chip pl022_loopback_chip_info = {
+	/* Nominally this is LOOPBACK_DISABLED, but this is our dummy chip! */
+	.lbm = LOOPBACK_ENABLED,
+	.com_mode = INTERRUPT_TRANSFER,
+	.iface = SSP_INTERFACE_MOTOROLA_SPI,
+	.hierarchy = SSP_MASTER,
+	.slave_tx_disable = 0,
+	/* LSB first */
+	.endian_tx = SSP_TX_LSB,
+	.endian_rx = SSP_RX_LSB,
+	.data_size = SSP_DATA_BITS_8,
+	.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
+	.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
+	.clk_phase = SSP_CLK_SECOND_EDGE,
+	.clk_pol = SSP_CLK_POL_IDLE_LOW,
+	.ctrl_len = SSP_BITS_12,
+	.wait_state = SSP_MWIRE_WAIT_ZERO,
+	.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
+	.cs_control = pl022_select_loopback_chip,
+};
+
+static struct spi_board_info pl022_loopback_device = {
+	/* A dummy chip used for loopback tests */
+	.modalias       = "pl022-loop",
+	/* Really dummy, pass in additional chip config here */
+	.platform_data  = NULL,
+	/* This defines how the controller shall handle the device */
+	.controller_data = &pl022_loopback_chip_info,
+	/* .irq - no external IRQ routed from this device */
+	.max_speed_hz   = 1000000,
+	.bus_num        = 0, /* Only one bus on this chip */
+	.chip_select    = 0,
+	/* Means SPI_CS_HIGH, change if e.g low CS */
+	.mode           = 0,
+};
+
+/*
+ * This is called from the PL022 driver to register a loopback
+ * on itself if this module is compiled in.
+ */
+void pl022_loopback_register(struct spi_master *master)
+{
+	struct spi_device *spidev;
+
+	spidev = spi_new_device(master, &pl022_loopback_device);
+	if (!spidev)
+		dev_err(&master->dev,
+			"could not register loopback test chip\n");
+	else
+		dev_err(&master->dev,
+			"registered loopback test chip\n");
+}
+
+/*
+ * This is where the tests begin. When we issue:
+ * cat /sys/bus/spi/devices/spi0.0/looptest
+ * this will be triggered.
+ */
+static ssize_t pl022_looptest(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct spi_device *spi = to_spi_device(dev);
-	struct dummy *p_dummy = dev_get_drvdata(&spi->dev);
+	struct pl022_loopback *p_loop = dev_get_drvdata(&spi->dev);
 
 	/*
 	 * WARNING! Do not dereference the chip-specific data in any normal
@@ -55,7 +127,7 @@ static ssize_t dummy_looptest(struct device *dev,
 	u8 *bigtxbuf_virtual;
 	u8 *bigrxbuf_virtual;
 
-	if (mutex_lock_interruptible(&p_dummy->lock))
+	if (mutex_lock_interruptible(&p_loop->lock))
 		return -ERESTARTSYS;
 
 	bigtxbuf_virtual = kmalloc(DMA_TEST_SIZE, GFP_KERNEL);
@@ -217,25 +289,25 @@ static ssize_t dummy_looptest(struct device *dev,
 	kfree(bigrxbuf_virtual);
 	kfree(bigtxbuf_virtual);
  out:
-	mutex_unlock(&p_dummy->lock);
+	mutex_unlock(&p_loop->lock);
 	return status;
 }
 
-static DEVICE_ATTR(looptest, S_IRUGO, dummy_looptest, NULL);
+static DEVICE_ATTR(looptest, S_IRUGO, pl022_looptest, NULL);
 
-static int __devinit pl022_dummy_probe(struct spi_device *spi)
+static int __devinit pl022_loopback_probe(struct spi_device *spi)
 {
-	struct dummy *p_dummy;
+	struct pl022_loopback *p_loop;
 	int status;
 
 	dev_info(&spi->dev, "probing dummy SPI device\n");
 
-	p_dummy = kzalloc(sizeof *p_dummy, GFP_KERNEL);
-	if (!p_dummy)
+	p_loop = kzalloc(sizeof *p_loop, GFP_KERNEL);
+	if (!p_loop)
 		return -ENOMEM;
 
-	dev_set_drvdata(&spi->dev, p_dummy);
-	mutex_init(&p_dummy->lock);
+	dev_set_drvdata(&spi->dev, p_loop);
+	mutex_init(&p_loop->lock);
 
 	/* sysfs hook */
 	status = device_create_file(&spi->dev, &dev_attr_looptest);
@@ -248,29 +320,29 @@ static int __devinit pl022_dummy_probe(struct spi_device *spi)
 
 out_dev_create_looptest_failed:
 	dev_set_drvdata(&spi->dev, NULL);
-	kfree(p_dummy);
+	kfree(p_loop);
 	return status;
 }
 
-static int __devexit pl022_dummy_remove(struct spi_device *spi)
+static int __devexit pl022_loopback_remove(struct spi_device *spi)
 {
-	struct dummy *p_dummy = dev_get_drvdata(&spi->dev);
+	struct pl022_loopback *p_loop = dev_get_drvdata(&spi->dev);
 
 	dev_info(&spi->dev, "removing dummy SPI device\n");
 	device_remove_file(&spi->dev, &dev_attr_looptest);
 	dev_set_drvdata(&spi->dev, NULL);
-	kfree(p_dummy);
+	kfree(p_loop);
 
 	return 0;
 }
 
 static struct spi_driver pl022_dummy_driver = {
 	.driver = {
-		.name	= "spi-dummy",
+		.name	= "pl022-loop",
 		.owner	= THIS_MODULE,
 	},
-	.probe	= pl022_dummy_probe,
-	.remove	= __devexit_p(pl022_dummy_remove),
+	.probe	= pl022_loopback_probe,
+	.remove	= __devexit_p(pl022_loopback_remove),
 };
 
 static int __init pl022_init_dummy(void)
@@ -287,5 +359,5 @@ module_init(pl022_init_dummy);
 module_exit(pl022_exit_dummy);
 
 MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
-MODULE_DESCRIPTION("PL022 SSP/SPI DUMMY Linux driver");
+MODULE_DESCRIPTION("PL022 loopback test driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/spi/amba-pl022-looptest.h b/drivers/spi/amba-pl022-looptest.h
new file mode 100644
index 0000000..1bedcc6
--- /dev/null
+++ b/drivers/spi/amba-pl022-looptest.h
@@ -0,0 +1,11 @@
+/*
+ * Defines a single function for the master to create a loopback
+ * on itself.
+ */
+#ifdef CONFIG_SPI_PL022_LOOPTEST
+void pl022_loopback_register(struct spi_master *master);
+#else
+static void inline pl022_loopback_register(struct spi_master *master)
+{
+}
+#endif
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c
index f0a1418..6e4a657 100644
--- a/drivers/spi/amba-pl022.c
+++ b/drivers/spi/amba-pl022.c
@@ -46,6 +46,8 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 
+#include "amba-pl022-looptest.h"
+
 /*
  * This macro is used to define some register default values.
  * reg is masked with mask, the OR:ed with an (again masked)
@@ -1818,6 +1820,10 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
 		goto err_spi_register;
 	}
 	dev_dbg(dev, "probe succeded\n");
+
+	/* Register a loopback test if desired */
+	pl022_loopback_register(master);
+
 	return 0;
 
  err_spi_register:
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] SPI: make the moved loopback test work
  2010-07-11  0:43 [PATCH 2/2] SPI: make the moved loopback test work Linus Walleij
@ 2010-07-19  5:51 ` Grant Likely
  2010-07-19 10:16   ` [spi-devel-general] " David Brownell
  0 siblings, 1 reply; 9+ messages in thread
From: Grant Likely @ 2010-07-19  5:51 UTC (permalink / raw)
  To: Linus Walleij; +Cc: spi-devel-general, linux-arm-kernel

On Sat, Jul 10, 2010 at 6:43 PM, Linus Walleij
<linus.walleij@stericsson.com> wrote:
> This completes the move of the SPI test chip out of the U300
> architecture by modifying the loopback test to register itself on
> every PL022 master if it is compiled in. Also updates some minor
> things like naming to make the code stricter.
>
> Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>

Having a test driver in common code that purposefully does bad things
is a sure fire way to get people to copy those bad practices when they
write their own drivers (despite all the comments in the code that say
don't do this).  I'm talking about things like the dereferencing of
controller data, and calling the setup() hook in something that looks
like a normal spi_device driver.  As-is, I'm not excited about merging
this patch (and it isn't bisectable either).

If you want this loopback functionality, It should be integrated into
the pl022 driver itself.  It should not pretend to be an spi_device.

> ---
>  arch/arm/mach-u300/Kconfig        |   12 ----
>  arch/arm/mach-u300/Makefile       |    1 -
>  arch/arm/mach-u300/spi.c          |   61 -------------------
>  drivers/spi/Kconfig               |   13 ++++
>  drivers/spi/Makefile              |    1 +
>  drivers/spi/amba-pl022-looptest.c |  120 +++++++++++++++++++++++++++++-------
>  drivers/spi/amba-pl022-looptest.h |   11 ++++
>  drivers/spi/amba-pl022.c          |    6 ++
>  8 files changed, 127 insertions(+), 98 deletions(-)
>  create mode 100644 drivers/spi/amba-pl022-looptest.h
>
> diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig
> index 801b21e..337b9aa 100644
> --- a/arch/arm/mach-u300/Kconfig
> +++ b/arch/arm/mach-u300/Kconfig
> @@ -81,18 +81,6 @@ config MACH_U300_SEMI_IS_SHARED
>                Memory Interface) from both from access and application
>                side.
>
> -config MACH_U300_SPIDUMMY
> -       bool "SSP/SPI dummy chip"
> -       select SPI
> -       select SPI_MASTER
> -       select SPI_PL022
> -       help
> -               This creates a small kernel module that creates a dummy
> -               SPI device to be used for loopback tests. Regularly used
> -               to test reference designs. If you're not testing SPI,
> -               you don't need it. Selecting this will activate the
> -               SPI framework and ARM PL022 support.
> -
>  comment "All the settings below must match the bootloader's settings"
>
>  config MACH_U300_ACCESS_MEM_SIZE
> diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile
> index fab46fe..1f0f4b8 100644
> --- a/arch/arm/mach-u300/Makefile
> +++ b/arch/arm/mach-u300/Makefile
> @@ -10,6 +10,5 @@ obj-          :=
>  obj-$(CONFIG_ARCH_U300)                  += u300.o
>  obj-$(CONFIG_MMC)                 += mmc.o
>  obj-$(CONFIG_SPI_PL022)           += spi.o
> -obj-$(CONFIG_MACH_U300_SPIDUMMY)  += dummyspichip.o
>  obj-$(CONFIG_I2C_STU300)          += i2c.o
>  obj-$(CONFIG_REGULATOR_AB3100)    += regulator.o
> diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c
> index f0e887b..0790cce 100644
> --- a/arch/arm/mach-u300/spi.c
> +++ b/arch/arm/mach-u300/spi.c
> @@ -16,68 +16,8 @@
>  /*
>  * The following is for the actual devices on the SSP/SPI bus
>  */
> -#ifdef CONFIG_MACH_U300_SPIDUMMY
> -static void select_dummy_chip(u32 chipselect)
> -{
> -       pr_debug("CORE: %s called with CS=0x%x (%s)\n",
> -                __func__,
> -                chipselect,
> -                chipselect ? "unselect chip" : "select chip");
> -       /*
> -        * Here you would write the chip select value to the GPIO pins if
> -        * this was a real chip (but this is a loopback dummy).
> -        */
> -}
> -
> -struct pl022_config_chip dummy_chip_info = {
> -       /* Nominally this is LOOPBACK_DISABLED, but this is our dummy chip! */
> -       .lbm = LOOPBACK_ENABLED,
> -       /*
> -        * available POLLING_TRANSFER and INTERRUPT_TRANSFER,
> -        * DMA_TRANSFER does not work
> -        */
> -       .com_mode = INTERRUPT_TRANSFER,
> -       .iface = SSP_INTERFACE_MOTOROLA_SPI,
> -       /* We can only act as master but SSP_SLAVE is possible in theory */
> -       .hierarchy = SSP_MASTER,
> -       /* 0 = drive TX even as slave, 1 = do not drive TX as slave */
> -       .slave_tx_disable = 0,
> -       /* LSB first */
> -       .endian_tx = SSP_TX_LSB,
> -       .endian_rx = SSP_RX_LSB,
> -       .data_size = SSP_DATA_BITS_8, /* used to be 12 in some default */
> -       .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
> -       .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
> -       .clk_phase = SSP_CLK_SECOND_EDGE,
> -       .clk_pol = SSP_CLK_POL_IDLE_LOW,
> -       .ctrl_len = SSP_BITS_12,
> -       .wait_state = SSP_MWIRE_WAIT_ZERO,
> -       .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
> -       /*
> -        * This is where you insert a call to a function to enable CS
> -        * (usually GPIO) for a certain chip.
> -        */
> -       .cs_control = select_dummy_chip,
> -};
> -#endif
>
>  static struct spi_board_info u300_spi_devices[] = {
> -#ifdef CONFIG_MACH_U300_SPIDUMMY
> -       {
> -               /* A dummy chip used for loopback tests */
> -               .modalias       = "spi-dummy",
> -               /* Really dummy, pass in additional chip config here */
> -               .platform_data  = NULL,
> -               /* This defines how the controller shall handle the device */
> -               .controller_data = &dummy_chip_info,
> -               /* .irq - no external IRQ routed from this device */
> -               .max_speed_hz   = 1000000,
> -               .bus_num        = 0, /* Only one bus on this chip */
> -               .chip_select    = 0,
> -               /* Means SPI_CS_HIGH, change if e.g low CS */
> -               .mode           = 0,
> -       },
> -#endif
>  };
>
>  static struct pl022_ssp_controller ssp_platform_data = {
> @@ -94,7 +34,6 @@ static struct pl022_ssp_controller ssp_platform_data = {
>        .num_chipselect = 3,
>  };
>
> -
>  void __init u300_spi_init(struct amba_device *adev)
>  {
>        struct pmx *pmx;
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 91c2f4f..9e584dc 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -227,6 +227,19 @@ config SPI_PL022
>          controller. If you have an embedded system with an AMBA(R)
>          bus and a PL022 controller, say Y or M here.
>
> +config SPI_PL022_LOOPTEST
> +       bool "PL022 loopback chip"
> +       depends on SPI_PL022
> +       help
> +         The PL022 supports a loopback mode where the output is
> +         looped back to the input for testing.
> +
> +         This creates a small kernel module that creates a dummy
> +         SPI device on each PL022 SPI bus to be used for loopback
> +         tests. You find the device in the /sys filesystem, e.g.
> +         /sys/bus/spi/devices/spi0.0/looptest and the test is run by
> +         issuing cat <looptest>.

Questionable usage of sysfs.  sysfs files should contain single values
only, or a list of things-of-the-same-type, and by convention sysfs
files are supposed to be available immediately when the struct device
is registered.  It looks like debugfs should really be used instead.

> +
>  config SPI_PPC4xx
>        tristate "PPC4xx SPI Controller"
>        depends on PPC32 && 4xx && SPI_MASTER
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index e9cbd18..9ac8e95 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -31,6 +31,7 @@ obj-$(CONFIG_SPI_OMAP24XX)            += omap2_mcspi.o
>  obj-$(CONFIG_SPI_OMAP_100K)            += omap_spi_100k.o
>  obj-$(CONFIG_SPI_ORION)                        += orion_spi.o
>  obj-$(CONFIG_SPI_PL022)                        += amba-pl022.o
> +obj-$(CONFIG_SPI_PL022_LOOPTEST)       += amba-pl022-looptest.o
>  obj-$(CONFIG_SPI_MPC512x_PSC)          += mpc512x_psc_spi.o
>  obj-$(CONFIG_SPI_MPC52xx_PSC)          += mpc52xx_psc_spi.o
>  obj-$(CONFIG_SPI_MPC52xx)              += mpc52xx_spi.o
> diff --git a/drivers/spi/amba-pl022-looptest.c b/drivers/spi/amba-pl022-looptest.c
> index 5f55012..561886a 100644
> --- a/drivers/spi/amba-pl022-looptest.c
> +++ b/drivers/spi/amba-pl022-looptest.c
> @@ -1,7 +1,5 @@
>  /*
> - * arch/arm/mach-u300/dummyspichip.c
> - *
> - * Copyright (C) 2007-2009 ST-Ericsson AB
> + * Copyright (C) 2007-2010 ST-Ericsson SA
>  * License terms: GNU General Public License (GPL) version 2
>  * This is a dummy loopback SPI "chip" used for testing SPI.
>  * Author: Linus Walleij <linus.walleij@stericsson.com>
> @@ -25,19 +23,93 @@
>  */
>  #include <linux/amba/pl022.h>
>
> -struct dummy {
> +struct pl022_loopback {
>        struct device *dev;
>        struct mutex lock;
>  };
>
>  #define DMA_TEST_SIZE 2048
>
> -/* When we cat /sys/bus/spi/devices/spi0.0/looptest this will be triggered */
> -static ssize_t dummy_looptest(struct device *dev,
> +/*
> + * The following code self-registers the PL022 loopback
> + * chip on each PL022 SPI bus.
> + */
> +
> +static void pl022_select_loopback_chip(u32 chipselect)
> +{
> +       pr_debug("PL022 loopback chip: %s called with CS=0x%x (%s)\n",
> +                __func__,
> +                chipselect,
> +                chipselect ? "unselect chip" : "select chip");
> +       /*
> +        * Here you would write the chip select value to the GPIO pins if
> +        * this was a real chip (but this is a loopback dummy).
> +        */
> +}
> +
> +struct pl022_config_chip pl022_loopback_chip_info = {
> +       /* Nominally this is LOOPBACK_DISABLED, but this is our dummy chip! */
> +       .lbm = LOOPBACK_ENABLED,
> +       .com_mode = INTERRUPT_TRANSFER,
> +       .iface = SSP_INTERFACE_MOTOROLA_SPI,
> +       .hierarchy = SSP_MASTER,
> +       .slave_tx_disable = 0,
> +       /* LSB first */
> +       .endian_tx = SSP_TX_LSB,
> +       .endian_rx = SSP_RX_LSB,
> +       .data_size = SSP_DATA_BITS_8,
> +       .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
> +       .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
> +       .clk_phase = SSP_CLK_SECOND_EDGE,
> +       .clk_pol = SSP_CLK_POL_IDLE_LOW,
> +       .ctrl_len = SSP_BITS_12,
> +       .wait_state = SSP_MWIRE_WAIT_ZERO,
> +       .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
> +       .cs_control = pl022_select_loopback_chip,
> +};
> +
> +static struct spi_board_info pl022_loopback_device = {
> +       /* A dummy chip used for loopback tests */
> +       .modalias       = "pl022-loop",
> +       /* Really dummy, pass in additional chip config here */
> +       .platform_data  = NULL,
> +       /* This defines how the controller shall handle the device */
> +       .controller_data = &pl022_loopback_chip_info,
> +       /* .irq - no external IRQ routed from this device */
> +       .max_speed_hz   = 1000000,
> +       .bus_num        = 0, /* Only one bus on this chip */
> +       .chip_select    = 0,
> +       /* Means SPI_CS_HIGH, change if e.g low CS */
> +       .mode           = 0,
> +};
> +
> +/*
> + * This is called from the PL022 driver to register a loopback
> + * on itself if this module is compiled in.
> + */
> +void pl022_loopback_register(struct spi_master *master)
> +{
> +       struct spi_device *spidev;
> +
> +       spidev = spi_new_device(master, &pl022_loopback_device);
> +       if (!spidev)
> +               dev_err(&master->dev,
> +                       "could not register loopback test chip\n");
> +       else
> +               dev_err(&master->dev,
> +                       "registered loopback test chip\n");
> +}
> +
> +/*
> + * This is where the tests begin. When we issue:
> + * cat /sys/bus/spi/devices/spi0.0/looptest
> + * this will be triggered.
> + */
> +static ssize_t pl022_looptest(struct device *dev,
>                struct device_attribute *attr, char *buf)
>  {
>        struct spi_device *spi = to_spi_device(dev);
> -       struct dummy *p_dummy = dev_get_drvdata(&spi->dev);
> +       struct pl022_loopback *p_loop = dev_get_drvdata(&spi->dev);
>
>        /*
>         * WARNING! Do not dereference the chip-specific data in any normal
> @@ -55,7 +127,7 @@ static ssize_t dummy_looptest(struct device *dev,
>        u8 *bigtxbuf_virtual;
>        u8 *bigrxbuf_virtual;
>
> -       if (mutex_lock_interruptible(&p_dummy->lock))
> +       if (mutex_lock_interruptible(&p_loop->lock))
>                return -ERESTARTSYS;
>
>        bigtxbuf_virtual = kmalloc(DMA_TEST_SIZE, GFP_KERNEL);
> @@ -217,25 +289,25 @@ static ssize_t dummy_looptest(struct device *dev,
>        kfree(bigrxbuf_virtual);
>        kfree(bigtxbuf_virtual);
>  out:
> -       mutex_unlock(&p_dummy->lock);
> +       mutex_unlock(&p_loop->lock);
>        return status;
>  }
>
> -static DEVICE_ATTR(looptest, S_IRUGO, dummy_looptest, NULL);
> +static DEVICE_ATTR(looptest, S_IRUGO, pl022_looptest, NULL);
>
> -static int __devinit pl022_dummy_probe(struct spi_device *spi)
> +static int __devinit pl022_loopback_probe(struct spi_device *spi)
>  {
> -       struct dummy *p_dummy;
> +       struct pl022_loopback *p_loop;
>        int status;
>
>        dev_info(&spi->dev, "probing dummy SPI device\n");
>
> -       p_dummy = kzalloc(sizeof *p_dummy, GFP_KERNEL);
> -       if (!p_dummy)
> +       p_loop = kzalloc(sizeof *p_loop, GFP_KERNEL);
> +       if (!p_loop)
>                return -ENOMEM;
>
> -       dev_set_drvdata(&spi->dev, p_dummy);
> -       mutex_init(&p_dummy->lock);
> +       dev_set_drvdata(&spi->dev, p_loop);
> +       mutex_init(&p_loop->lock);
>
>        /* sysfs hook */
>        status = device_create_file(&spi->dev, &dev_attr_looptest);
> @@ -248,29 +320,29 @@ static int __devinit pl022_dummy_probe(struct spi_device *spi)
>
>  out_dev_create_looptest_failed:
>        dev_set_drvdata(&spi->dev, NULL);
> -       kfree(p_dummy);
> +       kfree(p_loop);
>        return status;
>  }
>
> -static int __devexit pl022_dummy_remove(struct spi_device *spi)
> +static int __devexit pl022_loopback_remove(struct spi_device *spi)
>  {
> -       struct dummy *p_dummy = dev_get_drvdata(&spi->dev);
> +       struct pl022_loopback *p_loop = dev_get_drvdata(&spi->dev);
>
>        dev_info(&spi->dev, "removing dummy SPI device\n");
>        device_remove_file(&spi->dev, &dev_attr_looptest);
>        dev_set_drvdata(&spi->dev, NULL);
> -       kfree(p_dummy);
> +       kfree(p_loop);
>
>        return 0;
>  }
>
>  static struct spi_driver pl022_dummy_driver = {
>        .driver = {
> -               .name   = "spi-dummy",
> +               .name   = "pl022-loop",
>                .owner  = THIS_MODULE,
>        },
> -       .probe  = pl022_dummy_probe,
> -       .remove = __devexit_p(pl022_dummy_remove),
> +       .probe  = pl022_loopback_probe,
> +       .remove = __devexit_p(pl022_loopback_remove),
>  };
>
>  static int __init pl022_init_dummy(void)
> @@ -287,5 +359,5 @@ module_init(pl022_init_dummy);
>  module_exit(pl022_exit_dummy);
>
>  MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
> -MODULE_DESCRIPTION("PL022 SSP/SPI DUMMY Linux driver");
> +MODULE_DESCRIPTION("PL022 loopback test driver");
>  MODULE_LICENSE("GPL");
> diff --git a/drivers/spi/amba-pl022-looptest.h b/drivers/spi/amba-pl022-looptest.h
> new file mode 100644
> index 0000000..1bedcc6
> --- /dev/null
> +++ b/drivers/spi/amba-pl022-looptest.h
> @@ -0,0 +1,11 @@
> +/*
> + * Defines a single function for the master to create a loopback
> + * on itself.
> + */
> +#ifdef CONFIG_SPI_PL022_LOOPTEST
> +void pl022_loopback_register(struct spi_master *master);
> +#else
> +static void inline pl022_loopback_register(struct spi_master *master)
> +{
> +}
> +#endif
> diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c
> index f0a1418..6e4a657 100644
> --- a/drivers/spi/amba-pl022.c
> +++ b/drivers/spi/amba-pl022.c
> @@ -46,6 +46,8 @@
>  #include <linux/io.h>
>  #include <linux/slab.h>
>
> +#include "amba-pl022-looptest.h"
> +
>  /*
>  * This macro is used to define some register default values.
>  * reg is masked with mask, the OR:ed with an (again masked)
> @@ -1818,6 +1820,10 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
>                goto err_spi_register;
>        }
>        dev_dbg(dev, "probe succeded\n");
> +
> +       /* Register a loopback test if desired */
> +       pl022_loopback_register(master);
> +
>        return 0;
>
>  err_spi_register:
> --
> 1.7.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>



-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [spi-devel-general] [PATCH 2/2] SPI: make the moved loopback test work
  2010-07-19  5:51 ` Grant Likely
@ 2010-07-19 10:16   ` David Brownell
       [not found]     ` <377310.49674.qm-4JhmkcZgSkmORdMXk8NaZPu2YVrzzGjVVpNB7YpNyf8@public.gmane.org>
  0 siblings, 1 reply; 9+ messages in thread
From: David Brownell @ 2010-07-19 10:16 UTC (permalink / raw)
  To: Linus Walleij, Grant Likely; +Cc: spi-devel-general, linux-arm-kernel

A dedicated loopback test is the wrong model,
given that SPI_LOOP exists.  And is even used
in the sample userspace code ...

- Dave

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] SPI: make the moved loopback test work
       [not found]     ` <377310.49674.qm-4JhmkcZgSkmORdMXk8NaZPu2YVrzzGjVVpNB7YpNyf8@public.gmane.org>
@ 2010-07-19 16:03       ` Linus Walleij
  2010-07-19 23:53       ` Linus Walleij
  1 sibling, 0 replies; 9+ messages in thread
From: Linus Walleij @ 2010-07-19 16:03 UTC (permalink / raw)
  To: David Brownell
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

2010/7/19 David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>:

> A dedicated loopback test is the wrong model,
> given that SPI_LOOP exists.  And is even used
> in the sample userspace code ...

Yeah I see, I never quite understood how SPI_LOOP
was intended really.

>From there to writing a *generic* loopback test is a bit
of road to cover though, let's see if I can figure it out.

The way I read the code I still have to provide some
kind of dummychip on the bus in order to perform a
loopback test on a bus with no devices connected,
am I right?

Yours,
Linus Walleij

------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] SPI: make the moved loopback test work
       [not found]     ` <377310.49674.qm-4JhmkcZgSkmORdMXk8NaZPu2YVrzzGjVVpNB7YpNyf8@public.gmane.org>
  2010-07-19 16:03       ` Linus Walleij
@ 2010-07-19 23:53       ` Linus Walleij
  2010-07-20  1:32         ` [spi-devel-general] " David Brownell
  1 sibling, 1 reply; 9+ messages in thread
From: Linus Walleij @ 2010-07-19 23:53 UTC (permalink / raw)
  To: David Brownell, Anton Vorontsov
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

2010/7/19 David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>:

> A dedicated loopback test is the wrong model,
> given that SPI_LOOP exists.  And is even used
> in the sample userspace code ...

Hm looking over and grepping everywhere about this gives
me no clues as to how an in-kernel SPI loopback test could
use spi->mode |= SPI_LOOP. It can be set, and then it expects
the hardware to set the corresponding bit.

No matter how much I look at it, it seems like all use of this
require you to first register *some* device, whether real or
not, then you may play with it from kernelspace or userspace
alike.

So for a generic loopback in-kernel test I would need
something like:

loop over all masters
  for each master
    if it supports SPI_LOOP
      look for devices on master - make sure first device is a
      loopback dummy
      locate loopback dummy
      perform loopback test on the dummy

This means I still would have to register some dummychip
on the devices that should be able to run the test.

Anton, any hints on this, execept that you added it for
spidev?

I'll try to dream some use model up otherwise.

Yours,
Linus Walleij

------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [spi-devel-general] [PATCH 2/2] SPI: make the moved loopback test work
  2010-07-19 23:53       ` Linus Walleij
@ 2010-07-20  1:32         ` David Brownell
       [not found]           ` <812288.2599.qm-4JhmkcZgSkkA0QRgWO9Mevu2YVrzzGjVVpNB7YpNyf8@public.gmane.org>
  0 siblings, 1 reply; 9+ messages in thread
From: David Brownell @ 2010-07-20  1:32 UTC (permalink / raw)
  To: Anton Vorontsov, Linus Walleij; +Cc: spi-devel-general, linux-arm-kernel

> No matter how much I look at it, it seems like
> all use of this require you to first register
> *some* device, 

OBVIOUSLY.  You can't use SPI without a device;
it's like any other driver framework in Linux.
What else should you expect???

Look at the sample code though, ISTR you'll see
that when the SPI master works correctly, putting
it into loopback mode just means that the writes
and reads (should) get the same data -- full duplex.
No matter what the device is (given SPI_LOOP).

- Dave

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] SPI: make the moved loopback test work
       [not found]           ` <812288.2599.qm-4JhmkcZgSkkA0QRgWO9Mevu2YVrzzGjVVpNB7YpNyf8@public.gmane.org>
@ 2010-07-20 21:10             ` Linus Walleij
  2010-07-25  7:48               ` [spi-devel-general] " Grant Likely
  0 siblings, 1 reply; 9+ messages in thread
From: Linus Walleij @ 2010-07-20 21:10 UTC (permalink / raw)
  To: David Brownell
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	Anton Vorontsov,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

2010/7/20 David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>:

>> No matter how much I look at it, it seems like
>> all use of this require you to first register
>> *some* device,
>
> OBVIOUSLY.  You can't use SPI without a device;
> it's like any other driver framework in Linux.
> What else should you expect???

I didn't expect anything else, it just makes it clear that
the part of my patch registering a dummy device is
not what is being disagreed upon, so this should be OK.

Yours,
Linus Walleij

------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [spi-devel-general] [PATCH 2/2] SPI: make the moved loopback test work
  2010-07-20 21:10             ` Linus Walleij
@ 2010-07-25  7:48               ` Grant Likely
  2010-07-25  8:14                 ` Linus Walleij
  0 siblings, 1 reply; 9+ messages in thread
From: Grant Likely @ 2010-07-25  7:48 UTC (permalink / raw)
  To: Linus Walleij
  Cc: David Brownell, spi-devel-general, Anton Vorontsov,
	linux-arm-kernel

On Tue, Jul 20, 2010 at 3:10 PM, Linus Walleij
<linus.ml.walleij@gmail.com> wrote:
> 2010/7/20 David Brownell <david-b@pacbell.net>:
>
>>> No matter how much I look at it, it seems like
>>> all use of this require you to first register
>>> *some* device,
>>
>> OBVIOUSLY.  You can't use SPI without a device;
>> it's like any other driver framework in Linux.
>> What else should you expect???
>
> I didn't expect anything else, it just makes it clear that
> the part of my patch registering a dummy device is
> not what is being disagreed upon, so this should be OK.

What's disagreed with is the dummy device knowing the intimate working
details of the SPI bus driver.

g.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] SPI: make the moved loopback test work
  2010-07-25  7:48               ` [spi-devel-general] " Grant Likely
@ 2010-07-25  8:14                 ` Linus Walleij
  0 siblings, 0 replies; 9+ messages in thread
From: Linus Walleij @ 2010-07-25  8:14 UTC (permalink / raw)
  To: Grant Likely
  Cc: David Brownell,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	Anton Vorontsov,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

2010/7/25 Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>:

> What's disagreed with is the dummy device knowing the intimate working
> details of the SPI bus driver.

OK I'll send the other patch I've been holding back, it merges that part into
the driver itself so it sits in the apropriate containment, and solves
that specific issue.

But I understood Davids criticism like this: "you shouldn't make tests
using loopback for a specific driver, it should be generic, i.e. being
able to perform a loopback test on any driver supporting SPI_LOOP".

A generic loopback test is a lot harder for me to produce, that's
why I was troubled...

Yours,
Linus Walleij

------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2010-07-25  8:14 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-11  0:43 [PATCH 2/2] SPI: make the moved loopback test work Linus Walleij
2010-07-19  5:51 ` Grant Likely
2010-07-19 10:16   ` [spi-devel-general] " David Brownell
     [not found]     ` <377310.49674.qm-4JhmkcZgSkmORdMXk8NaZPu2YVrzzGjVVpNB7YpNyf8@public.gmane.org>
2010-07-19 16:03       ` Linus Walleij
2010-07-19 23:53       ` Linus Walleij
2010-07-20  1:32         ` [spi-devel-general] " David Brownell
     [not found]           ` <812288.2599.qm-4JhmkcZgSkkA0QRgWO9Mevu2YVrzzGjVVpNB7YpNyf8@public.gmane.org>
2010-07-20 21:10             ` Linus Walleij
2010-07-25  7:48               ` [spi-devel-general] " Grant Likely
2010-07-25  8:14                 ` Linus Walleij

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).