mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
spi: ep93xx: add DT support for Cirrus EP93xx
- add OF ID match table - add device tree DMA request, so we can probe defer, in case DMA is not ready yet - drop DMA platform code Signed-off-by: Nikita Shubin <nikita.shubin@maquefel.me> Tested-by: Alexander Sverdlin <alexander.sverdlin@gmail.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Mark Brown <broonie@kernel.org> Acked-by: Alexander Sverdlin <alexander.sverdlin@gmail.com> Acked-by: Vinod Koul <vkoul@kernel.org> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
committed by
Arnd Bergmann
parent
cb0291776f
commit
e79e7c2df6
+23
-43
@@ -18,18 +18,18 @@
|
|||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/dma-direction.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/dmaengine.h>
|
#include <linux/dmaengine.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/property.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/scatterlist.h>
|
#include <linux/scatterlist.h>
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
|
|
||||||
#include <linux/platform_data/dma-ep93xx.h>
|
|
||||||
#include <linux/platform_data/spi-ep93xx.h>
|
|
||||||
|
|
||||||
#define SSPCR0 0x0000
|
#define SSPCR0 0x0000
|
||||||
#define SSPCR0_SPO BIT(6)
|
#define SSPCR0_SPO BIT(6)
|
||||||
#define SSPCR0_SPH BIT(7)
|
#define SSPCR0_SPH BIT(7)
|
||||||
@@ -92,8 +92,6 @@ struct ep93xx_spi {
|
|||||||
size_t fifo_level;
|
size_t fifo_level;
|
||||||
struct dma_chan *dma_rx;
|
struct dma_chan *dma_rx;
|
||||||
struct dma_chan *dma_tx;
|
struct dma_chan *dma_tx;
|
||||||
struct ep93xx_dma_data dma_rx_data;
|
|
||||||
struct ep93xx_dma_data dma_tx_data;
|
|
||||||
struct sg_table rx_sgt;
|
struct sg_table rx_sgt;
|
||||||
struct sg_table tx_sgt;
|
struct sg_table tx_sgt;
|
||||||
void *zeropage;
|
void *zeropage;
|
||||||
@@ -575,46 +573,23 @@ static int ep93xx_spi_unprepare_hardware(struct spi_controller *host)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ep93xx_spi_dma_filter(struct dma_chan *chan, void *filter_param)
|
static int ep93xx_spi_setup_dma(struct device *dev, struct ep93xx_spi *espi)
|
||||||
{
|
{
|
||||||
if (ep93xx_dma_chan_is_m2p(chan))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
chan->private = filter_param;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi)
|
|
||||||
{
|
|
||||||
dma_cap_mask_t mask;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
espi->zeropage = (void *)get_zeroed_page(GFP_KERNEL);
|
espi->zeropage = (void *)get_zeroed_page(GFP_KERNEL);
|
||||||
if (!espi->zeropage)
|
if (!espi->zeropage)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
dma_cap_zero(mask);
|
espi->dma_rx = dma_request_chan(dev, "rx");
|
||||||
dma_cap_set(DMA_SLAVE, mask);
|
if (IS_ERR(espi->dma_rx)) {
|
||||||
|
ret = dev_err_probe(dev, PTR_ERR(espi->dma_rx), "rx DMA setup failed");
|
||||||
espi->dma_rx_data.port = EP93XX_DMA_SSP;
|
|
||||||
espi->dma_rx_data.direction = DMA_DEV_TO_MEM;
|
|
||||||
espi->dma_rx_data.name = "ep93xx-spi-rx";
|
|
||||||
|
|
||||||
espi->dma_rx = dma_request_channel(mask, ep93xx_spi_dma_filter,
|
|
||||||
&espi->dma_rx_data);
|
|
||||||
if (!espi->dma_rx) {
|
|
||||||
ret = -ENODEV;
|
|
||||||
goto fail_free_page;
|
goto fail_free_page;
|
||||||
}
|
}
|
||||||
|
|
||||||
espi->dma_tx_data.port = EP93XX_DMA_SSP;
|
espi->dma_tx = dma_request_chan(dev, "tx");
|
||||||
espi->dma_tx_data.direction = DMA_MEM_TO_DEV;
|
if (IS_ERR(espi->dma_tx)) {
|
||||||
espi->dma_tx_data.name = "ep93xx-spi-tx";
|
ret = dev_err_probe(dev, PTR_ERR(espi->dma_tx), "tx DMA setup failed");
|
||||||
|
|
||||||
espi->dma_tx = dma_request_channel(mask, ep93xx_spi_dma_filter,
|
|
||||||
&espi->dma_tx_data);
|
|
||||||
if (!espi->dma_tx) {
|
|
||||||
ret = -ENODEV;
|
|
||||||
goto fail_release_rx;
|
goto fail_release_rx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,18 +622,11 @@ static void ep93xx_spi_release_dma(struct ep93xx_spi *espi)
|
|||||||
static int ep93xx_spi_probe(struct platform_device *pdev)
|
static int ep93xx_spi_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct spi_controller *host;
|
struct spi_controller *host;
|
||||||
struct ep93xx_spi_info *info;
|
|
||||||
struct ep93xx_spi *espi;
|
struct ep93xx_spi *espi;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
int irq;
|
int irq;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
info = dev_get_platdata(&pdev->dev);
|
|
||||||
if (!info) {
|
|
||||||
dev_err(&pdev->dev, "missing platform data\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0)
|
if (irq < 0)
|
||||||
return irq;
|
return irq;
|
||||||
@@ -713,12 +681,17 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
|
|||||||
goto fail_release_host;
|
goto fail_release_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->use_dma && ep93xx_spi_setup_dma(espi))
|
error = ep93xx_spi_setup_dma(&pdev->dev, espi);
|
||||||
|
if (error == -EPROBE_DEFER)
|
||||||
|
goto fail_release_host;
|
||||||
|
|
||||||
|
if (error)
|
||||||
dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n");
|
dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n");
|
||||||
|
|
||||||
/* make sure that the hardware is disabled */
|
/* make sure that the hardware is disabled */
|
||||||
writel(0, espi->mmio + SSPCR1);
|
writel(0, espi->mmio + SSPCR1);
|
||||||
|
|
||||||
|
device_set_node(&host->dev, dev_fwnode(&pdev->dev));
|
||||||
error = devm_spi_register_controller(&pdev->dev, host);
|
error = devm_spi_register_controller(&pdev->dev, host);
|
||||||
if (error) {
|
if (error) {
|
||||||
dev_err(&pdev->dev, "failed to register SPI host\n");
|
dev_err(&pdev->dev, "failed to register SPI host\n");
|
||||||
@@ -746,9 +719,16 @@ static void ep93xx_spi_remove(struct platform_device *pdev)
|
|||||||
ep93xx_spi_release_dma(espi);
|
ep93xx_spi_release_dma(espi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id ep93xx_spi_of_ids[] = {
|
||||||
|
{ .compatible = "cirrus,ep9301-spi" },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, ep93xx_spi_of_ids);
|
||||||
|
|
||||||
static struct platform_driver ep93xx_spi_driver = {
|
static struct platform_driver ep93xx_spi_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "ep93xx-spi",
|
.name = "ep93xx-spi",
|
||||||
|
.of_match_table = ep93xx_spi_of_ids,
|
||||||
},
|
},
|
||||||
.probe = ep93xx_spi_probe,
|
.probe = ep93xx_spi_probe,
|
||||||
.remove_new = ep93xx_spi_remove,
|
.remove_new = ep93xx_spi_remove,
|
||||||
|
|||||||
Reference in New Issue
Block a user