From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753510AbcLNANp (ORCPT ); Tue, 13 Dec 2016 19:13:45 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:42884 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751704AbcLNANm (ORCPT ); Tue, 13 Dec 2016 19:13:42 -0500 From: Holger Dengler To: Lee Jones , Arnd Bergmann , Greg Kroah-Hartman , Vinod Koul Cc: linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org, Thomas Gleixner , Sebastian Siewior , Juergen Bubeck , Peter Mahler , Holger Dengler , Benedikt Spranger Subject: [PATCH 08/12] misc: Flexcard misc device support Date: Wed, 14 Dec 2016 01:11:49 +0100 Message-Id: <1481674313-30378-9-git-send-email-dengler@linutronix.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1481674313-30378-1-git-send-email-dengler@linutronix.de> References: <1481674313-30378-1-git-send-email-dengler@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1,SHORTCIRCUIT=-0.0001 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The Flexcard PCI BAR0 contain registers for configuration but also for informational purpose like error counter, statistical information and some timestamps. The read-only mmap of the misc device offers the userspace a fast access to these registers. Signed-off-by: Benedikt Spranger Signed-off-by: Holger Dengler cc: Arnd Bergmann cc: Greg Kroah-Hartman --- drivers/mfd/Kconfig | 1 + drivers/misc/Kconfig | 6 ++ drivers/misc/Makefile | 1 + drivers/misc/flexcard_misc.c | 165 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 drivers/misc/flexcard_misc.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 85fedf6..580f521 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -303,6 +303,7 @@ config MFD_FLEXCARD tristate "Eberspaecher Flexcard PMC II Carrier Board" select MFD_CORE select IRQ_DOMAIN + select FLEXCARD_MISC depends on PCI help This is the core driver for the Eberspaecher Flexcard diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 64971ba..3f54b58 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -766,6 +766,12 @@ config PANEL_BOOT_MESSAGE An empty message will only clear the display at driver init time. Any other printf()-formatted message is valid with newline and escape codes. +config FLEXCARD_MISC + tristate "Flexcard Misc Device driver" + depends on MFD_FLEXCARD + help + Misc driver for Flexcard PMC II. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 3198336..08a1729 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_ECHO) += echo/ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o obj-$(CONFIG_CXL_BASE) += cxl/ obj-$(CONFIG_PANEL) += panel.o +obj-$(CONFIG_FLEXCARD_MISC) += flexcard_misc.o lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o diff --git a/drivers/misc/flexcard_misc.c b/drivers/misc/flexcard_misc.c new file mode 100644 index 0000000..93c951c --- /dev/null +++ b/drivers/misc/flexcard_misc.c @@ -0,0 +1,165 @@ +/* + * Eberspächer Flexcard PMC II Misc Device + * + * Copyright (c) 2014 - 2016, Linutronix GmbH + * Author: Benedikt Spranger + * Holger Dengler + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define FLEXCARD_MAX_NAME 16 + +struct flexcard_misc { + char name[FLEXCARD_MAX_NAME]; + struct miscdevice dev; + struct platform_device *pdev; + struct fc_bar0_conf __iomem *conf; + struct fc_bar0_nf __iomem *nf; +}; + +static int flexcard_misc_mmap(struct file *filp, struct vm_area_struct *vma) +{ + unsigned long offset, vsize, psize, addr; + struct flexcard_misc *priv; + struct resource *res; + + priv = container_of(filp->private_data, struct flexcard_misc, dev); + if (!priv) + return -EINVAL; + + if (vma->vm_flags & (VM_WRITE | VM_EXEC)) + return -EPERM; + + res = platform_get_resource(priv->pdev, IORESOURCE_MEM, 0); + offset = vma->vm_pgoff << PAGE_SHIFT; + if (offset > resource_size(res)) { + dev_err(&priv->pdev->dev, + "mmap offset out of resource range\n"); + return -EINVAL; + } + + vsize = vma->vm_end - vma->vm_start; + psize = round_up(resource_size(res) - offset, PAGE_SIZE); + addr = (res->start + offset) >> PAGE_SHIFT; + if (vsize > psize) { + dev_err(&priv->pdev->dev, + "requested mmap mapping too large\n"); + return -EINVAL; + } + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + return io_remap_pfn_range(vma, vma->vm_start, addr, vsize, + vma->vm_page_prot); +} + +static const struct file_operations flexcard_misc_fops = { + .owner = THIS_MODULE, + .open = nonseekable_open, + .mmap = flexcard_misc_mmap, + .llseek = no_llseek, +}; + +static int flexcard_misc_iomap(struct platform_device *pdev) +{ + struct flexcard_misc *priv = platform_get_drvdata(pdev); + struct resource *res; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENXIO; + + priv->conf = ioremap_nocache(res->start, resource_size(res)); + if (!priv->conf) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + ret = -ENXIO; + goto out; + } + + priv->nf = ioremap_nocache(res->start, resource_size(res)); + if (!priv->nf) { + ret = -ENOMEM; + goto out; + } + + return 0; +out: + iounmap(priv->conf); + return ret; +} + +static int flexcard_misc_probe(struct platform_device *pdev) +{ + struct flexcard_misc *priv; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + + ret = flexcard_misc_iomap(pdev); + if (ret) { + dev_err(&pdev->dev, "failed to map resource: %d\n", ret); + return ret; + } + + snprintf(priv->name, sizeof(priv->name), + "flexcard%d", pdev->id); + priv->dev.name = priv->name; + priv->dev.minor = MISC_DYNAMIC_MINOR; + priv->dev.fops = &flexcard_misc_fops; + priv->dev.parent = &pdev->dev; + priv->pdev = pdev; + + ret = misc_register(&priv->dev); + if (ret) { + dev_err(&pdev->dev, "unable to register miscdevice: %d\n", ret); + return ret; + } + + return 0; +} + +static int flexcard_misc_remove(struct platform_device *pdev) +{ + struct flexcard_misc *priv = platform_get_drvdata(pdev); + + misc_deregister(&priv->dev); + + return 0; +} + +static struct platform_driver flexcard_misc_driver = { + .probe = flexcard_misc_probe, + .remove = flexcard_misc_remove, + .driver = { + .name = "flexcard-misc", + }, +}; + +module_platform_driver(flexcard_misc_driver); + +MODULE_AUTHOR("Holger Dengler "); +MODULE_AUTHOR("Benedikt Spranger "); +MODULE_DESCRIPTION("Eberspaecher Flexcard PMC II Misc Driver"); +MODULE_LICENSE("GPL v2"); -- 2.1.4