Skip to content

Commit

Permalink
Merge branch 'next-spi' of git://git.secretlab.ca/git/linux-2.6
Browse files Browse the repository at this point in the history
* 'next-spi' of git://git.secretlab.ca/git/linux-2.6:
  spi/xilinx: Fix compile error
  spi/davinci: Fix clock prescale factor computation
  spi: move bitbang txrx utility functions to private header
  spi/mpc5121: Add SPI master driver for MPC5121 PSC
  powerpc/mpc5121: move PSC FIFO memory init to platform code
  spi/ep93xx: implemented driver for Cirrus EP93xx SPI controller
  Documentation/spi/* compile warning fix
  spi/omap2_mcspi: Check params before dereference or use
  spi/omap2_mcspi: add turbo mode support
  spi/omap2_mcspi: change default DMA_MIN_BYTES value to 160
  spi/pl022: fix stop queue procedure
  spi/pl022: add support for the PL023 derivate
  spi/pl022: fix up differences between ARM and ST versions
  spi/spi_mpc8xxx: Do not use map_tx_dma to unmap rx_dma
  spi/spi_mpc8xxx: Fix QE mode Litte Endian
  spi/spi_mpc8xxx: fix potential memory corruption.
  • Loading branch information
Linus Torvalds committed May 25, 2010
2 parents c19eb8f + bf6a67e commit 702c0b0
Show file tree
Hide file tree
Showing 23 changed files with 2,262 additions and 319 deletions.
95 changes: 95 additions & 0 deletions Documentation/spi/ep93xx_spi
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
Cirrus EP93xx SPI controller driver HOWTO
=========================================

ep93xx_spi driver brings SPI master support for EP93xx SPI controller. Chip
selects are implemented with GPIO lines.

NOTE: If possible, don't use SFRMOUT (SFRM1) signal as a chip select. It will
not work correctly (it cannot be controlled by software). Use GPIO lines
instead.

Sample configuration
====================

Typically driver configuration is done in platform board files (the files under
arch/arm/mach-ep93xx/*.c). In this example we configure MMC over SPI through
this driver on TS-7260 board. You can adapt the code to suit your needs.

This example uses EGPIO9 as SD/MMC card chip select (this is wired in DIO1
header on the board).

You need to select CONFIG_MMC_SPI to use mmc_spi driver.

arch/arm/mach-ep93xx/ts72xx.c:

...
#include <linux/gpio.h>
#include <linux/spi/spi.h>

#include <mach/ep93xx_spi.h>

/* this is our GPIO line used for chip select */
#define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO9

static int ts72xx_mmc_spi_setup(struct spi_device *spi)
{
int err;

err = gpio_request(MMC_CHIP_SELECT_GPIO, spi->modalias);
if (err)
return err;

gpio_direction_output(MMC_CHIP_SELECT_GPIO, 1);

return 0;
}

static void ts72xx_mmc_spi_cleanup(struct spi_device *spi)
{
gpio_set_value(MMC_CHIP_SELECT_GPIO, 1);
gpio_direction_input(MMC_CHIP_SELECT_GPIO);
gpio_free(MMC_CHIP_SELECT_GPIO);
}

static void ts72xx_mmc_spi_cs_control(struct spi_device *spi, int value)
{
gpio_set_value(MMC_CHIP_SELECT_GPIO, value);
}

static struct ep93xx_spi_chip_ops ts72xx_mmc_spi_ops = {
.setup = ts72xx_mmc_spi_setup,
.cleanup = ts72xx_mmc_spi_cleanup,
.cs_control = ts72xx_mmc_spi_cs_control,
};

static struct spi_board_info ts72xx_spi_devices[] __initdata = {
{
.modalias = "mmc_spi",
.controller_data = &ts72xx_mmc_spi_ops,
/*
* We use 10 MHz even though the maximum is 7.4 MHz. The driver
* will limit it automatically to max. frequency.
*/
.max_speed_hz = 10 * 1000 * 1000,
.bus_num = 0,
.chip_select = 0,
.mode = SPI_MODE_0,
},
};

static struct ep93xx_spi_info ts72xx_spi_info = {
.num_chipselect = ARRAY_SIZE(ts72xx_spi_devices),
};

static void __init ts72xx_init_machine(void)
{
...
ep93xx_register_spi(&ts72xx_spi_info, ts72xx_spi_devices,
ARRAY_SIZE(ts72xx_spi_devices));
}

Thanks to
=========
Martin Guy, H. Hartley Sweeten and others who helped me during development of
the driver. Simplemachines.it donated me a Sim.One board which I used testing
the driver on EP9307.
4 changes: 2 additions & 2 deletions Documentation/spi/spidev_fdx.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ static void do_msg(int fd, int len)
len = sizeof buf;

buf[0] = 0xaa;
xfer[0].tx_buf = (__u64) buf;
xfer[0].tx_buf = (unsigned long)buf;
xfer[0].len = 1;

xfer[1].rx_buf = (__u64) buf;
xfer[1].rx_buf = (unsigned long) buf;
xfer[1].len = len;

status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);
Expand Down
27 changes: 27 additions & 0 deletions arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef __ASM_MACH_EP93XX_SPI_H
#define __ASM_MACH_EP93XX_SPI_H

struct spi_device;

/**
* struct ep93xx_spi_info - EP93xx specific SPI descriptor
* @num_chipselect: number of chip selects on this board, must be
* at least one
*/
struct ep93xx_spi_info {
int num_chipselect;
};

/**
* struct ep93xx_spi_chip_ops - operation callbacks for SPI slave device
* @setup: setup the chip select mechanism
* @cleanup: cleanup the chip select mechanism
* @cs_control: control the device chip select
*/
struct ep93xx_spi_chip_ops {
int (*setup)(struct spi_device *spi);
void (*cleanup)(struct spi_device *spi);
void (*cs_control)(struct spi_device *spi, int value);
};

#endif /* __ASM_MACH_EP93XX_SPI_H */
1 change: 1 addition & 0 deletions arch/powerpc/include/asm/mpc52xx_psc.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ struct mpc52xx_psc_fifo {
u16 tflwfptr; /* PSC + 0x9e */
};

#define MPC512x_PSC_FIFO_EOF 0x100
#define MPC512x_PSC_FIFO_RESET_SLICE 0x80
#define MPC512x_PSC_FIFO_ENABLE_SLICE 0x01
#define MPC512x_PSC_FIFO_ENABLE_DMA 0x04
Expand Down
78 changes: 78 additions & 0 deletions arch/powerpc/platforms/512x/mpc512x_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <asm/prom.h>
#include <asm/time.h>
#include <asm/mpc5121.h>
#include <asm/mpc52xx_psc.h>

#include "mpc512x.h"

Expand Down Expand Up @@ -95,9 +96,86 @@ void __init mpc512x_declare_of_platform_devices(void)
}
}

#define DEFAULT_FIFO_SIZE 16

static unsigned int __init get_fifo_size(struct device_node *np,
char *prop_name)
{
const unsigned int *fp;

fp = of_get_property(np, prop_name, NULL);
if (fp)
return *fp;

pr_warning("no %s property in %s node, defaulting to %d\n",
prop_name, np->full_name, DEFAULT_FIFO_SIZE);

return DEFAULT_FIFO_SIZE;
}

#define FIFOC(_base) ((struct mpc512x_psc_fifo __iomem *) \
((u32)(_base) + sizeof(struct mpc52xx_psc)))

/* Init PSC FIFO space for TX and RX slices */
void __init mpc512x_psc_fifo_init(void)
{
struct device_node *np;
void __iomem *psc;
unsigned int tx_fifo_size;
unsigned int rx_fifo_size;
int fifobase = 0; /* current fifo address in 32 bit words */

for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
tx_fifo_size = get_fifo_size(np, "fsl,tx-fifo-size");
rx_fifo_size = get_fifo_size(np, "fsl,rx-fifo-size");

/* size in register is in 4 byte units */
tx_fifo_size /= 4;
rx_fifo_size /= 4;
if (!tx_fifo_size)
tx_fifo_size = 1;
if (!rx_fifo_size)
rx_fifo_size = 1;

psc = of_iomap(np, 0);
if (!psc) {
pr_err("%s: Can't map %s device\n",
__func__, np->full_name);
continue;
}

/* FIFO space is 4KiB, check if requested size is available */
if ((fifobase + tx_fifo_size + rx_fifo_size) > 0x1000) {
pr_err("%s: no fifo space available for %s\n",
__func__, np->full_name);
iounmap(psc);
/*
* chances are that another device requests less
* fifo space, so we continue.
*/
continue;
}

/* set tx and rx fifo size registers */
out_be32(&FIFOC(psc)->txsz, (fifobase << 16) | tx_fifo_size);
fifobase += tx_fifo_size;
out_be32(&FIFOC(psc)->rxsz, (fifobase << 16) | rx_fifo_size);
fifobase += rx_fifo_size;

/* reset and enable the slices */
out_be32(&FIFOC(psc)->txcmd, 0x80);
out_be32(&FIFOC(psc)->txcmd, 0x01);
out_be32(&FIFOC(psc)->rxcmd, 0x80);
out_be32(&FIFOC(psc)->rxcmd, 0x01);

iounmap(psc);
}
}

void __init mpc512x_init(void)
{
mpc512x_declare_of_platform_devices();
mpc5121_clk_init();
mpc512x_restart_init();
mpc512x_psc_fifo_init();
}
69 changes: 0 additions & 69 deletions drivers/serial/mpc52xx_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,34 +397,10 @@ static unsigned long mpc512x_getuartclk(void *p)
return mpc5xxx_get_bus_frequency(p);
}

