summaryrefslogtreecommitdiff
path: root/arch/arm/plat-pxa
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2013-08-12 10:37:16 +0200
committerMark Brown <broonie@linaro.org>2013-08-14 19:54:23 +0100
commita6e56c28a178cef5f93d1e11698a23a5482175d9 (patch)
tree89c6fd87f13ac178257e314320103e7c5f31b38c /arch/arm/plat-pxa
parent970d8a7152aa884b9bab6a8db1ff148ee22df899 (diff)
downloadlwn-a6e56c28a178cef5f93d1e11698a23a5482175d9.tar.gz
lwn-a6e56c28a178cef5f93d1e11698a23a5482175d9.zip
ARM: pxa: ssp: add DT bindings
This patch contains an ugly hack for looking up the the DMA request number. The problem here is that the implementation as it stands will allocate the DMA channel from the user of the ssp port, and hence we cannot allocate a real channel here. Signed-off-by: Daniel Mack <zonque@gmail.com> Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'arch/arm/plat-pxa')
-rw-r--r--arch/arm/plat-pxa/ssp.c90
1 files changed, 69 insertions, 21 deletions
diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c
index 65ba28a0e3c6..c3afcec7094c 100644
--- a/arch/arm/plat-pxa/ssp.c
+++ b/arch/arm/plat-pxa/ssp.c
@@ -30,6 +30,8 @@
#include <linux/platform_device.h>
#include <linux/spi/pxa2xx_spi.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <asm/irq.h>
#include <mach/hardware.h>
@@ -72,9 +74,23 @@ void pxa_ssp_free(struct ssp_device *ssp)
}
EXPORT_SYMBOL(pxa_ssp_free);
+#ifdef CONFIG_OF
+static const struct of_device_id pxa_ssp_of_ids[] = {
+ { .compatible = "mrvl,pxa25x-ssp", .data = (void *) PXA25x_SSP },
+ { .compatible = "mvrl,pxa25x-nssp", .data = (void *) PXA25x_NSSP },
+ { .compatible = "mrvl,pxa27x-ssp", .data = (void *) PXA27x_SSP },
+ { .compatible = "mrvl,pxa3xx-ssp", .data = (void *) PXA3xx_SSP },
+ { .compatible = "mvrl,pxa168-ssp", .data = (void *) PXA168_SSP },
+ { .compatible = "mrvl,pxa910-ssp", .data = (void *) PXA910_SSP },
+ { .compatible = "mrvl,ce4100-ssp", .data = (void *) CE4100_SSP },
+ { .compatible = "mrvl,lpss-ssp", .data = (void *) LPSS_SSP },
+ { },
+};
+MODULE_DEVICE_TABLE(of, pxa_ssp_of_ids);
+#endif
+
static int pxa_ssp_probe(struct platform_device *pdev)
{
- const struct platform_device_id *id = platform_get_device_id(pdev);
struct resource *res;
struct ssp_device *ssp;
struct device *dev = &pdev->dev;
@@ -92,21 +108,42 @@ static int pxa_ssp_probe(struct platform_device *pdev)
goto err_free;
}
- res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (res == NULL) {
- dev_err(dev, "no SSP RX DRCMR defined\n");
- ret = -ENODEV;
- goto err_free_clk;
- }
- ssp->drcmr_rx = res->start;
+ if (dev->of_node) {
+ struct of_phandle_args dma_spec;
+ struct device_node *np = dev->of_node;
+
+ /*
+ * FIXME: we should allocate the DMA channel from this
+ * context and pass the channel down to the ssp users.
+ * For now, we lookup the rx and tx indices manually
+ */
+
+ /* rx */
+ of_parse_phandle_with_args(np, "dmas", "#dma-cells",
+ 0, &dma_spec);
+ ssp->drcmr_rx = dma_spec.args[0];
+ of_node_put(dma_spec.np);
+
+ /* tx */
+ of_parse_phandle_with_args(np, "dmas", "#dma-cells",
+ 1, &dma_spec);
+ ssp->drcmr_tx = dma_spec.args[0];
+ of_node_put(dma_spec.np);
+ } else {
+ res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (res == NULL) {
+ dev_err(dev, "no SSP RX DRCMR defined\n");
+ return -ENODEV;
+ }
+ ssp->drcmr_rx = res->start;
- res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (res == NULL) {
- dev_err(dev, "no SSP TX DRCMR defined\n");
- ret = -ENODEV;
- goto err_free_clk;
+ res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (res == NULL) {
+ dev_err(dev, "no SSP TX DRCMR defined\n");
+ return -ENODEV;
+ }
+ ssp->drcmr_tx = res->start;
}
- ssp->drcmr_tx = res->start;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
@@ -139,12 +176,22 @@ static int pxa_ssp_probe(struct platform_device *pdev)
goto err_free_io;
}
- /* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id
- * starts from 0, do a translation here
- */
- ssp->port_id = pdev->id + 1;
+ if (dev->of_node) {
+ const struct of_device_id *id =
+ of_match_device(of_match_ptr(pxa_ssp_of_ids), dev);
+ ssp->type = (int) id->data;
+ } else {
+ const struct platform_device_id *id =
+ platform_get_device_id(pdev);
+ ssp->type = (int) id->driver_data;
+
+ /* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id
+ * starts from 0, do a translation here
+ */
+ ssp->port_id = pdev->id + 1;
+ }
+
ssp->use_count = 0;
- ssp->type = (int)id->driver_data;
mutex_lock(&ssp_lock);
list_add(&ssp->node, &ssp_list);
@@ -201,8 +248,9 @@ static struct platform_driver pxa_ssp_driver = {
.probe = pxa_ssp_probe,
.remove = pxa_ssp_remove,
.driver = {
- .owner = THIS_MODULE,
- .name = "pxa2xx-ssp",
+ .owner = THIS_MODULE,
+ .name = "pxa2xx-ssp",
+ .of_match_table = of_match_ptr(pxa_ssp_of_ids),
},
.id_table = ssp_id_table,
};