Merge branch 'next-spi' of git://git.secretlab.ca/git/linux-2.6

* 'next-spi' of git://git.secretlab.ca/git/linux-2.6:
  spi/pl022: move probe call to subsys_initcall()
  powerpc/5200: mpc52xx_uart.c: Add of_node_put to avoid memory leak
  spi/pl022: fix APB pclk power regression on U300
  spi/spi_s3c64xx: Warn if PIO transfers time out
  spi/s3c64xx: Fix incorrect reuse of 'val' local variable.
  spi/s3c64xx: Fix compilation warning
  spi/dw_spi: clean the cs_control code
  spi/dw_spi: Allow interrupt sharing
  spi/spi_s3c64xx: Increase dead reckoning time in wait_for_xfer()
  spi/spi_s3c64xx: Move to subsys_initcall()
  spi: free children in spi_unregister_master, not siblings
  gpiolib: Add 'struct gpio_chip' forward declaration for !GPIOLIB case
  of: Fix missing includes - ll_temac
  spi/spi_s3c64xx: Staticise non-exported functions
  spi/spi_s3c64xx: Make probe more robust against missing board config
This commit is contained in:
Linus Torvalds 2010-09-13 12:45:50 -07:00
commit 6142811a33
9 changed files with 54 additions and 38 deletions

View File

@ -38,6 +38,7 @@
#include <linux/of_device.h>
#include <linux/of_mdio.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/tcp.h> /* needed for sizeof(tcphdr) */

View File

@ -10,6 +10,7 @@
#include <linux/phy.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/of_mdio.h>

View File

@ -500,6 +500,7 @@ static int __init mpc512x_psc_fifoc_init(void)
psc_fifoc = of_iomap(np, 0);
if (!psc_fifoc) {
pr_err("%s: Can't map FIFOC\n", __func__);
of_node_put(np);
return -ENODEV;
}

View File

@ -503,8 +503,9 @@ static void giveback(struct pl022 *pl022)
msg->state = NULL;
if (msg->complete)
msg->complete(msg->context);
/* This message is completed, so let's turn off the clock! */
/* This message is completed, so let's turn off the clocks! */
clk_disable(pl022->clk);
amba_pclk_disable(pl022->adev);
}
/**
@ -1139,9 +1140,10 @@ static void pump_messages(struct work_struct *work)
/* Setup the SPI using the per chip configuration */
pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
/*
* We enable the clock here, then the clock will be disabled when
* We enable the clocks here, then the clocks will be disabled when
* giveback() is called in each method (poll/interrupt/DMA)
*/
amba_pclk_enable(pl022->adev);
clk_enable(pl022->clk);
restore_state(pl022);
flush(pl022);
@ -1786,11 +1788,9 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
}
/* Disable SSP */
clk_enable(pl022->clk);
writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
SSP_CR1(pl022->virtbase));
load_ssp_default_config(pl022);
clk_disable(pl022->clk);
status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022",
pl022);
@ -1818,6 +1818,8 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
goto err_spi_register;
}
dev_dbg(dev, "probe succeded\n");
/* Disable the silicon block pclk and clock it when needed */
amba_pclk_disable(adev);
return 0;
err_spi_register:
@ -1879,9 +1881,9 @@ static int pl022_suspend(struct amba_device *adev, pm_message_t state)
return status;
}
clk_enable(pl022->clk);
amba_pclk_enable(adev);
load_ssp_default_config(pl022);
clk_disable(pl022->clk);
amba_pclk_disable(adev);
dev_dbg(&adev->dev, "suspended\n");
return 0;
}
@ -1981,7 +1983,7 @@ static int __init pl022_init(void)
return amba_driver_register(&pl022_driver);
}
module_init(pl022_init);
subsys_initcall(pl022_init);
static void __exit pl022_exit(void)
{

View File

@ -181,10 +181,6 @@ static void flush(struct dw_spi *dws)
wait_till_not_busy(dws);
}
static void null_cs_control(u32 command)
{
}
static int null_writer(struct dw_spi *dws)
{
u8 n_bytes = dws->n_bytes;
@ -322,7 +318,7 @@ static void giveback(struct dw_spi *dws)
struct spi_transfer,
transfer_list);
if (!last_transfer->cs_change)
if (!last_transfer->cs_change && dws->cs_control)
dws->cs_control(MRST_SPI_DEASSERT);
msg->state = NULL;
@ -396,6 +392,11 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
static irqreturn_t dw_spi_irq(int irq, void *dev_id)
{
struct dw_spi *dws = dev_id;
u16 irq_status, irq_mask = 0x3f;
irq_status = dw_readw(dws, isr) & irq_mask;
if (!irq_status)
return IRQ_NONE;
if (!dws->cur_msg) {
spi_mask_intr(dws, SPI_INT_TXEI);
@ -544,13 +545,13 @@ static void pump_transfers(unsigned long data)
*/
if (dws->cs_control) {
if (dws->rx && dws->tx)
chip->tmode = 0x00;
chip->tmode = SPI_TMOD_TR;
else if (dws->rx)
chip->tmode = 0x02;
chip->tmode = SPI_TMOD_RO;
else
chip->tmode = 0x01;
chip->tmode = SPI_TMOD_TO;
cr0 &= ~(0x3 << SPI_MODE_OFFSET);
cr0 &= ~SPI_TMOD_MASK;
cr0 |= (chip->tmode << SPI_TMOD_OFFSET);
}
@ -699,9 +700,6 @@ static int dw_spi_setup(struct spi_device *spi)
chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
if (!chip)
return -ENOMEM;
chip->cs_control = null_cs_control;
chip->enable_dma = 0;
}
/*
@ -883,7 +881,7 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)
dws->dma_inited = 0;
dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
ret = request_irq(dws->irq, dw_spi_irq, 0,
ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED,
"dw_spi", dws);
if (ret < 0) {
dev_err(&master->dev, "can not get IRQ\n");

View File

@ -554,11 +554,9 @@ done:
EXPORT_SYMBOL_GPL(spi_register_master);
static int __unregister(struct device *dev, void *master_dev)
static int __unregister(struct device *dev, void *null)
{
/* note: before about 2.6.14-rc1 this would corrupt memory: */
if (dev != master_dev)
spi_unregister_device(to_spi_device(dev));
spi_unregister_device(to_spi_device(dev));
return 0;
}
@ -576,8 +574,7 @@ void spi_unregister_master(struct spi_master *master)
{
int dummy;
dummy = device_for_each_child(master->dev.parent, &master->dev,
__unregister);
dummy = device_for_each_child(&master->dev, NULL, __unregister);
device_unregister(&master->dev);
}
EXPORT_SYMBOL_GPL(spi_unregister_master);