#define DEFAULT_FIFO_SIZE 16

static unsigned int __init get_fifo_size(struct device_node *np,
char *fifo_name)
{
const unsigned int *fp;

fp = of_get_property(np, fifo_name, NULL);
if (fp)
return *fp;

pr_warning("no %s property in %s node, defaulting to %d\n",
fifo_name, np->full_name, DEFAULT_FIFO_SIZE);

return DEFAULT_FIFO_SIZE;
}

#define FIFOC(_base) ((struct mpc512x_psc_fifo __iomem *) \
((u32)(_base) + sizeof(struct mpc52xx_psc)))

/* Init PSC FIFO Controller */
static int __init mpc512x_psc_fifoc_init(void)
{
struct device_node *np;
void __iomem *psc;
unsigned int tx_fifo_size;
unsigned int rx_fifo_size;
int fifobase = 0; /* current fifo address in 32 bit words */

np = of_find_compatible_node(NULL, NULL,
"fsl,mpc5121-psc-fifo");
Expand All @@ -447,51 +423,6 @@ static int __init mpc512x_psc_fifoc_init(void)
return -ENODEV;
}

for_each_compatible_node(np, NULL, "fsl,mpc5121-psc-uart") {
tx_fifo_size = get_fifo_size(np, "fsl,tx-fifo-size");
rx_fifo_size = get_fifo_size(np, "fsl,rx-fifo-size");

/* size in register is in 4 byte units */
tx_fifo_size /= 4;
rx_fifo_size /= 4;
if (!tx_fifo_size)
tx_fifo_size = 1;
if (!rx_fifo_size)
rx_fifo_size = 1;

psc = of_iomap(np, 0);
if (!psc) {
pr_err("%s: Can't map %s device\n",
__func__, np->full_name);
continue;
}

/* FIFO space is 4KiB, check if requested size is available */
if ((fifobase + tx_fifo_size + rx_fifo_size) > 0x1000) {
pr_err("%s: no fifo space available for %s\n",
__func__, np->full_name);
iounmap(psc);
/*
* chances are that another device requests less
* fifo space, so we continue.
*/
continue;
}
/* set tx and rx fifo size registers */
out_be32(&FIFOC(psc)->txsz, (fifobase << 16) | tx_fifo_size);
fifobase += tx_fifo_size;
out_be32(&FIFOC(psc)->rxsz, (fifobase << 16) | rx_fifo_size);
fifobase += rx_fifo_size;

/* reset and enable the slices */
out_be32(&FIFOC(psc)->txcmd, 0x80);
out_be32(&FIFOC(psc)->txcmd, 0x01);
out_be32(&FIFOC(psc)->rxcmd, 0x80);
out_be32(&FIFOC(psc)->rxcmd, 0x01);

iounmap(psc);
}

return 0;
}

Expand Down
17 changes: 17 additions & 0 deletions drivers/spi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,16 @@ config SPI_DAVINCI
help
SPI master controller for DaVinci and DA8xx SPI modules.

config SPI_EP93XX
tristate "Cirrus Logic EP93xx SPI controller"
depends on ARCH_EP93XX
help
This enables using the Cirrus EP93xx SPI controller in master
mode.

To compile this driver as a module, choose M here. The module will be
called ep93xx_spi.

config SPI_GPIO
tristate "GPIO-based bitbanging SPI Master"
depends on GENERIC_GPIO
Expand Down Expand Up @@ -165,6 +175,13 @@ config SPI_MPC52xx_PSC
This enables using the Freescale MPC52xx Programmable Serial
Controller in master SPI mode.

config SPI_MPC512x_PSC
tristate "Freescale MPC512x PSC SPI controller"
depends on SPI_MASTER && PPC_MPC512x
help
This enables using the Freescale MPC5121 Programmable Serial
Controller in SPI master mode.

config SPI_MPC8xxx
tristate "Freescale MPC8xxx SPI controller"
depends on FSL_SOC
Expand Down
2 changes: 2 additions & 0 deletions drivers/spi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ obj-$(CONFIG_SPI_DAVINCI) += davinci_spi.o
obj-$(CONFIG_SPI_DESIGNWARE) += dw_spi.o
obj-$(CONFIG_SPI_DW_PCI) += dw_spi_pci.o
obj-$(CONFIG_SPI_DW_MMIO) += dw_spi_mmio.o
obj-$(CONFIG_SPI_EP93XX) += ep93xx_spi.o
obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
obj-$(CONFIG_SPI_IMX) += spi_imx.o
obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
Expand All @@ -30,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_MPC512x_PSC) += mpc512x_psc_spi.o
obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o
obj-$(CONFIG_SPI_MPC52xx) += mpc52xx_spi.o
obj-$(CONFIG_SPI_MPC8xxx) += spi_mpc8xxx.o
Expand Down
Loading

0 comments on commit 702c0b0

Please sign in to comment.