@@ -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
@@ -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
@@ -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;
@@ -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
@@ -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
@@ -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");
new file mode 100644
@@ -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
@@ -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: