summaryrefslogtreecommitdiff
path: root/drivers/spi/spi-dw-mmio.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-22 14:52:44 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-22 14:52:44 -0700
commit7235dd74a4733d4b3651349b5261d2e06996427d (patch)
tree737d4141e77fdd6bfd8c9878ed4f7fe293e7b629 /drivers/spi/spi-dw-mmio.c
parentc7c8518498e82591d7784452f5674c3aeb4d079c (diff)
parent22a85e4cd51b49ec99703ddfdff8686d5442a093 (diff)
Merge branch 'spi/next' of git://git.secretlab.ca/git/linux-2.6
* 'spi/next' of git://git.secretlab.ca/git/linux-2.6: (34 commits) spi/imx: add device tree probe support spi/imx: copy gpio number passed by platform data into driver private data spi/imx: use soc name in spi device type naming scheme spi/imx: merge type SPI_IMX_VER_0_7 into SPI_IMX_VER_0_4 spi/imx: do not use spi_imx2_3 to name SPI_IMX_VER_2_3 function and macro spi/imx: use mx21 to name SPI_IMX_VER_0_0 function and macro spi/imx: do not make copy of spi_imx_devtype_data spi/dw: Add spi number into spi irq desc spi/tegra: Use engineering names in DT compatible property spi/fsl_spi: fix CPM spi driver mach-s3c2410: remove unused spi-gpio.h file spi: remove obsolete spi-s3c24xx-gpio driver mach-gta2: remove unused spi-gpio.h include mach-qt2410: convert to spi_gpio mach-jive: convert to spi_gpio spi/pxa2xx: Remove unavailable ssp_type from documentation spi/bfin_spi: uninline fat queue funcs spi/bfin_spi: constify pin array spi/bfin_spi: use structs for accessing hardware regs spi/topcliff-pch: Support new device ML7223 IOH ... Fix up trivial conflict in arch/arm/mach-ep93xx/Makefile
Diffstat (limited to 'drivers/spi/spi-dw-mmio.c')
-rw-r--r--drivers/spi/spi-dw-mmio.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
new file mode 100644
index 000000000000..34eb66501dbf
--- /dev/null
+++ b/drivers/spi/spi-dw-mmio.c
@@ -0,0 +1,151 @@
+/*
+ * Memory-mapped interface driver for DW SPI Core
+ *
+ * Copyright (c) 2010, Octasic semiconductor.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/scatterlist.h>
+
+#include "spi-dw.h"
+
+#define DRIVER_NAME "dw_spi_mmio"
+
+struct dw_spi_mmio {
+ struct dw_spi dws;
+ struct clk *clk;
+};
+
+static int __devinit dw_spi_mmio_probe(struct platform_device *pdev)
+{
+ struct dw_spi_mmio *dwsmmio;
+ struct dw_spi *dws;
+ struct resource *mem, *ioarea;
+ int ret;
+
+ dwsmmio = kzalloc(sizeof(struct dw_spi_mmio), GFP_KERNEL);
+ if (!dwsmmio) {
+ ret = -ENOMEM;
+ goto err_end;
+ }
+
+ dws = &dwsmmio->dws;
+
+ /* Get basic io resource and map it */
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "no mem resource?\n");
+ ret = -EINVAL;
+ goto err_kfree;
+ }
+
+ ioarea = request_mem_region(mem->start, resource_size(mem),
+ pdev->name);
+ if (!ioarea) {
+ dev_err(&pdev->dev, "SPI region already claimed\n");
+ ret = -EBUSY;
+ goto err_kfree;
+ }
+
+ dws->regs = ioremap_nocache(mem->start, resource_size(mem));
+ if (!dws->regs) {
+ dev_err(&pdev->dev, "SPI region already mapped\n");
+ ret = -ENOMEM;
+ goto err_release_reg;
+ }
+
+ dws->irq = platform_get_irq(pdev, 0);
+ if (dws->irq < 0) {
+ dev_err(&pdev->dev, "no irq resource?\n");
+ ret = dws->irq; /* -ENXIO */
+ goto err_unmap;
+ }
+
+ dwsmmio->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(dwsmmio->clk)) {
+ ret = PTR_ERR(dwsmmio->clk);
+ goto err_irq;
+ }
+ clk_enable(dwsmmio->clk);
+
+ dws->parent_dev = &pdev->dev;
+ dws->bus_num = 0;
+ dws->num_cs = 4;
+ dws->max_freq = clk_get_rate(dwsmmio->clk);
+
+ ret = dw_spi_add_host(dws);
+ if (ret)
+ goto err_clk;
+
+ platform_set_drvdata(pdev, dwsmmio);
+ return 0;
+
+err_clk:
+ clk_disable(dwsmmio->clk);
+ clk_put(dwsmmio->clk);
+ dwsmmio->clk = NULL;
+err_irq:
+ free_irq(dws->irq, dws);
+err_unmap:
+ iounmap(dws->regs);
+err_release_reg:
+ release_mem_region(mem->start, resource_size(mem));
+err_kfree:
+ kfree(dwsmmio);
+err_end:
+ return ret;
+}
+
+static int __devexit dw_spi_mmio_remove(struct platform_device *pdev)
+{
+ struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev);
+ struct resource *mem;
+
+ platform_set_drvdata(pdev, NULL);
+
+ clk_disable(dwsmmio->clk);
+ clk_put(dwsmmio->clk);
+ dwsmmio->clk = NULL;
+
+ free_irq(dwsmmio->dws.irq, &dwsmmio->dws);
+ dw_spi_remove_host(&dwsmmio->dws);
+ iounmap(dwsmmio->dws.regs);
+ kfree(dwsmmio);
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(mem->start, resource_size(mem));
+ return 0;
+}
+
+static struct platform_driver dw_spi_mmio_driver = {
+ .remove = __devexit_p(dw_spi_mmio_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init dw_spi_mmio_init(void)
+{
+ return platform_driver_probe(&dw_spi_mmio_driver, dw_spi_mmio_probe);
+}
+module_init(dw_spi_mmio_init);
+
+static void __exit dw_spi_mmio_exit(void)
+{
+ platform_driver_unregister(&dw_spi_mmio_driver);
+}
+module_exit(dw_spi_mmio_exit);
+
+MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>");
+MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core");
+MODULE_LICENSE("GPL v2");