diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-dw.c | 1 | ||||
-rw-r--r-- | drivers/spi/spi-orion.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-pl022.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx-dma.c | 15 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx-pci.c | 101 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-rockchip.c | 50 | ||||
-rw-r--r-- | drivers/spi/spi.c | 13 |
8 files changed, 135 insertions, 51 deletions
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 729215885250..72e12bad14b9 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -669,6 +669,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) master->cleanup = dw_spi_cleanup; master->transfer_one_message = dw_spi_transfer_one_message; master->max_speed_hz = dws->max_freq; + master->dev.of_node = dev->of_node; /* Basic HW init */ spi_hw_init(dws); diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 835cdda6f4f5..c76b7d7879df 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -454,7 +454,7 @@ static int orion_spi_probe(struct platform_device *pdev) spi->master = master; of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); - devdata = of_id->data; + devdata = (of_id) ? of_id->data : &orion_spi_dev_data; spi->devdata = devdata; spi->clk = devm_clk_get(&pdev->dev, NULL); diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index f35f723816ea..fc2dd8441608 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1106,7 +1106,7 @@ err_rxdesc: pl022->sgt_tx.nents, DMA_TO_DEVICE); err_tx_sgmap: dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl, - pl022->sgt_tx.nents, DMA_FROM_DEVICE); + pl022->sgt_rx.nents, DMA_FROM_DEVICE); err_rx_sgmap: sg_free_table(&pl022->sgt_tx); err_alloc_tx_sg: diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c index c41ff148a2b4..62a9297e96ac 100644 --- a/drivers/spi/spi-pxa2xx-dma.c +++ b/drivers/spi/spi-pxa2xx-dma.c @@ -157,7 +157,6 @@ static struct dma_async_tx_descriptor * pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data, enum dma_transfer_direction dir) { - struct pxa2xx_spi_master *pdata = drv_data->master_info; struct chip_data *chip = drv_data->cur_chip; enum dma_slave_buswidth width; struct dma_slave_config cfg; @@ -184,7 +183,6 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data, cfg.dst_addr = drv_data->ssdr_physical; cfg.dst_addr_width = width; cfg.dst_maxburst = chip->dma_burst_size; - cfg.slave_id = pdata->tx_slave_id; sgt = &drv_data->tx_sgt; nents = drv_data->tx_nents; @@ -193,7 +191,6 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data, cfg.src_addr = drv_data->ssdr_physical; cfg.src_addr_width = width; cfg.src_maxburst = chip->dma_burst_size; - cfg.slave_id = pdata->rx_slave_id; sgt = &drv_data->rx_sgt; nents = drv_data->rx_nents; @@ -210,14 +207,6 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } -static bool pxa2xx_spi_dma_filter(struct dma_chan *chan, void *param) -{ - const struct pxa2xx_spi_master *pdata = param; - - return chan->chan_id == pdata->tx_chan_id || - chan->chan_id == pdata->rx_chan_id; -} - bool pxa2xx_spi_dma_is_possible(size_t len) { return len <= MAX_DMA_LEN; @@ -321,12 +310,12 @@ int pxa2xx_spi_dma_setup(struct driver_data *drv_data) return -ENOMEM; drv_data->tx_chan = dma_request_slave_channel_compat(mask, - pxa2xx_spi_dma_filter, pdata, dev, "tx"); + pdata->dma_filter, pdata->tx_param, dev, "tx"); if (!drv_data->tx_chan) return -ENODEV; drv_data->rx_chan = dma_request_slave_channel_compat(mask, - pxa2xx_spi_dma_filter, pdata, dev, "rx"); + pdata->dma_filter, pdata->rx_param, dev, "rx"); if (!drv_data->rx_chan) { dma_release_channel(drv_data->tx_chan); drv_data->tx_chan = NULL; diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index 536c863bebf1..6beee8ce2d68 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -10,42 +10,87 @@ #include <linux/clk.h> #include <linux/clk-provider.h> +#include <linux/dmaengine.h> +#include <linux/platform_data/dma-dw.h> + enum { PORT_CE4100, PORT_BYT, + PORT_BSW0, + PORT_BSW1, + PORT_BSW2, }; struct pxa_spi_info { enum pxa_ssp_type type; int port_id; int num_chipselect; - int tx_slave_id; - int tx_chan_id; - int rx_slave_id; - int rx_chan_id; unsigned long max_clk_rate; + + /* DMA channel request parameters */ + void *tx_param; + void *rx_param; }; +static struct dw_dma_slave byt_tx_param = { .dst_id = 0 }; +static struct dw_dma_slave byt_rx_param = { .src_id = 1 }; + +static struct dw_dma_slave bsw0_tx_param = { .dst_id = 0 }; +static struct dw_dma_slave bsw0_rx_param = { .src_id = 1 }; +static struct dw_dma_slave bsw1_tx_param = { .dst_id = 6 }; +static struct dw_dma_slave bsw1_rx_param = { .src_id = 7 }; +static struct dw_dma_slave bsw2_tx_param = { .dst_id = 8 }; +static struct dw_dma_slave bsw2_rx_param = { .src_id = 9 }; + +static bool lpss_dma_filter(struct dma_chan *chan, void *param) +{ + struct dw_dma_slave *dws = param; + + if (dws->dma_dev != chan->device->dev) + return false; + + chan->private = dws; + return true; +} + static struct pxa_spi_info spi_info_configs[] = { [PORT_CE4100] = { .type = PXA25x_SSP, .port_id = -1, .num_chipselect = -1, - .tx_slave_id = -1, - .tx_chan_id = -1, - .rx_slave_id = -1, - .rx_chan_id = -1, .max_clk_rate = 3686400, }, [PORT_BYT] = { .type = LPSS_SSP, .port_id = 0, .num_chipselect = 1, - .tx_slave_id = 0, - .tx_chan_id = 0, - .rx_slave_id = 1, - .rx_chan_id = 1, .max_clk_rate = 50000000, + .tx_param = &byt_tx_param, + .rx_param = &byt_rx_param, + }, + [PORT_BSW0] = { + .type = LPSS_SSP, + .port_id = 0, + .num_chipselect = 1, + .max_clk_rate = 50000000, + .tx_param = &bsw0_tx_param, + .rx_param = &bsw0_rx_param, + }, + [PORT_BSW1] = { + .type = LPSS_SSP, + .port_id = 1, + .num_chipselect = 1, + .max_clk_rate = 50000000, + .tx_param = &bsw1_tx_param, + .rx_param = &bsw1_rx_param, + }, + [PORT_BSW2] = { + .type = LPSS_SSP, + .port_id = 2, + .num_chipselect = 1, + .max_clk_rate = 50000000, + .tx_param = &bsw2_tx_param, + .rx_param = &bsw2_rx_param, }, }; @@ -59,6 +104,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, struct ssp_device *ssp; struct pxa_spi_info *c; char buf[40]; + struct pci_dev *dma_dev; ret = pcim_enable_device(dev); if (ret) @@ -73,11 +119,29 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, memset(&spi_pdata, 0, sizeof(spi_pdata)); spi_pdata.num_chipselect = (c->num_chipselect > 0) ? c->num_chipselect : dev->devfn; - spi_pdata.tx_slave_id = c->tx_slave_id; - spi_pdata.tx_chan_id = c->tx_chan_id; - spi_pdata.rx_slave_id = c->rx_slave_id; - spi_pdata.rx_chan_id = c->rx_chan_id; - spi_pdata.enable_dma = c->rx_slave_id >= 0 && c->tx_slave_id >= 0; + + dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); + + if (c->tx_param) { + struct dw_dma_slave *slave = c->tx_param; + + slave->dma_dev = &dma_dev->dev; + slave->src_master = 1; + slave->dst_master = 0; + } + + if (c->rx_param) { + struct dw_dma_slave *slave = c->rx_param; + + slave->dma_dev = &dma_dev->dev; + slave->src_master = 1; + slave->dst_master = 0; + } + + spi_pdata.dma_filter = lpss_dma_filter; + spi_pdata.tx_param = c->tx_param; + spi_pdata.rx_param = c->rx_param; + spi_pdata.enable_dma = c->rx_param && c->tx_param; ssp = &spi_pdata.ssp; ssp->phys_base = pci_resource_start(dev, 0); @@ -128,6 +192,9 @@ static void pxa2xx_spi_pci_remove(struct pci_dev *dev) static const struct pci_device_id pxa2xx_spi_pci_devices[] = { { PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 }, { PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT }, + { PCI_VDEVICE(INTEL, 0x228e), PORT_BSW0 }, + { PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 }, + { PCI_VDEVICE(INTEL, 0x22ac), PORT_BSW2 }, { }, }; MODULE_DEVICE_TABLE(pci, pxa2xx_spi_pci_devices); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 46f45ca2c694..d8a105f76837 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1062,8 +1062,6 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) pdata->num_chipselect = 1; pdata->enable_dma = true; - pdata->tx_chan_id = -1; - pdata->rx_chan_id = -1; return pdata; } diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index f96ea8a38d64..87bc16f491f0 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -145,6 +145,9 @@ #define RXBUSY (1 << 0) #define TXBUSY (1 << 1) +/* sclk_out: spi master internal logic in rk3x can support 50Mhz */ +#define MAX_SCLK_OUT 50000000 + enum rockchip_ssi_type { SSI_MOTO_SPI = 0, SSI_TI_SSP, @@ -325,6 +328,8 @@ static int rockchip_spi_unprepare_message(struct spi_master *master, spin_unlock_irqrestore(&rs->lock, flags); + spi_enable_chip(rs, 0); + return 0; } @@ -381,6 +386,8 @@ static int rockchip_spi_pio_transfer(struct rockchip_spi *rs) if (rs->tx) wait_for_idle(rs); + spi_enable_chip(rs, 0); + return 0; } @@ -392,8 +399,10 @@ static void rockchip_spi_dma_rxcb(void *data) spin_lock_irqsave(&rs->lock, flags); rs->state &= ~RXBUSY; - if (!(rs->state & TXBUSY)) + if (!(rs->state & TXBUSY)) { + spi_enable_chip(rs, 0); spi_finalize_current_transfer(rs->master); + } spin_unlock_irqrestore(&rs->lock, flags); } @@ -409,8 +418,10 @@ static void rockchip_spi_dma_txcb(void *data) spin_lock_irqsave(&rs->lock, flags); rs->state &= ~TXBUSY; - if (!(rs->state & RXBUSY)) + if (!(rs->state & RXBUSY)) { + spi_enable_chip(rs, 0); spi_finalize_current_transfer(rs->master); + } spin_unlock_irqrestore(&rs->lock, flags); } @@ -496,12 +507,19 @@ static void rockchip_spi_config(struct rockchip_spi *rs) dmacr |= RF_DMA_EN; } + if (WARN_ON(rs->speed > MAX_SCLK_OUT)) + rs->speed = MAX_SCLK_OUT; + + /* the minimum divsor is 2 */ + if (rs->max_freq < 2 * rs->speed) { + clk_set_rate(rs->spiclk, 2 * rs->speed); + rs->max_freq = clk_get_rate(rs->spiclk); + } + /* div doesn't support odd number */ div = max_t(u32, rs->max_freq / rs->speed, 1); div = (div + 1) & 0xfffe; - spi_enable_chip(rs, 0); - writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); @@ -515,8 +533,6 @@ static void rockchip_spi_config(struct rockchip_spi *rs) spi_set_clk(rs, div); dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div); - - spi_enable_chip(rs, 1); } static int rockchip_spi_transfer_one( @@ -524,7 +540,7 @@ static int rockchip_spi_transfer_one( struct spi_device *spi, struct spi_transfer *xfer) { - int ret = 0; + int ret = 1; struct rockchip_spi *rs = spi_master_get_devdata(master); WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) && @@ -556,17 +572,27 @@ static int rockchip_spi_transfer_one( rs->tmode = CR0_XFM_RO; /* we need prepare dma before spi was enabled */ - if (master->can_dma && master->can_dma(master, spi, xfer)) { + if (master->can_dma && master->can_dma(master, spi, xfer)) rs->use_dma = 1; - rockchip_spi_prepare_dma(rs); - } else { + else rs->use_dma = 0; - } rockchip_spi_config(rs); - if (!rs->use_dma) + if (rs->use_dma) { + if (rs->tmode == CR0_XFM_RO) { + /* rx: dma must be prepared first */ + rockchip_spi_prepare_dma(rs); + spi_enable_chip(rs, 1); + } else { + /* tx or tr: spi must be enabled first */ + spi_enable_chip(rs, 1); + rockchip_spi_prepare_dma(rs); + } + } else { + spi_enable_chip(rs, 1); ret = rockchip_spi_pio_transfer(rs); + } return ret; } diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index e19512ffc40e..ebcb33df2eb2 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -35,6 +35,7 @@ #include <linux/spi/spi.h> #include <linux/of_gpio.h> #include <linux/pm_runtime.h> +#include <linux/pm_domain.h> #include <linux/export.h> #include <linux/sched/rt.h> #include <linux/delay.h> @@ -264,10 +265,12 @@ static int spi_drv_probe(struct device *dev) if (ret) return ret; - acpi_dev_pm_attach(dev, true); - ret = sdrv->probe(to_spi_device(dev)); - if (ret) - acpi_dev_pm_detach(dev, true); + ret = dev_pm_domain_attach(dev, true); + if (ret != -EPROBE_DEFER) { + ret = sdrv->probe(to_spi_device(dev)); + if (ret) + dev_pm_domain_detach(dev, true); + } return ret; } @@ -278,7 +281,7 @@ static int spi_drv_remove(struct device *dev) int ret; ret = sdrv->remove(to_spi_device(dev)); - acpi_dev_pm_detach(dev, true); + dev_pm_domain_detach(dev, true); return ret; } |