From patchwork Mon Jan 18 16:50:01 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Hugues Deschenes X-Patchwork-Id: 73677 Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by demeter.kernel.org (8.14.3/8.14.2) with ESMTP id o0IHCZc4016907 for ; Mon, 18 Jan 2010 17:12:35 GMT Received: from localhost ([127.0.0.1] helo=sfs-ml-2.v29.ch3.sourceforge.com) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1NWv9S-00045V-Cc; Mon, 18 Jan 2010 17:12:30 +0000 Received: from sfi-mx-3.v28.ch3.sourceforge.com ([172.29.28.123] helo=mx.sourceforge.net) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1NWv9O-00045A-1E for spi-devel-general@lists.sourceforge.net; Mon, 18 Jan 2010 17:12:26 +0000 X-ACL-Warn: Received: from mail.octasic.com ([70.54.254.106] helo=MAILEXCH.octasic.com) by sfi-mx-3.v28.ch3.sourceforge.com with esmtp (Exim 4.69) id 1NWv9M-0007ly-Pa for spi-devel-general@lists.sourceforge.net; Mon, 18 Jan 2010 17:12:25 +0000 Received: from station520.octasic.com ([142.138.24.20]) by MAILEXCH.octasic.com with Microsoft SMTPSVC(6.0.3790.3959); Mon, 18 Jan 2010 11:50:01 -0500 To: spi-devel-general@lists.sourceforge.net From: Jean-Hugues Deschenes Date: Mon, 18 Jan 2010 11:50:01 -0500 Message-ID: <20100118164921.23527.74770.stgit@station520.octasic.com> User-Agent: StGit/0.15 MIME-Version: 1.0 X-OriginalArrivalTime: 18 Jan 2010 16:50:01.0707 (UTC) FILETIME=[46E263B0:01CA985E] X-Sender-Verify: failed, postmaster X-Spam-Score: -1.0 (-) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.5 VA_SENDER_VERIFY_POSTMASTER Unable to Verify postmaster@domain.tld -1.5 AWL AWL: From: address is in the auto white-list X-Headers-End: 1NWv9M-0007ly-Pa Cc: David Brownell Subject: [spi-devel-general] [PATCH] Memory-mapped Dwsignware SPI driver X-BeenThere: spi-devel-general@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Linux SPI core/device drivers discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: spi-devel-general-bounces@lists.sourceforge.net diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index f55eb01..79c8d5f 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -308,14 +308,24 @@ config SPI_NUC900 # config SPI_DESIGNWARE - bool "DesignWare SPI controller core support" + tristate "DesignWare SPI controller core support" depends on SPI_MASTER help general driver for SPI controller core from DesignWare +choice + prompt "Designware bus type" + depends on SPI_DESIGNWARE + default SPI_DW_PCI + config SPI_DW_PCI - tristate "PCI interface driver for DW SPI core" - depends on SPI_DESIGNWARE && PCI + bool "PCI interface driver for DW SPI core" + depends on PCI + +config SPI_DW_MMIO + bool "Memory-mapped io interface driver for DW SPI core" + +endchoice # # There are lots of SPI device types, with sensors and memory diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index f3d2810..c3e5ce7 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_SPI_AU1550) += au1550_spi.o obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o obj-$(CONFIG_SPI_DESIGNWARE) += dw_spi.o obj-$(CONFIG_SPI_DW_PCI) += dw_spi_pci.o +obj-$(CONFIG_SPI_DW_MMIO) += dw_spi_mmio.o obj-$(CONFIG_SPI_GPIO) += spi_gpio.o obj-$(CONFIG_SPI_IMX) += spi_imx.o obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o diff --git a/drivers/spi/dw_spi_mmio.c b/drivers/spi/dw_spi_mmio.c new file mode 100644 index 0000000..9abeb45 --- /dev/null +++ b/drivers/spi/dw_spi_mmio.c @@ -0,0 +1,164 @@ +/* + * dw_spi_mmio.c - Memory-mapped interface driver for DW SPI Core + * + * Copyright (c) 2010, Octasic semiconductor. + * + * Somewhat derived from PCI implementation, + * Copyright (c) 2009, Intel Corporation. + * + * ...and from designware i2c driver + * Copyright (C) 2006 Texas Instruments. + * Copyright (C) 2007 MontaVista Software Inc. + * Copyright (C) 2009 Provigent Ltd. + * + * 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. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include + +#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 (!dwsmmio->clk) { + ret = -ENODEV; + 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); + 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); +} + +static void __exit dw_spi_mmio_exit(void) +{ + platform_driver_unregister(&dw_spi_mmio_driver); +} + +module_init(dw_spi_mmio_init); +module_exit(dw_spi_mmio_exit); + +MODULE_AUTHOR("Jean-Hugues Deschenes "); +MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core"); +MODULE_LICENSE("GPL v2");