mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 00:34:20 +08:00
Miscellaneous SPI device driver bug fixes for v3.4
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJPmubjAAoJEEFnBt12D9kBPZ4P/2wrFqNy2+Fxatstmb1GKwqW Yx0acIZkJK/gfZetFDSiTzM8bcxp/oz2lfqHE7xFq96s36wSZyO9B9Ry+YiD9x4g wzN/Gb7UufnuSEEJo19E13sJxMXJ/4dVFHKtJnxSL3k9lC6nO/YkEn7C2OXE9gXy d3a8H2jyGK9CPPHzQVxDP+9vYj8RpZcXz1M49H8dZ7UZblPfHlvPNzsclKbuTiFK 8zg16sX01BjvbawwMuAuJH/SGytKpM7WtlzDni/OplqX3CDjIoNZ8BEqDgXDVcS8 dwhmhPEf89v5ctWhaDHlskwAkL8oFjwFAHMZ7pjiIZ1aTxPPEKtyegVqPKoQwQmK XCbjb9SqFNRXI2nIkbeX1xGHQS1wngRcfWJ13qLDEDi3d3aGLUJDYTtMHPrjvNnI kzqbNC6fFuKZNOaDYMb1nqV3oWa8VLlDhXgEn5K8ZzBInZ/12LsqybRqImwLQnN0 flRCcOWApbHmJB64IAI1NzbG5Y6FxG53lwW+bwkw83W1fWw1WaUNNvJ8HBfDoN3G QflSqY8TtRE5vGvTburRbDIF3YBeGsaPDTksIg2t82PZ1SabUfIhpWRbhzS6YvMH NiKlgk88Q3VHLUF4TOxDThXZEJpL4VcJWOV0/Y4eSDNNhOtBKfGMoo9EBCfLwevM q6EyapSjiDz0pu9jUN/P =V4y2 -----END PGP SIGNATURE----- Merge tag 'spi-for-linus' of git://git.secretlab.ca/git/linux-2.6 Pull misc SPI device driver bug fixes from Grant Likely. * tag 'spi-for-linus' of git://git.secretlab.ca/git/linux-2.6: spi/spi-bfin5xx: Fix flush of last bit after each spi transfer spi/spi-bfin5xx: fix reversed if condition in interrupt mode spi/spi_bfin_sport: drop bits_per_word from client data spi/bfin_spi: drop bits_per_word from client data spi/spi-bfin-sport: move word length setup to transfer handler spi/bfin5xx: rename config macro name for bfin5xx spi controller driver spi/pl022: Allow request for higher frequency than maximum possible spi/bcm63xx: set master driver mode_bits. spi/bcm63xx: don't use the stopping state spi/bcm63xx: convert to the pump message infrastructure spi/spi-ep93xx.c: use dma_transfer_direction instead of dma_data_direction spi: fix spi.h kernel-doc warning spi/pl022: Fix calculate_effective_freq() spi/pl022: Fix range checking for bits per word
This commit is contained in:
commit
84c6a81bc6
@ -74,7 +74,7 @@ config SPI_ATMEL
|
||||
This selects a driver for the Atmel SPI Controller, present on
|
||||
many AT32 (AVR32) and AT91 (ARM) chips.
|
||||
|
||||
config SPI_BFIN
|
||||
config SPI_BFIN5XX
|
||||
tristate "SPI controller driver for ADI Blackfin5xx"
|
||||
depends on BLACKFIN
|
||||
help
|
||||
|
@ -15,7 +15,7 @@ obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
|
||||
obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
|
||||
obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
|
||||
obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
|
||||
obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.o
|
||||
obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o
|
||||
obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
|
||||
obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
|
||||
obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Broadcom BCM63xx SPI controller support
|
||||
*
|
||||
* Copyright (C) 2009-2011 Florian Fainelli <florian@openwrt.org>
|
||||
* Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
|
||||
* Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -30,6 +30,8 @@
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <bcm63xx_dev_spi.h>
|
||||
|
||||
@ -37,8 +39,6 @@
|
||||
#define DRV_VER "0.1.2"
|
||||
|
||||
struct bcm63xx_spi {
|
||||
spinlock_t lock;
|
||||
int stopping;
|
||||
struct completion done;
|
||||
|
||||
void __iomem *regs;
|
||||
@ -96,17 +96,12 @@ static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
|
||||
{ 391000, SPI_CLK_0_391MHZ }
|
||||
};
|
||||
|
||||
static int bcm63xx_spi_setup_transfer(struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
static int bcm63xx_spi_check_transfer(struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
|
||||
u8 bits_per_word;
|
||||
u8 clk_cfg, reg;
|
||||
u32 hz;
|
||||
int i;
|
||||
|
||||
bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
|
||||
hz = (t) ? t->speed_hz : spi->max_speed_hz;
|
||||
if (bits_per_word != 8) {
|
||||
dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
|
||||
__func__, bits_per_word);
|
||||
@ -119,6 +114,19 @@ static int bcm63xx_spi_setup_transfer(struct spi_device *spi,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
|
||||
u32 hz;
|
||||
u8 clk_cfg, reg;
|
||||
int i;
|
||||
|
||||
hz = (t) ? t->speed_hz : spi->max_speed_hz;
|
||||
|
||||
/* Find the closest clock configuration */
|
||||
for (i = 0; i < SPI_CLK_MASK; i++) {
|
||||
if (hz <= bcm63xx_spi_freq_table[i][0]) {
|
||||
@ -139,8 +147,6 @@ static int bcm63xx_spi_setup_transfer(struct spi_device *spi,
|
||||
bcm_spi_writeb(bs, reg, SPI_CLK_CFG);
|
||||
dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n",
|
||||
clk_cfg, hz);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* the spi->mode bits understood by this driver: */
|
||||
@ -153,9 +159,6 @@ static int bcm63xx_spi_setup(struct spi_device *spi)
|
||||
|
||||
bs = spi_master_get_devdata(spi->master);
|
||||
|
||||
if (bs->stopping)
|
||||
return -ESHUTDOWN;
|
||||
|
||||
if (!spi->bits_per_word)
|
||||
spi->bits_per_word = 8;
|
||||
|
||||
@ -165,7 +168,7 @@ static int bcm63xx_spi_setup(struct spi_device *spi)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = bcm63xx_spi_setup_transfer(spi, NULL);
|
||||
ret = bcm63xx_spi_check_transfer(spi, NULL);
|
||||
if (ret < 0) {
|
||||
dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
|
||||
spi->mode & ~MODEBITS);
|
||||
@ -190,28 +193,29 @@ static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs)
|
||||
bs->remaining_bytes -= size;
|
||||
}
|
||||
|
||||
static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
|
||||
static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
|
||||
u16 msg_ctl;
|
||||
u16 cmd;
|
||||
|
||||
/* Disable the CMD_DONE interrupt */
|
||||
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
|
||||
|
||||
dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
|
||||
t->tx_buf, t->rx_buf, t->len);
|
||||
|
||||
/* Transmitter is inhibited */
|
||||
bs->tx_ptr = t->tx_buf;
|
||||
bs->rx_ptr = t->rx_buf;
|
||||
init_completion(&bs->done);
|
||||
|
||||
if (t->tx_buf) {
|
||||
bs->remaining_bytes = t->len;
|
||||
bcm63xx_spi_fill_tx_fifo(bs);
|
||||
}
|
||||
|
||||
/* Enable the command done interrupt which
|
||||
* we use to determine completion of a command */
|
||||
bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
|
||||
init_completion(&bs->done);
|
||||
|
||||
/* Fill in the Message control register */
|
||||
msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);
|
||||
@ -230,33 +234,76 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
|
||||
cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
|
||||
cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT);
|
||||
bcm_spi_writew(bs, cmd, SPI_CMD);
|
||||
wait_for_completion(&bs->done);
|
||||
|
||||
/* Disable the CMD_DONE interrupt */
|
||||
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
|
||||
/* Enable the CMD_DONE interrupt */
|
||||
bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
|
||||
|
||||
return t->len - bs->remaining_bytes;
|
||||
}
|
||||
|
||||
static int bcm63xx_transfer(struct spi_device *spi, struct spi_message *m)
|
||||
static int bcm63xx_spi_prepare_transfer(struct spi_master *master)
|
||||
{
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
||||
|
||||
pm_runtime_get_sync(&bs->pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm63xx_spi_unprepare_transfer(struct spi_master *master)
|
||||
{
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
||||
|
||||
pm_runtime_put(&bs->pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm63xx_spi_transfer_one(struct spi_master *master,
|
||||
struct spi_message *m)
|
||||
{
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
||||
struct spi_transfer *t;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(list_empty(&m->transfers)))
|
||||
return -EINVAL;
|
||||
|
||||
if (bs->stopping)
|
||||
return -ESHUTDOWN;
|
||||
struct spi_device *spi = m->spi;
|
||||
int status = 0;
|
||||
unsigned int timeout = 0;
|
||||
|
||||
list_for_each_entry(t, &m->transfers, transfer_list) {
|
||||
ret += bcm63xx_txrx_bufs(spi, t);
|
||||
unsigned int len = t->len;
|
||||
u8 rx_tail;
|
||||
|
||||
status = bcm63xx_spi_check_transfer(spi, t);
|
||||
if (status < 0)
|
||||
goto exit;
|
||||
|
||||
/* configure adapter for a new transfer */
|
||||
bcm63xx_spi_setup_transfer(spi, t);
|
||||
|
||||
while (len) {
|
||||
/* send the data */
|
||||
len -= bcm63xx_txrx_bufs(spi, t);
|
||||
|
||||
timeout = wait_for_completion_timeout(&bs->done, HZ);
|
||||
if (!timeout) {
|
||||
status = -ETIMEDOUT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* read out all data */
|
||||
rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
|
||||
|
||||
/* Read out all the data */
|
||||
if (rx_tail)
|
||||
memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail);
|
||||
}
|
||||
|
||||
m->actual_length += t->len;
|
||||
}
|
||||
exit:
|
||||
m->status = status;
|
||||
spi_finalize_current_message(master);
|
||||
|
||||
m->complete(m->context);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This driver supports single master mode only. Hence
|
||||
@ -267,39 +314,15 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
|
||||
struct spi_master *master = (struct spi_master *)dev_id;
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
||||
u8 intr;
|
||||
u16 cmd;
|
||||
|
||||
/* Read interupts and clear them immediately */
|
||||
intr = bcm_spi_readb(bs, SPI_INT_STATUS);
|
||||
bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
|
||||
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
|
||||
|
||||
/* A tansfer completed */
|
||||
if (intr & SPI_INTR_CMD_DONE) {
|
||||
u8 rx_tail;
|
||||
|
||||
rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
|
||||
|
||||
/* Read out all the data */
|
||||
if (rx_tail)
|
||||
memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail);
|
||||
|
||||
/* See if there is more data to send */
|
||||
if (bs->remaining_bytes > 0) {
|
||||
bcm63xx_spi_fill_tx_fifo(bs);
|
||||
|
||||
/* Start the transfer */
|
||||
bcm_spi_writew(bs, SPI_HD_W << SPI_MSG_TYPE_SHIFT,
|
||||
SPI_MSG_CTL);
|
||||
cmd = bcm_spi_readw(bs, SPI_CMD);
|
||||
cmd |= SPI_CMD_START_IMMEDIATE;
|
||||
cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
|
||||
bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
|
||||
bcm_spi_writew(bs, cmd, SPI_CMD);
|
||||
} else {
|
||||
complete(&bs->done);
|
||||
}
|
||||
}
|
||||
/* A transfer completed */
|
||||
if (intr & SPI_INTR_CMD_DONE)
|
||||
complete(&bs->done);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -345,7 +368,6 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
bs = spi_master_get_devdata(master);
|
||||
init_completion(&bs->done);
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
bs->pdev = pdev;
|
||||
@ -379,12 +401,13 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
|
||||
master->bus_num = pdata->bus_num;
|
||||
master->num_chipselect = pdata->num_chipselect;
|
||||
master->setup = bcm63xx_spi_setup;
|
||||
master->transfer = bcm63xx_transfer;
|
||||
master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer;
|
||||
master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer;
|
||||
master->transfer_one_message = bcm63xx_spi_transfer_one;
|
||||
master->mode_bits = MODEBITS;
|
||||
bs->speed_hz = pdata->speed_hz;
|
||||
bs->stopping = 0;
|
||||
bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
|
||||
bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
|
||||
spin_lock_init(&bs->lock);
|
||||
|
||||
/* Initialize hardware */
|
||||
clk_enable(bs->clk);
|
||||
@ -418,18 +441,16 @@ static int __devexit bcm63xx_spi_remove(struct platform_device *pdev)
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
||||
|
||||
spi_unregister_master(master);
|
||||
|
||||
/* reset spi block */
|
||||
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
|
||||
spin_lock(&bs->lock);
|
||||
bs->stopping = 1;
|
||||
|
||||
/* HW shutdown */
|
||||
clk_disable(bs->clk);
|
||||
clk_put(bs->clk);
|
||||
|
||||
spin_unlock(&bs->lock);
|
||||
platform_set_drvdata(pdev, 0);
|
||||
spi_unregister_master(master);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -252,19 +252,15 @@ static void
|
||||
bfin_sport_spi_restore_state(struct bfin_sport_spi_master_data *drv_data)
|
||||
{
|
||||
struct bfin_sport_spi_slave_data *chip = drv_data->cur_chip;
|
||||
unsigned int bits = (drv_data->ops == &bfin_sport_transfer_ops_u8 ? 7 : 15);
|
||||
|
||||
bfin_sport_spi_disable(drv_data);
|
||||
dev_dbg(drv_data->dev, "restoring spi ctl state\n");
|
||||
|
||||
bfin_write(&drv_data->regs->tcr1, chip->ctl_reg);
|
||||
bfin_write(&drv_data->regs->tcr2, bits);
|
||||
bfin_write(&drv_data->regs->tclkdiv, chip->baud);
|
||||
bfin_write(&drv_data->regs->tfsdiv, bits);
|
||||
SSYNC();
|
||||
|
||||
bfin_write(&drv_data->regs->rcr1, chip->ctl_reg & ~(ITCLK | ITFS));
|
||||
bfin_write(&drv_data->regs->rcr2, bits);
|
||||
SSYNC();
|
||||
|
||||
bfin_sport_spi_cs_active(chip);
|
||||
@ -420,11 +416,15 @@ bfin_sport_spi_pump_transfers(unsigned long data)
|
||||
drv_data->cs_change = transfer->cs_change;
|
||||
|
||||
/* Bits per word setup */
|
||||
bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word;
|
||||
if (bits_per_word == 8)
|
||||
drv_data->ops = &bfin_sport_transfer_ops_u8;
|
||||
else
|
||||
bits_per_word = transfer->bits_per_word ? :
|
||||
message->spi->bits_per_word ? : 8;
|
||||
if (bits_per_word % 16 == 0)
|
||||
drv_data->ops = &bfin_sport_transfer_ops_u16;
|
||||
else
|
||||
drv_data->ops = &bfin_sport_transfer_ops_u8;
|
||||
bfin_write(&drv_data->regs->tcr2, bits_per_word - 1);
|
||||
bfin_write(&drv_data->regs->tfsdiv, bits_per_word - 1);
|
||||
bfin_write(&drv_data->regs->rcr2, bits_per_word - 1);
|
||||
|
||||
drv_data->state = RUNNING_STATE;
|
||||
|
||||
@ -598,11 +598,12 @@ bfin_sport_spi_setup(struct spi_device *spi)
|
||||
}
|
||||
chip->cs_chg_udelay = chip_info->cs_chg_udelay;
|
||||
chip->idle_tx_val = chip_info->idle_tx_val;
|
||||
spi->bits_per_word = chip_info->bits_per_word;
|
||||
}
|
||||
}
|
||||
|
||||
if (spi->bits_per_word != 8 && spi->bits_per_word != 16) {
|
||||
if (spi->bits_per_word % 8) {
|
||||
dev_err(&spi->dev, "%d bits_per_word is not supported\n",
|
||||
spi->bits_per_word);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
@ -396,7 +396,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
|
||||
/* last read */
|
||||
if (drv_data->rx) {
|
||||
dev_dbg(&drv_data->pdev->dev, "last read\n");
|
||||
if (n_bytes % 2) {
|
||||
if (!(n_bytes % 2)) {
|
||||
u16 *buf = (u16 *)drv_data->rx;
|
||||
for (loop = 0; loop < n_bytes / 2; loop++)
|
||||
*buf++ = bfin_read(&drv_data->regs->rdbr);
|
||||
@ -424,7 +424,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
|
||||
if (drv_data->rx && drv_data->tx) {
|
||||
/* duplex */
|
||||
dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n");
|
||||
if (n_bytes % 2) {
|
||||
if (!(n_bytes % 2)) {
|
||||
u16 *buf = (u16 *)drv_data->rx;
|
||||
u16 *buf2 = (u16 *)drv_data->tx;
|
||||
for (loop = 0; loop < n_bytes / 2; loop++) {
|
||||
@ -442,7 +442,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
|
||||
} else if (drv_data->rx) {
|
||||
/* read */
|
||||
dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n");
|
||||
if (n_bytes % 2) {
|
||||
if (!(n_bytes % 2)) {
|
||||
u16 *buf = (u16 *)drv_data->rx;
|
||||
for (loop = 0; loop < n_bytes / 2; loop++) {
|
||||
*buf++ = bfin_read(&drv_data->regs->rdbr);
|
||||
@ -458,7 +458,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
|
||||
} else if (drv_data->tx) {
|
||||
/* write */
|
||||
dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n");
|
||||
if (n_bytes % 2) {
|
||||
if (!(n_bytes % 2)) {
|
||||
u16 *buf = (u16 *)drv_data->tx;
|
||||
for (loop = 0; loop < n_bytes / 2; loop++) {
|
||||
bfin_read(&drv_data->regs->rdbr);
|
||||
@ -587,6 +587,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
|
||||
if (message->state == DONE_STATE) {
|
||||
dev_dbg(&drv_data->pdev->dev, "transfer: all done!\n");
|
||||
message->status = 0;
|
||||
bfin_spi_flush(drv_data);
|
||||
bfin_spi_giveback(drv_data);
|
||||
return;
|
||||
}
|
||||
@ -870,8 +871,10 @@ static void bfin_spi_pump_transfers(unsigned long data)
|
||||
message->actual_length += drv_data->len_in_bytes;
|
||||
/* Move to next transfer of this msg */
|
||||
message->state = bfin_spi_next_transfer(drv_data);
|
||||
if (drv_data->cs_change)
|
||||
if (drv_data->cs_change && message->state != DONE_STATE) {
|
||||
bfin_spi_flush(drv_data);
|
||||
bfin_spi_cs_deactive(drv_data, chip);
|
||||
}
|
||||
}
|
||||
|
||||
/* Schedule next transfer tasklet */
|
||||
@ -1026,7 +1029,6 @@ static int bfin_spi_setup(struct spi_device *spi)
|
||||
chip->cs_chg_udelay = chip_info->cs_chg_udelay;
|
||||
chip->idle_tx_val = chip_info->idle_tx_val;
|
||||
chip->pio_interrupt = chip_info->pio_interrupt;
|
||||
spi->bits_per_word = chip_info->bits_per_word;
|
||||
} else {
|
||||
/* force a default base state */
|
||||
chip->ctl_reg &= bfin_ctl_reg;
|
||||
|
@ -545,13 +545,12 @@ static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi)
|
||||
* in case of failure.
|
||||
*/
|
||||
static struct dma_async_tx_descriptor *
|
||||
ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
|
||||
ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
|
||||
{
|
||||
struct spi_transfer *t = espi->current_msg->state;
|
||||
struct dma_async_tx_descriptor *txd;
|
||||
enum dma_slave_buswidth buswidth;
|
||||
struct dma_slave_config conf;
|
||||
enum dma_transfer_direction slave_dirn;
|
||||
struct scatterlist *sg;
|
||||
struct sg_table *sgt;
|
||||
struct dma_chan *chan;
|
||||
@ -567,14 +566,13 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
|
||||
memset(&conf, 0, sizeof(conf));
|
||||
conf.direction = dir;
|
||||
|
||||
if (dir == DMA_FROM_DEVICE) {
|
||||
if (dir == DMA_DEV_TO_MEM) {
|
||||
chan = espi->dma_rx;
|
||||
buf = t->rx_buf;
|
||||
sgt = &espi->rx_sgt;
|
||||
|
||||
conf.src_addr = espi->sspdr_phys;
|
||||
conf.src_addr_width = buswidth;
|
||||
slave_dirn = DMA_DEV_TO_MEM;
|
||||
} else {
|
||||
chan = espi->dma_tx;
|
||||
buf = t->tx_buf;
|
||||
@ -582,7 +580,6 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
|
||||
|
||||
conf.dst_addr = espi->sspdr_phys;
|
||||
conf.dst_addr_width = buswidth;
|
||||
slave_dirn = DMA_MEM_TO_DEV;
|
||||
}
|
||||
|
||||
ret = dmaengine_slave_config(chan, &conf);
|
||||
@ -633,8 +630,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
|
||||
if (!nents)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents,
|
||||
slave_dirn, DMA_CTRL_ACK);
|
||||
txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents, dir, DMA_CTRL_ACK);
|
||||
if (!txd) {
|
||||
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@ -651,12 +647,12 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
|
||||
* unmapped.
|
||||
*/
|
||||
static void ep93xx_spi_dma_finish(struct ep93xx_spi *espi,
|
||||
enum dma_data_direction dir)
|
||||
enum dma_transfer_direction dir)
|
||||
{
|
||||
struct dma_chan *chan;
|
||||
struct sg_table *sgt;
|
||||
|
||||
if (dir == DMA_FROM_DEVICE) {
|
||||
if (dir == DMA_DEV_TO_MEM) {
|
||||
chan = espi->dma_rx;
|
||||
sgt = &espi->rx_sgt;
|
||||
} else {
|
||||
@ -677,16 +673,16 @@ static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi)
|
||||
struct spi_message *msg = espi->current_msg;
|
||||
struct dma_async_tx_descriptor *rxd, *txd;
|
||||
|
||||
rxd = ep93xx_spi_dma_prepare(espi, DMA_FROM_DEVICE);
|
||||
rxd = ep93xx_spi_dma_prepare(espi, DMA_DEV_TO_MEM);
|
||||
if (IS_ERR(rxd)) {
|
||||
dev_err(&espi->pdev->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd));
|
||||
msg->status = PTR_ERR(rxd);
|
||||
return;
|
||||
}
|
||||
|
||||
txd = ep93xx_spi_dma_prepare(espi, DMA_TO_DEVICE);
|
||||
txd = ep93xx_spi_dma_prepare(espi, DMA_MEM_TO_DEV);
|
||||
if (IS_ERR(txd)) {
|
||||
ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
|
||||
ep93xx_spi_dma_finish(espi, DMA_DEV_TO_MEM);
|
||||
dev_err(&espi->pdev->dev, "DMA TX failed: %ld\n", PTR_ERR(rxd));
|
||||
msg->status = PTR_ERR(txd);
|
||||
return;
|
||||
@ -705,8 +701,8 @@ static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi)
|
||||
|
||||
wait_for_completion(&espi->wait);
|
||||
|
||||
ep93xx_spi_dma_finish(espi, DMA_TO_DEVICE);
|
||||
ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
|
||||
ep93xx_spi_dma_finish(espi, DMA_MEM_TO_DEV);
|
||||
ep93xx_spi_dma_finish(espi, DMA_DEV_TO_MEM);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1667,9 +1667,15 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
|
||||
/* cpsdvsr = 254 & scr = 255 */
|
||||
min_tclk = spi_rate(rate, CPSDVR_MAX, SCR_MAX);
|
||||
|
||||
if (!((freq <= max_tclk) && (freq >= min_tclk))) {
|
||||
if (freq > max_tclk)
|
||||
dev_warn(&pl022->adev->dev,
|
||||
"Max speed that can be programmed is %d Hz, you requested %d\n",
|
||||
max_tclk, freq);
|
||||
|
||||
if (freq < min_tclk) {
|
||||
dev_err(&pl022->adev->dev,
|
||||
"controller data is incorrect: out of range frequency");
|
||||
"Requested frequency: %d Hz is less than minimum possible %d Hz\n",
|
||||
freq, min_tclk);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1681,26 +1687,37 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
|
||||
while (scr <= SCR_MAX) {
|
||||
tmp = spi_rate(rate, cpsdvsr, scr);
|
||||
|
||||
if (tmp > freq)
|
||||
if (tmp > freq) {
|
||||
/* we need lower freq */
|
||||
scr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If found exact value, update and break.
|
||||
* If found more closer value, update and continue.
|
||||
* If found exact value, mark found and break.
|
||||
* If found more closer value, update and break.
|
||||
*/
|
||||
else if ((tmp == freq) || (tmp > best_freq)) {
|
||||
if (tmp > best_freq) {
|
||||
best_freq = tmp;
|
||||
best_cpsdvsr = cpsdvsr;
|
||||
best_scr = scr;
|
||||
|
||||
if (tmp == freq)
|
||||
break;
|
||||
found = 1;
|
||||
}
|
||||
scr++;
|
||||
/*
|
||||
* increased scr will give lower rates, which are not
|
||||
* required
|
||||
*/
|
||||
break;
|
||||
}
|
||||
cpsdvsr += 2;
|
||||
scr = SCR_MIN;
|
||||
}
|
||||
|
||||
WARN(!best_freq, "pl022: Matching cpsdvsr and scr not found for %d Hz rate \n",
|
||||
freq);
|
||||
|
||||
clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF);
|
||||
clk_freq->scr = (u8) (best_scr & 0xFF);
|
||||
dev_dbg(&pl022->adev->dev,
|
||||
@ -1823,9 +1840,12 @@ static int pl022_setup(struct spi_device *spi)
|
||||
} else
|
||||
chip->cs_control = chip_info->cs_control;
|
||||
|
||||
if (bits <= 3) {
|
||||
/* PL022 doesn't support less than 4-bits */
|
||||
/* Check bits per word with vendor specific range */
|
||||
if ((bits <= 3) || (bits > pl022->vendor->max_bpw)) {
|
||||
status = -ENOTSUPP;
|
||||
dev_err(&spi->dev, "illegal data size for this controller!\n");
|
||||
dev_err(&spi->dev, "This controller can only handle 4 <= n <= %d bit words\n",
|
||||
pl022->vendor->max_bpw);
|
||||
goto err_config_params;
|
||||
} else if (bits <= 8) {
|
||||
dev_dbg(&spi->dev, "4 <= n <=8 bits per word\n");
|
||||
@ -1838,20 +1858,10 @@ static int pl022_setup(struct spi_device *spi)
|
||||
chip->read = READING_U16;
|
||||
chip->write = WRITING_U16;
|
||||
} else {
|
||||
if (pl022->vendor->max_bpw >= 32) {
|
||||
dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n");
|
||||
chip->n_bytes = 4;
|
||||
chip->read = READING_U32;
|
||||
chip->write = WRITING_U32;
|
||||
} else {
|
||||
dev_err(&spi->dev,
|
||||
"illegal data size for this controller!\n");
|
||||
dev_err(&spi->dev,
|
||||
"a standard pl022 can only handle "
|
||||
"1 <= n <= 16 bit words\n");
|
||||
status = -ENOTSUPP;
|
||||
goto err_config_params;
|
||||
}
|
||||
dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n");
|
||||
chip->n_bytes = 4;
|
||||
chip->read = READING_U32;
|
||||
chip->write = WRITING_U32;
|
||||
}
|
||||
|
||||
/* Now Initialize all register settings required for this chip */
|
||||
|
@ -254,7 +254,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
|
||||
* driver is finished with this message, it must call
|
||||
* spi_finalize_current_message() so the subsystem can issue the next
|
||||
* transfer
|
||||
* @prepare_transfer_hardware: there are currently no more messages on the
|
||||
* @unprepare_transfer_hardware: there are currently no more messages on the
|
||||
* queue so the subsystem notifies the driver that it may relax the
|
||||
* hardware by issuing this call
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user