From patchwork Wed Apr 16 17:17:15 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Yanovich X-Patchwork-Id: 4003271 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 9AAC09F2CC for ; Wed, 16 Apr 2014 17:22:51 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8534C20374 for ; Wed, 16 Apr 2014 17:22:50 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5A5362027D for ; Wed, 16 Apr 2014 17:22:49 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WaTUv-0007cl-Go; Wed, 16 Apr 2014 17:19:45 +0000 Received: from mail-lb0-x22b.google.com ([2a00:1450:4010:c04::22b]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WaTUP-0006BA-Ph; Wed, 16 Apr 2014 17:19:16 +0000 Received: by mail-lb0-f171.google.com with SMTP id w7so8507236lbi.30 for ; Wed, 16 Apr 2014 10:18:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=XFHEq4Zbwpdvtgmj8XG0CnXry6LDeM5PZQrOZD1pwoo=; b=Dquii1NxZTeoh+3Mll+Q909gdP6cX5tAEL+fC3bR5Gc1DYc/p4XUEx31/nAM6ca3UW xN9y7ts4l6cbsW0fBxHY7PM7eTAgOPeahOt73n1Bneaw8cNlmk56U+RerZ0yhsBjI1q4 dtVXPOuBEQvJIZdCmZlQKPJGvEAe30ttNgkdhP5twI7hcUewvyNdVfeU+6p8VGqCOXtk bOgQ17AuVDqkZR1oIVbzljgBBAWiHouJ76X71efqZu3vn/q7WFT7YQlCevUyAZGZ510/ PPXe+3H+dV9yZt7F5kQuEIfVN+clLPlbMrjpHaAAqMkiuw+5z+hn/wSex7MP0VNwgvLJ 60JA== X-Received: by 10.112.56.148 with SMTP id a20mr2416960lbq.44.1397668734493; Wed, 16 Apr 2014 10:18:54 -0700 (PDT) Received: from host5.omatika.ru (0893675324.static.corbina.ru. [95.31.1.192]) by mx.google.com with ESMTPSA id q4sm21186297lbh.20.2014.04.16.10.18.52 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 16 Apr 2014 10:18:53 -0700 (PDT) From: Sergei Ianovich To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v4 10/21] mtd: support BB SRAM on ICP DAS LP-8x4x Date: Wed, 16 Apr 2014 21:17:15 +0400 Message-Id: <1397668667-27328-4-git-send-email-ynvich@gmail.com> X-Mailer: git-send-email 1.9.2 In-Reply-To: <1397668667-27328-1-git-send-email-ynvich@gmail.com> References: <1397668411-27162-7-git-send-email-ynvich@gmail.com> <1397668667-27328-1-git-send-email-ynvich@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140416_101914_292180_84F09FFD X-CRM114-Status: GOOD ( 22.91 ) X-Spam-Score: -0.1 (/) Cc: Mark Rutland , "open list:OPEN FIRMWARE AND..." , Heikki Krogerus , Russell King , "open list:DOCUMENTATION" , Pawel Moll , Ian Campbell , Lee Jones , Robert Jarzmik , Randy Dunlap , Artem Bityutskiy , Sergei Ianovich , Michael Opdenacker , Rob Herring , "open list:MEMORY TECHNOLOGY..." , Kumar Gala , Grant Likely , Brian Norris , David Woodhouse X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This provides an MTD device driver for 512kB of battery backed up SRAM on ICPDAS LP-8X4X programmable automation controllers. SRAM chip is connected via FPGA and is not accessible without a driver, unlike flash memory which is wired to CPU MMU. This SRAM becomes an excellent persisent storage of volatile process data like counter values and sensor statuses. Storing those data in flash or mmc card is not a viable solution. Signed-off-by: Sergei Ianovich Reviewed-by: Brian Norris --- v3..v4 for Brian Norris 'Reviewed-by' * add doc file for DT binding * move DTS binding to a different patch (8/21) * drop unused include directive * drop safely unused callback * drop non-default partion probe types * drop duplicate error checks * drop duplicate error reporting * fixed error message on MTD registeration * fixed module removal routine v2..v3 * no changes (except number 08/16 -> 10/21) v0..v2 * use device tree * use devm helpers where possible .../devicetree/bindings/mtd/sram-lp8x4x.txt | 22 +++ arch/arm/configs/lp8x4x_defconfig | 1 + drivers/mtd/devices/Kconfig | 14 ++ drivers/mtd/devices/Makefile | 1 + drivers/mtd/devices/sram_lp8x4x.c | 204 +++++++++++++++++++++ 5 files changed, 242 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt create mode 100644 drivers/mtd/devices/sram_lp8x4x.c diff --git a/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt new file mode 100644 index 0000000..8b1e864 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/sram-lp8x4x.txt @@ -0,0 +1,22 @@ +512kB battery backed up SRAM on LP-8x4x industrial computers + +Required properties: +- compatible : should be "icpdas,sram-lp8x4x" + +- reg: physical base addresses and region lengths of + * IO memory range + * SRAM page selector + +- eeprom-gpios : should point to active-low write enable GPIO + +SRAM chip is connected via FPGA and is not accessible without a driver, +unlike flash memory which is wired to CPU MMU. Driver is essentially +an address translation routine. + +Example: + + sram@a000 { + compatible = "icpdas,sram-lp8x4x"; + reg = <0xa000 0x1000 + 0x901e 0x1>; + }; diff --git a/arch/arm/configs/lp8x4x_defconfig b/arch/arm/configs/lp8x4x_defconfig index d60e37a..17a4e6f 100644 --- a/arch/arm/configs/lp8x4x_defconfig +++ b/arch/arm/configs/lp8x4x_defconfig @@ -57,6 +57,7 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y CONFIG_MTD_CFI_GEOMETRY=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_PHYSMAP_OF=y +CONFIG_MTD_SRAM_LP8X4X=y CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_LOOP_MIN_COUNT=2 diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 1210bc2..fc8552b 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -225,4 +225,18 @@ config BCH_CONST_T default 4 endif +config MTD_SRAM_LP8X4X + tristate "SRAM on ICPDAS LP-8X4X" + depends on OF && ARCH_PXA + ---help--- + This provides an MTD device driver for 512kiB of battery backed up SRAM + on ICPDAS LP-8X4X programmable automation controllers. + + SRAM chip is connected via FPGA and is not accessible without a driver, + unlike flash memory which is wired to CPU MMU. + + Say N, unless you plan to run this kernel on LP-8X4X. + + If you say M, the module will be called sram_lp8x4x. + endmenu diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index c68868f..a7d86e2 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o obj-$(CONFIG_MTD_SST25L) += sst25l.o obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o obj-$(CONFIG_MTD_ST_SPI_FSM) += st_spi_fsm.o +obj-$(CONFIG_MTD_SRAM_LP8X4X) += sram_lp8x4x.o CFLAGS_docg3.o += -I$(src) diff --git a/drivers/mtd/devices/sram_lp8x4x.c b/drivers/mtd/devices/sram_lp8x4x.c new file mode 100644 index 0000000..4cfa70b --- /dev/null +++ b/drivers/mtd/devices/sram_lp8x4x.c @@ -0,0 +1,204 @@ +/* + * linux/drivers/mtd/devices/lp8x4x_sram.c + * + * MTD Driver for SRAM on ICPDAS LP-8x4x + * Copyright (C) 2013 Sergei Ianovich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation or any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct lp8x4x_sram_info { + void __iomem *bank; + void __iomem *virt; + struct mutex lock; + unsigned active_bank; + struct mtd_info mtd; +}; + +static int +lp8x4x_sram_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct lp8x4x_sram_info *info = mtd->priv; + unsigned bank = instr->addr >> 11; + unsigned offset = (instr->addr & 0x7ff) << 1; + loff_t i; + + mutex_lock(&info->lock); + if (unlikely(bank != info->active_bank)) { + info->active_bank = bank; + iowrite8(bank, info->bank); + } + for (i = 0; i < instr->len; i++) { + iowrite8(0xff, info->virt + offset); + offset += 2; + if (unlikely(offset == 0)) { + info->active_bank++; + iowrite8(info->active_bank, info->bank); + } + } + mutex_unlock(&info->lock); + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + + return 0; +} + +static int +lp8x4x_sram_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *b) +{ + struct lp8x4x_sram_info *info = mtd->priv; + unsigned bank = to >> 11; + unsigned offset = (to & 0x7ff) << 1; + loff_t i; + + mutex_lock(&info->lock); + if (unlikely(bank != info->active_bank)) { + info->active_bank = bank; + iowrite8(bank, info->bank); + } + for (i = 0; i < len; i++) { + iowrite8(b[i], info->virt + offset); + offset += 2; + if (unlikely(offset == 0)) { + info->active_bank++; + iowrite8(info->active_bank, info->bank); + } + } + mutex_unlock(&info->lock); + *retlen = len; + return 0; +} + +static int +lp8x4x_sram_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *b) +{ + struct lp8x4x_sram_info *info = mtd->priv; + unsigned bank = from >> 11; + unsigned offset = (from & 0x7ff) << 1; + loff_t i; + + mutex_lock(&info->lock); + if (unlikely(bank != info->active_bank)) { + info->active_bank = bank; + iowrite8(bank, info->bank); + } + for (i = 0; i < len; i++) { + b[i] = ioread8(info->virt + offset); + offset += 2; + if (unlikely(offset == 0)) { + info->active_bank++; + iowrite8(info->active_bank, info->bank); + } + } + mutex_unlock(&info->lock); + *retlen = len; + return 0; +} + +static struct of_device_id of_flash_match[] = { + { + .compatible = "icpdas,sram-lp8x4x", + }, + { }, +}; +MODULE_DEVICE_TABLE(of, of_flash_match); + +static int +lp8x4x_sram_probe(struct platform_device *pdev) +{ + const struct of_device_id *match; + struct lp8x4x_sram_info *info; + struct resource *res_virt, *res_bank; + char sz_str[16]; + struct mtd_part_parser_data ppdata; + int err = 0; + + match = of_match_device(of_flash_match, &pdev->dev); + if (!match) + return -EINVAL; + + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + res_virt = platform_get_resource(pdev, IORESOURCE_MEM, 0); + info->virt = devm_ioremap_resource(&pdev->dev, res_virt); + if (IS_ERR(info->virt)) + return PTR_ERR(info->virt); + + res_bank = platform_get_resource(pdev, IORESOURCE_MEM, 1); + info->bank = devm_ioremap_resource(&pdev->dev, res_bank); + if (IS_ERR(info->bank)) + return PTR_ERR(info->bank); + + info->mtd.priv = info; + info->mtd.name = "SRAM"; + info->mtd.type = MTD_RAM; + info->mtd.flags = MTD_CAP_RAM; + info->mtd.size = resource_size(res_virt) << 7; + info->mtd.erasesize = 512; + info->mtd.writesize = 4; + info->mtd._erase = lp8x4x_sram_erase; + info->mtd._write = lp8x4x_sram_write; + info->mtd._read = lp8x4x_sram_read; + info->mtd.owner = THIS_MODULE; + + mutex_init(&info->lock); + iowrite8(info->active_bank, info->bank); + platform_set_drvdata(pdev, info); + + ppdata.of_node = pdev->dev.of_node; + err = mtd_device_parse_register(&info->mtd, NULL, &ppdata, + NULL, 0); + + if (err < 0) { + dev_err(&pdev->dev, "failed to register MTD\n"); + return err; + } + + string_get_size(info->mtd.size, STRING_UNITS_2, sz_str, + sizeof(sz_str)); + dev_info(&pdev->dev, "using %s SRAM on LP-8X4X as %s\n", sz_str, + dev_name(&info->mtd.dev)); + return 0; +} + +static int +lp8x4x_sram_remove(struct platform_device *dev) +{ + struct lp8x4x_sram_info *info = platform_get_drvdata(dev); + return mtd_device_unregister(&info->mtd); +} + +static struct platform_driver lp8x4x_sram_driver = { + .driver = { + .name = "sram-lp8x4x", + .owner = THIS_MODULE, + .of_match_table = of_flash_match, + }, + .probe = lp8x4x_sram_probe, + .remove = lp8x4x_sram_remove, +}; + +module_platform_driver(lp8x4x_sram_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Sergei Ianovich "); +MODULE_DESCRIPTION("MTD driver for SRAM on ICPDAS LP-8x4x");