View File

@ -200,6 +200,9 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
val = readl(regs + S3C64XX_SPI_STATUS);
} while (TX_FIFO_LVL(val, sci) && loops--);
if (loops == 0)
dev_warn(&sdd->pdev->dev, "Timed out flushing TX FIFO\n");
/* Flush RxFIFO*/
loops = msecs_to_loops(1);
do {
@ -210,6 +213,9 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
break;
} while (loops--);
if (loops == 0)
dev_warn(&sdd->pdev->dev, "Timed out flushing RX FIFO\n");
val = readl(regs + S3C64XX_SPI_CH_CFG);
val &= ~S3C64XX_SPI_CH_SW_RST;
writel(val, regs + S3C64XX_SPI_CH_CFG);
@ -320,16 +326,17 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
/* millisecs to xfer 'len' bytes @ 'cur_speed' */
ms = xfer->len * 8 * 1000 / sdd->cur_speed;
ms += 5; /* some tolerance */
ms += 10; /* some tolerance */
if (dma_mode) {
val = msecs_to_jiffies(ms) + 10;
val = wait_for_completion_timeout(&sdd->xfer_completion, val);
} else {
u32 status;
val = msecs_to_loops(ms);
do {
val = readl(regs + S3C64XX_SPI_STATUS);
} while (RX_FIFO_LVL(val, sci) < xfer->len && --val);
status = readl(regs + S3C64XX_SPI_STATUS);
} while (RX_FIFO_LVL(status, sci) < xfer->len && --val);
}
if (!val)
@ -447,8 +454,8 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
writel(val, regs + S3C64XX_SPI_CLK_CFG);
}
void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
int size, enum s3c2410_dma_buffresult res)
static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
int size, enum s3c2410_dma_buffresult res)
{
struct s3c64xx_spi_driver_data *sdd = buf_id;
unsigned long flags;
@ -467,8 +474,8 @@ void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
spin_unlock_irqrestore(&sdd->lock, flags);
}
void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
int size, enum s3c2410_dma_buffresult res)
static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
int size, enum s3c2410_dma_buffresult res)
{
struct s3c64xx_spi_driver_data *sdd = buf_id;
unsigned long flags;
@ -508,8 +515,9 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (xfer->tx_buf != NULL) {
xfer->tx_dma = dma_map_single(dev, xfer->tx_buf,
xfer->len, DMA_TO_DEVICE);
xfer->tx_dma = dma_map_single(dev,
(void *)xfer->tx_buf, xfer->len,
DMA_TO_DEVICE);
if (dma_mapping_error(dev, xfer->tx_dma)) {
dev_err(dev, "dma_map_single Tx failed\n");
xfer->tx_dma = XFER_DMAADDR_INVALID;
@ -919,6 +927,13 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
return -ENODEV;
}
sci = pdev->dev.platform_data;
if (!sci->src_clk_name) {
dev_err(&pdev->dev,
"Board init must call s3c64xx_spi_set_info()\n");
return -EINVAL;
}
/* Check for availability of necessary resource */
dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@ -946,8 +961,6 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
return -ENOMEM;
}
sci = pdev->dev.platform_data;
platform_set_drvdata(pdev, master);
sdd = spi_master_get_devdata(master);
@ -1170,7 +1183,7 @@ static int __init s3c64xx_spi_init(void)
{
return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe);
}
module_init(s3c64xx_spi_init);
subsys_initcall(s3c64xx_spi_init);
static void __exit s3c64xx_spi_exit(void)
{

View File

@ -13,6 +13,7 @@
#include <linux/errno.h>
struct device;
struct gpio_chip;
/*
* Some platforms don't support the GPIO programming interface.

View File

@ -14,7 +14,9 @@
#define SPI_MODE_OFFSET 6
#define SPI_SCPH_OFFSET 6
#define SPI_SCOL_OFFSET 7
#define SPI_TMOD_OFFSET 8
#define SPI_TMOD_MASK (0x3 << SPI_TMOD_OFFSET)
#define SPI_TMOD_TR 0x0 /* xmit & recv */
#define SPI_TMOD_TO 0x1 /* xmit only */
#define SPI_TMOD_RO 0x2 /* recv only */