Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aae7147d authored by Murali Karicheri's avatar Murali Karicheri Committed by Grant Likely
Browse files

spi/davinci: add OF support for the spi controller



This adds OF support to DaVinci SPI controller to configure platform
data through device bindings. Also replaces clk_enable() with
of clk_prepare_enable() as well as clk_disable() with
clk_disable_unprepare().

Signed-off-by: default avatarMurali Karicheri <m-karicheri2@ti.com>
Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
parent 830379e0
Loading
Loading
Loading
Loading
+88 −14
Original line number Original line Diff line number Diff line
@@ -28,6 +28,8 @@
#include <linux/dmaengine.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/dma-mapping.h>
#include <linux/edma.h>
#include <linux/edma.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/slab.h>
#include <linux/slab.h>
@@ -135,7 +137,7 @@ struct davinci_spi {
	int			dma_rx_chnum;
	int			dma_rx_chnum;
	int			dma_tx_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 *);
	void			(*get_rx)(u32 rx_data, struct davinci_spi *);
	u32			(*get_tx)(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;
	bool gpio_chipsel = false;


	dspi = spi_master_get_devdata(spi->master);
	dspi = spi_master_get_devdata(spi->master);
	pdata = dspi->pdata;
	pdata = &dspi->pdata;


	if (pdata->chip_sel && chip_sel < pdata->num_chipselect &&
	if (pdata->chip_sel && chip_sel < pdata->num_chipselect &&
				pdata->chip_sel[chip_sel] != SPI_INTERN_CS)
				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;
	struct davinci_spi_platform_data *pdata;


	dspi = spi_master_get_devdata(spi->master);
	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 bits per word length is zero then set it default 8 */
	if (!spi->bits_per_word)
	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;
	struct scatterlist sg_rx, sg_tx;


	dspi = spi_master_get_devdata(spi->master);
	dspi = spi_master_get_devdata(spi->master);
	pdata = dspi->pdata;
	pdata = &dspi->pdata;
	spicfg = (struct davinci_spi_config *)spi->controller_data;
	spicfg = (struct davinci_spi_config *)spi->controller_data;
	if (!spicfg)
	if (!spicfg)
		spicfg = &davinci_spi_default_cfg;
		spicfg = &davinci_spi_default_cfg;
@@ -758,6 +760,70 @@ static int davinci_spi_request_dma(struct davinci_spi *dspi)
	return r;
	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
 * davinci_spi_probe - probe function for SPI Master Controller
 * @pdev: platform_device structure which contains plateform specific data
 * @pdev: platform_device structure which contains plateform specific data
@@ -780,12 +846,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
	int i = 0, ret = 0;
	int i = 0, ret = 0;
	u32 spipc0;
	u32 spipc0;


	pdata = pdev->dev.platform_data;
	if (pdata == NULL) {
		ret = -ENODEV;
		goto err;
	}

	master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi));
	master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi));
	if (master == NULL) {
	if (master == NULL) {
		ret = -ENOMEM;
		ret = -ENOMEM;
@@ -800,6 +860,19 @@ static int davinci_spi_probe(struct platform_device *pdev)
		goto free_master;
		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);
	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (r == NULL) {
	if (r == NULL) {
		ret = -ENOENT;
		ret = -ENOENT;
@@ -807,7 +880,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
	}
	}


	dspi->pbase = r->start;
	dspi->pbase = r->start;
	dspi->pdata = pdata;


	mem = request_mem_region(r->start, resource_size(r), pdev->name);
	mem = request_mem_region(r->start, resource_size(r), pdev->name);
	if (mem == NULL) {
	if (mem == NULL) {
@@ -843,8 +915,9 @@ static int davinci_spi_probe(struct platform_device *pdev)
		ret = -ENODEV;
		ret = -ENODEV;
		goto put_master;
		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->bus_num = pdev->id;
	master->num_chipselect = pdata->num_chipselect;
	master->num_chipselect = pdata->num_chipselect;
	master->setup = davinci_spi_setup;
	master->setup = davinci_spi_setup;
@@ -927,7 +1000,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
	dma_release_channel(dspi->dma_rx);
	dma_release_channel(dspi->dma_rx);
	dma_release_channel(dspi->dma_tx);
	dma_release_channel(dspi->dma_tx);
free_clk:
free_clk:
	clk_disable(dspi->clk);
	clk_disable_unprepare(dspi->clk);
	clk_put(dspi->clk);
	clk_put(dspi->clk);
put_master:
put_master:
	spi_master_put(master);
	spi_master_put(master);
@@ -963,7 +1036,7 @@ static int davinci_spi_remove(struct platform_device *pdev)


	spi_bitbang_stop(&dspi->bitbang);
	spi_bitbang_stop(&dspi->bitbang);


	clk_disable(dspi->clk);
	clk_disable_unprepare(dspi->clk);
	clk_put(dspi->clk);
	clk_put(dspi->clk);
	spi_master_put(master);
	spi_master_put(master);
	free_irq(dspi->irq, dspi);
	free_irq(dspi->irq, dspi);
@@ -978,6 +1051,7 @@ static struct platform_driver davinci_spi_driver = {
	.driver = {
	.driver = {
		.name = "spi_davinci",
		.name = "spi_davinci",
		.owner = THIS_MODULE,
		.owner = THIS_MODULE,
		.of_match_table = davinci_spi_of_match,
	},
	},
	.probe = davinci_spi_probe,
	.probe = davinci_spi_probe,
	.remove = davinci_spi_remove,
	.remove = davinci_spi_remove,