Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/816395/?format=api
{ "id": 816395, "url": "http://patchwork.ozlabs.org/api/patches/816395/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-mtd/patch/1505932139-2905-3-git-send-email-matthew.gerlach@linux.intel.com/", "project": { "id": 3, "url": "http://patchwork.ozlabs.org/api/projects/3/?format=api", "name": "Linux MTD development", "link_name": "linux-mtd", "list_id": "linux-mtd.lists.infradead.org", "list_email": "linux-mtd@lists.infradead.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<1505932139-2905-3-git-send-email-matthew.gerlach@linux.intel.com>", "list_archive_url": null, "date": "2017-09-20T18:28:58", "name": "[v2,2/3] mtd: spi-nor: Altera ASMI Parallel II IP Core", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "2815caff5d1f6b6bb76df3c1709c6e579cc68508", "submitter": { "id": 70992, "url": "http://patchwork.ozlabs.org/api/people/70992/?format=api", "name": "Matthew Gerlach", "email": "matthew.gerlach@linux.intel.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-mtd/patch/1505932139-2905-3-git-send-email-matthew.gerlach@linux.intel.com/mbox/", "series": [ { "id": 4190, "url": "http://patchwork.ozlabs.org/api/series/4190/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-mtd/list/?series=4190", "date": "2017-09-20T18:28:57", "name": "Altera ASMI Parallel II IP Core", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/4190/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/816395/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/816395/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": [ "ozlabs.org; spf=none (mailfrom)\n\tsmtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133;\n\thelo=bombadil.infradead.org;\n\tenvelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=lists.infradead.org\n\theader.i=@lists.infradead.org header.b=\"TRLyfbev\"; \n\tdkim-atps=neutral" ], "Received": [ "from bombadil.infradead.org (bombadil.infradead.org\n\t[65.50.211.133])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xy7b02Rnkz9s7g\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 21 Sep 2017 04:30:20 +1000 (AEST)", "from localhost ([127.0.0.1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux))\n\tid 1dujlD-00031H-78; Wed, 20 Sep 2017 18:30:11 +0000", "from mga09.intel.com ([134.134.136.24])\n\tby bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux))\n\tid 1dujkY-00024i-Ij\n\tfor linux-mtd@lists.infradead.org; Wed, 20 Sep 2017 18:29:33 +0000", "from orsmga002.jf.intel.com ([10.7.209.21])\n\tby orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t20 Sep 2017 11:29:07 -0700", "from mgerlach-mobl.amr.corp.intel.com (HELO\n\tmgerlach-VirtualBox.amr.corp.intel.com) ([10.254.74.152])\n\tby orsmga002.jf.intel.com with ESMTP; 20 Sep 2017 11:29:06 -0700" ], "DKIM-Signature": "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20170209; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:\n\tMessage-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description:\n\tResent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=mREf1IcOiuBmsb/V2cffxK5qpXps/gQFCtuTjzCEvHc=;\n\tb=TRLyfbevlYYho9\n\tv+1f93A1UH2xxNE/Nk8svoEWy0J8NqXghue0QcRmOx59nh1pg55DnBOHwIGSu1btLPAL4Aic96gJq\n\tvMzwCPXLmpzTVn1eprnyHcJRqN/x3LR/BnBvkREAgSv/DwbJegYQCQ1M4wmBLXuw/DelborNBulUB\n\txCoqIpB7iaH6qwXDubXOHTKzI/58SwzaK/3e52tUJrQ+WCBsm3R2Mf6CODVJt02zQzGq2UhOFQhbn\n\tm11eMcP7LDlnWuv7Ao3UWwnLi2wlzzFNfpo1kqBWy5dnZqmZNbUzD1V1NPrSeTTpWO/LEL4KuOrjb\n\t4BgPLUFUfiBEIwvPYtdw==;", "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos;i=\"5.42,422,1500966000\"; d=\"scan'208\";a=\"137603179\"", "From": "matthew.gerlach@linux.intel.com", "To": "vndao@altera.com, dwmw2@infradead.org, computersforpeace@gmail.com,\n\tboris.brezillon@free-electrons.com, marek.vasut@gmail.com,\n\trichard@nod.at, \n\tcyrille.pitchen@wedev4u.fr, robh+dt@kernel.org, mark.rutland@arm.com, \n\tlinux-mtd@lists.infradead.org, devicetree@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org, gregkh@linuxfoundation.org,\n\tdavem@davemloft.net, mchehab@kernel.org, linux-fpga@vger.kernel.org, \n\ttien.hock.loh@intel.com, hean.loong.ong@intel.com", "Subject": "[PATCH v2 2/3] mtd: spi-nor: Altera ASMI Parallel II IP Core", "Date": "Wed, 20 Sep 2017 11:28:58 -0700", "Message-Id": "<1505932139-2905-3-git-send-email-matthew.gerlach@linux.intel.com>", "X-Mailer": "git-send-email 2.7.4", "In-Reply-To": "<1505932139-2905-1-git-send-email-matthew.gerlach@linux.intel.com>", "References": "<1505932139-2905-1-git-send-email-matthew.gerlach@linux.intel.com>", "MIME-Version": "1.0", "X-CRM114-Version": "20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ", "X-CRM114-CacheID": "sfid-20170920_112930_779776_FEA9445A ", "X-CRM114-Status": "GOOD ( 24.28 )", "X-Spam-Score": "-6.9 (------)", "X-Spam-Report": "SpamAssassin version 3.4.1 on bombadil.infradead.org summary:\n\tContent analysis details: (-6.9 points)\n\tpts rule name description\n\t---- ----------------------\n\t--------------------------------------------------\n\t-5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/,\n\thigh trust [134.134.136.24 listed in list.dnswl.org]\n\t-0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3)\n\t[134.134.136.24 listed in wl.mailspike.net]\n\t-0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay\n\tdomain\n\t-1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1%\n\t[score: 0.0000]\n\t-0.0 RCVD_IN_MSPIKE_WL Mailspike good senders", "X-BeenThere": "linux-mtd@lists.infradead.org", "X-Mailman-Version": "2.1.21", "Precedence": "list", "List-Id": "Linux MTD discussion mailing list <linux-mtd.lists.infradead.org>", "List-Unsubscribe": "<http://lists.infradead.org/mailman/options/linux-mtd>,\n\t<mailto:linux-mtd-request@lists.infradead.org?subject=unsubscribe>", "List-Archive": "<http://lists.infradead.org/pipermail/linux-mtd/>", "List-Post": "<mailto:linux-mtd@lists.infradead.org>", "List-Help": "<mailto:linux-mtd-request@lists.infradead.org?subject=help>", "List-Subscribe": "<http://lists.infradead.org/mailman/listinfo/linux-mtd>,\n\t<mailto:linux-mtd-request@lists.infradead.org?subject=subscribe>", "Cc": "Matthew Gerlach <matthew.gerlach@linux.intel.com>", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "base64", "Sender": "\"linux-mtd\" <linux-mtd-bounces@lists.infradead.org>", "Errors-To": "linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org" }, "content": "From: Matthew Gerlach <matthew.gerlach@linux.intel.com>\n\nThis patch adds support for a spi-nor, platform driver for the\nAltera ASMI Parallel II IP Core. The intended use case is to be able\nto update the flash used to load a FPGA at power up with mtd-utils.\n\nSigned-off-by: Matthew Gerlach <matthew.gerlach@linux.intel.com>\n---\nv2:\n minor checkpatch fixing by Wu Hao <hao.wu@intel.com>\n Use read_dummy value as suggested by Cyrille Pitchen.\n Don't assume 4 byte addressing (Cryille Pichecn and Marek Vasut).\n Fixed #define indenting as suggested by Marek Vasut.\n Added units to timer values as suggested by Marek Vasut.\n Use io(read|write)8_rep() as suggested by Marek Vasut.\n Renamed function prefixed with __ as suggested by Marek Vasut.\n---\n MAINTAINERS | 7 +\n drivers/mtd/spi-nor/Kconfig | 6 +\n drivers/mtd/spi-nor/Makefile | 1 +\n drivers/mtd/spi-nor/altera-asmip2.c | 457 ++++++++++++++++++++++++++++++++++++\n include/linux/mtd/altera-asmip2.h | 24 ++\n 5 files changed, 495 insertions(+)\n create mode 100644 drivers/mtd/spi-nor/altera-asmip2.c\n create mode 100644 include/linux/mtd/altera-asmip2.h", "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex b87c698..af48255 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -644,6 +644,13 @@ ALPS PS/2 TOUCHPAD DRIVER\n R:\tPali Rohár <pali.rohar@gmail.com>\n F:\tdrivers/input/mouse/alps.*\n \n+ALTERA ASMI Parallel II Driver\n+M: Matthew Gerlach <matthew.gerlach@linux.intel.com>\n+L: linux-mtd@lists.infradead.org\n+S: Maintained\n+F: drivers/mtd/spi-nor/altera-asmip2.c\n+F: inclulde/linux/mtd/altera-asmip2.h\n+\n ALTERA I2C CONTROLLER DRIVER\n M:\tThor Thayer <thor.thayer@linux.intel.com>\n S:\tMaintained\ndiff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig\nindex 69c638d..f81dbec 100644\n--- a/drivers/mtd/spi-nor/Kconfig\n+++ b/drivers/mtd/spi-nor/Kconfig\n@@ -129,4 +129,10 @@ config SPI_STM32_QUADSPI\n \t This enables support for the STM32 Quad SPI controller.\n \t We only connect the NOR to this controller.\n \n+config SPI_ALTERA_ASMIP2\n+ tristate \"Altera ASMI Parallel II IP\"\n+ depends on OF && HAS_IOMEM\n+ help\n+ Enable support for Altera ASMI Parallel II.\n+\n endif # MTD_SPI_NOR\ndiff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile\nindex 7d84c51..1c79324 100644\n--- a/drivers/mtd/spi-nor/Makefile\n+++ b/drivers/mtd/spi-nor/Makefile\n@@ -1,4 +1,5 @@\n obj-$(CONFIG_MTD_SPI_NOR)\t+= spi-nor.o\n+obj-$(CONFIG_SPI_ALTERA_ASMIP2)\t+= altera-asmip2.o\n obj-$(CONFIG_SPI_ASPEED_SMC)\t+= aspeed-smc.o\n obj-$(CONFIG_SPI_ATMEL_QUADSPI)\t+= atmel-quadspi.o\n obj-$(CONFIG_SPI_CADENCE_QUADSPI)\t+= cadence-quadspi.o\ndiff --git a/drivers/mtd/spi-nor/altera-asmip2.c b/drivers/mtd/spi-nor/altera-asmip2.c\nnew file mode 100644\nindex 0000000..a977765\n--- /dev/null\n+++ b/drivers/mtd/spi-nor/altera-asmip2.c\n@@ -0,0 +1,457 @@\n+/*\n+ * Copyright (C) 2017 Intel Corporation. All rights reserved.\n+ *\n+ * This program is free software; you can redistribute it and/or modify it\n+ * under the terms and conditions of the GNU General Public License,\n+ * version 2, as published by the Free Software Foundation.\n+ *\n+ * This program is distributed in the hope it will be useful, but WITHOUT\n+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n+ * more details.\n+ *\n+ * You should have received a copy of the GNU General Public License along with\n+ * this program. If not, see <http://www.gnu.org/licenses/>.\n+ */\n+\n+#include <linux/iopoll.h>\n+#include <linux/module.h>\n+#include <linux/mtd/altera-asmip2.h>\n+#include <linux/mtd/mtd.h>\n+#include <linux/mtd/spi-nor.h>\n+#include <linux/of_device.h>\n+\n+#define QSPI_ACTION_REG\t\t\t0\n+#define QSPI_ACTION_RST\t\t\tBIT(0)\n+#define QSPI_ACTION_EN\t\t\tBIT(1)\n+#define QSPI_ACTION_SC\t\t\tBIT(2)\n+#define QSPI_ACTION_CHIP_SEL_SFT\t4\n+#define QSPI_ACTION_DUMMY_SFT\t\t8\n+#define QSPI_ACTION_READ_BACK_SFT\t16\n+\n+#define QSPI_FIFO_CNT_REG\t\t4\n+#define QSPI_FIFO_DEPTH\t\t\t0x200\n+#define QSPI_FIFO_CNT_MSK\t\t0x3ff\n+#define QSPI_FIFO_CNT_RX_SFT\t\t0\n+#define QSPI_FIFO_CNT_TX_SFT\t\t12\n+\n+#define QSPI_DATA_REG\t\t\t0x8\n+\n+#define QSPI_POLL_TIMEOUT_US\t\t10000000\n+#define QSPI_POLL_INTERVAL_US\t\t5\n+\n+struct altera_asmip2 {\n+\tvoid __iomem *csr_base;\n+\tu32 num_flashes;\n+\tstruct device *dev;\n+\tstruct altera_asmip2_flash *flash[ALTERA_ASMIP2_MAX_NUM_FLASH_CHIP];\n+\tstruct mutex bus_mutex;\n+};\n+\n+struct altera_asmip2_flash {\n+\tstruct spi_nor nor;\n+\tstruct altera_asmip2 *q;\n+};\n+\n+static int altera_asmip2_write_reg(struct spi_nor *nor, u8 opcode, u8 *val,\n+\t\t\t\t int len)\n+{\n+\tstruct altera_asmip2_flash *flash = nor->priv;\n+\tstruct altera_asmip2 *q = flash->q;\n+\tu32 reg;\n+\tint ret;\n+\n+\tif ((len + 1) > QSPI_FIFO_DEPTH) {\n+\t\tdev_err(q->dev, \"%s bad len %d > %d\\n\",\n+\t\t\t__func__, len + 1, QSPI_FIFO_DEPTH);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\twriteb(opcode, q->csr_base + QSPI_DATA_REG);\n+\n+\tiowrite8_rep(q->csr_base + QSPI_DATA_REG, val, len);\n+\n+\treg = QSPI_ACTION_EN | QSPI_ACTION_SC;\n+\n+\twritel(reg, q->csr_base + QSPI_ACTION_REG);\n+\n+\tret = readl_poll_timeout(q->csr_base + QSPI_FIFO_CNT_REG, reg,\n+\t\t\t\t (((reg >> QSPI_FIFO_CNT_TX_SFT) &\n+\t\t\t\t QSPI_FIFO_CNT_MSK) == 0),\n+\t\t\t\t QSPI_POLL_INTERVAL_US, QSPI_POLL_TIMEOUT_US);\n+\tif (ret)\n+\t\tdev_err(q->dev, \"%s timed out\\n\", __func__);\n+\n+\treg = QSPI_ACTION_EN;\n+\n+\twritel(reg, q->csr_base + QSPI_ACTION_REG);\n+\n+\treturn ret;\n+}\n+\n+static int altera_asmip2_read_reg(struct spi_nor *nor, u8 opcode, u8 *val,\n+\t\t\t\t int len)\n+{\n+\tstruct altera_asmip2_flash *flash = nor->priv;\n+\tstruct altera_asmip2 *q = flash->q;\n+\tu32 reg;\n+\tint ret;\n+\n+\tif (len > QSPI_FIFO_DEPTH) {\n+\t\tdev_err(q->dev, \"%s bad len %d > %d\\n\",\n+\t\t\t__func__, len, QSPI_FIFO_DEPTH);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\twriteb(opcode, q->csr_base + QSPI_DATA_REG);\n+\n+\treg = QSPI_ACTION_EN | QSPI_ACTION_SC |\n+\t\t(len << QSPI_ACTION_READ_BACK_SFT);\n+\n+\twritel(reg, q->csr_base + QSPI_ACTION_REG);\n+\n+\tret = readl_poll_timeout(q->csr_base + QSPI_FIFO_CNT_REG, reg,\n+\t\t\t\t ((reg & QSPI_FIFO_CNT_MSK) == len),\n+\t\t\t\t QSPI_POLL_INTERVAL_US, QSPI_POLL_TIMEOUT_US);\n+\n+\tif (!ret)\n+\t\tioread8_rep(q->csr_base + QSPI_DATA_REG, val, len);\n+\telse\n+\t\tdev_err(q->dev, \"%s timeout\\n\", __func__);\n+\n+\twritel(QSPI_ACTION_EN, q->csr_base + QSPI_ACTION_REG);\n+\n+\treturn ret;\n+}\n+\n+static inline void altera_asmip2_push_offset(struct altera_asmip2 *q,\n+\t\t\t\t\t struct spi_nor *nor,\n+\t\t\t\t\t loff_t offset)\n+{\n+\tint i;\n+\tu32 val;\n+\n+\tfor (i = (nor->addr_width - 1) * 8; i >= 0; i -= 8) {\n+\t\tval = (offset & (0xff << i)) >> i;\n+\t\twriteb(val, q->csr_base + QSPI_DATA_REG);\n+\t}\n+}\n+\n+static ssize_t altera_asmip2_read(struct spi_nor *nor, loff_t from, size_t len,\n+\t\t\t\t u_char *buf)\n+{\n+\tstruct altera_asmip2_flash *flash = nor->priv;\n+\tstruct altera_asmip2 *q = flash->q;\n+\tsize_t bytes_to_read;\n+\tu32 reg;\n+\tint ret;\n+\n+\tbytes_to_read = min_t(size_t, len, QSPI_FIFO_DEPTH);\n+\n+\twriteb(nor->read_opcode, q->csr_base + QSPI_DATA_REG);\n+\n+\taltera_asmip2_push_offset(q, nor, from);\n+\n+\treg = QSPI_ACTION_EN | QSPI_ACTION_SC |\n+\t\t(nor->read_dummy << QSPI_ACTION_DUMMY_SFT) |\n+\t\t(bytes_to_read << QSPI_ACTION_READ_BACK_SFT);\n+\n+\twritel(reg, q->csr_base + QSPI_ACTION_REG);\n+\n+\tret = readl_poll_timeout(q->csr_base + QSPI_FIFO_CNT_REG, reg,\n+\t\t\t\t ((reg & QSPI_FIFO_CNT_MSK) ==\n+\t\t\t\t bytes_to_read), QSPI_POLL_INTERVAL_US,\n+\t\t\t\t QSPI_POLL_TIMEOUT_US);\n+\tif (ret) {\n+\t\tdev_err(q->dev, \"%s timed out\\n\", __func__);\n+\t\tbytes_to_read = 0;\n+\t} else\n+\t\tioread8_rep(q->csr_base + QSPI_DATA_REG, buf, bytes_to_read);\n+\n+\twritel(QSPI_ACTION_EN, q->csr_base + QSPI_ACTION_REG);\n+\n+\treturn bytes_to_read;\n+}\n+\n+static ssize_t altera_asmip2_write(struct spi_nor *nor, loff_t to,\n+\t\t\t\t size_t len, const u_char *buf)\n+{\n+\tstruct altera_asmip2_flash *flash = nor->priv;\n+\tstruct altera_asmip2 *q = flash->q;\n+\tsize_t bytes_to_write;\n+\tu32 reg;\n+\tint ret;\n+\n+\tbytes_to_write = min_t(size_t, len,\n+\t\t\t (QSPI_FIFO_DEPTH - (nor->addr_width + 1)));\n+\n+\twriteb(nor->program_opcode, q->csr_base + QSPI_DATA_REG);\n+\n+\taltera_asmip2_push_offset(q, nor, to);\n+\n+\tiowrite8_rep(q->csr_base + QSPI_DATA_REG, buf, bytes_to_write);\n+\n+\treg = QSPI_ACTION_EN | QSPI_ACTION_SC;\n+\n+\twritel(reg, q->csr_base + QSPI_ACTION_REG);\n+\n+\tret = readl_poll_timeout(q->csr_base + QSPI_FIFO_CNT_REG, reg,\n+\t\t\t\t (((reg >> QSPI_FIFO_CNT_TX_SFT) &\n+\t\t\t\t QSPI_FIFO_CNT_MSK) == 0),\n+\t\t\t\t QSPI_POLL_INTERVAL_US, QSPI_POLL_TIMEOUT_US);\n+\n+\tif (ret) {\n+\t\tdev_err(q->dev,\n+\t\t\t\"%s timed out waiting for fifo to clear\\n\",\n+\t\t\t__func__);\n+\t\tbytes_to_write = 0;\n+\t}\n+\n+\twritel(QSPI_ACTION_EN, q->csr_base + QSPI_ACTION_REG);\n+\n+\treturn bytes_to_write;\n+}\n+\n+static int altera_asmip2_prep(struct spi_nor *nor, enum spi_nor_ops ops)\n+{\n+\tstruct altera_asmip2_flash *flash = nor->priv;\n+\tstruct altera_asmip2 *q = flash->q;\n+\n+\tmutex_lock(&q->bus_mutex);\n+\n+\treturn 0;\n+}\n+\n+static void altera_asmip2_unprep(struct spi_nor *nor, enum spi_nor_ops ops)\n+{\n+\tstruct altera_asmip2_flash *flash = nor->priv;\n+\tstruct altera_asmip2 *q = flash->q;\n+\n+\tmutex_unlock(&q->bus_mutex);\n+}\n+\n+static int altera_asmip2_setup_banks(struct device *dev,\n+\t\t\t\t u32 bank, struct device_node *np)\n+{\n+\tconst struct spi_nor_hwcaps hwcaps = {\n+\t\t.mask = SNOR_HWCAPS_READ |\n+\t\t\tSNOR_HWCAPS_READ_FAST |\n+\t\t\tSNOR_HWCAPS_PP,\n+\t};\n+\tstruct altera_asmip2 *q = dev_get_drvdata(dev);\n+\tstruct altera_asmip2_flash *flash;\n+\tstruct spi_nor *nor;\n+\tint ret = 0;\n+\n+\tif (bank > q->num_flashes - 1)\n+\t\treturn -EINVAL;\n+\n+\tflash = devm_kzalloc(q->dev, sizeof(*flash), GFP_KERNEL);\n+\tif (!flash)\n+\t\treturn -ENOMEM;\n+\n+\tq->flash[bank] = flash;\n+\tflash->q = q;\n+\n+\tnor = &flash->nor;\n+\tnor->dev = dev;\n+\tnor->priv = flash;\n+\tnor->mtd.priv = nor;\n+\tspi_nor_set_flash_node(nor, np);\n+\n+\t/* spi nor framework*/\n+\tnor->read_reg = altera_asmip2_read_reg;\n+\tnor->write_reg = altera_asmip2_write_reg;\n+\tnor->read = altera_asmip2_read;\n+\tnor->write = altera_asmip2_write;\n+\tnor->prepare = altera_asmip2_prep;\n+\tnor->unprepare = altera_asmip2_unprep;\n+\n+\tret = spi_nor_scan(nor, NULL, &hwcaps);\n+\tif (ret) {\n+\t\tdev_err(nor->dev, \"flash not found\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\tret = mtd_device_register(&nor->mtd, NULL, 0);\n+\n+\treturn ret;\n+}\n+\n+static int altera_asmip2_create(struct device *dev, void __iomem *csr_base)\n+{\n+\tstruct altera_asmip2 *q;\n+\tu32 reg;\n+\n+\tq = devm_kzalloc(dev, sizeof(*q), GFP_KERNEL);\n+\tif (!q)\n+\t\treturn -ENOMEM;\n+\n+\tq->dev = dev;\n+\tq->csr_base = csr_base;\n+\n+\tmutex_init(&q->bus_mutex);\n+\n+\tdev_set_drvdata(dev, q);\n+\n+\treg = readl(q->csr_base + QSPI_ACTION_REG);\n+\tif (!(reg & QSPI_ACTION_RST)) {\n+\t\twritel((reg | QSPI_ACTION_RST), q->csr_base + QSPI_ACTION_REG);\n+\t\tdev_info(dev, \"%s asserting reset\\n\", __func__);\n+\t\tudelay(10);\n+\t}\n+\n+\twritel((reg & ~QSPI_ACTION_RST), q->csr_base + QSPI_ACTION_REG);\n+\tudelay(10);\n+\n+\treturn 0;\n+}\n+\n+static int altera_asmip2_add_bank(struct device *dev,\n+\t\t\t u32 bank, struct device_node *np)\n+{\n+\tstruct altera_asmip2 *q = dev_get_drvdata(dev);\n+\n+\tif (q->num_flashes >= ALTERA_ASMIP2_MAX_NUM_FLASH_CHIP)\n+\t\treturn -ENOMEM;\n+\n+\tq->num_flashes++;\n+\n+\treturn altera_asmip2_setup_banks(dev, bank, np);\n+}\n+\n+static int altera_asmip2_remove_banks(struct device *dev)\n+{\n+\tstruct altera_asmip2 *q = dev_get_drvdata(dev);\n+\tstruct altera_asmip2_flash *flash;\n+\tint i;\n+\tint ret = 0;\n+\n+\tif (!q)\n+\t\treturn -EINVAL;\n+\n+\t/* clean up for all nor flash */\n+\tfor (i = 0; i < q->num_flashes; i++) {\n+\t\tflash = q->flash[i];\n+\t\tif (!flash)\n+\t\t\tcontinue;\n+\n+\t\t/* clean up mtd stuff */\n+\t\tret = mtd_device_unregister(&flash->nor.mtd);\n+\t\tif (ret) {\n+\t\t\tdev_err(dev, \"error removing mtd\\n\");\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int altera_asmip2_probe_with_pdata(struct platform_device *pdev,\n+\t\t\t struct altera_asmip2_plat_data *qdata)\n+{\n+\tstruct device *dev = &pdev->dev;\n+\tint ret, i;\n+\n+\tret = altera_asmip2_create(dev, qdata->csr_base);\n+\n+\tif (ret) {\n+\t\tdev_err(dev, \"failed to create qspi device %d\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\tfor (i = 0; i < qdata->num_chip_sel; i++) {\n+\t\tret = altera_asmip2_add_bank(dev, i, NULL);\n+\t\tif (ret) {\n+\t\t\tdev_err(dev, \"failed to add qspi bank %d\\n\", ret);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int altera_asmip2_probe(struct platform_device *pdev)\n+{\n+\tstruct device_node *np = pdev->dev.of_node;\n+\tstruct device *dev = &pdev->dev;\n+\tstruct altera_asmip2_plat_data *qdata;\n+\tstruct resource *res;\n+\tvoid __iomem *csr_base;\n+\tu32 bank;\n+\tint ret;\n+\tstruct device_node *pp;\n+\n+\tqdata = dev_get_platdata(dev);\n+\n+\tif (qdata)\n+\t\treturn altera_asmip2_probe_with_pdata(pdev, qdata);\n+\n+\tif (!np) {\n+\t\tdev_err(dev, \"no device tree found %p\\n\", pdev);\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tres = platform_get_resource(pdev, IORESOURCE_MEM, 0);\n+\tcsr_base = devm_ioremap_resource(dev, res);\n+\tif (IS_ERR(csr_base)) {\n+\t\tdev_err(dev, \"%s: ERROR: failed to map csr base\\n\", __func__);\n+\t\treturn PTR_ERR(csr_base);\n+\t}\n+\n+\tret = altera_asmip2_create(dev, csr_base);\n+\n+\tif (ret) {\n+\t\tdev_err(dev, \"failed to create qspi device\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\tfor_each_available_child_of_node(np, pp) {\n+\t\tof_property_read_u32(pp, \"reg\", &bank);\n+\t\tif (bank >= ALTERA_ASMIP2_MAX_NUM_FLASH_CHIP) {\n+\t\t\tdev_err(dev, \"bad reg value %u >= %u\\n\", bank,\n+\t\t\t\tALTERA_ASMIP2_MAX_NUM_FLASH_CHIP);\n+\t\t\tgoto error;\n+\t\t}\n+\n+\t\tif (altera_asmip2_add_bank(dev, bank, pp)) {\n+\t\t\tdev_err(dev, \"failed to add bank %u\\n\", bank);\n+\t\t\tgoto error;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+error:\n+\taltera_asmip2_remove_banks(dev);\n+\treturn -EIO;\n+}\n+\n+static int altera_asmip2_remove(struct platform_device *pdev)\n+{\n+\tstruct altera_asmip2 *q = dev_get_drvdata(&pdev->dev);\n+\n+\tmutex_destroy(&q->bus_mutex);\n+\n+\treturn altera_asmip2_remove_banks(&pdev->dev);\n+}\n+\n+static const struct of_device_id altera_asmip2_id_table[] = {\n+\t{ .compatible = \"altr,asmi-parallel2-spi-nor\",},\n+\t{}\n+};\n+MODULE_DEVICE_TABLE(of, altera_asmip2_id_table);\n+\n+static struct platform_driver altera_asmip2_driver = {\n+\t.driver = {\n+\t\t.name = ALTERA_ASMIP2_DRV_NAME,\n+\t\t.of_match_table = altera_asmip2_id_table,\n+\t},\n+\t.probe = altera_asmip2_probe,\n+\t.remove = altera_asmip2_remove,\n+};\n+module_platform_driver(altera_asmip2_driver);\n+\n+MODULE_AUTHOR(\"Matthew Gerlach <matthew.gerlach@linux.intel.com>\");\n+MODULE_DESCRIPTION(\"Altera ASMI Parallel II\");\n+MODULE_LICENSE(\"GPL v2\");\n+MODULE_ALIAS(\"platform:\" ALTERA_ASMIP2_DRV_NAME);\ndiff --git a/include/linux/mtd/altera-asmip2.h b/include/linux/mtd/altera-asmip2.h\nnew file mode 100644\nindex 0000000..580c43c\n--- /dev/null\n+++ b/include/linux/mtd/altera-asmip2.h\n@@ -0,0 +1,24 @@\n+/*\n+ *\n+ * Copyright 2017 Intel Corporation, Inc.\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License as published by\n+ * the Free Software Foundation; either version 2 of the License, or\n+ * (at your option) any later version.\n+ */\n+#ifndef __ALTERA_QUADSPI_H\n+#define __ALTERA_QUADSPI_H\n+\n+#include <linux/device.h>\n+\n+#define ALTERA_ASMIP2_DRV_NAME \"altr-asmip2\"\n+#define ALTERA_ASMIP2_MAX_NUM_FLASH_CHIP 3\n+#define ALTERA_ASMIP2_RESOURCE_SIZE 0x10\n+\n+struct altera_asmip2_plat_data {\n+\tvoid __iomem *csr_base;\n+\tu32 num_chip_sel;\n+};\n+\n+#endif\n", "prefixes": [ "v2", "2/3" ] }