mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 16:49:22 +00:00
Merge remote-tracking branches 'spi/fix/bcm2835', 'spi/fix/bcm2835-code', 'spi/fix/bitbang', 'spi/fix/fsl-cpm' and 'spi/fix/omap2-mcspi' into spi-linus
This commit is contained in:
commit
5a1b11cbcc
5 changed files with 43 additions and 31 deletions
|
@ -78,6 +78,7 @@ config SPI_ATMEL
|
||||||
config SPI_BCM2835
|
config SPI_BCM2835
|
||||||
tristate "BCM2835 SPI controller"
|
tristate "BCM2835 SPI controller"
|
||||||
depends on ARCH_BCM2835 || COMPILE_TEST
|
depends on ARCH_BCM2835 || COMPILE_TEST
|
||||||
|
depends on GPIOLIB
|
||||||
help
|
help
|
||||||
This selects a driver for the Broadcom BCM2835 SPI master.
|
This selects a driver for the Broadcom BCM2835 SPI master.
|
||||||
|
|
||||||
|
|
|
@ -164,13 +164,12 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master,
|
||||||
unsigned long xfer_time_us)
|
unsigned long xfer_time_us)
|
||||||
{
|
{
|
||||||
struct bcm2835_spi *bs = spi_master_get_devdata(master);
|
struct bcm2835_spi *bs = spi_master_get_devdata(master);
|
||||||
unsigned long timeout = jiffies +
|
/* set timeout to 1 second of maximum polling */
|
||||||
max(4 * xfer_time_us * HZ / 1000000, 2uL);
|
unsigned long timeout = jiffies + HZ;
|
||||||
|
|
||||||
/* enable HW block without interrupts */
|
/* enable HW block without interrupts */
|
||||||
bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA);
|
bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA);
|
||||||
|
|
||||||
/* set timeout to 4x the expected time, or 2 jiffies */
|
|
||||||
/* loop until finished the transfer */
|
/* loop until finished the transfer */
|
||||||
while (bs->rx_len) {
|
while (bs->rx_len) {
|
||||||
/* read from fifo as much as possible */
|
/* read from fifo as much as possible */
|
||||||
|
|
|
@ -180,7 +180,6 @@ int spi_bitbang_setup(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct spi_bitbang_cs *cs = spi->controller_state;
|
struct spi_bitbang_cs *cs = spi->controller_state;
|
||||||
struct spi_bitbang *bitbang;
|
struct spi_bitbang *bitbang;
|
||||||
int retval;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
bitbang = spi_master_get_devdata(spi->master);
|
bitbang = spi_master_get_devdata(spi->master);
|
||||||
|
@ -197,9 +196,11 @@ int spi_bitbang_setup(struct spi_device *spi)
|
||||||
if (!cs->txrx_word)
|
if (!cs->txrx_word)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
retval = bitbang->setup_transfer(spi, NULL);
|
if (bitbang->setup_transfer) {
|
||||||
|
int retval = bitbang->setup_transfer(spi, NULL);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
return retval;
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs);
|
dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs);
|
||||||
|
|
||||||
|
@ -295,9 +296,11 @@ static int spi_bitbang_transfer_one(struct spi_master *master,
|
||||||
|
|
||||||
/* init (-1) or override (1) transfer params */
|
/* init (-1) or override (1) transfer params */
|
||||||
if (do_setup != 0) {
|
if (do_setup != 0) {
|
||||||
|
if (bitbang->setup_transfer) {
|
||||||
status = bitbang->setup_transfer(spi, t);
|
status = bitbang->setup_transfer(spi, t);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
if (do_setup == -1)
|
if (do_setup == -1)
|
||||||
do_setup = 0;
|
do_setup = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
#include "spi-fsl-cpm.h"
|
#include "spi-fsl-cpm.h"
|
||||||
#include "spi-fsl-lib.h"
|
#include "spi-fsl-lib.h"
|
||||||
|
@ -269,17 +270,6 @@ static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
|
||||||
if (mspi->flags & SPI_CPM2) {
|
if (mspi->flags & SPI_CPM2) {
|
||||||
pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
|
pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
|
||||||
out_be16(spi_base, pram_ofs);
|
out_be16(spi_base, pram_ofs);
|
||||||
} else {
|
|
||||||
struct spi_pram __iomem *pram = spi_base;
|
|
||||||
u16 rpbase = in_be16(&pram->rpbase);
|
|
||||||
|
|
||||||
/* Microcode relocation patch applied? */
|
|
||||||
if (rpbase) {
|
|
||||||
pram_ofs = rpbase;
|
|
||||||
} else {
|
|
||||||
pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
|
|
||||||
out_be16(spi_base, pram_ofs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iounmap(spi_base);
|
iounmap(spi_base);
|
||||||
|
@ -292,7 +282,6 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
|
||||||
struct device_node *np = dev->of_node;
|
struct device_node *np = dev->of_node;
|
||||||
const u32 *iprop;
|
const u32 *iprop;
|
||||||
int size;
|
int size;
|
||||||
unsigned long pram_ofs;
|
|
||||||
unsigned long bds_ofs;
|
unsigned long bds_ofs;
|
||||||
|
|
||||||
if (!(mspi->flags & SPI_CPM_MODE))
|
if (!(mspi->flags & SPI_CPM_MODE))
|
||||||
|
@ -319,8 +308,21 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pram_ofs = fsl_spi_cpm_get_pram(mspi);
|
if (mspi->flags & SPI_CPM1) {
|
||||||
if (IS_ERR_VALUE(pram_ofs)) {
|
struct resource *res;
|
||||||
|
|
||||||
|
res = platform_get_resource(to_platform_device(dev),
|
||||||
|
IORESOURCE_MEM, 1);
|
||||||
|
mspi->pram = devm_ioremap_resource(dev, res);
|
||||||
|
} else {
|
||||||
|
unsigned long pram_ofs = fsl_spi_cpm_get_pram(mspi);
|
||||||
|
|
||||||
|
if (IS_ERR_VALUE(pram_ofs))
|
||||||
|
mspi->pram = NULL;
|
||||||
|
else
|
||||||
|
mspi->pram = cpm_muram_addr(pram_ofs);
|
||||||
|
}
|
||||||
|
if (mspi->pram == NULL) {
|
||||||
dev_err(dev, "can't allocate spi parameter ram\n");
|
dev_err(dev, "can't allocate spi parameter ram\n");
|
||||||
goto err_pram;
|
goto err_pram;
|
||||||
}
|
}
|
||||||
|
@ -346,8 +348,6 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
|
||||||
goto err_dummy_rx;
|
goto err_dummy_rx;
|
||||||
}
|
}
|
||||||
|
|
||||||
mspi->pram = cpm_muram_addr(pram_ofs);
|
|
||||||
|
|
||||||
mspi->tx_bd = cpm_muram_addr(bds_ofs);
|
mspi->tx_bd = cpm_muram_addr(bds_ofs);
|
||||||
mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
|
mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
|
||||||
|
|
||||||
|
@ -375,7 +375,8 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
|
||||||
err_dummy_tx:
|
err_dummy_tx:
|
||||||
cpm_muram_free(bds_ofs);
|
cpm_muram_free(bds_ofs);
|
||||||
err_bds:
|
err_bds:
|
||||||
cpm_muram_free(pram_ofs);
|
if (!(mspi->flags & SPI_CPM1))
|
||||||
|
cpm_muram_free(cpm_muram_offset(mspi->pram));
|
||||||
err_pram:
|
err_pram:
|
||||||
fsl_spi_free_dummy_rx();
|
fsl_spi_free_dummy_rx();
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -1210,6 +1210,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
|
||||||
struct omap2_mcspi *mcspi;
|
struct omap2_mcspi *mcspi;
|
||||||
struct omap2_mcspi_dma *mcspi_dma;
|
struct omap2_mcspi_dma *mcspi_dma;
|
||||||
struct spi_transfer *t;
|
struct spi_transfer *t;
|
||||||
|
int status;
|
||||||
|
|
||||||
spi = m->spi;
|
spi = m->spi;
|
||||||
mcspi = spi_master_get_devdata(master);
|
mcspi = spi_master_get_devdata(master);
|
||||||
|
@ -1229,7 +1230,8 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
|
||||||
tx_buf ? "tx" : "",
|
tx_buf ? "tx" : "",
|
||||||
rx_buf ? "rx" : "",
|
rx_buf ? "rx" : "",
|
||||||
t->bits_per_word);
|
t->bits_per_word);
|
||||||
return -EINVAL;
|
status = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->is_dma_mapped || len < DMA_MIN_BYTES)
|
if (m->is_dma_mapped || len < DMA_MIN_BYTES)
|
||||||
|
@ -1241,7 +1243,8 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
|
||||||
if (dma_mapping_error(mcspi->dev, t->tx_dma)) {
|
if (dma_mapping_error(mcspi->dev, t->tx_dma)) {
|
||||||
dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",
|
dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",
|
||||||
'T', len);
|
'T', len);
|
||||||
return -EINVAL;
|
status = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mcspi_dma->dma_rx && rx_buf != NULL) {
|
if (mcspi_dma->dma_rx && rx_buf != NULL) {
|
||||||
|
@ -1253,14 +1256,19 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
|
||||||
if (tx_buf != NULL)
|
if (tx_buf != NULL)
|
||||||
dma_unmap_single(mcspi->dev, t->tx_dma,
|
dma_unmap_single(mcspi->dev, t->tx_dma,
|
||||||
len, DMA_TO_DEVICE);
|
len, DMA_TO_DEVICE);
|
||||||
return -EINVAL;
|
status = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
omap2_mcspi_work(mcspi, m);
|
omap2_mcspi_work(mcspi, m);
|
||||||
|
/* spi_finalize_current_message() changes the status inside the
|
||||||
|
* spi_message, save the status here. */
|
||||||
|
status = m->status;
|
||||||
|
out:
|
||||||
spi_finalize_current_message(master);
|
spi_finalize_current_message(master);
|
||||||
return 0;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
|
static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
|
||||||
|
|
Loading…
Reference in a new issue