You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'spi-for-linus' of git://git.secretlab.ca/git/linux
Pull SPI changes from Grant Likely:
"Changes to both core spi code and spi device drivers. The driver
changes are the usual set of bug fixes and platform enablement.
Core code changes include:
- More intelligent assignment of SPI bus numbers when using DT
- Common mechanism for using gpios as CS lines
- Pull checks for bits_per_word and transfer speed out of drivers and
into core code
- Ensure temporary DMA buffers are DMA safe"
* tag 'spi-for-linus' of git://git.secretlab.ca/git/linux: (50 commits)
spi: Document cs_gpios and cs_gpio in kernel-doc
spi/of: Fix initialization of cs_gpios array
spi/pxa2xx: add support for Lynxpoint SPI controllers
spi/pxa2xx: add support for Intel Low Power Subsystem SPI
spi/pxa2xx: add support for SPI_LOOP
spi/pxa2xx: add support for runtime PM
spi/pxa2xx: add support for DMA engine
spi/pxa2xx: break out the private DMA API usage into a separate file
spi/ath79: add shutdown handler
spi/mips-lantiq: set SPI_MASTER_HALF_DUPLEX flag
spi/mips-lantiq: make use of spi_finalize_current_message
spi/bcm63xx: work around inability to keep CS up
spi/davinci: use request_threaded_irq() to fix deadlock
spi/orion: Use module_platform_driver()
spi/bcm63xx: reject transfers unable to transfer
spi: Ensure memory used for spi_write_then_read() is DMA safe
spi/spi-mpc512x-psc: init mode bits supported by the driver
spi/mpc512x-psc: don't use obsolet cell-index property
spi: Remove erroneous __init, __exit and __exit_p() references in drivers
spi/s3c64xx: fix checkpatch warnings and error
...
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
Renesas MSIOF spi controller
|
||||
|
||||
Required properties:
|
||||
- compatible : "renesas,sh-msiof" for SuperH or
|
||||
"renesas,sh-mobile-msiof" for SH Mobile series
|
||||
- reg : Offset and length of the register set for the device
|
||||
- interrupts : interrupt line used by MSIOF
|
||||
|
||||
Optional properties:
|
||||
- num-cs : total number of chip-selects
|
||||
- renesas,tx-fifo-size : Overrides the default tx fifo size given in words
|
||||
- renesas,rx-fifo-size : Overrides the default rx fifo size given in words
|
||||
@@ -7168,6 +7168,7 @@ F: drivers/clk/spear/
|
||||
|
||||
SPI SUBSYSTEM
|
||||
M: Grant Likely <grant.likely@secretlab.ca>
|
||||
M: Mark Brown <broonie@opensource.wolfsonmicro.com>
|
||||
L: spi-devel-general@lists.sourceforge.net
|
||||
Q: http://patchwork.kernel.org/project/spi-devel-general/list/
|
||||
T: git git://git.secretlab.ca/git/linux-2.6.git
|
||||
|
||||
+13
-2
@@ -297,9 +297,20 @@ config SPI_PPC4xx
|
||||
help
|
||||
This selects a driver for the PPC4xx SPI Controller.
|
||||
|
||||
config SPI_PXA2XX_PXADMA
|
||||
bool "PXA2xx SSP legacy PXA DMA API support"
|
||||
depends on SPI_PXA2XX && ARCH_PXA
|
||||
help
|
||||
Enable PXA private legacy DMA API support. Note that this is
|
||||
deprecated in favor of generic DMA engine API.
|
||||
|
||||
config SPI_PXA2XX_DMA
|
||||
def_bool y
|
||||
depends on SPI_PXA2XX && !SPI_PXA2XX_PXADMA
|
||||
|
||||
config SPI_PXA2XX
|
||||
tristate "PXA2xx SSP SPI master"
|
||||
depends on (ARCH_PXA || (X86_32 && PCI)) && EXPERIMENTAL
|
||||
depends on ARCH_PXA || PCI || ACPI
|
||||
select PXA_SSP if ARCH_PXA
|
||||
help
|
||||
This enables using a PXA2xx or Sodaville SSP port as a SPI master
|
||||
@@ -307,7 +318,7 @@ config SPI_PXA2XX
|
||||
additional documentation can be found a Documentation/spi/pxa2xx.
|
||||
|
||||
config SPI_PXA2XX_PCI
|
||||
def_bool SPI_PXA2XX && X86_32 && PCI
|
||||
def_tristate SPI_PXA2XX && PCI
|
||||
|
||||
config SPI_RSPI
|
||||
tristate "Renesas RSPI controller"
|
||||
|
||||
@@ -47,7 +47,10 @@ obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o
|
||||
obj-$(CONFIG_SPI_ORION) += spi-orion.o
|
||||
obj-$(CONFIG_SPI_PL022) += spi-pl022.o
|
||||
obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o
|
||||
obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx.o
|
||||
spi-pxa2xx-platform-objs := spi-pxa2xx.o
|
||||
spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_PXADMA) += spi-pxa2xx-pxadma.o
|
||||
spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o
|
||||
obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o
|
||||
obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
|
||||
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
|
||||
obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
|
||||
|
||||
@@ -134,7 +134,7 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
|
||||
hw->tx = t->tx_buf;
|
||||
hw->rx = t->rx_buf;
|
||||
hw->count = 0;
|
||||
hw->bytes_per_word = (t->bits_per_word ? : spi->bits_per_word) / 8;
|
||||
hw->bytes_per_word = t->bits_per_word / 8;
|
||||
hw->len = t->len / hw->bytes_per_word;
|
||||
|
||||
if (hw->irq >= 0) {
|
||||
|
||||
+91
-40
@@ -24,17 +24,24 @@
|
||||
#include <linux/spi/spi_bitbang.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <asm/mach-ath79/ar71xx_regs.h>
|
||||
#include <asm/mach-ath79/ath79_spi_platform.h>
|
||||
|
||||
#define DRV_NAME "ath79-spi"
|
||||
|
||||
#define ATH79_SPI_RRW_DELAY_FACTOR 12000
|
||||
#define MHZ (1000 * 1000)
|
||||
|
||||
struct ath79_spi {
|
||||
struct spi_bitbang bitbang;
|
||||
u32 ioc_base;
|
||||
u32 reg_ctrl;
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
unsigned rrw_delay;
|
||||
};
|
||||
|
||||
static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
|
||||
@@ -52,6 +59,12 @@ static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi)
|
||||
return spi_master_get_devdata(spi->master);
|
||||
}
|
||||
|
||||
static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned nsecs)
|
||||
{
|
||||
if (nsecs > sp->rrw_delay)
|
||||
ndelay(nsecs - sp->rrw_delay);
|
||||
}
|
||||
|
||||
static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
|
||||
{
|
||||
struct ath79_spi *sp = ath79_spidev_to_sp(spi);
|
||||
@@ -83,15 +96,8 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
|
||||
|
||||
}
|
||||
|
||||
static int ath79_spi_setup_cs(struct spi_device *spi)
|
||||
static void ath79_spi_enable(struct ath79_spi *sp)
|
||||
{
|
||||
struct ath79_spi *sp = ath79_spidev_to_sp(spi);
|
||||
struct ath79_spi_controller_data *cdata;
|
||||
|
||||
cdata = spi->controller_data;
|
||||
if (spi->chip_select && !cdata)
|
||||
return -EINVAL;
|
||||
|
||||
/* enable GPIO mode */
|
||||
ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
|
||||
|
||||
@@ -101,46 +107,50 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
|
||||
|
||||
/* TODO: setup speed? */
|
||||
ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
|
||||
|
||||
if (spi->chip_select) {
|
||||
int status = 0;
|
||||
|
||||
status = gpio_request(cdata->gpio, dev_name(&spi->dev));
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = gpio_direction_output(cdata->gpio,
|
||||
spi->mode & SPI_CS_HIGH);
|
||||
if (status) {
|
||||
gpio_free(cdata->gpio);
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
if (spi->mode & SPI_CS_HIGH)
|
||||
sp->ioc_base |= AR71XX_SPI_IOC_CS0;
|
||||
else
|
||||
sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
|
||||
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath79_spi_cleanup_cs(struct spi_device *spi)
|
||||
static void ath79_spi_disable(struct ath79_spi *sp)
|
||||
{
|
||||
struct ath79_spi *sp = ath79_spidev_to_sp(spi);
|
||||
|
||||
if (spi->chip_select) {
|
||||
struct ath79_spi_controller_data *cdata = spi->controller_data;
|
||||
gpio_free(cdata->gpio);
|
||||
}
|
||||
|
||||
/* restore CTRL register */
|
||||
ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl);
|
||||
/* disable GPIO mode */
|
||||
ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
|
||||
}
|
||||
|
||||
static int ath79_spi_setup_cs(struct spi_device *spi)
|
||||
{
|
||||
struct ath79_spi_controller_data *cdata;
|
||||
int status;
|
||||
|
||||
cdata = spi->controller_data;
|
||||
if (spi->chip_select && !cdata)
|
||||
return -EINVAL;
|
||||
|
||||
status = 0;
|
||||
if (spi->chip_select) {
|
||||
unsigned long flags;
|
||||
|
||||
flags = GPIOF_DIR_OUT;
|
||||
if (spi->mode & SPI_CS_HIGH)
|
||||
flags |= GPIOF_INIT_HIGH;
|
||||
else
|
||||
flags |= GPIOF_INIT_LOW;
|
||||
|
||||
status = gpio_request_one(cdata->gpio, flags,
|
||||
dev_name(&spi->dev));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void ath79_spi_cleanup_cs(struct spi_device *spi)
|
||||
{
|
||||
if (spi->chip_select) {
|
||||
struct ath79_spi_controller_data *cdata = spi->controller_data;
|
||||
gpio_free(cdata->gpio);
|
||||
}
|
||||
}
|
||||
|
||||
static int ath79_spi_setup(struct spi_device *spi)
|
||||
{
|
||||
int status = 0;
|
||||
@@ -184,7 +194,11 @@ static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs,
|
||||
|
||||
/* setup MSB (to slave) on trailing edge */
|
||||
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
|
||||
ath79_spi_delay(sp, nsecs);
|
||||
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
|
||||
ath79_spi_delay(sp, nsecs);
|
||||
if (bits == 1)
|
||||
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
|
||||
|
||||
word <<= 1;
|
||||
}
|
||||
@@ -198,6 +212,7 @@ static int ath79_spi_probe(struct platform_device *pdev)
|
||||
struct ath79_spi *sp;
|
||||
struct ath79_spi_platform_data *pdata;
|
||||
struct resource *r;
|
||||
unsigned long rate;
|
||||
int ret;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*sp));
|
||||
@@ -236,12 +251,39 @@ static int ath79_spi_probe(struct platform_device *pdev)
|
||||
goto err_put_master;
|
||||
}
|
||||
|
||||
sp->clk = clk_get(&pdev->dev, "ahb");
|
||||
if (IS_ERR(sp->clk)) {
|
||||
ret = PTR_ERR(sp->clk);
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
ret = clk_enable(sp->clk);
|
||||
if (ret)
|
||||
goto err_clk_put;
|
||||
|
||||
rate = DIV_ROUND_UP(clk_get_rate(sp->clk), MHZ);
|
||||
if (!rate) {
|
||||
ret = -EINVAL;
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
sp->rrw_delay = ATH79_SPI_RRW_DELAY_FACTOR / rate;
|
||||
dev_dbg(&pdev->dev, "register read/write delay is %u nsecs\n",
|
||||
sp->rrw_delay);
|
||||
|
||||
ath79_spi_enable(sp);
|
||||
ret = spi_bitbang_start(&sp->bitbang);
|
||||
if (ret)
|
||||
goto err_unmap;
|
||||
goto err_disable;
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable:
|
||||
ath79_spi_disable(sp);
|
||||
err_clk_disable:
|
||||
clk_disable(sp->clk);
|
||||
err_clk_put:
|
||||
clk_put(sp->clk);
|
||||
err_unmap:
|
||||
iounmap(sp->base);
|
||||
err_put_master:
|
||||
@@ -256,6 +298,9 @@ static int ath79_spi_remove(struct platform_device *pdev)
|
||||
struct ath79_spi *sp = platform_get_drvdata(pdev);
|
||||
|
||||
spi_bitbang_stop(&sp->bitbang);
|
||||
ath79_spi_disable(sp);
|
||||
clk_disable(sp->clk);
|
||||
clk_put(sp->clk);
|
||||
iounmap(sp->base);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
spi_master_put(sp->bitbang.master);
|
||||
@@ -263,9 +308,15 @@ static int ath79_spi_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath79_spi_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
ath79_spi_remove(pdev);
|
||||
}
|
||||
|
||||
static struct platform_driver ath79_spi_driver = {
|
||||
.probe = ath79_spi_probe,
|
||||
.remove = ath79_spi_remove,
|
||||
.shutdown = ath79_spi_shutdown,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
@@ -1088,7 +1088,7 @@ static struct platform_driver atmel_spi_driver = {
|
||||
.suspend = atmel_spi_suspend,
|
||||
.resume = atmel_spi_resume,
|
||||
.probe = atmel_spi_probe,
|
||||
.remove = __exit_p(atmel_spi_remove),
|
||||
.remove = atmel_spi_remove,
|
||||
};
|
||||
module_platform_driver(atmel_spi_driver);
|
||||
|
||||
|
||||
@@ -717,7 +717,7 @@ static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw)
|
||||
}
|
||||
}
|
||||
|
||||
static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
|
||||
static void au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
|
||||
{
|
||||
u32 stat, cfg;
|
||||
|
||||
@@ -766,7 +766,7 @@ static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
|
||||
}
|
||||
|
||||
|
||||
static int __init au1550_spi_probe(struct platform_device *pdev)
|
||||
static int au1550_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct au1550_spi *hw;
|
||||
struct spi_master *master;
|
||||
@@ -968,7 +968,7 @@ err_nomem:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __exit au1550_spi_remove(struct platform_device *pdev)
|
||||
static int au1550_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct au1550_spi *hw = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -997,7 +997,7 @@ static int __exit au1550_spi_remove(struct platform_device *pdev)
|
||||
MODULE_ALIAS("platform:au1550-spi");
|
||||
|
||||
static struct platform_driver au1550_spi_drv = {
|
||||
.remove = __exit_p(au1550_spi_remove),
|
||||
.remove = au1550_spi_remove,
|
||||
.driver = {
|
||||
.name = "au1550-spi",
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
+125
-54
@@ -37,6 +37,8 @@
|
||||
|
||||
#define PFX KBUILD_MODNAME
|
||||
|
||||
#define BCM63XX_SPI_MAX_PREPEND 15
|
||||
|
||||
struct bcm63xx_spi {
|
||||
struct completion done;
|
||||
|
||||
@@ -49,16 +51,10 @@ struct bcm63xx_spi {
|
||||
unsigned int msg_type_shift;
|
||||
unsigned int msg_ctl_width;
|
||||
|
||||
/* Data buffers */
|
||||
const unsigned char *tx_ptr;
|
||||
unsigned char *rx_ptr;
|
||||
|
||||
/* data iomem */
|
||||
u8 __iomem *tx_io;
|
||||
const u8 __iomem *rx_io;
|
||||
|
||||
int remaining_bytes;
|
||||
|
||||
struct clk *clk;
|
||||
struct platform_device *pdev;
|
||||
};
|
||||
@@ -175,24 +171,17 @@ static int bcm63xx_spi_setup(struct spi_device *spi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fill the TX FIFO with as many bytes as possible */
|
||||
static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs)
|
||||
{
|
||||
u8 size;
|
||||
|
||||
/* Fill the Tx FIFO with as many bytes as possible */
|
||||
size = bs->remaining_bytes < bs->fifo_size ? bs->remaining_bytes :
|
||||
bs->fifo_size;
|
||||
memcpy_toio(bs->tx_io, bs->tx_ptr, size);
|
||||
bs->remaining_bytes -= size;
|
||||
}
|
||||
|
||||
static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
|
||||
unsigned int num_transfers)
|
||||
{
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
|
||||
u16 msg_ctl;
|
||||
u16 cmd;
|
||||
u8 rx_tail;
|
||||
unsigned int i, timeout = 0, prepend_len = 0, len = 0;
|
||||
struct spi_transfer *t = first;
|
||||
bool do_rx = false;
|
||||
bool do_tx = false;
|
||||
|
||||
/* Disable the CMD_DONE interrupt */
|
||||
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
|
||||
@@ -200,25 +189,45 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
|
||||
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;
|
||||
if (num_transfers > 1 && t->tx_buf && t->len <= BCM63XX_SPI_MAX_PREPEND)
|
||||
prepend_len = t->len;
|
||||
|
||||
if (t->tx_buf) {
|
||||
bs->remaining_bytes = t->len;
|
||||
bcm63xx_spi_fill_tx_fifo(bs);
|
||||
/* prepare the buffer */
|
||||
for (i = 0; i < num_transfers; i++) {
|
||||
if (t->tx_buf) {
|
||||
do_tx = true;
|
||||
memcpy_toio(bs->tx_io + len, t->tx_buf, t->len);
|
||||
|
||||
/* don't prepend more than one tx */
|
||||
if (t != first)
|
||||
prepend_len = 0;
|
||||
}
|
||||
|
||||
if (t->rx_buf) {
|
||||
do_rx = true;
|
||||
/* prepend is half-duplex write only */
|
||||
if (t == first)
|
||||
prepend_len = 0;
|
||||
}
|
||||
|
||||
len += t->len;
|
||||
|
||||
t = list_entry(t->transfer_list.next, struct spi_transfer,
|
||||
transfer_list);
|
||||
}
|
||||
|
||||
len -= prepend_len;
|
||||
|
||||
init_completion(&bs->done);
|
||||
|
||||
/* Fill in the Message control register */
|
||||
msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);
|
||||
msg_ctl = (len << SPI_BYTE_CNT_SHIFT);
|
||||
|
||||
if (t->rx_buf && t->tx_buf)
|
||||
if (do_rx && do_tx && prepend_len == 0)
|
||||
msg_ctl |= (SPI_FD_RW << bs->msg_type_shift);
|
||||
else if (t->rx_buf)
|
||||
else if (do_rx)
|
||||
msg_ctl |= (SPI_HD_R << bs->msg_type_shift);
|
||||
else if (t->tx_buf)
|
||||
else if (do_tx)
|
||||
msg_ctl |= (SPI_HD_W << bs->msg_type_shift);
|
||||
|
||||
switch (bs->msg_ctl_width) {
|
||||
@@ -232,14 +241,41 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
|
||||
|
||||
/* Issue the transfer */
|
||||
cmd = SPI_CMD_START_IMMEDIATE;
|
||||
cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
|
||||
cmd |= (prepend_len << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
|
||||
cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT);
|
||||
bcm_spi_writew(bs, cmd, SPI_CMD);
|
||||
|
||||
/* Enable the CMD_DONE interrupt */
|
||||
bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
|
||||
|
||||
return t->len - bs->remaining_bytes;
|
||||
timeout = wait_for_completion_timeout(&bs->done, HZ);
|
||||
if (!timeout)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* read out all data */
|
||||
rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
|
||||
|
||||
if (do_rx && rx_tail != len)
|
||||
return -EIO;
|
||||
|
||||
if (!rx_tail)
|
||||
return 0;
|
||||
|
||||
len = 0;
|
||||
t = first;
|
||||
/* Read out all the data */
|
||||
for (i = 0; i < num_transfers; i++) {
|
||||
if (t->rx_buf)
|
||||
memcpy_fromio(t->rx_buf, bs->rx_io + len, t->len);
|
||||
|
||||
if (t != first || prepend_len == 0)
|
||||
len += t->len;
|
||||
|
||||
t = list_entry(t->transfer_list.next, struct spi_transfer,
|
||||
transfer_list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm63xx_spi_prepare_transfer(struct spi_master *master)
|
||||
@@ -264,41 +300,76 @@ 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_transfer *t, *first = NULL;
|
||||
struct spi_device *spi = m->spi;
|
||||
int status = 0;
|
||||
unsigned int timeout = 0;
|
||||
unsigned int n_transfers = 0, total_len = 0;
|
||||
bool can_use_prepend = false;
|
||||
|
||||
/*
|
||||
* This SPI controller does not support keeping CS active after a
|
||||
* transfer.
|
||||
* Work around this by merging as many transfers we can into one big
|
||||
* full-duplex transfers.
|
||||
*/
|
||||
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);
|
||||
if (!first)
|
||||
first = t;
|
||||
|
||||
while (len) {
|
||||
/* send the data */
|
||||
len -= bcm63xx_txrx_bufs(spi, t);
|
||||
n_transfers++;
|
||||
total_len += t->len;
|
||||
|
||||
timeout = wait_for_completion_timeout(&bs->done, HZ);
|
||||
if (!timeout) {
|
||||
status = -ETIMEDOUT;
|
||||
goto exit;
|
||||
}
|
||||
if (n_transfers == 2 && !first->rx_buf && !t->tx_buf &&
|
||||
first->len <= BCM63XX_SPI_MAX_PREPEND)
|
||||
can_use_prepend = true;
|
||||
else if (can_use_prepend && t->tx_buf)
|
||||
can_use_prepend = false;
|
||||
|
||||
/* 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);
|
||||
/* we can only transfer one fifo worth of data */
|
||||
if ((can_use_prepend &&
|
||||
total_len > (bs->fifo_size + BCM63XX_SPI_MAX_PREPEND)) ||
|
||||
(!can_use_prepend && total_len > bs->fifo_size)) {
|
||||
dev_err(&spi->dev, "unable to do transfers larger than FIFO size (%i > %i)\n",
|
||||
total_len, bs->fifo_size);
|
||||
status = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
m->actual_length += t->len;
|
||||
/* all combined transfers have to have the same speed */
|
||||
if (t->speed_hz != first->speed_hz) {
|
||||
dev_err(&spi->dev, "unable to change speed between transfers\n");
|
||||
status = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* CS will be deasserted directly after transfer */
|
||||
if (t->delay_usecs) {
|
||||
dev_err(&spi->dev, "unable to keep CS asserted after transfer\n");
|
||||
status = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (t->cs_change ||
|
||||
list_is_last(&t->transfer_list, &m->transfers)) {
|
||||
/* configure adapter for a new transfer */
|
||||
bcm63xx_spi_setup_transfer(spi, first);
|
||||
|
||||
/* send the data */
|
||||
status = bcm63xx_txrx_bufs(spi, first, n_transfers);
|
||||
if (status)
|
||||
goto exit;
|
||||
|
||||
m->actual_length += total_len;
|
||||
|
||||
first = NULL;
|
||||
n_transfers = 0;
|
||||
total_len = 0;
|
||||
can_use_prepend = false;
|
||||
}
|
||||
}
|
||||
exit:
|
||||
m->status = status;
|
||||
|
||||
@@ -416,8 +416,7 @@ 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 ? : 8;
|
||||
bits_per_word = transfer->bits_per_word;
|
||||
if (bits_per_word % 16 == 0)
|
||||
drv_data->ops = &bfin_sport_transfer_ops_u16;
|
||||
else
|
||||
|
||||
@@ -642,8 +642,7 @@ static void bfin_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 ? : 8;
|
||||
bits_per_word = transfer->bits_per_word;
|
||||
if (bits_per_word % 16 == 0) {
|
||||
drv_data->n_bytes = bits_per_word/8;
|
||||
drv_data->len = (transfer->len) >> 1;
|
||||
@@ -1274,7 +1273,7 @@ static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init bfin_spi_probe(struct platform_device *pdev)
|
||||
static int bfin_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct bfin5xx_spi_master *platform_info;
|
||||
|
||||
+17
-16
@@ -69,7 +69,7 @@ static unsigned bitbang_txrx_8(
|
||||
unsigned ns,
|
||||
struct spi_transfer *t
|
||||
) {
|
||||
unsigned bits = t->bits_per_word ? : spi->bits_per_word;
|
||||
unsigned bits = t->bits_per_word;
|
||||
unsigned count = t->len;
|
||||
const u8 *tx = t->tx_buf;
|
||||
u8 *rx = t->rx_buf;
|
||||
@@ -95,7 +95,7 @@ static unsigned bitbang_txrx_16(
|
||||
unsigned ns,
|
||||
struct spi_transfer *t
|
||||
) {
|
||||
unsigned bits = t->bits_per_word ? : spi->bits_per_word;
|
||||
unsigned bits = t->bits_per_word;
|
||||
unsigned count = t->len;
|
||||
const u16 *tx = t->tx_buf;
|
||||
u16 *rx = t->rx_buf;
|
||||
@@ -121,7 +121,7 @@ static unsigned bitbang_txrx_32(
|
||||
unsigned ns,
|
||||
struct spi_transfer *t
|
||||
) {
|
||||
unsigned bits = t->bits_per_word ? : spi->bits_per_word;
|
||||
unsigned bits = t->bits_per_word;
|
||||
unsigned count = t->len;
|
||||
const u32 *tx = t->tx_buf;
|
||||
u32 *rx = t->rx_buf;
|
||||
@@ -427,40 +427,41 @@ EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
|
||||
*/
|
||||
int spi_bitbang_start(struct spi_bitbang *bitbang)
|
||||
{
|
||||
int status;
|
||||
struct spi_master *master = bitbang->master;
|
||||
int status;
|
||||
|
||||
if (!bitbang->master || !bitbang->chipselect)
|
||||
if (!master || !bitbang->chipselect)
|
||||
return -EINVAL;
|
||||
|
||||
INIT_WORK(&bitbang->work, bitbang_work);
|
||||
spin_lock_init(&bitbang->lock);
|
||||
INIT_LIST_HEAD(&bitbang->queue);
|
||||
|
||||
if (!bitbang->master->mode_bits)
|
||||
bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
|
||||
if (!master->mode_bits)
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
|
||||
|
||||
if (!bitbang->master->transfer)
|
||||
bitbang->master->transfer = spi_bitbang_transfer;
|
||||
if (!master->transfer)
|
||||
master->transfer = spi_bitbang_transfer;
|
||||
if (!bitbang->txrx_bufs) {
|
||||
bitbang->use_dma = 0;
|
||||
bitbang->txrx_bufs = spi_bitbang_bufs;
|
||||
if (!bitbang->master->setup) {
|
||||
if (!master->setup) {
|
||||
if (!bitbang->setup_transfer)
|
||||
bitbang->setup_transfer =
|
||||
spi_bitbang_setup_transfer;
|
||||
bitbang->master->setup = spi_bitbang_setup;
|
||||
bitbang->master->cleanup = spi_bitbang_cleanup;
|
||||
master->setup = spi_bitbang_setup;
|
||||
master->cleanup = spi_bitbang_cleanup;
|
||||
}
|
||||
} else if (!bitbang->master->setup)
|
||||
} else if (!master->setup)
|
||||
return -EINVAL;
|
||||
if (bitbang->master->transfer == spi_bitbang_transfer &&
|
||||
if (master->transfer == spi_bitbang_transfer &&
|
||||
!bitbang->setup_transfer)
|
||||
return -EINVAL;
|
||||
|
||||
/* this task is the only thing to touch the SPI bits */
|
||||
bitbang->busy = 0;
|
||||
bitbang->workqueue = create_singlethread_workqueue(
|
||||
dev_name(bitbang->master->dev.parent));
|
||||
dev_name(master->dev.parent));
|
||||
if (bitbang->workqueue == NULL) {
|
||||
status = -EBUSY;
|
||||
goto err1;
|
||||
@@ -469,7 +470,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
|
||||
/* driver may get busy before register() returns, especially
|
||||
* if someone registered boardinfo for devices
|
||||
*/
|
||||
status = spi_register_master(bitbang->master);
|
||||
status = spi_register_master(master);
|
||||
if (status < 0)
|
||||
goto err2;
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ static int spi_clps711x_setup_xfer(struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
u32 speed = xfer->speed_hz ? : spi->max_speed_hz;
|
||||
u8 bpw = xfer->bits_per_word ? : spi->bits_per_word;
|
||||
u8 bpw = xfer->bits_per_word;
|
||||
struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master);
|
||||
|
||||
if (bpw != 8) {
|
||||
|
||||
@@ -329,8 +329,7 @@ static int mcfqspi_transfer_one_message(struct spi_master *master,
|
||||
mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high);
|
||||
|
||||
mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE);
|
||||
if ((t->bits_per_word ? t->bits_per_word :
|
||||
spi->bits_per_word) == 8)
|
||||
if (t->bits_per_word == 8)
|
||||
mcfqspi_transfer_msg8(mcfqspi, t->len, t->tx_buf,
|
||||
t->rx_buf);
|
||||
else
|
||||
|
||||
+103
-16
@@ -28,6 +28,8 @@
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/edma.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi_bitbang.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -135,7 +137,7 @@ struct davinci_spi {
|
||||
int dma_rx_chnum;
|
||||
int dma_tx_chnum;
|
||||
|
||||
struct davinci_spi_platform_data *pdata;
|
||||
struct davinci_spi_platform_data pdata;
|
||||
|
||||
void (*get_rx)(u32 rx_data, struct davinci_spi *);
|
||||
u32 (*get_tx)(struct davinci_spi *);
|
||||
@@ -213,7 +215,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
|
||||
bool gpio_chipsel = false;
|
||||
|
||||
dspi = spi_master_get_devdata(spi->master);
|
||||
pdata = dspi->pdata;
|
||||
pdata = &dspi->pdata;
|
||||
|
||||
if (pdata->chip_sel && chip_sel < pdata->num_chipselect &&
|
||||
pdata->chip_sel[chip_sel] != SPI_INTERN_CS)
|
||||
@@ -392,7 +394,7 @@ static int davinci_spi_setup(struct spi_device *spi)
|
||||
struct davinci_spi_platform_data *pdata;
|
||||
|
||||
dspi = spi_master_get_devdata(spi->master);
|
||||
pdata = dspi->pdata;
|
||||
pdata = &dspi->pdata;
|
||||
|
||||
/* if bits per word length is zero then set it default 8 */
|
||||
if (!spi->bits_per_word)
|
||||
@@ -534,7 +536,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
|
||||
struct scatterlist sg_rx, sg_tx;
|
||||
|
||||
dspi = spi_master_get_devdata(spi->master);
|
||||
pdata = dspi->pdata;
|
||||
pdata = &dspi->pdata;
|
||||
spicfg = (struct davinci_spi_config *)spi->controller_data;
|
||||
if (!spicfg)
|
||||
spicfg = &davinci_spi_default_cfg;
|
||||
@@ -699,6 +701,19 @@ err_alloc_dummy_buf:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* dummy_thread_fn - dummy thread function
|
||||
* @irq: IRQ number for this SPI Master
|
||||
* @context_data: structure for SPI Master controller davinci_spi
|
||||
*
|
||||
* This is to satisfy the request_threaded_irq() API so that the irq
|
||||
* handler is called in interrupt context.
|
||||
*/
|
||||
static irqreturn_t dummy_thread_fn(s32 irq, void *data)
|
||||
{
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* davinci_spi_irq - Interrupt handler for SPI Master Controller
|
||||
* @irq: IRQ number for this SPI Master
|
||||
@@ -758,6 +773,70 @@ rx_dma_failed:
|
||||
return r;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static const struct of_device_id davinci_spi_of_match[] = {
|
||||
{
|
||||
.compatible = "ti,dm644x-spi",
|
||||
},
|
||||
{
|
||||
.compatible = "ti,da8xx-spi",
|
||||
.data = (void *)SPI_VERSION_2,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, davini_spi_of_match);
|
||||
|
||||
/**
|
||||
* spi_davinci_get_pdata - Get platform data from DTS binding
|
||||
* @pdev: ptr to platform data
|
||||
* @dspi: ptr to driver data
|
||||
*
|
||||
* Parses and populates pdata in dspi from device tree bindings.
|
||||
*
|
||||
* NOTE: Not all platform data params are supported currently.
|
||||
*/
|
||||
static int spi_davinci_get_pdata(struct platform_device *pdev,
|
||||
struct davinci_spi *dspi)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct davinci_spi_platform_data *pdata;
|
||||
unsigned int num_cs, intr_line = 0;
|
||||
const struct of_device_id *match;
|
||||
|
||||
pdata = &dspi->pdata;
|
||||
|
||||
pdata->version = SPI_VERSION_1;
|
||||
match = of_match_device(of_match_ptr(davinci_spi_of_match),
|
||||
&pdev->dev);
|
||||
if (!match)
|
||||
return -ENODEV;
|
||||
|
||||
/* match data has the SPI version number for SPI_VERSION_2 */
|
||||
if (match->data == (void *)SPI_VERSION_2)
|
||||
pdata->version = SPI_VERSION_2;
|
||||
|
||||
/*
|
||||
* default num_cs is 1 and all chipsel are internal to the chip
|
||||
* indicated by chip_sel being NULL. GPIO based CS is not
|
||||
* supported yet in DT bindings.
|
||||
*/
|
||||
num_cs = 1;
|
||||
of_property_read_u32(node, "num-cs", &num_cs);
|
||||
pdata->num_chipselect = num_cs;
|
||||
of_property_read_u32(node, "ti,davinci-spi-intr-line", &intr_line);
|
||||
pdata->intr_line = intr_line;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define davinci_spi_of_match NULL
|
||||
static struct davinci_spi_platform_data
|
||||
*spi_davinci_get_pdata(struct platform_device *pdev,
|
||||
struct davinci_spi *dspi)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* davinci_spi_probe - probe function for SPI Master Controller
|
||||
* @pdev: platform_device structure which contains plateform specific data
|
||||
@@ -780,12 +859,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
|
||||
int i = 0, ret = 0;
|
||||
u32 spipc0;
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
if (pdata == NULL) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi));
|
||||
if (master == NULL) {
|
||||
ret = -ENOMEM;
|
||||
@@ -800,6 +873,19 @@ static int davinci_spi_probe(struct platform_device *pdev)
|
||||
goto free_master;
|
||||
}
|
||||
|
||||
if (pdev->dev.platform_data) {
|
||||
pdata = pdev->dev.platform_data;
|
||||
dspi->pdata = *pdata;
|
||||
} else {
|
||||
/* update dspi pdata with that from the DT */
|
||||
ret = spi_davinci_get_pdata(pdev, dspi);
|
||||
if (ret < 0)
|
||||
goto free_master;
|
||||
}
|
||||
|
||||
/* pdata in dspi is now updated and point pdata to that */
|
||||
pdata = &dspi->pdata;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (r == NULL) {
|
||||
ret = -ENOENT;
|
||||
@@ -807,7 +893,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
dspi->pbase = r->start;
|
||||
dspi->pdata = pdata;
|
||||
|
||||
mem = request_mem_region(r->start, resource_size(r), pdev->name);
|
||||
if (mem == NULL) {
|
||||
@@ -827,8 +912,8 @@ static int davinci_spi_probe(struct platform_device *pdev)
|
||||
goto unmap_io;
|
||||
}
|
||||
|
||||
ret = request_irq(dspi->irq, davinci_spi_irq, 0, dev_name(&pdev->dev),
|
||||
dspi);
|
||||
ret = request_threaded_irq(dspi->irq, davinci_spi_irq, dummy_thread_fn,
|
||||
0, dev_name(&pdev->dev), dspi);
|
||||
if (ret)
|
||||
goto unmap_io;
|
||||
|
||||
@@ -843,8 +928,9 @@ static int davinci_spi_probe(struct platform_device *pdev)
|
||||
ret = -ENODEV;
|
||||
goto put_master;
|
||||
}
|
||||
clk_enable(dspi->clk);
|
||||
clk_prepare_enable(dspi->clk);
|
||||
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
master->bus_num = pdev->id;
|
||||
master->num_chipselect = pdata->num_chipselect;
|
||||
master->setup = davinci_spi_setup;
|
||||
@@ -927,7 +1013,7 @@ free_dma:
|
||||
dma_release_channel(dspi->dma_rx);
|
||||
dma_release_channel(dspi->dma_tx);
|
||||
free_clk:
|
||||
clk_disable(dspi->clk);
|
||||
clk_disable_unprepare(dspi->clk);
|
||||
clk_put(dspi->clk);
|
||||
put_master:
|
||||
spi_master_put(master);
|
||||
@@ -963,7 +1049,7 @@ static int davinci_spi_remove(struct platform_device *pdev)
|
||||
|
||||
spi_bitbang_stop(&dspi->bitbang);
|
||||
|
||||
clk_disable(dspi->clk);
|
||||
clk_disable_unprepare(dspi->clk);
|
||||
clk_put(dspi->clk);
|
||||
spi_master_put(master);
|
||||
free_irq(dspi->irq, dspi);
|
||||
@@ -978,6 +1064,7 @@ static struct platform_driver davinci_spi_driver = {
|
||||
.driver = {
|
||||
.name = "spi_davinci",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = davinci_spi_of_match,
|
||||
},
|
||||
.probe = davinci_spi_probe,
|
||||
.remove = davinci_spi_remove,
|
||||
|
||||
@@ -446,7 +446,7 @@ static inline int bits_per_word(const struct ep93xx_spi *espi)
|
||||
struct spi_message *msg = espi->current_msg;
|
||||
struct spi_transfer *t = msg->state;
|
||||
|
||||
return t->bits_per_word ? t->bits_per_word : msg->spi->bits_per_word;
|
||||
return t->bits_per_word;
|
||||
}
|
||||
|
||||
static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t)
|
||||
|
||||
@@ -398,7 +398,7 @@ static int falcon_sflash_xfer_one(struct spi_master *master,
|
||||
}
|
||||
|
||||
m->status = ret;
|
||||
m->complete(m->context);
|
||||
spi_finalize_current_message(master);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -423,6 +423,7 @@ static int falcon_sflash_probe(struct platform_device *pdev)
|
||||
|
||||
master->mode_bits = SPI_MODE_3;
|
||||
master->num_chipselect = 1;
|
||||
master->flags = SPI_MASTER_HALF_DUPLEX;
|
||||
master->bus_num = -1;
|
||||
master->setup = falcon_sflash_setup;
|
||||
master->prepare_transfer_hardware = falcon_sflash_prepare_xfer;
|
||||
|
||||
+20
-3
@@ -365,9 +365,26 @@ static int spi_gpio_probe_dt(struct platform_device *pdev)
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
pdata->sck = of_get_named_gpio(np, "gpio-sck", 0);
|
||||
pdata->miso = of_get_named_gpio(np, "gpio-miso", 0);
|
||||
pdata->mosi = of_get_named_gpio(np, "gpio-mosi", 0);
|
||||
ret = of_get_named_gpio(np, "gpio-sck", 0);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "gpio-sck property not found\n");
|
||||
goto error_free;
|
||||
}
|
||||
pdata->sck = ret;
|
||||
|
||||
ret = of_get_named_gpio(np, "gpio-miso", 0);
|
||||
if (ret < 0) {
|
||||
dev_info(&pdev->dev, "gpio-miso property not found, switching to no-rx mode\n");
|
||||
pdata->miso = SPI_GPIO_NO_MISO;
|
||||
} else
|
||||
pdata->miso = ret;
|
||||
|
||||
ret = of_get_named_gpio(np, "gpio-mosi", 0);
|
||||
if (ret < 0) {
|
||||
dev_info(&pdev->dev, "gpio-mosi property not found, switching to no-tx mode\n");
|
||||
pdata->mosi = SPI_GPIO_NO_MOSI;
|
||||
} else
|
||||
pdata->mosi = ret;
|
||||
|
||||
ret = of_property_read_u32(np, "num-chipselects", &tmp);
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -949,3 +949,4 @@ module_platform_driver(spi_imx_driver);
|
||||
MODULE_DESCRIPTION("SPI Master Controller driver");
|
||||
MODULE_AUTHOR("Sascha Hauer, Pengutronix");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
|
||||
@@ -438,6 +438,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
|
||||
master->num_chipselect = pdata->max_chipselect;
|
||||
}
|
||||
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
|
||||
master->setup = mpc512x_psc_spi_setup;
|
||||
master->transfer = mpc512x_psc_spi_transfer;
|
||||
master->cleanup = mpc512x_psc_spi_cleanup;
|
||||
@@ -522,17 +523,11 @@ static int mpc512x_psc_spi_of_probe(struct platform_device *op)
|
||||
regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
|
||||
|
||||
/* get PSC id (0..11, used by port_config) */
|
||||
if (op->dev.platform_data == NULL) {
|
||||
const u32 *psc_nump;
|
||||
|
||||
psc_nump = of_get_property(op->dev.of_node, "cell-index", NULL);
|
||||
if (!psc_nump || *psc_nump > 11) {
|
||||
dev_err(&op->dev, "mpc512x_psc_spi: Device node %s "
|
||||
"has invalid cell-index property\n",
|
||||
op->dev.of_node->full_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
id = *psc_nump;
|
||||
id = of_alias_get_id(op->dev.of_node, "spi");
|
||||
if (id < 0) {
|
||||
dev_err(&op->dev, "no alias id for %s\n",
|
||||
op->dev.of_node->full_name);
|
||||
return id;
|
||||
}
|
||||
|
||||
return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user