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
|
This selects a driver for the Atmel SPI Controller, present on
|
||||||
many AT32 (AVR32) and AT91 (ARM) chips.
|
many AT32 (AVR32) and AT91 (ARM) chips.
|
||||||
|
|
||||||
config SPI_BFIN
|
config SPI_BFIN5XX
|
||||||
tristate "SPI controller driver for ADI Blackfin5xx"
|
tristate "SPI controller driver for ADI Blackfin5xx"
|
||||||
depends on BLACKFIN
|
depends on BLACKFIN
|
||||||
help
|
help
|
||||||
|
@ -15,7 +15,7 @@ obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
|
|||||||
obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
|
obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
|
||||||
obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
|
obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
|
||||||
obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.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_BFIN_SPORT) += spi-bfin-sport.o
|
||||||
obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
|
obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
|
||||||
obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
|
obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Broadcom BCM63xx SPI controller support
|
* 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>
|
* Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@ -30,6 +30,8 @@
|
|||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
#include <bcm63xx_dev_spi.h>
|
#include <bcm63xx_dev_spi.h>
|
||||||
|
|
||||||
@ -37,8 +39,6 @@
|
|||||||
#define DRV_VER "0.1.2"
|
#define DRV_VER "0.1.2"
|
||||||
|
|
||||||
struct bcm63xx_spi {
|
struct bcm63xx_spi {
|
||||||
spinlock_t lock;
|
|
||||||
int stopping;
|
|
||||||
struct completion done;
|
struct completion done;
|
||||||
|
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
@ -96,17 +96,12 @@ static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
|
|||||||
{ 391000, SPI_CLK_0_391MHZ }
|
{ 391000, SPI_CLK_0_391MHZ }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int bcm63xx_spi_setup_transfer(struct spi_device *spi,
|
static int bcm63xx_spi_check_transfer(struct spi_device *spi,
|
||||||
struct spi_transfer *t)
|
struct spi_transfer *t)
|
||||||
{
|
{
|
||||||
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
|
|
||||||
u8 bits_per_word;
|
u8 bits_per_word;
|
||||||
u8 clk_cfg, reg;
|
|
||||||
u32 hz;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
|
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) {
|
if (bits_per_word != 8) {
|
||||||
dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
|
dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
|
||||||
__func__, bits_per_word);
|
__func__, bits_per_word);
|
||||||
@ -119,6 +114,19 @@ static int bcm63xx_spi_setup_transfer(struct spi_device *spi,
|
|||||||
return -EINVAL;
|
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 */
|
/* Find the closest clock configuration */
|
||||||
for (i = 0; i < SPI_CLK_MASK; i++) {
|
for (i = 0; i < SPI_CLK_MASK; i++) {
|
||||||
if (hz <= bcm63xx_spi_freq_table[i][0]) {
|
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);
|
bcm_spi_writeb(bs, reg, SPI_CLK_CFG);
|
||||||
dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n",
|
dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n",
|
||||||
clk_cfg, hz);
|
clk_cfg, hz);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the spi->mode bits understood by this driver: */
|
/* 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);
|
bs = spi_master_get_devdata(spi->master);
|
||||||
|
|
||||||
if (bs->stopping)
|
|
||||||
return -ESHUTDOWN;
|
|
||||||
|
|
||||||
if (!spi->bits_per_word)
|
if (!spi->bits_per_word)
|
||||||
spi->bits_per_word = 8;
|
spi->bits_per_word = 8;
|
||||||
|
|
||||||
@ -165,7 +168,7 @@ static int bcm63xx_spi_setup(struct spi_device *spi)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bcm63xx_spi_setup_transfer(spi, NULL);
|
ret = bcm63xx_spi_check_transfer(spi, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
|
dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
|
||||||
spi->mode & ~MODEBITS);
|
spi->mode & ~MODEBITS);
|
||||||
@ -190,28 +193,29 @@ static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs)
|
|||||||
bs->remaining_bytes -= size;
|
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);
|
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
|
||||||
u16 msg_ctl;
|
u16 msg_ctl;
|
||||||
u16 cmd;
|
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",
|
dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
|
||||||
t->tx_buf, t->rx_buf, t->len);
|
t->tx_buf, t->rx_buf, t->len);
|
||||||
|
|
||||||
/* Transmitter is inhibited */
|
/* Transmitter is inhibited */
|
||||||
bs->tx_ptr = t->tx_buf;
|
bs->tx_ptr = t->tx_buf;
|
||||||
bs->rx_ptr = t->rx_buf;
|
bs->rx_ptr = t->rx_buf;
|
||||||
init_completion(&bs->done);
|
|
||||||
|
|
||||||
if (t->tx_buf) {
|
if (t->tx_buf) {
|
||||||
bs->remaining_bytes = t->len;
|
bs->remaining_bytes = t->len;
|
||||||
bcm63xx_spi_fill_tx_fifo(bs);
|
bcm63xx_spi_fill_tx_fifo(bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable the command done interrupt which
|
init_completion(&bs->done);
|
||||||
* we use to determine completion of a command */
|
|
||||||
bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
|
|
||||||
|
|
||||||
/* Fill in the Message control register */
|
/* Fill in the Message control register */
|
||||||
msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);
|
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 |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
|
||||||
cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT);
|
cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT);
|
||||||
bcm_spi_writew(bs, cmd, SPI_CMD);
|
bcm_spi_writew(bs, cmd, SPI_CMD);
|
||||||
wait_for_completion(&bs->done);
|
|
||||||
|
|
||||||
/* Disable the CMD_DONE interrupt */
|
/* Enable the CMD_DONE interrupt */
|
||||||
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
|
bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
|
||||||
|
|
||||||
return t->len - bs->remaining_bytes;
|
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);
|
||||||
struct spi_transfer *t;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (unlikely(list_empty(&m->transfers)))
|
pm_runtime_get_sync(&bs->pdev->dev);
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (bs->stopping)
|
return 0;
|
||||||
return -ESHUTDOWN;
|
|
||||||
|
|
||||||
list_for_each_entry(t, &m->transfers, transfer_list) {
|
|
||||||
ret += bcm63xx_txrx_bufs(spi, t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m->complete(m->context);
|
static int bcm63xx_spi_unprepare_transfer(struct spi_master *master)
|
||||||
|
{
|
||||||
|
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
||||||
|
|
||||||
return ret;
|
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;
|
||||||
|
struct spi_device *spi = m->spi;
|
||||||
|
int status = 0;
|
||||||
|
unsigned int timeout = 0;
|
||||||
|
|
||||||
|
list_for_each_entry(t, &m->transfers, transfer_list) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This driver supports single master mode only. Hence
|
/* 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 spi_master *master = (struct spi_master *)dev_id;
|
||||||
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
||||||
u8 intr;
|
u8 intr;
|
||||||
u16 cmd;
|
|
||||||
|
|
||||||
/* Read interupts and clear them immediately */
|
/* Read interupts and clear them immediately */
|
||||||
intr = bcm_spi_readb(bs, SPI_INT_STATUS);
|
intr = bcm_spi_readb(bs, SPI_INT_STATUS);
|
||||||
bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
|
bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
|
||||||
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
|
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
|
||||||
|
|
||||||
/* A tansfer completed */
|
/* A transfer completed */
|
||||||
if (intr & SPI_INTR_CMD_DONE) {
|
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);
|
complete(&bs->done);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
@ -345,7 +368,6 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bs = spi_master_get_devdata(master);
|
bs = spi_master_get_devdata(master);
|
||||||
init_completion(&bs->done);
|
|
||||||
|
|
||||||
platform_set_drvdata(pdev, master);
|
platform_set_drvdata(pdev, master);
|
||||||
bs->pdev = pdev;
|
bs->pdev = pdev;
|
||||||
@ -379,12 +401,13 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
|
|||||||
master->bus_num = pdata->bus_num;
|
master->bus_num = pdata->bus_num;
|
||||||
master->num_chipselect = pdata->num_chipselect;
|
master->num_chipselect = pdata->num_chipselect;
|
||||||
master->setup = bcm63xx_spi_setup;
|
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->speed_hz = pdata->speed_hz;
|
||||||
bs->stopping = 0;
|
|
||||||
bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
|
bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
|
||||||
bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
|
bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
|
||||||
spin_lock_init(&bs->lock);
|
|
||||||
|
|
||||||
/* Initialize hardware */
|
/* Initialize hardware */
|
||||||
clk_enable(bs->clk);
|
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 spi_master *master = platform_get_drvdata(pdev);
|
||||||
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
||||||
|
|
||||||
|
spi_unregister_master(master);
|
||||||
|
|
||||||
/* reset spi block */
|
/* reset spi block */
|
||||||
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
|
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
|
||||||
spin_lock(&bs->lock);
|
|
||||||
bs->stopping = 1;
|
|
||||||
|
|
||||||
/* HW shutdown */
|
/* HW shutdown */
|
||||||
clk_disable(bs->clk);
|
clk_disable(bs->clk);
|
||||||
clk_put(bs->clk);
|
clk_put(bs->clk);
|
||||||
|
|
||||||
spin_unlock(&bs->lock);
|
|
||||||
platform_set_drvdata(pdev, 0);
|
platform_set_drvdata(pdev, 0);
|
||||||
spi_unregister_master(master);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -252,19 +252,15 @@ static void
|
|||||||
bfin_sport_spi_restore_state(struct bfin_sport_spi_master_data *drv_data)
|
bfin_sport_spi_restore_state(struct bfin_sport_spi_master_data *drv_data)
|
||||||
{
|
{
|
||||||
struct bfin_sport_spi_slave_data *chip = drv_data->cur_chip;
|
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);
|
bfin_sport_spi_disable(drv_data);
|
||||||
dev_dbg(drv_data->dev, "restoring spi ctl state\n");
|
dev_dbg(drv_data->dev, "restoring spi ctl state\n");
|
||||||
|
|
||||||
bfin_write(&drv_data->regs->tcr1, chip->ctl_reg);
|
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->tclkdiv, chip->baud);
|
||||||
bfin_write(&drv_data->regs->tfsdiv, bits);
|
|
||||||
SSYNC();
|
SSYNC();
|
||||||
|
|
||||||
bfin_write(&drv_data->regs->rcr1, chip->ctl_reg & ~(ITCLK | ITFS));
|
bfin_write(&drv_data->regs->rcr1, chip->ctl_reg & ~(ITCLK | ITFS));
|
||||||
bfin_write(&drv_data->regs->rcr2, bits);
|
|
||||||
SSYNC();
|
SSYNC();
|
||||||
|
|
||||||
bfin_sport_spi_cs_active(chip);
|
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;
|
drv_data->cs_change = transfer->cs_change;
|
||||||
|
|
||||||
/* Bits per word setup */
|
/* Bits per word setup */
|
||||||
bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word;
|
bits_per_word = transfer->bits_per_word ? :
|
||||||
if (bits_per_word == 8)
|
message->spi->bits_per_word ? : 8;
|
||||||
drv_data->ops = &bfin_sport_transfer_ops_u8;
|
if (bits_per_word % 16 == 0)
|
||||||
else
|
|
||||||
drv_data->ops = &bfin_sport_transfer_ops_u16;
|
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;
|
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->cs_chg_udelay = chip_info->cs_chg_udelay;
|
||||||
chip->idle_tx_val = chip_info->idle_tx_val;
|
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;
|
ret = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -396,7 +396,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
|
|||||||
/* last read */
|
/* last read */
|
||||||
if (drv_data->rx) {
|
if (drv_data->rx) {
|
||||||
dev_dbg(&drv_data->pdev->dev, "last read\n");
|
dev_dbg(&drv_data->pdev->dev, "last read\n");
|
||||||
if (n_bytes % 2) {
|
if (!(n_bytes % 2)) {
|
||||||
u16 *buf = (u16 *)drv_data->rx;
|
u16 *buf = (u16 *)drv_data->rx;
|
||||||
for (loop = 0; loop < n_bytes / 2; loop++)
|
for (loop = 0; loop < n_bytes / 2; loop++)
|
||||||
*buf++ = bfin_read(&drv_data->regs->rdbr);
|
*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) {
|
if (drv_data->rx && drv_data->tx) {
|
||||||
/* duplex */
|
/* duplex */
|
||||||
dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n");
|
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 *buf = (u16 *)drv_data->rx;
|
||||||
u16 *buf2 = (u16 *)drv_data->tx;
|
u16 *buf2 = (u16 *)drv_data->tx;
|
||||||
for (loop = 0; loop < n_bytes / 2; loop++) {
|
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) {
|
} else if (drv_data->rx) {
|
||||||
/* read */
|
/* read */
|
||||||
dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n");
|
dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n");
|
||||||
if (n_bytes % 2) {
|
if (!(n_bytes % 2)) {
|
||||||
u16 *buf = (u16 *)drv_data->rx;
|
u16 *buf = (u16 *)drv_data->rx;
|
||||||
for (loop = 0; loop < n_bytes / 2; loop++) {
|
for (loop = 0; loop < n_bytes / 2; loop++) {
|
||||||
*buf++ = bfin_read(&drv_data->regs->rdbr);
|
*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) {
|
} else if (drv_data->tx) {
|
||||||
/* write */
|
/* write */
|
||||||
dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n");
|
dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n");
|
||||||
if (n_bytes % 2) {
|
if (!(n_bytes % 2)) {
|
||||||
u16 *buf = (u16 *)drv_data->tx;
|
u16 *buf = (u16 *)drv_data->tx;
|
||||||
for (loop = 0; loop < n_bytes / 2; loop++) {
|
for (loop = 0; loop < n_bytes / 2; loop++) {
|
||||||
bfin_read(&drv_data->regs->rdbr);
|
bfin_read(&drv_data->regs->rdbr);
|
||||||
@ -587,6 +587,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
|
|||||||
if (message->state == DONE_STATE) {
|
if (message->state == DONE_STATE) {
|
||||||
dev_dbg(&drv_data->pdev->dev, "transfer: all done!\n");
|
dev_dbg(&drv_data->pdev->dev, "transfer: all done!\n");
|
||||||
message->status = 0;
|
message->status = 0;
|
||||||
|
bfin_spi_flush(drv_data);
|
||||||
bfin_spi_giveback(drv_data);
|
bfin_spi_giveback(drv_data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -870,9 +871,11 @@ static void bfin_spi_pump_transfers(unsigned long data)
|
|||||||
message->actual_length += drv_data->len_in_bytes;
|
message->actual_length += drv_data->len_in_bytes;
|
||||||
/* Move to next transfer of this msg */
|
/* Move to next transfer of this msg */
|
||||||
message->state = bfin_spi_next_transfer(drv_data);
|
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);
|
bfin_spi_cs_deactive(drv_data, chip);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Schedule next transfer tasklet */
|
/* Schedule next transfer tasklet */
|
||||||
tasklet_schedule(&drv_data->pump_transfers);
|
tasklet_schedule(&drv_data->pump_transfers);
|
||||||
@ -1026,7 +1029,6 @@ static int bfin_spi_setup(struct spi_device *spi)
|
|||||||
chip->cs_chg_udelay = chip_info->cs_chg_udelay;
|
chip->cs_chg_udelay = chip_info->cs_chg_udelay;
|
||||||
chip->idle_tx_val = chip_info->idle_tx_val;
|
chip->idle_tx_val = chip_info->idle_tx_val;
|
||||||
chip->pio_interrupt = chip_info->pio_interrupt;
|
chip->pio_interrupt = chip_info->pio_interrupt;
|
||||||
spi->bits_per_word = chip_info->bits_per_word;
|
|
||||||
} else {
|
} else {
|
||||||
/* force a default base state */
|
/* force a default base state */
|
||||||
chip->ctl_reg &= bfin_ctl_reg;
|
chip->ctl_reg &= bfin_ctl_reg;
|
||||||
|
@ -545,13 +545,12 @@ static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi)
|
|||||||
* in case of failure.
|
* in case of failure.
|
||||||
*/
|
*/
|
||||||
static struct dma_async_tx_descriptor *
|
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 spi_transfer *t = espi->current_msg->state;
|
||||||
struct dma_async_tx_descriptor *txd;
|
struct dma_async_tx_descriptor *txd;
|
||||||
enum dma_slave_buswidth buswidth;
|
enum dma_slave_buswidth buswidth;
|
||||||
struct dma_slave_config conf;
|
struct dma_slave_config conf;
|
||||||
enum dma_transfer_direction slave_dirn;
|
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
struct sg_table *sgt;
|
struct sg_table *sgt;
|
||||||
struct dma_chan *chan;
|
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));
|
memset(&conf, 0, sizeof(conf));
|
||||||
conf.direction = dir;
|
conf.direction = dir;
|
||||||
|
|
||||||
if (dir == DMA_FROM_DEVICE) {
|
if (dir == DMA_DEV_TO_MEM) {
|
||||||
chan = espi->dma_rx;
|
chan = espi->dma_rx;
|
||||||
buf = t->rx_buf;
|
buf = t->rx_buf;
|
||||||
sgt = &espi->rx_sgt;
|
sgt = &espi->rx_sgt;
|
||||||
|
|
||||||
conf.src_addr = espi->sspdr_phys;
|
conf.src_addr = espi->sspdr_phys;
|
||||||
conf.src_addr_width = buswidth;
|
conf.src_addr_width = buswidth;
|
||||||
slave_dirn = DMA_DEV_TO_MEM;
|
|
||||||
} else {
|
} else {
|
||||||
chan = espi->dma_tx;
|
chan = espi->dma_tx;
|
||||||
buf = t->tx_buf;
|
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 = espi->sspdr_phys;
|
||||||
conf.dst_addr_width = buswidth;
|
conf.dst_addr_width = buswidth;
|
||||||
slave_dirn = DMA_MEM_TO_DEV;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = dmaengine_slave_config(chan, &conf);
|
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)
|
if (!nents)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents,
|
txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents, dir, DMA_CTRL_ACK);
|
||||||
slave_dirn, DMA_CTRL_ACK);
|
|
||||||
if (!txd) {
|
if (!txd) {
|
||||||
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
|
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
@ -651,12 +647,12 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
|
|||||||
* unmapped.
|
* unmapped.
|
||||||
*/
|
*/
|
||||||
static void ep93xx_spi_dma_finish(struct ep93xx_spi *espi,
|
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 dma_chan *chan;
|
||||||
struct sg_table *sgt;
|
struct sg_table *sgt;
|
||||||
|
|
||||||
if (dir == DMA_FROM_DEVICE) {
|
if (dir == DMA_DEV_TO_MEM) {
|
||||||
chan = espi->dma_rx;
|
chan = espi->dma_rx;
|
||||||
sgt = &espi->rx_sgt;
|
sgt = &espi->rx_sgt;
|
||||||
} else {
|
} else {
|
||||||
@ -677,16 +673,16 @@ static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi)
|
|||||||
struct spi_message *msg = espi->current_msg;
|
struct spi_message *msg = espi->current_msg;
|
||||||
struct dma_async_tx_descriptor *rxd, *txd;
|
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)) {
|
if (IS_ERR(rxd)) {
|
||||||
dev_err(&espi->pdev->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd));
|
dev_err(&espi->pdev->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd));
|
||||||
msg->status = PTR_ERR(rxd);
|
msg->status = PTR_ERR(rxd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
txd = ep93xx_spi_dma_prepare(espi, DMA_TO_DEVICE);
|
txd = ep93xx_spi_dma_prepare(espi, DMA_MEM_TO_DEV);
|
||||||
if (IS_ERR(txd)) {
|
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));
|
dev_err(&espi->pdev->dev, "DMA TX failed: %ld\n", PTR_ERR(rxd));
|
||||||
msg->status = PTR_ERR(txd);
|
msg->status = PTR_ERR(txd);
|
||||||
return;
|
return;
|
||||||
@ -705,8 +701,8 @@ static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi)
|
|||||||
|
|
||||||
wait_for_completion(&espi->wait);
|
wait_for_completion(&espi->wait);
|
||||||
|
|
||||||
ep93xx_spi_dma_finish(espi, DMA_TO_DEVICE);
|
ep93xx_spi_dma_finish(espi, DMA_MEM_TO_DEV);
|
||||||
ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
|
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 */
|
/* cpsdvsr = 254 & scr = 255 */
|
||||||
min_tclk = spi_rate(rate, CPSDVR_MAX, SCR_MAX);
|
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,
|
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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1681,26 +1687,37 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
|
|||||||
while (scr <= SCR_MAX) {
|
while (scr <= SCR_MAX) {
|
||||||
tmp = spi_rate(rate, cpsdvsr, scr);
|
tmp = spi_rate(rate, cpsdvsr, scr);
|
||||||
|
|
||||||
if (tmp > freq)
|
if (tmp > freq) {
|
||||||
|
/* we need lower freq */
|
||||||
scr++;
|
scr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If found exact value, update and break.
|
* If found exact value, mark found and break.
|
||||||
* If found more closer value, update and continue.
|
* If found more closer value, update and break.
|
||||||
*/
|
*/
|
||||||
else if ((tmp == freq) || (tmp > best_freq)) {
|
if (tmp > best_freq) {
|
||||||
best_freq = tmp;
|
best_freq = tmp;
|
||||||
best_cpsdvsr = cpsdvsr;
|
best_cpsdvsr = cpsdvsr;
|
||||||
best_scr = scr;
|
best_scr = scr;
|
||||||
|
|
||||||
if (tmp == freq)
|
if (tmp == freq)
|
||||||
break;
|
found = 1;
|
||||||
}
|
}
|
||||||
scr++;
|
/*
|
||||||
|
* increased scr will give lower rates, which are not
|
||||||
|
* required
|
||||||
|
*/
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
cpsdvsr += 2;
|
cpsdvsr += 2;
|
||||||
scr = SCR_MIN;
|
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->cpsdvsr = (u8) (best_cpsdvsr & 0xFF);
|
||||||
clk_freq->scr = (u8) (best_scr & 0xFF);
|
clk_freq->scr = (u8) (best_scr & 0xFF);
|
||||||
dev_dbg(&pl022->adev->dev,
|
dev_dbg(&pl022->adev->dev,
|
||||||
@ -1823,9 +1840,12 @@ static int pl022_setup(struct spi_device *spi)
|
|||||||
} else
|
} else
|
||||||
chip->cs_control = chip_info->cs_control;
|
chip->cs_control = chip_info->cs_control;
|
||||||
|
|
||||||
if (bits <= 3) {
|
/* Check bits per word with vendor specific range */
|
||||||
/* PL022 doesn't support less than 4-bits */
|
if ((bits <= 3) || (bits > pl022->vendor->max_bpw)) {
|
||||||
status = -ENOTSUPP;
|
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;
|
goto err_config_params;
|
||||||
} else if (bits <= 8) {
|
} else if (bits <= 8) {
|
||||||
dev_dbg(&spi->dev, "4 <= n <=8 bits per word\n");
|
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->read = READING_U16;
|
||||||
chip->write = WRITING_U16;
|
chip->write = WRITING_U16;
|
||||||
} else {
|
} else {
|
||||||
if (pl022->vendor->max_bpw >= 32) {
|
|
||||||
dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n");
|
dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n");
|
||||||
chip->n_bytes = 4;
|
chip->n_bytes = 4;
|
||||||
chip->read = READING_U32;
|
chip->read = READING_U32;
|
||||||
chip->write = WRITING_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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now Initialize all register settings required for this chip */
|
/* 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
|
* driver is finished with this message, it must call
|
||||||
* spi_finalize_current_message() so the subsystem can issue the next
|
* spi_finalize_current_message() so the subsystem can issue the next
|
||||||
* transfer
|
* 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
|
* queue so the subsystem notifies the driver that it may relax the
|
||||||
* hardware by issuing this call
|
* hardware by issuing this call
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user