linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/12] Eberspaecher Flexcard PMC II base support
@ 2016-12-14  0:11 Holger Dengler
  2016-12-14  0:11 ` [PATCH 01/12] mfd: Eberspaecher Flexcard PMC II Carrier Board support Holger Dengler
                   ` (12 more replies)
  0 siblings, 13 replies; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  0:11 UTC (permalink / raw)
  To: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul
  Cc: linux-kernel, dmaengine, Thomas Gleixner, Sebastian Siewior,
	Juergen Bubeck, Peter Mahler, Holger Dengler


The Eberspaecher Flexcard PMC II is a PMC (PCI Mezzanine Card) II
carrier board. The carrier board can take up to 4 exchangeable physical
layer boards for CAN, FlexRay or Ethernet.
This patchset adds support for the common infrastructure of the carrier
board.

This patch series apply on v4.9.

First post:  http://www.spinics.net/lists/netdev/msg246290.html
Second post: http://www.spinics.net/lists/kernel/msg1954275.html

According to the comments regarding our first posting, the MFD driver
patchset has been split up into separate functional parts.

According to the comments regarding our second port, we moved the
separated driver to their particular subsystems. All other comments
are also reflected.

The timer functionality was wrongly named as clocksource in the second post,
although it is a posix_clock. We renamed it and moved it together with the
misc_device funtions to drivers/misc/. If someone know a better place for
the posix_clock, please let me know.

The irq part of the mfd driver has been mainly reworked (thanks to Thomas
and Sebastian for their input). The irq-demux is now implementet without a
loop and the irq_chips share the irq-table and functions.

Holger Dengler (12):
  mfd: Eberspaecher Flexcard PMC II Carrier Board support
  mfd: flexcard: add flexcard misc mfd-cell
  mfd: flexcard: add posix clock mfd-cell
  mfd: flexcard: add interrupt support
  mfd: flexcard: add DMA interrupts
  mfd: flexcard: add DMA device
  mfd: flexcard: add UIO IRQ devices
  misc: Flexcard misc device support
  misc: flexcard: add device attributes
  misc: Flexcard basic timestamp counter support
  misc: flexcard: Support timestamp trigger selection
  dma: Flexcard DMA ringbuffer demux driver

 drivers/dma/Kconfig                 |   9 +
 drivers/dma/Makefile                |   1 +
 drivers/dma/flexcard/Makefile       |   2 +
 drivers/dma/flexcard/core.c         | 292 ++++++++++++++++++++++
 drivers/dma/flexcard/flexcard-dma.h | 218 +++++++++++++++++
 drivers/dma/flexcard/parser.c       | 227 +++++++++++++++++
 drivers/mfd/Kconfig                 |  14 ++
 drivers/mfd/Makefile                |   3 +
 drivers/mfd/flexcard_core.c         | 476 ++++++++++++++++++++++++++++++++++++
 drivers/mfd/flexcard_irq.c          | 305 +++++++++++++++++++++++
 drivers/misc/Kconfig                |  15 ++
 drivers/misc/Makefile               |   2 +
 drivers/misc/flexcard_misc.c        | 361 +++++++++++++++++++++++++++
 drivers/misc/flexcard_posixclock.c  | 295 ++++++++++++++++++++++
 include/linux/mfd/flexcard.h        | 116 +++++++++
 include/uapi/linux/Kbuild           |   1 +
 include/uapi/linux/flexcard.h       |  80 ++++++
 17 files changed, 2417 insertions(+)
 create mode 100644 drivers/dma/flexcard/Makefile
 create mode 100644 drivers/dma/flexcard/core.c
 create mode 100644 drivers/dma/flexcard/flexcard-dma.h
 create mode 100644 drivers/dma/flexcard/parser.c
 create mode 100644 drivers/mfd/flexcard_core.c
 create mode 100644 drivers/mfd/flexcard_irq.c
 create mode 100644 drivers/misc/flexcard_misc.c
 create mode 100644 drivers/misc/flexcard_posixclock.c
 create mode 100644 include/linux/mfd/flexcard.h
 create mode 100644 include/uapi/linux/flexcard.h

-- 
2.1.4

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 01/12] mfd: Eberspaecher Flexcard PMC II Carrier Board support
  2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
@ 2016-12-14  0:11 ` Holger Dengler
  2016-12-14  8:38   ` Arnd Bergmann
  2016-12-14  0:11 ` [PATCH 02/12] mfd: flexcard: add flexcard misc mfd-cell Holger Dengler
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  0:11 UTC (permalink / raw)
  To: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul
  Cc: linux-kernel, dmaengine, Thomas Gleixner, Sebastian Siewior,
	Juergen Bubeck, Peter Mahler, Holger Dengler, Benedikt Spranger

The Eberspaecher Flexcard PMC II is a PMC (PCI Mezzanine Card) II
carrier board. The carrier board can take up to 4 exchangeable physical
layer boards for e.g. CAN, FlexRay or Ethernet.

Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
Signed-off-by: Holger Dengler <dengler@linutronix.de>
cc: Lee Jones <lee.jones@linaro.org>
---
 drivers/mfd/Kconfig           |  10 ++
 drivers/mfd/Makefile          |   2 +
 drivers/mfd/flexcard_core.c   | 218 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/flexcard.h  | 103 ++++++++++++++++++++
 include/uapi/linux/Kbuild     |   1 +
 include/uapi/linux/flexcard.h |  64 +++++++++++++
 6 files changed, 398 insertions(+)
 create mode 100644 drivers/mfd/flexcard_core.c
 create mode 100644 include/linux/mfd/flexcard.h
 create mode 100644 include/uapi/linux/flexcard.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c6df644..a5a12da 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -299,6 +299,16 @@ config MFD_EXYNOS_LPASS
 	  Select this option to enable support for Samsung Exynos Low Power
 	  Audio Subsystem.
 
+config MFD_FLEXCARD
+	tristate "Eberspaecher Flexcard PMC II Carrier Board"
+	select MFD_CORE
+	depends on PCI
+	help
+	  This is the core driver for the Eberspaecher Flexcard
+	  PMC (PCI Mezzanine Card) II carrier board. This carrier board
+	  can take up to 4 exchangeable physical layer boards for
+	  CAN, FlexRay or Ethernet.
+
 config MFD_MC13XXX
 	tristate
 	depends on (SPI_MASTER || I2C)
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9834e66..843e57c 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -211,3 +211,5 @@ obj-$(CONFIG_INTEL_SOC_PMIC)	+= intel-soc-pmic.o
 obj-$(CONFIG_MFD_MT6397)	+= mt6397-core.o
 
 obj-$(CONFIG_MFD_ALTERA_A10SR)	+= altera-a10sr.o
+flexcard-objs			:= flexcard_core.o
+obj-$(CONFIG_MFD_FLEXCARD)	+= flexcard.o
diff --git a/drivers/mfd/flexcard_core.c b/drivers/mfd/flexcard_core.c
new file mode 100644
index 0000000..e580971
--- /dev/null
+++ b/drivers/mfd/flexcard_core.c
@@ -0,0 +1,218 @@
+/*
+ * Eberspächer Flexcard PMC II Carrier Board PCI Driver
+ *
+ * Copyright (c) 2014 - 2016, Linutronix GmbH
+ * Author: Benedikt Spranger <b.spranger@linutronix.de>
+ *         Holger Dengler <dengler@linutronix.de>
+ *
+ * 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 <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/flexcard.h>
+
+#define FLEXCARD_CAN_OFFSET	0x2000
+#define FLEXCARD_CAN_SIZE	0x2000
+
+#define FLEXCARD_FR_OFFSET	0x4000
+#define FLEXCARD_FR_SIZE	0x2000
+
+enum flexcard_cell_id {
+	FLEXCARD_CELL_CAN,
+	FLEXCARD_CELL_FLEXRAY,
+};
+
+static int flexcard_tiny_can(struct flexcard_device *priv,
+			     int idx, int id, u32 offset)
+{
+	struct mfd_cell *cell = &priv->cells[idx];
+	struct resource *res = &priv->res[idx];
+	struct pci_dev *pci = priv->pdev;
+
+	cell->name = "flexcard-dcan";
+	cell->resources = res;
+	cell->num_resources = 1;
+	cell->id = id;
+
+	res->name = "flexcard-dcan";
+	res->flags = IORESOURCE_MEM;
+	res->parent = &pci->resource[1];
+	res->start = pci->resource[1].start + offset;
+	res->end = res->start + FLEXCARD_CAN_SIZE - 1;
+
+	if (res->end > pci->resource[1].end)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int flexcard_tiny_flexray(struct flexcard_device *priv,
+				 int idx, int id, u32 offset)
+{
+	struct mfd_cell *cell = &priv->cells[idx];
+	struct resource *res = &priv->res[idx];
+	struct pci_dev *pci = priv->pdev;
+
+	cell->name = "flexcard-eray";
+	cell->resources = res;
+	cell->num_resources = 1;
+	cell->id = id;
+
+	res->name = "flexcard-eray";
+	res->flags = IORESOURCE_MEM;
+	res->parent = &pci->resource[1];
+	res->start = pci->resource[1].start + offset;
+	res->end = res->start + FLEXCARD_FR_SIZE - 1;
+
+	if (res->end > pci->resource[1].end)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int flexcard_tiny_probe(struct flexcard_device *priv)
+{
+	struct pci_dev *pdev = priv->pdev;
+	u32 fc_slic0, offset = 0;
+	u8 nr_can, nr_fr, nr;
+	int i, ret;
+
+	/*
+	 * Reading FC_LIC[0] register to determine the number of CAN and
+	 * FlexRay Devices
+	 */
+	fc_slic0 = readl(&priv->bar0->conf.fc_slic[0]);
+	nr_can = (fc_slic0 >> 4) & 0xf;
+	nr_fr = fc_slic0 & 0xf;
+	nr = nr_can + nr_fr;
+
+	dev_info(&pdev->dev, "tinys: CAN: %d FR: %d", nr_can, nr_fr);
+
+	priv->cells = devm_kzalloc(&pdev->dev, nr * sizeof(struct mfd_cell),
+				   GFP_KERNEL);
+	if (!priv->cells)
+		return -ENOMEM;
+
+	priv->res = devm_kzalloc(&pdev->dev, nr * sizeof(struct resource),
+				 GFP_KERNEL);
+	if (!priv->res)
+		return -ENOMEM;
+
+	for (i = 0; i < nr_fr; i++) {
+		ret = flexcard_tiny_flexray(priv, i, i, offset);
+		if (ret)
+			return ret;
+		offset += FLEXCARD_FR_OFFSET;
+	}
+
+	for (i = 0; i < nr_can; i++) {
+		ret = flexcard_tiny_can(priv, nr_fr + i, i, offset);
+		if (ret)
+			return ret;
+		offset += FLEXCARD_CAN_OFFSET;
+	}
+
+	return mfd_add_devices(&pdev->dev, 0, priv->cells, nr, NULL, 0, NULL);
+}
+
+static int flexcard_probe(struct pci_dev *pdev,
+			  const struct pci_device_id *id)
+{
+	struct flexcard_device *priv;
+	union {
+		struct fc_version ver;
+		u32 reg;
+	} fw_ver, hw_ver;
+
+	int ret;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	pci_set_drvdata(pdev, priv);
+	priv->pdev = pdev;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable device: %d\n", ret);
+		return ret;
+	}
+
+	pci_set_master(pdev);
+	ret = pci_request_regions(pdev, "flexcard");
+	if (ret) {
+		dev_err(&pdev->dev, "unable to request regions: %d\n", ret);
+		goto out_disable;
+	}
+
+	priv->bar0 = pci_ioremap_bar(pdev, 0);
+	if (!priv->bar0) {
+		dev_err(&pdev->dev, "unable to remap bar0 regs\n");
+		ret = -ENOMEM;
+		goto out_release;
+	}
+	fw_ver.reg = readl(&priv->bar0->conf.fc_fw_ver);
+	hw_ver.reg = readl(&priv->bar0->conf.fc_hw_ver);
+
+	ret = flexcard_tiny_probe(priv);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to probe tinys: %d", ret);
+		goto out_unmap;
+	}
+
+	dev_info(&pdev->dev, "HW %02x.%02x.%02x FW %02x.%02x.%02x\n",
+		 hw_ver.ver.maj, hw_ver.ver.min, hw_ver.ver.dev,
+		 fw_ver.ver.maj, fw_ver.ver.min, fw_ver.ver.dev);
+
+	return 0;
+
+out_unmap:
+	iounmap(priv->bar0);
+out_release:
+	pci_release_regions(pdev);
+out_disable:
+	pci_disable_device(pdev);
+
+	return ret;
+}
+
+static void flexcard_remove(struct pci_dev *pdev)
+{
+	struct flexcard_device *priv = pci_get_drvdata(pdev);
+
+	mfd_remove_devices(&pdev->dev);
+	iounmap(priv->bar0);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+#define PCI_VENDOR_ID_EBEL	0x1974
+
+static const struct pci_device_id flexcard_pci_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_EBEL, 0x0009), },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, flexcard_pci_ids);
+
+static struct pci_driver flexcard_driver = {
+	.name     = "flexcard",
+	.id_table = flexcard_pci_ids,
+	.probe    = flexcard_probe,
+	.remove   = flexcard_remove,
+};
+
+module_pci_driver(flexcard_driver);
+
+MODULE_AUTHOR("Holger Dengler <dengler@linutronix.de>");
+MODULE_AUTHOR("Benedikt Spranger <b.spranger@linutronix.de>");
+MODULE_DESCRIPTION("Eberspaecher Flexcard PMC II Carrier Board Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/flexcard.h b/include/linux/mfd/flexcard.h
new file mode 100644
index 0000000..362b909
--- /dev/null
+++ b/include/linux/mfd/flexcard.h
@@ -0,0 +1,103 @@
+/*
+ * Eberspächer Flexcard PMC II Carrier Board PCI Driver - device attributes
+ *
+ * Copyright (c) 2014 - 2016, Linutronix GmbH
+ * Author: Benedikt Spranger <b.spranger@linutronix.de>
+ *         Holger Dengler <dengler@linutronix.de>
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_MFD_FLEXCARD_H
+#define _LINUX_MFD_FLEXCARD_H
+
+#include <uapi/linux/flexcard.h>
+
+/* PCI BAR 0: Flexcard DMA register */
+struct fc_bar0_dma {
+	__u32 dma_ctrl;			/* 500 */
+	__u32 dma_stat;			/* 504 */
+	__u32 r16[2];			/* 508 */
+	__u64 dma_cba;			/* 510 */
+	__u32 dma_cbs;			/* 518 */
+	__u32 dma_txr;			/* 51c */
+	__u32 dma_irer;			/* 520 */
+	__u32 dma_irsr;			/* 524 */
+	__u32 r17[10];			/* 528 */
+	__u32 dma_cbcr;			/* 550 */
+	__u32 dma_cblr;			/* 554 */
+	__u32 r18[2];			/* 558 */
+	__u32 dma_itcr;			/* 560 */
+	__u32 dma_itr;			/* 564 */
+	__u32 r19[2];			/* 568 */
+	__u32 dma_wptr;			/* 570 */
+	__u32 dma_rptr;			/* 574 */
+} __packed;
+
+/* PCI BAR 0: Flexcard clock register */
+struct fc_bar0_time {
+	__u32 ts_high;			/* 700 */
+	__u32 ts_low;			/* 704 */
+	__u32 r21[2];			/* 708 */
+	__u32 clk_src;			/* 710 */
+} __packed;
+
+struct fc_bar0_nf {
+	__u32 fc_nfctrl;		/* 170 */
+	__u32 nf_cnt;			/* 174 */
+} __packed;
+
+/* PCI BAR 0: Flexcard register */
+struct fc_bar0 {
+	struct fc_bar0_conf conf;	/* 000-13c */
+	__u32 fc_ts;			/* 140 */
+	__u32 fc_reset;			/* 144 */
+	__u32 trig_sc_ctrl;		/* 148 */
+	__u32 trig_ctrl;		/* 14c */
+	__u32 r12;			/* 150 */
+	__u32 tirqir;			/* 154 */
+	__u32 pccr1;			/* 158 */
+	__u32 pccr2;			/* 15c */
+	__u32 r13[4];			/* 160 */
+	struct fc_bar0_nf nf;		/* 170-174 */
+	__u32 r14;			/* 178 */
+	struct fc_bar0_dma dma;		/* 500-574 */
+	__u32 r20[0x62];		/* 578 */
+	struct fc_bar0_time time;	/* 700-710 */
+	__u32 r22[0x7b];		/* 714 */
+	__u32 faddr;			/* 900 */
+	__u32 fwdat;			/* 904 */
+	__u32 fctrl;			/* 908 */
+	__u32 frdat;			/* 90c */
+	__u32 bwdat[16];		/* 910 */
+	__u32 brdat[16];		/* 950 */
+	__u32 r23[28];			/* 990 */
+	__u32 fwmode;			/* a00 */
+	__u32 recond;			/* a04 */
+	__u32 wdtctrl;			/* a08 */
+	__u32 imgsel;			/* a0c */
+	__u32 actimg;			/* a10 */
+	__u32 updimginf;		/* a14 */
+	__u32 r24[0x32];		/* a18 */
+	__u32 factory_image_info[8];	/* ae0 */
+	__u32 app_image0_info[8];	/* b00 */
+	__u32 app_image1_info[8];	/* b20 */
+	__u32 app_image2_info[8];	/* b40 */
+	__u32 app_image3_info[8];	/* b60 */
+	__u32 app_image4_info[8];	/* b80 */
+	__u32 app_image5_info[8];	/* ba0 */
+	__u32 app_image6_info[8];	/* bc0 */
+	__u32 app_image7_info[8];	/* be0 */
+	__u32 r25[0x100];		/* c00 */
+} __packed;
+
+struct flexcard_device {
+	struct pci_dev *pdev;
+	struct fc_bar0 __iomem *bar0;
+	struct mfd_cell *cells;
+	struct resource *res;
+};
+
+#endif /* _LINUX_FLEXCARD_H */
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index cd2be1c..46dc3c1 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -131,6 +131,7 @@ header-y += filter.h
 header-y += firewire-cdev.h
 header-y += firewire-constants.h
 header-y += flat.h
+header-y += flexcard.h
 header-y += fou.h
 header-y += fs.h
 header-y += fsl_hypervisor.h
diff --git a/include/uapi/linux/flexcard.h b/include/uapi/linux/flexcard.h
new file mode 100644
index 0000000..4e9f07b4
--- /dev/null
+++ b/include/uapi/linux/flexcard.h
@@ -0,0 +1,64 @@
+/*
+ * Eberspächer Flexcard PMC II Carrier Board PCI Driver - device attributes
+ *
+ * Copyright (c) 2014,2016 Linutronix GmbH
+ * Author: Benedikt Spranger <b.spranger@linutronix.de>
+ *         Holger Dengler <dengler@linutronix.de>
+ *
+ * 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.
+ */
+
+#ifndef _UAPI_LINUX_FLEXCARD_H
+#define _UAPI_LINUX_FLEXCARD_H
+
+#include <linux/types.h>
+
+struct fc_version {
+	__u8	dev;
+	__u8	min;
+	__u8	maj;
+	__u8	reserved;
+} __packed;
+
+/* PCI BAR 0: Flexcard configuration */
+struct fc_bar0_conf {
+	__u32 r1;			/* 000 */
+	struct fc_version fc_fw_ver;	/* 004 */
+	struct fc_version fc_hw_ver;	/* 008 */
+	__u32 r2[3];			/* 00c */
+	__u64 fc_sn;			/* 018 */
+	__u32 fc_uid;			/* 020 */
+	__u32 r3[7];			/* 024 */
+	__u32 fc_lic[6];		/* 040 */
+	__u32 fc_slic[6];		/* 058 */
+	__u32 trig_ctrl1;		/* 070 */
+	__u32 r4;			/* 074 */
+	__u32 trig_ctrl2;		/* 078 */
+	__u32 r5[22];			/* 07c */
+	__u32 amreg;			/* 0d4 */
+	__u32 tiny_stat;		/* 0d8 */
+	__u32 r6[5];			/* 0dc */
+	__u32 can_dat_cnt;		/* 0f0 */
+	__u32 can_err_cnt;		/* 0f4 */
+	__u32 fc_data_cnt;		/* 0f8 */
+	__u32 r7;			/* 0fc */
+	__u32 fc_rocr;			/* 100 */
+	__u32 r8;			/* 104 */
+	__u32 pg_ctrl;			/* 108 */
+	__u32 pg_term;			/* 10c */
+	__u32 r9;			/* 110 */
+	__u32 irs;			/* 114 */
+	__u32 fr_tx_cnt;		/* 118 */
+	__u32 irc;			/* 11c */
+	__u64 pcnt;			/* 120 */
+	__u32 r10;			/* 128 */
+	__u32 nmv_cnt;			/* 12c */
+	__u32 info_cnt;			/* 130 */
+	__u32 stat_trg_cnt;		/* 134 */
+	__u32 r11;			/* 138 */
+	__u32 fr_rx_cnt;		/* 13c */
+} __packed;
+
+#endif /* _UAPI_LINUX_FLEXCARD_H */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 02/12] mfd: flexcard: add flexcard misc mfd-cell
  2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
  2016-12-14  0:11 ` [PATCH 01/12] mfd: Eberspaecher Flexcard PMC II Carrier Board support Holger Dengler
@ 2016-12-14  0:11 ` Holger Dengler
  2016-12-14  0:11 ` [PATCH 03/12] mfd: flexcard: add posix clock mfd-cell Holger Dengler
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  0:11 UTC (permalink / raw)
  To: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul
  Cc: linux-kernel, dmaengine, Thomas Gleixner, Sebastian Siewior,
	Juergen Bubeck, Peter Mahler, Holger Dengler, Benedikt Spranger

The Flexcard PCI BAR0 contain registers for configuration and
informational purpose. Add an appropriate MFD-cell for these registers.

Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
Signed-off-by: Holger Dengler <dengler@linutronix.de>
cc: Lee Jones <lee.jones@linaro.org>
---
 drivers/mfd/flexcard_core.c  | 58 +++++++++++++++++++++++++++++++++++++++++++-
 include/linux/mfd/flexcard.h |  1 +
 2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/flexcard_core.c b/drivers/mfd/flexcard_core.c
index e580971..2ee9089 100644
--- a/drivers/mfd/flexcard_core.c
+++ b/drivers/mfd/flexcard_core.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -25,11 +26,48 @@
 #define FLEXCARD_FR_OFFSET	0x4000
 #define FLEXCARD_FR_SIZE	0x2000
 
+#define FLEXCARD_CONF_START	0x000
+#define FLEXCARD_CONF_SIZE	0x13F
+#define FLEXCARD_NF_START	0x170
+#define FLEXCARD_NF_SIZE	0x7
+
+static DEFINE_IDA(flexcard_ida);
+
+static struct resource flexcard_misc_res[] = {
+	DEFINE_RES_MEM_NAMED(FLEXCARD_CONF_START,
+			     FLEXCARD_CONF_SIZE,
+			     "flexcard-conf"),
+	DEFINE_RES_MEM_NAMED(FLEXCARD_NF_START,
+			     FLEXCARD_NF_SIZE,
+			     "flexcard-nf"),
+};
+
+static struct mfd_cell flexcard_misc_dev[] = {
+	{
+		.name = "flexcard-misc",
+		.num_resources = ARRAY_SIZE(flexcard_misc_res),
+		.resources = flexcard_misc_res,
+	},
+};
+
 enum flexcard_cell_id {
 	FLEXCARD_CELL_CAN,
 	FLEXCARD_CELL_FLEXRAY,
 };
 
+static int flexcard_misc_setup(struct flexcard_device *priv)
+{
+	struct pci_dev *pdev = priv->pdev;
+
+	flexcard_misc_dev[0].id = priv->cardnr;
+	flexcard_misc_res[0].parent = &pdev->resource[0];
+	flexcard_misc_res[1].parent = &pdev->resource[0];
+
+	return mfd_add_devices(&pdev->dev, 0, flexcard_misc_dev,
+			       ARRAY_SIZE(flexcard_misc_dev),
+			       &pdev->resource[0], 0, NULL);
+}
+
 static int flexcard_tiny_can(struct flexcard_device *priv,
 			     int idx, int id, u32 offset)
 {
@@ -163,10 +201,23 @@ static int flexcard_probe(struct pci_dev *pdev,
 	fw_ver.reg = readl(&priv->bar0->conf.fc_fw_ver);
 	hw_ver.reg = readl(&priv->bar0->conf.fc_hw_ver);
 
+	ret = ida_simple_get(&flexcard_ida, 0, 0, GFP_KERNEL);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "could not get new Flexcard id:%d\n", ret);
+		goto out_unmap;
+	}
+	priv->cardnr = ret;
+
 	ret = flexcard_tiny_probe(priv);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to probe tinys: %d", ret);
-		goto out_unmap;
+		goto out_ida;
+	}
+
+	ret = flexcard_misc_setup(priv);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to probe tinys: %d", ret);
+		goto out_mfd_dev_remove;
 	}
 
 	dev_info(&pdev->dev, "HW %02x.%02x.%02x FW %02x.%02x.%02x\n",
@@ -175,6 +226,10 @@ static int flexcard_probe(struct pci_dev *pdev,
 
 	return 0;
 
+out_mfd_dev_remove:
+	mfd_remove_devices(&pdev->dev);
+out_ida:
+	ida_simple_remove(&flexcard_ida, priv->cardnr);
 out_unmap:
 	iounmap(priv->bar0);
 out_release:
@@ -190,6 +245,7 @@ static void flexcard_remove(struct pci_dev *pdev)
 	struct flexcard_device *priv = pci_get_drvdata(pdev);
 
 	mfd_remove_devices(&pdev->dev);
+	ida_simple_remove(&flexcard_ida, priv->cardnr);
 	iounmap(priv->bar0);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
diff --git a/include/linux/mfd/flexcard.h b/include/linux/mfd/flexcard.h
index 362b909..4116305 100644
--- a/include/linux/mfd/flexcard.h
+++ b/include/linux/mfd/flexcard.h
@@ -94,6 +94,7 @@ struct fc_bar0 {
 } __packed;
 
 struct flexcard_device {
+	unsigned int cardnr;
 	struct pci_dev *pdev;
 	struct fc_bar0 __iomem *bar0;
 	struct mfd_cell *cells;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 03/12] mfd: flexcard: add posix clock mfd-cell
  2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
  2016-12-14  0:11 ` [PATCH 01/12] mfd: Eberspaecher Flexcard PMC II Carrier Board support Holger Dengler
  2016-12-14  0:11 ` [PATCH 02/12] mfd: flexcard: add flexcard misc mfd-cell Holger Dengler
@ 2016-12-14  0:11 ` Holger Dengler
  2016-12-14  0:11 ` [PATCH 04/12] mfd: flexcard: add interrupt support Holger Dengler
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  0:11 UTC (permalink / raw)
  To: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul
  Cc: linux-kernel, dmaengine, Thomas Gleixner, Sebastian Siewior,
	Juergen Bubeck, Peter Mahler, Holger Dengler, Benedikt Spranger

The Flexcard offers a Flexray network synchronized counter with a
selectable resolution of 1us, 100ns or 10ns. Add an appropriate MFD-cell
to use the counter.

Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
Signed-off-by: Holger Dengler <dengler@linutronix.de>
cc: Lee Jones <lee.jones@linaro.org>
---
 drivers/mfd/flexcard_core.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/drivers/mfd/flexcard_core.c b/drivers/mfd/flexcard_core.c
index 2ee9089..73eb726 100644
--- a/drivers/mfd/flexcard_core.c
+++ b/drivers/mfd/flexcard_core.c
@@ -28,11 +28,32 @@
 
 #define FLEXCARD_CONF_START	0x000
 #define FLEXCARD_CONF_SIZE	0x13F
+#define FLEXCARD_CLKRST_START	0x144
+#define FLEXCARD_CLKRST_SIZE	0x3
 #define FLEXCARD_NF_START	0x170
 #define FLEXCARD_NF_SIZE	0x7
+#define FLEXCARD_CLK_START	0x700
+#define FLEXCARD_CLK_SIZE	0x13
 
 static DEFINE_IDA(flexcard_ida);
 
+static struct resource flexcard_clk_res[] = {
+	DEFINE_RES_MEM_NAMED(FLEXCARD_CLK_START,
+			     FLEXCARD_CLK_SIZE,
+			     "flexcard-clock"),
+	DEFINE_RES_MEM_NAMED(FLEXCARD_CLKRST_START,
+			     FLEXCARD_CLKRST_SIZE,
+			     "flexcard-clock-reset"),
+};
+
+static struct mfd_cell flexcard_clk_dev[] = {
+	{
+		.name = "flexcard-clock",
+		.num_resources = ARRAY_SIZE(flexcard_clk_res),
+		.resources = flexcard_clk_res,
+	},
+};
+
 static struct resource flexcard_misc_res[] = {
 	DEFINE_RES_MEM_NAMED(FLEXCARD_CONF_START,
 			     FLEXCARD_CONF_SIZE,
@@ -55,6 +76,19 @@ enum flexcard_cell_id {
 	FLEXCARD_CELL_FLEXRAY,
 };
 
+static int flexcard_clk_setup(struct flexcard_device *priv)
+{
+	struct pci_dev *pdev = priv->pdev;
+
+	flexcard_clk_dev[0].id = priv->cardnr;
+	flexcard_clk_res[0].parent = &pdev->resource[0];
+	flexcard_clk_res[1].parent = &pdev->resource[0];
+
+	return mfd_add_devices(&pdev->dev, 0, flexcard_clk_dev,
+			       ARRAY_SIZE(flexcard_clk_dev),
+			       &pdev->resource[0], 0, NULL);
+}
+
 static int flexcard_misc_setup(struct flexcard_device *priv)
 {
 	struct pci_dev *pdev = priv->pdev;
@@ -220,6 +254,12 @@ static int flexcard_probe(struct pci_dev *pdev,
 		goto out_mfd_dev_remove;
 	}
 
+	ret = flexcard_clk_setup(priv);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to register clksrc: %d\n", ret);
+		goto out_mfd_dev_remove;
+	}
+
 	dev_info(&pdev->dev, "HW %02x.%02x.%02x FW %02x.%02x.%02x\n",
 		 hw_ver.ver.maj, hw_ver.ver.min, hw_ver.ver.dev,
 		 fw_ver.ver.maj, fw_ver.ver.min, fw_ver.ver.dev);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 04/12] mfd: flexcard: add interrupt support
  2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
                   ` (2 preceding siblings ...)
  2016-12-14  0:11 ` [PATCH 03/12] mfd: flexcard: add posix clock mfd-cell Holger Dengler
@ 2016-12-14  0:11 ` Holger Dengler
  2016-12-14  2:47   ` kbuild test robot
  2016-12-14  3:37   ` kbuild test robot
  2016-12-14  0:11 ` [PATCH 05/12] mfd: flexcard: add DMA interrupts Holger Dengler
                   ` (8 subsequent siblings)
  12 siblings, 2 replies; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  0:11 UTC (permalink / raw)
  To: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul
  Cc: linux-kernel, dmaengine, Thomas Gleixner, Sebastian Siewior,
	Juergen Bubeck, Peter Mahler, Holger Dengler, Benedikt Spranger

The Flexcard comprise an interrupt controller for the attached
tinys, timer, a Flexray related trigger and a second one for DMA.
Both controllers share a single IRQ line.

Add an interrupt domain for the non-DMA interrupts.

Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
Signed-off-by: Holger Dengler <dengler@linutronix.de>
cc: Lee Jones <lee.jones@linaro.org>
---
 drivers/mfd/Kconfig          |   1 +
 drivers/mfd/Makefile         |   1 +
 drivers/mfd/flexcard_core.c  |  14 ++-
 drivers/mfd/flexcard_irq.c   | 238 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/flexcard.h |   6 ++
 5 files changed, 258 insertions(+), 2 deletions(-)
 create mode 100644 drivers/mfd/flexcard_irq.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index a5a12da..85fedf6 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -302,6 +302,7 @@ config MFD_EXYNOS_LPASS
 config MFD_FLEXCARD
 	tristate "Eberspaecher Flexcard PMC II Carrier Board"
 	select MFD_CORE
+	select IRQ_DOMAIN
 	depends on PCI
 	help
 	  This is the core driver for the Eberspaecher Flexcard
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 843e57c..7d9feb4 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -212,4 +212,5 @@ obj-$(CONFIG_MFD_MT6397)	+= mt6397-core.o
 
 obj-$(CONFIG_MFD_ALTERA_A10SR)	+= altera-a10sr.o
 flexcard-objs			:= flexcard_core.o
+flexcard-objs			:= flexcard_core.o flexcard_irq.o
 obj-$(CONFIG_MFD_FLEXCARD)	+= flexcard.o
diff --git a/drivers/mfd/flexcard_core.c b/drivers/mfd/flexcard_core.c
index 73eb726..b7aead5 100644
--- a/drivers/mfd/flexcard_core.c
+++ b/drivers/mfd/flexcard_core.c
@@ -192,7 +192,8 @@ static int flexcard_tiny_probe(struct flexcard_device *priv)
 		offset += FLEXCARD_CAN_OFFSET;
 	}
 
-	return mfd_add_devices(&pdev->dev, 0, priv->cells, nr, NULL, 0, NULL);
+	return mfd_add_devices(&pdev->dev, 0, priv->cells, nr, NULL,
+			       0, priv->irq_domain);
 }
 
 static int flexcard_probe(struct pci_dev *pdev,
@@ -242,10 +243,16 @@ static int flexcard_probe(struct pci_dev *pdev,
 	}
 	priv->cardnr = ret;
 
+	ret = flexcard_setup_irq(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to setup irq controller: %d", ret);
+		goto out_ida;
+	}
+
 	ret = flexcard_tiny_probe(priv);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to probe tinys: %d", ret);
-		goto out_ida;
+		goto out_remove_irq;
 	}
 
 	ret = flexcard_misc_setup(priv);
@@ -268,6 +275,8 @@ static int flexcard_probe(struct pci_dev *pdev,
 
 out_mfd_dev_remove:
 	mfd_remove_devices(&pdev->dev);
+out_remove_irq:
+	flexcard_remove_irq(pdev);
 out_ida:
 	ida_simple_remove(&flexcard_ida, priv->cardnr);
 out_unmap:
@@ -285,6 +294,7 @@ static void flexcard_remove(struct pci_dev *pdev)
 	struct flexcard_device *priv = pci_get_drvdata(pdev);
 
 	mfd_remove_devices(&pdev->dev);
+	flexcard_remove_irq(pdev);
 	ida_simple_remove(&flexcard_ida, priv->cardnr);
 	iounmap(priv->bar0);
 	pci_release_regions(pdev);
diff --git a/drivers/mfd/flexcard_irq.c b/drivers/mfd/flexcard_irq.c
new file mode 100644
index 0000000..fa2063f
--- /dev/null
+++ b/drivers/mfd/flexcard_irq.c
@@ -0,0 +1,238 @@
+/*
+ * Eberspächer Flexcard PMC II Carrier Board PCI Driver - Interrupt controller
+ *
+ * Copyright (c) 2014 - 2016, Linutronix GmbH
+ * Author: Benedikt Spranger <b.spranger@linutronix.de>
+ *         Holger Dengler <dengler@linutronix.de>
+ *
+ * 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 <linux/export.h>
+#include <linux/flexcard.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/pci.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/flexcard.h>
+
+struct fc_irq_tab {
+	u32 mskcache;
+	u32 mskoffs;
+	u32 msk;
+	u32 ackoffs;
+	u32 ack;
+};
+
+#define to_irq_tab_ack(statbit, cofs, mskofs, mskbit, ackofs, ackbit)	\
+	[statbit] = {							\
+			.mskcache	= cofs,				\
+			.mskoffs	= mskofs,			\
+			.msk		= (1U << mskbit),		\
+			.ackoffs	= ackofs,			\
+			.ack		= (1U << ackbit) }
+
+#define to_irq_tab(statbit, cofs, mskofs, mskbit)			\
+	[statbit] = {							\
+			.mskcache	= cofs,				\
+			.mskoffs	= mskofs,			\
+			.msk		= (1U << mskbit) }
+
+#define DEVMSK_OFFS	offsetof(struct fc_bar0, conf.irc)
+#define DEVACK_OFFS	offsetof(struct fc_bar0, conf.irs)
+#define DEVMSK_CACHE	offsetof(struct flexcard_device, dev_irqmsk)
+
+#define dev_to_irq_tab_ack(s, m, a)				\
+		to_irq_tab_ack(s, DEVMSK_CACHE, DEVMSK_OFFS, m,	\
+			       DEVACK_OFFS, a)
+
+#define dev_to_irq_tab(s, m)				\
+		to_irq_tab(s, DEVMSK_CACHE, DEVMSK_OFFS, m)
+
+static const struct fc_irq_tab flexcard_irq_tab[] = {
+	/* Device Interrupts */
+	dev_to_irq_tab_ack(28, 28, 0),	/* TIMER  */
+	dev_to_irq_tab_ack(29, 29, 1),	/* CC1CYS */
+	dev_to_irq_tab_ack(21, 30, 10),	/* CC2CYS */
+	dev_to_irq_tab_ack(30, 18, 2),	/* CC3CYS */
+	dev_to_irq_tab_ack(25, 19, 6),	/* CC4CYS */
+	dev_to_irq_tab_ack(26, 26, 4),	/* WAKE1A */
+	dev_to_irq_tab_ack(27, 27, 5),	/* WAKE1B */
+	dev_to_irq_tab_ack(23, 24, 8),	/* WAKE2A */
+	dev_to_irq_tab_ack(22, 25, 9),	/* WAKE2B */
+	dev_to_irq_tab_ack(19, 22, 12),	/* WAKE3A */
+	dev_to_irq_tab_ack(18, 23, 13),	/* WAKE3B */
+	dev_to_irq_tab_ack(17, 20, 14),	/* WAKE4A */
+	dev_to_irq_tab_ack(16, 21, 15),	/* WAKE4B */
+	dev_to_irq_tab(31, 15),		/* CC1T0  */
+	dev_to_irq_tab(3, 14),		/* CC2T0  */
+	dev_to_irq_tab(24, 16),		/* CC3T0  */
+	dev_to_irq_tab(20, 17),		/* CC4T0  */
+};
+
+#define NR_FLEXCARD_IRQ		ARRAY_SIZE(flexcard_irq_tab)
+
+#define VALID_DEVIRQ_MSK	((1U << 28) | \
+				 (1U << 29) | \
+				 (1U << 21) | \
+				 (1U << 30) | \
+				 (1U << 25) | \
+				 (1U << 26) | \
+				 (1U << 27) | \
+				 (1U << 23) | \
+				 (1U << 22) | \
+				 (1U << 19) | \
+				 (1U << 18) | \
+				 (1U << 17) | \
+				 (1U << 16) | \
+				 (1U << 31) | \
+				 (1U << 3)  | \
+				 (1U << 24) | \
+				 (1U << 20))
+
+static irqreturn_t flexcard_demux(int irq, void *data)
+{
+	struct flexcard_device *priv = data;
+	irqreturn_t ret = IRQ_NONE;
+	unsigned int slot, cur, stat;
+
+	stat = readl(&priv->bar0->conf.irs) & VALID_DEVIRQ_MSK;
+	while (stat) {
+		slot = __ffs(stat);
+		stat &= (1 << slot);
+		cur = irq_linear_revmap(priv->irq_domain, slot);
+		generic_handle_irq(cur);
+		ret = IRQ_HANDLED;
+	}
+	return ret;
+}
+
+static void flexcard_irq_ack(struct irq_data *d)
+{
+	struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
+	const struct fc_irq_tab *tp = &flexcard_irq_tab[d->hwirq];
+	void __iomem *p = (void __iomem *)priv->bar0 + tp->ackoffs;
+
+	writel(tp->ack, p);
+}
+
+static void flexcard_irq_mask(struct irq_data *d)
+{
+	struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
+	const struct fc_irq_tab *tp = &flexcard_irq_tab[d->hwirq];
+	void __iomem *p = (void __iomem *)priv->bar0 + tp->mskoffs;
+	u32 *msk = (void *)priv + tp->mskcache;
+
+	raw_spin_lock(&priv->irq_lock);
+	*msk &= ~tp->msk;
+	writel(*msk, p);
+	raw_spin_unlock(&priv->irq_lock);
+}
+
+static void flexcard_irq_unmask(struct irq_data *d)
+{
+	struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
+	const struct fc_irq_tab *tp = &flexcard_irq_tab[d->hwirq];
+	void __iomem *p = (void __iomem *)priv->bar0 + tp->mskoffs;
+	u32 *msk = (void *)priv + tp->mskcache;
+
+	raw_spin_lock(&priv->irq_lock);
+	*msk |= tp->msk;
+	writel(*msk, p);
+	raw_spin_unlock(&priv->irq_lock);
+}
+
+static int flexcard_req_irq(struct pci_dev *pdev)
+{
+	struct flexcard_device *priv = pci_get_drvdata(pdev);
+	int ret;
+
+	ret = pci_enable_msi(pdev);
+	if (ret) {
+		dev_warn(&pdev->dev, "could not enable MSI\n");
+		/* shared PCI irq fallback */
+		return request_irq(pdev->irq, flexcard_demux,
+				   IRQF_NO_THREAD | IRQF_SHARED,
+				   "flexcard", priv);
+	}
+	dev_info(&pdev->dev, "MSI enabled\n");
+
+	ret = request_irq(pdev->irq, flexcard_demux, IRQF_NO_THREAD,
+			  "flexcard", priv);
+	if (ret)
+		pci_disable_msi(pdev);
+
+	return ret;
+}
+
+static struct irq_chip flexcard_irq_chip = {
+	.name		= "flexcard_irq",
+	.irq_ack	= flexcard_irq_ack,
+	.irq_mask	= flexcard_irq_mask,
+	.irq_unmask	= flexcard_irq_unmask,
+};
+
+static int flexcard_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				   irq_hw_number_t hw)
+{
+	struct flexcard_device *priv = d->host_data;
+
+	irq_set_chip_and_handler_name(irq, &flexcard_irq_chip,
+				      handle_level_irq, "flexcard");
+	irq_set_chip_data(irq, priv);
+	irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
+
+	return 0;
+}
+
+static const struct irq_domain_ops flexcard_irq_domain_ops = {
+	.map = flexcard_irq_domain_map,
+};
+
+int flexcard_setup_irq(struct pci_dev *pdev)
+{
+	struct flexcard_device *priv = pci_get_drvdata(pdev);
+	struct irq_domain *domain;
+	int ret;
+
+	/* Make sure none of the subirqs is enabled */
+	writel(0, &priv->bar0->conf.irc);
+	writel(0, &priv->bar0->dma.dma_irer);
+
+	raw_spin_lock_init(&priv->irq_lock);
+
+	domain = irq_domain_add_linear(NULL, NR_FLEXCARD_IRQ,
+				       &flexcard_irq_domain_ops, priv);
+	if (!domain) {
+		dev_err(&pdev->dev, "could not request irq domain\n");
+		return -ENODEV;
+	}
+
+	priv->irq_domain = domain;
+
+	ret = flexcard_req_irq(pdev);
+	if (ret)
+		irq_domain_remove(priv->irq_domain);
+
+	return ret;
+}
+
+void flexcard_remove_irq(struct pci_dev *pdev)
+{
+	struct flexcard_device *priv = pci_get_drvdata(pdev);
+
+	/* Disable all subirqs */
+	writel(0, &priv->bar0->conf.irc);
+	writel(0, &priv->bar0->dma.dma_irer);
+
+	free_irq(pdev->irq, priv);
+	pci_disable_msi(pdev);
+	irq_domain_remove(priv->irq_domain);
+}
diff --git a/include/linux/mfd/flexcard.h b/include/linux/mfd/flexcard.h
index 4116305..6cb8ad0 100644
--- a/include/linux/mfd/flexcard.h
+++ b/include/linux/mfd/flexcard.h
@@ -96,9 +96,15 @@ struct fc_bar0 {
 struct flexcard_device {
 	unsigned int cardnr;
 	struct pci_dev *pdev;
+	raw_spinlock_t irq_lock;
+	struct irq_domain *irq_domain;
 	struct fc_bar0 __iomem *bar0;
 	struct mfd_cell *cells;
 	struct resource *res;
+	u32 dev_irqmsk;
 };
 
+int flexcard_setup_irq(struct pci_dev *pdev);
+void flexcard_remove_irq(struct pci_dev *pdev);
+
 #endif /* _LINUX_FLEXCARD_H */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 05/12] mfd: flexcard: add DMA interrupts
  2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
                   ` (3 preceding siblings ...)
  2016-12-14  0:11 ` [PATCH 04/12] mfd: flexcard: add interrupt support Holger Dengler
@ 2016-12-14  0:11 ` Holger Dengler
  2016-12-14  3:08   ` kbuild test robot
  2016-12-14  0:11 ` [PATCH 06/12] mfd: flexcard: add DMA device Holger Dengler
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  0:11 UTC (permalink / raw)
  To: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul
  Cc: linux-kernel, dmaengine, Thomas Gleixner, Sebastian Siewior,
	Juergen Bubeck, Peter Mahler, Holger Dengler, Benedikt Spranger

The Flexcard comprise an interrupt controller for the attached
tinys, timer, a Flexray related trigger and a second one for DMA.
Both controllers share a single IRQ line.

Add the DMA Controller interrupts.

Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
Signed-off-by: Holger Dengler <dengler@linutronix.de>
cc: Lee Jones <lee.jones@linaro.org>
---
 drivers/mfd/flexcard_irq.c   | 71 ++++++++++++++++++++++++++++++++++++++++++--
 include/linux/mfd/flexcard.h |  2 ++
 2 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/flexcard_irq.c b/drivers/mfd/flexcard_irq.c
index fa2063f..15acd18 100644
--- a/drivers/mfd/flexcard_irq.c
+++ b/drivers/mfd/flexcard_irq.c
@@ -23,6 +23,12 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/flexcard.h>
 
+/*
+ * Bit 31 in dma interrupt register:
+ * DMA interrupt enable. Must be 1 to enable the DMA interrupts
+ */
+#define FLEXCARD_DMA_IRER_DIRE		(1U << 31)
+
 struct fc_irq_tab {
 	u32 mskcache;
 	u32 mskoffs;
@@ -49,6 +55,10 @@ struct fc_irq_tab {
 #define DEVACK_OFFS	offsetof(struct fc_bar0, conf.irs)
 #define DEVMSK_CACHE	offsetof(struct flexcard_device, dev_irqmsk)
 
+#define DMAMSK_OFFS	offsetof(struct fc_bar0, dma.dma_irer)
+#define DMAACK_OFFS	offsetof(struct fc_bar0, dma.dma_irsr)
+#define DMAMSK_CACHE	offsetof(struct flexcard_device, dma_irqmsk)
+
 #define dev_to_irq_tab_ack(s, m, a)				\
 		to_irq_tab_ack(s, DEVMSK_CACHE, DEVMSK_OFFS, m,	\
 			       DEVACK_OFFS, a)
@@ -56,6 +66,10 @@ struct fc_irq_tab {
 #define dev_to_irq_tab(s, m)				\
 		to_irq_tab(s, DEVMSK_CACHE, DEVMSK_OFFS, m)
 
+#define dma_to_irq_tab_ack(s, m, a)				\
+		to_irq_tab_ack(s, DMAMSK_CACHE, DMAMSK_OFFS, m,	\
+			       DMAACK_OFFS, a)
+
 static const struct fc_irq_tab flexcard_irq_tab[] = {
 	/* Device Interrupts */
 	dev_to_irq_tab_ack(28, 28, 0),	/* TIMER  */
@@ -75,6 +89,11 @@ static const struct fc_irq_tab flexcard_irq_tab[] = {
 	dev_to_irq_tab(3, 14),		/* CC2T0  */
 	dev_to_irq_tab(24, 16),		/* CC3T0  */
 	dev_to_irq_tab(20, 17),		/* CC4T0  */
+	/* DMA Interrupts */
+	dma_to_irq_tab_ack(0, 0, 0),	/* DMA_C0 */
+	dma_to_irq_tab_ack(1, 1, 1),	/* DMA_TE */
+	dma_to_irq_tab_ack(4, 4, 4),	/* DMA_TI */
+	dma_to_irq_tab_ack(5, 5, 5),	/* DMA_CBL */
 };
 
 #define NR_FLEXCARD_IRQ		ARRAY_SIZE(flexcard_irq_tab)
@@ -96,6 +115,10 @@ static const struct fc_irq_tab flexcard_irq_tab[] = {
 				 (1U << 3)  | \
 				 (1U << 24) | \
 				 (1U << 20))
+#define VALID_DMAIRQ_MSK	((1U << 0) | \
+				 (1U << 1) | \
+				 (1U << 4) | \
+				 (1U << 5))
 
 static irqreturn_t flexcard_demux(int irq, void *data)
 {
@@ -104,6 +127,7 @@ static irqreturn_t flexcard_demux(int irq, void *data)
 	unsigned int slot, cur, stat;
 
 	stat = readl(&priv->bar0->conf.irs) & VALID_DEVIRQ_MSK;
+	stat |= readl(&priv->bar0->dma.dma_irsr) & VALID_DMAIRQ_MSK;
 	while (stat) {
 		slot = __ffs(stat);
 		stat &= (1 << slot);
@@ -196,6 +220,30 @@ static const struct irq_domain_ops flexcard_irq_domain_ops = {
 	.map = flexcard_irq_domain_map,
 };
 
+static struct irq_chip flexcard_dma_irq_chip = {
+	.name		= "flexcard_dma_irq",
+	.irq_ack	= flexcard_irq_ack,
+	.irq_mask	= flexcard_irq_mask,
+	.irq_unmask	= flexcard_irq_unmask,
+};
+
+static int flexcard_dma_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				       irq_hw_number_t hw)
+{
+	struct flexcard_device *priv = d->host_data;
+
+	irq_set_chip_and_handler_name(irq, &flexcard_dma_irq_chip,
+				      handle_level_irq, "flexcard-dma");
+	irq_set_chip_data(irq, priv);
+	irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
+
+	return 0;
+}
+
+static const struct irq_domain_ops flexcard_dma_irq_domain_ops = {
+	.map = flexcard_dma_irq_domain_map,
+};
+
 int flexcard_setup_irq(struct pci_dev *pdev)
 {
 	struct flexcard_device *priv = pci_get_drvdata(pdev);
@@ -217,9 +265,27 @@ int flexcard_setup_irq(struct pci_dev *pdev)
 
 	priv->irq_domain = domain;
 
+	domain = irq_domain_add_linear(NULL, NR_FLEXCARD_IRQ,
+				       &flexcard_dma_irq_domain_ops, priv);
+	if (!domain) {
+		dev_err(&pdev->dev, "could not request dma irq domain\n");
+		ret = -ENODEV;
+		goto out_irq;
+	}
+	priv->dma_domain = domain;
+
+	/* DMA IRQs must be device-globally enabled by setting bit 31 to 1 */
+	writel(FLEXCARD_DMA_IRER_DIRE, &priv->bar0->dma.dma_irer);
+
 	ret = flexcard_req_irq(pdev);
 	if (ret)
-		irq_domain_remove(priv->irq_domain);
+		goto out_dma;
+
+	return 0;
+out_dma:
+	irq_domain_remove(priv->dma_domain);
+out_irq:
+	irq_domain_remove(priv->irq_domain);
 
 	return ret;
 }
@@ -228,11 +294,12 @@ void flexcard_remove_irq(struct pci_dev *pdev)
 {
 	struct flexcard_device *priv = pci_get_drvdata(pdev);
 
-	/* Disable all subirqs */
+	/* Disable all subirqs (including global DMA-IRQ bit 31) */
 	writel(0, &priv->bar0->conf.irc);
 	writel(0, &priv->bar0->dma.dma_irer);
 
 	free_irq(pdev->irq, priv);
 	pci_disable_msi(pdev);
+	irq_domain_remove(priv->dma_domain);
 	irq_domain_remove(priv->irq_domain);
 }
diff --git a/include/linux/mfd/flexcard.h b/include/linux/mfd/flexcard.h
index 6cb8ad0..819c6ef 100644
--- a/include/linux/mfd/flexcard.h
+++ b/include/linux/mfd/flexcard.h
@@ -98,10 +98,12 @@ struct flexcard_device {
 	struct pci_dev *pdev;
 	raw_spinlock_t irq_lock;
 	struct irq_domain *irq_domain;
+	struct irq_domain *dma_domain;
 	struct fc_bar0 __iomem *bar0;
 	struct mfd_cell *cells;
 	struct resource *res;
 	u32 dev_irqmsk;
+	u32 dma_irqmsk;
 };
 
 int flexcard_setup_irq(struct pci_dev *pdev);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 06/12] mfd: flexcard: add DMA device
  2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
                   ` (4 preceding siblings ...)
  2016-12-14  0:11 ` [PATCH 05/12] mfd: flexcard: add DMA interrupts Holger Dengler
@ 2016-12-14  0:11 ` Holger Dengler
  2016-12-14  0:11 ` [PATCH 07/12] mfd: flexcard: add UIO IRQ devices Holger Dengler
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  0:11 UTC (permalink / raw)
  To: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul
  Cc: linux-kernel, dmaengine, Thomas Gleixner, Sebastian Siewior,
	Juergen Bubeck, Peter Mahler, Holger Dengler, Benedikt Spranger

The Flexcard interface design split packet receive and transmit. All
received packets and card status information are multiplexed with a
Flexcard specific protocol and handled through a DMA capable ringbuffer.
The TX path has to poke each available component separate.

Add a platform device for the DMA receive channel.

Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
Signed-off-by: Holger Dengler <dengler@linutronix.de>
cc: Lee Jones <lee.jones@linaro.org>
---
 drivers/mfd/flexcard_core.c | 67 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/drivers/mfd/flexcard_core.c b/drivers/mfd/flexcard_core.c
index b7aead5..55bcfec 100644
--- a/drivers/mfd/flexcard_core.c
+++ b/drivers/mfd/flexcard_core.c
@@ -32,11 +32,41 @@
 #define FLEXCARD_CLKRST_SIZE	0x3
 #define FLEXCARD_NF_START	0x170
 #define FLEXCARD_NF_SIZE	0x7
+#define FLEXCARD_DMA_START	0x500
+#define FLEXCARD_DMA_SIZE	0x80
 #define FLEXCARD_CLK_START	0x700
 #define FLEXCARD_CLK_SIZE	0x13
 
+#define FLEXCARD_DMA_IRQ_CO	0
+#define FLEXCARD_DMA_IRQ_TE	1
+#define FLEXCARD_DMA_IRQ_TI	2
+#define FLEXCARD_DMA_IRQ_CBL	3
+
+/* The first FW Version supporting DMA is 6.4.0 */
+#define DMA_MIN_FW_MAJOR	6
+#define DMA_MIN_FW_MINOR	4
+#define DMA_MIN_FW_UPDATE	0
+
 static DEFINE_IDA(flexcard_ida);
 
+static struct resource flexcard_dma_res[] = {
+	DEFINE_RES_MEM_NAMED(FLEXCARD_DMA_START,
+			     FLEXCARD_DMA_SIZE,
+			     "flexcard-dma"),
+	DEFINE_RES_IRQ_NAMED(FLEXCARD_DMA_IRQ_CBL,
+			     "flexcard-dma-cbl"),
+	DEFINE_RES_IRQ_NAMED(FLEXCARD_DMA_IRQ_CO,
+			     "flexcard-dma-co"),
+};
+
+static struct mfd_cell flexcard_dma_dev[] = {
+	{
+		.name = "flexcard-dma",
+		.num_resources = ARRAY_SIZE(flexcard_dma_res),
+		.resources = flexcard_dma_res,
+	},
+};
+
 static struct resource flexcard_clk_res[] = {
 	DEFINE_RES_MEM_NAMED(FLEXCARD_CLK_START,
 			     FLEXCARD_CLK_SIZE,
@@ -102,6 +132,37 @@ static int flexcard_misc_setup(struct flexcard_device *priv)
 			       &pdev->resource[0], 0, NULL);
 }
 
+static int flexcard_add_dma(struct flexcard_device *priv)
+{
+	struct pci_dev *pdev = priv->pdev;
+	union {
+		struct fc_version ver;
+		u32 reg;
+	} fw_ver;
+
+	/* check for a DMA capable firmware version*/
+	fw_ver.reg = readl(&priv->bar0->conf.fc_fw_ver);
+	if (fw_ver.ver.maj < DMA_MIN_FW_MAJOR)
+		goto out;
+
+	if (fw_ver.ver.maj == DMA_MIN_FW_MAJOR) {
+		if (fw_ver.ver.min < DMA_MIN_FW_MINOR)
+			goto out;
+		if ((fw_ver.ver.min == DMA_MIN_FW_MINOR) &&
+		    (fw_ver.ver.dev < DMA_MIN_FW_UPDATE))
+			goto out;
+	}
+
+	return mfd_add_devices(&pdev->dev, 0, flexcard_dma_dev,
+			       ARRAY_SIZE(flexcard_dma_dev),
+			       &pdev->resource[0], 0, priv->dma_domain);
+
+out:
+	dev_info(&pdev->dev, "Firmware is not DMA capable\n");
+
+	return 0;
+}
+
 static int flexcard_tiny_can(struct flexcard_device *priv,
 			     int idx, int id, u32 offset)
 {
@@ -267,6 +328,12 @@ static int flexcard_probe(struct pci_dev *pdev,
 		goto out_mfd_dev_remove;
 	}
 
+	ret = flexcard_add_dma(priv);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to add DMA device: %d", ret);
+		goto out_mfd_dev_remove;
+	}
+
 	dev_info(&pdev->dev, "HW %02x.%02x.%02x FW %02x.%02x.%02x\n",
 		 hw_ver.ver.maj, hw_ver.ver.min, hw_ver.ver.dev,
 		 fw_ver.ver.maj, fw_ver.ver.min, fw_ver.ver.dev);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 07/12] mfd: flexcard: add UIO IRQ devices
  2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
                   ` (5 preceding siblings ...)
  2016-12-14  0:11 ` [PATCH 06/12] mfd: flexcard: add DMA device Holger Dengler
@ 2016-12-14  0:11 ` Holger Dengler
  2016-12-14  0:11 ` [PATCH 08/12] misc: Flexcard misc device support Holger Dengler
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  0:11 UTC (permalink / raw)
  To: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul
  Cc: linux-kernel, dmaengine, Thomas Gleixner, Sebastian Siewior,
	Juergen Bubeck, Peter Mahler, Holger Dengler, Benedikt Spranger

Add an UIO device for each Flexcard Flexray related trigger. The trigger
devide into:
 - Flexray cycle start (CCYS)
 - Flexray timer 0 (CCxT0)
 - Bus wakeup (WAKE)

The UIO IRQ devices can be used to synchronize an application
with these events.

Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
Signed-off-by: Holger Dengler <dengler@linutronix.de>
cc: Lee Jones <lee.jones@linaro.org>
---
 drivers/mfd/flexcard_core.c | 85 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/drivers/mfd/flexcard_core.c b/drivers/mfd/flexcard_core.c
index 55bcfec..fc5b033 100644
--- a/drivers/mfd/flexcard_core.c
+++ b/drivers/mfd/flexcard_core.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
+#include <linux/uio_driver.h>
 
 #include <linux/mfd/core.h>
 #include <linux/mfd/flexcard.h>
@@ -47,6 +48,46 @@
 #define DMA_MIN_FW_MINOR	4
 #define DMA_MIN_FW_UPDATE	0
 
+#define FLEXCARD_IRQ_CC1CCYS_OFF	0
+#define FLEXCARD_IRQ_CC2CCYS_OFF	1
+#define FLEXCARD_IRQ_CC3CCYS_OFF	2
+#define FLEXCARD_IRQ_CC4CCYS_OFF	3
+#define FLEXCARD_IRQ_WAKE4A_OFF		4
+#define FLEXCARD_IRQ_WAKE4B_OFF		5
+#define FLEXCARD_IRQ_WAKE3A_OFF		6
+#define FLEXCARD_IRQ_WAKE3B_OFF		7
+#define FLEXCARD_IRQ_WAKE2A_OFF		8
+#define FLEXCARD_IRQ_WAKE2B_OFF		9
+#define FLEXCARD_IRQ_WAKE1A_OFF		10
+#define FLEXCARD_IRQ_WAKE1B_OFF		11
+#define FLEXCARD_IRQ_CC1T0_OFF		12
+#define FLEXCARD_IRQ_CC2T0_OFF		13
+#define FLEXCARD_IRQ_CC3T0_OFF		14
+#define FLEXCARD_IRQ_CC4T0_OFF		15
+
+#define flexcard_irq_resource(irq_name)					\
+	static struct resource flexcard_irq_res_##irq_name = {		\
+		.name = __stringify(fc_irq_##irq_name##_off),		\
+		.start  = FLEXCARD_IRQ_##irq_name##_OFF,		\
+		.end  = FLEXCARD_IRQ_##irq_name##_OFF,			\
+		.flags  = IORESOURCE_IRQ,				\
+	};								\
+									\
+	static struct uio_info flexcard_irq_pdata_##irq_name = {	\
+		.name   = __stringify(irq_name),			\
+		.version = "0",						\
+	}
+
+#define flexcard_irq_cell(irq_name, irq_id)				\
+	{								\
+		.id = irq_id,						\
+		.name = "uio_pdrv_genirq",				\
+		.platform_data = &flexcard_irq_pdata_##irq_name,	\
+		.pdata_size = sizeof(flexcard_irq_pdata_##irq_name),	\
+		.num_resources = 1,					\
+		.resources = &flexcard_irq_res_##irq_name		\
+	}
+
 static DEFINE_IDA(flexcard_ida);
 
 static struct resource flexcard_dma_res[] = {
@@ -163,6 +204,42 @@ static int flexcard_add_dma(struct flexcard_device *priv)
 	return 0;
 }
 
+flexcard_irq_resource(CC1CCYS);
+flexcard_irq_resource(CC2CCYS);
+flexcard_irq_resource(CC3CCYS);
+flexcard_irq_resource(CC4CCYS);
+flexcard_irq_resource(WAKE4A);
+flexcard_irq_resource(WAKE4B);
+flexcard_irq_resource(WAKE3A);
+flexcard_irq_resource(WAKE3B);
+flexcard_irq_resource(WAKE2A);
+flexcard_irq_resource(WAKE2B);
+flexcard_irq_resource(WAKE1A);
+flexcard_irq_resource(WAKE1B);
+flexcard_irq_resource(CC1T0);
+flexcard_irq_resource(CC2T0);
+flexcard_irq_resource(CC3T0);
+flexcard_irq_resource(CC4T0);
+
+static struct mfd_cell flexcard_uio_dev[] = {
+	flexcard_irq_cell(CC3CCYS, 0),
+	flexcard_irq_cell(CC4CCYS, 1),
+	flexcard_irq_cell(WAKE4A, 2),
+	flexcard_irq_cell(WAKE4B, 3),
+	flexcard_irq_cell(WAKE3A, 4),
+	flexcard_irq_cell(WAKE3B, 5),
+	flexcard_irq_cell(WAKE2A, 6),
+	flexcard_irq_cell(WAKE2B, 7),
+	flexcard_irq_cell(WAKE1A, 8),
+	flexcard_irq_cell(WAKE1B, 9),
+	flexcard_irq_cell(CC1CCYS, 10),
+	flexcard_irq_cell(CC2CCYS, 11),
+	flexcard_irq_cell(CC1T0, 12),
+	flexcard_irq_cell(CC2T0, 13),
+	flexcard_irq_cell(CC3T0, 14),
+	flexcard_irq_cell(CC4T0, 15),
+};
+
 static int flexcard_tiny_can(struct flexcard_device *priv,
 			     int idx, int id, u32 offset)
 {
@@ -334,6 +411,14 @@ static int flexcard_probe(struct pci_dev *pdev,
 		goto out_mfd_dev_remove;
 	}
 
+	ret = mfd_add_devices(&pdev->dev, 0, flexcard_uio_dev,
+			      ARRAY_SIZE(flexcard_uio_dev),
+			      NULL, 0, priv->irq_domain);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to add irq UIO devices: %d", ret);
+		goto out_mfd_dev_remove;
+	}
+
 	dev_info(&pdev->dev, "HW %02x.%02x.%02x FW %02x.%02x.%02x\n",
 		 hw_ver.ver.maj, hw_ver.ver.min, hw_ver.ver.dev,
 		 fw_ver.ver.maj, fw_ver.ver.min, fw_ver.ver.dev);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 08/12] misc: Flexcard misc device support
  2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
                   ` (6 preceding siblings ...)
  2016-12-14  0:11 ` [PATCH 07/12] mfd: flexcard: add UIO IRQ devices Holger Dengler
@ 2016-12-14  0:11 ` Holger Dengler
  2016-12-14  8:42   ` Arnd Bergmann
  2016-12-14  0:11 ` [PATCH 09/12] misc: flexcard: add device attributes Holger Dengler
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  0:11 UTC (permalink / raw)
  To: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul
  Cc: linux-kernel, dmaengine, Thomas Gleixner, Sebastian Siewior,
	Juergen Bubeck, Peter Mahler, Holger Dengler, Benedikt Spranger

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 <b.spranger@linutronix.de>
Signed-off-by: Holger Dengler <dengler@linutronix.de>
cc: Arnd Bergmann <arnd@arndb.de>
cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 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 <b.spranger@linutronix.de>
+ *         Holger Dengler <dengler@linutronix.de>
+ *
+ * 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 <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/kref.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+#include <linux/mfd/flexcard.h>
+
+#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 <dengler@linutronix.de>");
+MODULE_AUTHOR("Benedikt Spranger <b.spranger@linutronix.de>");
+MODULE_DESCRIPTION("Eberspaecher Flexcard PMC II Misc Driver");
+MODULE_LICENSE("GPL v2");
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 09/12] misc: flexcard: add device attributes
  2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
                   ` (7 preceding siblings ...)
  2016-12-14  0:11 ` [PATCH 08/12] misc: Flexcard misc device support Holger Dengler
@ 2016-12-14  0:11 ` Holger Dengler
  2016-12-14  1:33   ` kbuild test robot
  2017-01-10 16:58   ` Greg Kroah-Hartman
  2016-12-14  0:11 ` [PATCH 10/12] misc: Flexcard basic timestamp counter support Holger Dengler
                   ` (3 subsequent siblings)
  12 siblings, 2 replies; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  0:11 UTC (permalink / raw)
  To: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul
  Cc: linux-kernel, dmaengine, Thomas Gleixner, Sebastian Siewior,
	Juergen Bubeck, Peter Mahler, Holger Dengler, Benedikt Spranger

Add device attributes for common flexcard information access. The
attribiutes are read-only execpt "uid" (user ID register).
The "uid" attribute can also be used to change the user-defined ID of a
Flexcard.

Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
Signed-off-by: Holger Dengler <dengler@linutronix.de>
cc: Arnd Bergmann <arnd@arndb.de>
cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/misc/flexcard_misc.c | 196 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 196 insertions(+)

diff --git a/drivers/misc/flexcard_misc.c b/drivers/misc/flexcard_misc.c
index 93c951c..2a5c006 100644
--- a/drivers/misc/flexcard_misc.c
+++ b/drivers/misc/flexcard_misc.c
@@ -31,6 +31,183 @@ struct flexcard_misc {
 	struct fc_bar0_nf __iomem	*nf;
 };
 
+static ssize_t fw_version_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+	union {
+		struct fc_version ver;
+		u32 reg;
+	} fw_ver;
+
+	fw_ver.reg = readl(&priv->conf->fc_fw_ver);
+	return sprintf(buf, "%02x.%02x.%02x\n",
+		       fw_ver.ver.maj, fw_ver.ver.min, fw_ver.ver.dev);
+}
+static DEVICE_ATTR_RO(fw_version);
+
+static ssize_t hw_version_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+	union {
+		struct fc_version ver;
+		u32 reg;
+	} hw_ver;
+
+	hw_ver.reg = readl(&priv->conf->fc_hw_ver);
+	return sprintf(buf, "%02x.%02x.%02x\n",
+		       hw_ver.ver.maj, hw_ver.ver.min, hw_ver.ver.dev);
+}
+static DEVICE_ATTR_RO(hw_version);
+
+static ssize_t serialno_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+	u64 fc_sn;
+
+	fc_sn = readq(&priv->conf->fc_sn);
+	return sprintf(buf, "%lld\n", fc_sn);
+}
+static DEVICE_ATTR_RO(serialno);
+
+static ssize_t tiny_stat_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "0x%x\n", readl(&priv->conf->tiny_stat));
+}
+static DEVICE_ATTR_RO(tiny_stat);
+
+static ssize_t can_dat_show(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", readl(&priv->conf->can_dat_cnt));
+}
+static DEVICE_ATTR_RO(can_dat);
+
+static ssize_t can_err_show(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", readl(&priv->conf->can_err_cnt));
+}
+static DEVICE_ATTR_RO(can_err);
+
+static ssize_t fc_data_show(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", readl(&priv->conf->fc_data_cnt));
+}
+static DEVICE_ATTR_RO(fc_data);
+
+static ssize_t fr_rx_show(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", readl(&priv->conf->fr_rx_cnt));
+}
+static DEVICE_ATTR_RO(fr_rx);
+
+static ssize_t fr_tx_show(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", readl(&priv->conf->fr_tx_cnt));
+}
+static DEVICE_ATTR_RO(fr_tx);
+
+static ssize_t nmv_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", readl(&priv->conf->nmv_cnt));
+}
+static DEVICE_ATTR_RO(nmv);
+
+static ssize_t info_show(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", readl(&priv->conf->info_cnt));
+}
+static DEVICE_ATTR_RO(info);
+
+static ssize_t stat_trg_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", readl(&priv->conf->stat_trg_cnt));
+}
+static DEVICE_ATTR_RO(stat_trg);
+
+static ssize_t nf_show(struct device *dev,
+		       struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", readl(&priv->nf->nf_cnt));
+}
+static DEVICE_ATTR_RO(nf);
+
+static ssize_t uid_store(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+	u32 uid;
+	int ret;
+
+	ret = kstrtou32(buf, 0, &uid);
+	if (ret)
+		return ret;
+
+	writel(uid, &priv->conf->fc_uid);
+	return count;
+}
+
+static ssize_t uid_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct flexcard_misc *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", readl(&priv->conf->fc_uid));
+}
+static DEVICE_ATTR(uid, 0644, uid_show, uid_store);
+
+static struct attribute *flexcard_misc_dev_attrs[] = {
+	&dev_attr_fw_version.attr,
+	&dev_attr_hw_version.attr,
+	&dev_attr_serialno.attr,
+	&dev_attr_tiny_stat.attr,
+	&dev_attr_can_dat.attr,
+	&dev_attr_can_err.attr,
+	&dev_attr_fc_data.attr,
+	&dev_attr_fr_rx.attr,
+	&dev_attr_fr_tx.attr,
+	&dev_attr_nmv.attr,
+	&dev_attr_info.attr,
+	&dev_attr_stat_trg.attr,
+	&dev_attr_nf.attr,
+	&dev_attr_uid.attr,
+	NULL,
+};
+
+static const struct attribute_group flexcard_misc_dev_group = {
+	.attrs = flexcard_misc_dev_attrs,
+};
+
 static int flexcard_misc_mmap(struct file *filp, struct vm_area_struct *vma)
 {
 	unsigned long offset, vsize, psize, addr;
@@ -109,6 +286,7 @@ static int flexcard_misc_iomap(struct platform_device *pdev)
 static int flexcard_misc_probe(struct platform_device *pdev)
 {
 	struct flexcard_misc *priv;
+	struct device *this_device;
 	int ret;
 
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -137,13 +315,31 @@ static int flexcard_misc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	this_device = priv->dev.this_device;
+	dev_set_drvdata(this_device, priv);
+
+	ret = sysfs_create_group(&this_device->kobj,
+				 &flexcard_misc_dev_group);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to create sysfs attributes: %d\n", ret);
+		goto out;
+	}
+
 	return 0;
+
+out:
+	misc_deregister(&priv->dev);
+	return ret;
 }
 
 static int flexcard_misc_remove(struct platform_device *pdev)
 {
 	struct flexcard_misc *priv = platform_get_drvdata(pdev);
+	struct device *this_device = priv->dev.this_device;
 
+	sysfs_remove_group(&this_device->kobj,
+			   &flexcard_misc_dev_group);
 	misc_deregister(&priv->dev);
 
 	return 0;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 10/12] misc: Flexcard basic timestamp counter support
  2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
                   ` (8 preceding siblings ...)
  2016-12-14  0:11 ` [PATCH 09/12] misc: flexcard: add device attributes Holger Dengler
@ 2016-12-14  0:11 ` Holger Dengler
  2016-12-14  3:28   ` kbuild test robot
  2016-12-14  8:46   ` Arnd Bergmann
  2016-12-14  0:11 ` [PATCH 11/12] misc: flexcard: Support timestamp trigger selection Holger Dengler
                   ` (2 subsequent siblings)
  12 siblings, 2 replies; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  0:11 UTC (permalink / raw)
  To: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul
  Cc: linux-kernel, dmaengine, Thomas Gleixner, Sebastian Siewior,
	Juergen Bubeck, Peter Mahler, Holger Dengler, Benedikt Spranger

The Eberspaecher Flexcard PMC II offers a Flexray network synchronized
counter with a selectable resolution of 1us, 100ns or 10ns. Add basic
support for the timestamp counter with 1us resolution, which is the
standard Flexray bus resolution.

Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
Signed-off-by: Holger Dengler <dengler@linutronix.de>
cc: Arnd Bergmann <arnd@arndb.de>
cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/mfd/Kconfig                |   1 +
 drivers/misc/Kconfig               |   9 ++
 drivers/misc/Makefile              |   1 +
 drivers/misc/flexcard_posixclock.c | 240 +++++++++++++++++++++++++++++++++++++
 4 files changed, 251 insertions(+)
 create mode 100644 drivers/misc/flexcard_posixclock.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 580f521..490b435 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -304,6 +304,7 @@ config MFD_FLEXCARD
 	select MFD_CORE
 	select IRQ_DOMAIN
 	select FLEXCARD_MISC
+	select FLEXCARD_PCLOCK
 	depends on PCI
 	help
 	  This is the core driver for the Eberspaecher Flexcard
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 3f54b58..658a6df 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -772,6 +772,15 @@ config FLEXCARD_MISC
 	help
 	  Misc driver for Flexcard PMC II.
 
+config FLEXCARD_PCLOCK
+	tristate "Flexcard posix clock Function driver"
+	depends on MFD_FLEXCARD
+	help
+	  This is the posix clock function driver for the
+	  Eberspaecher Flexcard PMC II carrier board. The
+	  Flexcard provide a Flexray synchronized counter
+	  configurable at 1, 10 or 100MHz.
+
 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 08a1729..df655bb 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_VEXPRESS_SYSCFG)	+= vexpress-syscfg.o
 obj-$(CONFIG_CXL_BASE)		+= cxl/
 obj-$(CONFIG_PANEL)             += panel.o
 obj-$(CONFIG_FLEXCARD_MISC)	+= flexcard_misc.o
+obj-$(CONFIG_FLEXCARD_PCLOCK)	+= flexcard_posixclock.o
 
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_core.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_bugs.o
diff --git a/drivers/misc/flexcard_posixclock.c b/drivers/misc/flexcard_posixclock.c
new file mode 100644
index 0000000..146f0f3
--- /dev/null
+++ b/drivers/misc/flexcard_posixclock.c
@@ -0,0 +1,240 @@
+/*
+ * Eberspächer Flexcard PMC II - posix clock driver
+ *
+ * Copyright (c) 2014 - 2016, Linutronix GmbH
+ * Author: Benedikt Spranger <b.spranger@linutronix.de>
+ *         Holger Dengler <dengler@linutronix.de>
+ *
+ * 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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/posix-clock.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/flexcard.h>
+
+#define MAX_CLOCKS   16
+#define CLKSEL_OFF   0x10
+
+#define FLEXCARD_RST_TS		0x8000
+
+#define FLEXCARD_CLK_1MHZ	0
+
+static dev_t flexcard_clk_devt;
+static struct class *flexcard_clk_class;
+
+struct flexcard_clk {
+	struct posix_clock	clock;
+	dev_t			devid;
+	struct device		*dev;
+	void __iomem		*ts64;
+	void __iomem		*reset;
+};
+
+static int flexcard_clk_getres(struct posix_clock *pc, struct timespec *tp)
+{
+	tp->tv_sec = 0;
+	tp->tv_nsec = 1000;
+
+	return 0;
+}
+
+static int flexcard_clk_gettime(struct posix_clock *pc, struct timespec *tp)
+{
+	struct flexcard_clk *clk = container_of(pc, struct flexcard_clk, clock);
+	u64 now;
+	u32 upper, rem;
+
+retry:
+	upper = readl(clk->ts64);
+	now = ((u64) upper << 32) | readl(clk->ts64 + 4);
+	if (upper != readl(clk->ts64))
+		goto retry;
+
+	tp->tv_sec = div_u64_rem(now, 1000000, &rem);
+	tp->tv_nsec = rem * 1000;
+
+	return 0;
+}
+
+static int flexcard_clk_settime(struct posix_clock *pc,
+				  const struct timespec *tp)
+{
+	struct flexcard_clk *clk = container_of(pc, struct flexcard_clk, clock);
+
+	/* The FlexCard posix clock could only be reset to 0 and not set */
+	if (tp->tv_sec || tp->tv_nsec)
+		return -EINVAL;
+
+	writel(FLEXCARD_RST_TS, clk->reset);
+
+	return 0;
+}
+
+static struct posix_clock_operations flexcard_clk_ops = {
+	.owner		= THIS_MODULE,
+	.clock_getres	= flexcard_clk_getres,
+	.clock_gettime	= flexcard_clk_gettime,
+	.clock_settime	= flexcard_clk_settime,
+};
+
+static int flexcard_clk_iomap(struct platform_device *pdev)
+{
+	struct flexcard_clk *clk = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENXIO;
+
+	clk->ts64 = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!clk->ts64)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -ENXIO;
+
+	clk->reset = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!clk->reset)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int flexcard_clk_probe(struct platform_device *pdev)
+{
+	const struct mfd_cell *cell;
+	struct flexcard_clk *clk;
+	int major, ret;
+
+	cell = mfd_get_cell(pdev);
+	if (!cell)
+		return -ENODEV;
+
+	if (cell->id >= MAX_CLOCKS) {
+		dev_err(&pdev->dev, "all flexcard posix clocks in use: %d\n",
+			cell->id);
+		return -EBUSY;
+	}
+
+	clk = devm_kzalloc(&pdev->dev, sizeof(*clk), GFP_KERNEL);
+	if (!clk)
+		return -ENOMEM;
+
+	major = MAJOR(flexcard_clk_devt);
+	platform_set_drvdata(pdev, clk);
+
+	ret = flexcard_clk_iomap(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to map resources: %d\n", ret);
+		goto out;
+	}
+
+	clk->devid = MKDEV(major, cell->id);
+	clk->clock.ops = flexcard_clk_ops;
+
+	writel(FLEXCARD_CLK_1MHZ, clk->ts64 + CLKSEL_OFF);
+	writel(FLEXCARD_RST_TS, clk->reset);
+
+	clk->dev = device_create(flexcard_clk_class, &pdev->dev, clk->devid,
+				 clk, "flexcard_clock%d", cell->id);
+	if (IS_ERR(clk->dev)) {
+		ret = PTR_ERR(clk->dev);
+		goto out;
+	}
+
+	ret = posix_clock_register(&clk->clock, clk->devid);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to register flexcard posix clock: %d\n", ret);
+		goto out_destroy;
+	}
+
+	dev_info(&pdev->dev, "flexcard posix clock %d registered", cell->id);
+
+	return 0;
+
+out_destroy:
+	device_destroy(flexcard_clk_class, clk->devid);
+out:
+	return ret;
+}
+
+static int flexcard_clk_remove(struct platform_device *pdev)
+{
+	struct flexcard_clk *clk = platform_get_drvdata(pdev);
+
+	posix_clock_unregister(&clk->clock);
+	device_destroy(flexcard_clk_class, clk->devid);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static const struct platform_device_id flexcard_clk_id_table[] = {
+	{ "flexcard-clock", 0 },
+	{},
+};
+MODULE_DEVICE_TABLE(platform, flexcard_clk_id_table);
+
+static struct platform_driver flexcard_clk_driver = {
+	.probe		= flexcard_clk_probe,
+	.remove		= flexcard_clk_remove,
+	.driver		= {
+		.name	= "flexcard-clock",
+	},
+	.id_table	= flexcard_clk_id_table,
+};
+
+static int __init flexcard_clk_init(void)
+{
+	int ret;
+
+	flexcard_clk_class = class_create(THIS_MODULE, "flexcard_clock");
+	if (IS_ERR(flexcard_clk_class)) {
+		pr_err("flexcard_clock: failed to allocate class\n");
+		return PTR_ERR(flexcard_clk_class);
+	}
+
+	ret = alloc_chrdev_region(&flexcard_clk_devt, 0, MAX_CLOCKS,
+				  "flexcard_clock");
+	if (ret < 0) {
+		pr_err("failed to allocate device region\n");
+		goto out;
+	}
+
+	ret = platform_driver_register(&flexcard_clk_driver);
+	if (ret < 0)
+		goto out_unregister;
+
+	return 0;
+
+out_unregister:
+	unregister_chrdev_region(flexcard_clk_devt, MAX_CLOCKS);
+out:
+	class_destroy(flexcard_clk_class);
+
+	return ret;
+}
+
+static void __exit flexcard_clk_exit(void)
+{
+	platform_driver_unregister(&flexcard_clk_driver);
+	unregister_chrdev_region(flexcard_clk_devt, MAX_CLOCKS);
+	class_destroy(flexcard_clk_class);
+}
+
+module_init(flexcard_clk_init);
+module_exit(flexcard_clk_exit);
+
+MODULE_AUTHOR("Holger Dengler <dengler@linutronix.de>");
+MODULE_AUTHOR("Benedikt Spranger <b.spranger@linutronix.de>");
+MODULE_DESCRIPTION("Eberspaecher Flexcard PMC II posix clock driver");
+MODULE_LICENSE("GPL v2");
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 11/12] misc: flexcard: Support timestamp trigger selection
  2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
                   ` (9 preceding siblings ...)
  2016-12-14  0:11 ` [PATCH 10/12] misc: Flexcard basic timestamp counter support Holger Dengler
@ 2016-12-14  0:11 ` Holger Dengler
  2016-12-14  0:11 ` [PATCH 12/12] dma: Flexcard DMA ringbuffer demux driver Holger Dengler
  2017-01-04  9:43 ` [PATCH 00/12] Eberspaecher Flexcard PMC II base support Lee Jones
  12 siblings, 0 replies; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  0:11 UTC (permalink / raw)
  To: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul
  Cc: linux-kernel, dmaengine, Thomas Gleixner, Sebastian Siewior,
	Juergen Bubeck, Peter Mahler, Holger Dengler, Benedikt Spranger

The Flexcard timestamp counter can be triggered from two external
trigger inputs or an internal clock at 1 MHz, 10 Mhz or 100 MHz.
Add support for timestamp trigger selection.

Signed-off-by: Holger Dengler <dengler@linutronix.de>
Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
cc: Arnd Bergmann <arnd@arndb.de>
cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/misc/flexcard_posixclock.c | 63 +++++++++++++++++++++++++++++++++++---
 include/uapi/linux/flexcard.h      | 16 ++++++++++
 2 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/flexcard_posixclock.c b/drivers/misc/flexcard_posixclock.c
index 146f0f3..b4cb38e 100644
--- a/drivers/misc/flexcard_posixclock.c
+++ b/drivers/misc/flexcard_posixclock.c
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/flexcard.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/platform_device.h>
@@ -35,12 +36,15 @@ struct flexcard_clk {
 	struct device		*dev;
 	void __iomem		*ts64;
 	void __iomem		*reset;
+	u32			mul;
+	struct flexcard_clk_desc desc;
 };
 
 static int flexcard_clk_getres(struct posix_clock *pc, struct timespec *tp)
 {
+	struct flexcard_clk *clk = container_of(pc, struct flexcard_clk, clock);
 	tp->tv_sec = 0;
-	tp->tv_nsec = 1000;
+	tp->tv_nsec = clk->mul;
 
 	return 0;
 }
@@ -57,8 +61,8 @@ static int flexcard_clk_gettime(struct posix_clock *pc, struct timespec *tp)
 	if (upper != readl(clk->ts64))
 		goto retry;
 
-	tp->tv_sec = div_u64_rem(now, 1000000, &rem);
-	tp->tv_nsec = rem * 1000;
+	tp->tv_sec = div_u64_rem(now, clk->desc.freq, &rem);
+	tp->tv_nsec = rem * clk->mul;
 
 	return 0;
 }
@@ -77,11 +81,59 @@ static int flexcard_clk_settime(struct posix_clock *pc,
 	return 0;
 }
 
+static long flexcard_clk_ioctl(struct posix_clock *pc, unsigned int cmd,
+			       unsigned long arg)
+{
+	struct flexcard_clk *clk = container_of(pc, struct flexcard_clk, clock);
+	struct flexcard_clk_desc desc;
+
+	switch (cmd) {
+	case FCSCLKSRC:
+		if (copy_from_user(&desc, (void __user *)arg, sizeof(desc)))
+			return -EFAULT;
+
+		switch (desc.type) {
+		case FLEXCARD_CLK_1MHZ:
+			desc.freq = 1000000;
+			break;
+		case FLEXCARD_CLK_10MHZ:
+			desc.freq = 10000000;
+			break;
+		case FLEXCARD_CLK_100MHZ:
+			desc.freq = 100000000;
+			break;
+		case FLEXCARD_CLK_EXT1:
+		case FLEXCARD_CLK_EXT2:
+			if (desc.freq < 1 || desc.freq > NSEC_PER_SEC)
+				return -EINVAL;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		clk->desc = desc;
+		clk->mul = NSEC_PER_SEC/desc.freq;
+		writel(clk->desc.type, clk->ts64 + CLKSEL_OFF);
+		writel(FLEXCARD_RST_TS, clk->reset);
+
+		break;
+	case FCGCLKSRC:
+		if (copy_to_user((void __user *)arg, &clk->desc, sizeof(desc)))
+			return -EFAULT;
+		break;
+	default:
+		return -ENOTTY;
+	}
+
+	return 0;
+}
+
 static struct posix_clock_operations flexcard_clk_ops = {
 	.owner		= THIS_MODULE,
 	.clock_getres	= flexcard_clk_getres,
 	.clock_gettime	= flexcard_clk_gettime,
 	.clock_settime	= flexcard_clk_settime,
+	.ioctl		= flexcard_clk_ioctl,
 };
 
 static int flexcard_clk_iomap(struct platform_device *pdev)
@@ -139,8 +191,11 @@ static int flexcard_clk_probe(struct platform_device *pdev)
 
 	clk->devid = MKDEV(major, cell->id);
 	clk->clock.ops = flexcard_clk_ops;
+	clk->desc.type = FLEXCARD_CLK_1MHZ;
+	clk->desc.freq = 1000000;
+	clk->mul = 1000;
 
-	writel(FLEXCARD_CLK_1MHZ, clk->ts64 + CLKSEL_OFF);
+	writel(clk->desc.type, clk->ts64 + CLKSEL_OFF);
 	writel(FLEXCARD_RST_TS, clk->reset);
 
 	clk->dev = device_create(flexcard_clk_class, &pdev->dev, clk->devid,
diff --git a/include/uapi/linux/flexcard.h b/include/uapi/linux/flexcard.h
index 4e9f07b4..3ad0bf4 100644
--- a/include/uapi/linux/flexcard.h
+++ b/include/uapi/linux/flexcard.h
@@ -15,6 +15,22 @@
 
 #include <linux/types.h>
 
+enum flexcard_clk_type {
+	FLEXCARD_CLK_1MHZ = 0x0,
+	FLEXCARD_CLK_10MHZ = 0x1,
+	FLEXCARD_CLK_100MHZ = 0x2,
+	FLEXCARD_CLK_EXT1 = 0x11,
+	FLEXCARD_CLK_EXT2 = 0x12,
+};
+
+struct flexcard_clk_desc {
+	enum flexcard_clk_type type;
+	__u32 freq;
+};
+
+#define FCGCLKSRC       _IOR(0xeb, 0, struct flexcard_clk_desc)
+#define FCSCLKSRC       _IOW(0xeb, 1, struct flexcard_clk_desc)
+
 struct fc_version {
 	__u8	dev;
 	__u8	min;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 12/12] dma: Flexcard DMA ringbuffer demux driver
  2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
                   ` (10 preceding siblings ...)
  2016-12-14  0:11 ` [PATCH 11/12] misc: flexcard: Support timestamp trigger selection Holger Dengler
@ 2016-12-14  0:11 ` Holger Dengler
  2016-12-14  1:54   ` kbuild test robot
  2016-12-15  4:38   ` Vinod Koul
  2017-01-04  9:43 ` [PATCH 00/12] Eberspaecher Flexcard PMC II base support Lee Jones
  12 siblings, 2 replies; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  0:11 UTC (permalink / raw)
  To: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul
  Cc: linux-kernel, dmaengine, Thomas Gleixner, Sebastian Siewior,
	Juergen Bubeck, Peter Mahler, Holger Dengler, Benedikt Spranger

The Flexcard interface design split packet receive and transmit. All
received packets and card status information are multiplexed with a
Flexcard specific protocol and handled through a DMA capable ringbuffer.
The TX path has to poke each available component separate.

Add a Flexcard DMA ringbuffer driver and packet demultiplexer.

Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
Signed-off-by: Holger Dengler <dengler@linutronix.de>
cc: Vinod Koul <vinod.koul@intel.com>
---
 drivers/dma/Kconfig                 |   9 ++
 drivers/dma/Makefile                |   1 +
 drivers/dma/flexcard/Makefile       |   2 +
 drivers/dma/flexcard/core.c         | 292 ++++++++++++++++++++++++++++++++++++
 drivers/dma/flexcard/flexcard-dma.h | 218 +++++++++++++++++++++++++++
 drivers/dma/flexcard/parser.c       | 227 ++++++++++++++++++++++++++++
 drivers/mfd/Kconfig                 |   1 +
 include/linux/mfd/flexcard.h        |   4 +
 8 files changed, 754 insertions(+)
 create mode 100644 drivers/dma/flexcard/Makefile
 create mode 100644 drivers/dma/flexcard/core.c
 create mode 100644 drivers/dma/flexcard/flexcard-dma.h
 create mode 100644 drivers/dma/flexcard/parser.c

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 141aefb..b158544 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -40,6 +40,15 @@ config ASYNC_TX_ENABLE_CHANNEL_SWITCH
 config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
 	bool
 
+config FLEXCARD_DMA
+	tristate "DMA support for Eberspaecher Flexcard PMC II Carrier Board"
+	depends on MFD_FLEXCARD
+	help
+	  The Eberspaecher Flexcard PMC (PCI Mezzanine Card) II carrier
+	  board support one DMA capable receive ringbuffer for all devices.
+	  A card specific protocol is used to multiplex the received packets
+	  through the ringbuffer. Enable DMA and Packet parser.
+
 config DMA_ENGINE
 	bool
 
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index e4dc9ca..a9a5b3f 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_DMA_SUN4I) += sun4i-dma.o
 obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o
 obj-$(CONFIG_DW_DMAC_CORE) += dw/
 obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
+obj-$(CONFIG_FLEXCARD_DMA) += flexcard/
 obj-$(CONFIG_FSL_DMA) += fsldma.o
 obj-$(CONFIG_FSL_EDMA) += fsl-edma.o
 obj-$(CONFIG_FSL_RAID) += fsl_raid.o
diff --git a/drivers/dma/flexcard/Makefile b/drivers/dma/flexcard/Makefile
new file mode 100644
index 0000000..62ae627
--- /dev/null
+++ b/drivers/dma/flexcard/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_FLEXCARD_DMA) += flexcard_dma.o
+flexcard_dma-objs := core.o parser.o
diff --git a/drivers/dma/flexcard/core.c b/drivers/dma/flexcard/core.c
new file mode 100644
index 0000000..6809840
--- /dev/null
+++ b/drivers/dma/flexcard/core.c
@@ -0,0 +1,292 @@
+/*
+ * Eberspächer Flexcard PMC II Carrier Board PCI Driver - DMA controller
+ *
+ * Copyright (c) 2014 - 2016, Linutronix GmbH
+ * Author: Benedikt Spranger <b.spranger@linutronix.de>
+ *         Holger Dengler <dengler@linutronix.de>
+ *
+ * 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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/flexcard.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/flexcard.h>
+
+#include "flexcard-dma.h"
+
+/*
+ * Allocate twice the size of FLEXCARD_DMA_BUF_SIZE for the receiving
+ * ring buffer to easily handle wrap-arounds.
+ */
+#define DMA_TOTAL_BUF_SIZE		(2*FLEXCARD_DMA_BUF_SIZE)
+
+static int flexcard_dma_stop(struct flexcard_dma *dma)
+{
+	u32 __iomem *dma_ctrl = &dma->reg->dma_ctrl;
+	u32 __iomem *dma_stat = &dma->reg->dma_stat;
+	int retry;
+
+	writel(FLEXCARD_DMA_CTRL_STOP_REQ, dma_ctrl);
+
+	/*
+	 * DMA_IDLE bit reads 1 when the DMA state machine is in idle state
+	 * after a stop request, otherwise 0. DMA stop should complete in at
+	 * least 200us.
+	 */
+	retry = 200;
+	while (!(readl(dma_ctrl) & FLEXCARD_DMA_CTRL_DMA_IDLE) && retry--)
+		udelay(1);
+	if (!retry)
+		return -EBUSY;
+
+	/*
+	 * Check for max. 200us, if there are DMA jobs in progress.
+	 */
+	retry = 200;
+	while ((readl(dma_stat) & FLEXCARD_DMA_STAT_BUSY) && retry--)
+		udelay(1);
+
+	return retry ? 0 : -EBUSY;
+}
+
+static int flexcard_dma_reset(struct flexcard_dma *dma)
+{
+	u32 __iomem *dma_ctrl = &dma->reg->dma_ctrl;
+	int retry = 500;
+
+	writel(FLEXCARD_DMA_CTRL_RST_DMA, dma_ctrl);
+
+	/*
+	 * DMA_IDLE bit reads 1 when the DMA state machine is in idle state
+	 * after a reset request, otherwise 0. DMA reset should complete in
+	 * at least 5ms.
+	 */
+	while (!(readl(dma_ctrl) & FLEXCARD_DMA_CTRL_DMA_IDLE) && retry--)
+		udelay(10);
+
+	return retry ? 0 : -EIO;
+}
+
+static int flexcard_dma_setup(struct flexcard_dma *dma)
+{
+	int ret;
+
+	ret = flexcard_dma_reset(dma);
+	if (ret)
+		return ret;
+
+	writel(0x0, &dma->reg->dma_rptr);
+	writel(0x0, &dma->reg->dma_wptr);
+	writel(0x0, &dma->reg->dma_ctrl);
+
+	writeq(dma->phys, &dma->reg->dma_cba);
+	writel(FLEXCARD_DMA_BUF_SIZE, &dma->reg->dma_cbs);
+
+	return ret;
+}
+
+static irqreturn_t flexcard_dma_isr(int irq, void *dev_id)
+{
+	struct platform_device *pdev = dev_id;
+	struct flexcard_dma *dma = platform_get_drvdata(pdev);
+	u32 avail, parsed, rptr = dma->rptr;
+
+	avail = readl(&dma->reg->dma_cblr);
+	if (!avail)
+		return IRQ_NONE;
+
+	do {
+		u32 tocp = rptr + FLEXCARD_MAX_PAKET_SIZE;
+		/*
+		 * For simplicity the parser always looks at contiguous
+		 * buffer space.
+		 *
+		 * We ensure that by copying the eventually wrapped
+		 * bytes of the next message from the bottom of the
+		 * dma buffer to the space right after the dma buffer
+		 * which has been allocated just for that reason.
+		 */
+		if (tocp > FLEXCARD_DMA_BUF_SIZE) {
+			tocp &= FLEXCARD_DMA_BUF_MASK;
+			memcpy(dma->buf + FLEXCARD_DMA_BUF_SIZE,
+			       dma->buf, tocp);
+		}
+
+		parsed = flexcard_parse_packet(dma->buf + rptr, avail, dma);
+		if (parsed > avail) {
+			dev_err(&pdev->dev, "Parser overrun\n");
+			rptr = (rptr + parsed) & FLEXCARD_DMA_BUF_MASK;
+			break;
+		}
+		avail -= parsed;
+		rptr = (rptr + parsed) & FLEXCARD_DMA_BUF_MASK;
+	} while (parsed && avail);
+
+	/* Update the read pointer in the device if we processed data */
+	if (dma->rptr != rptr) {
+		dma->rptr = rptr;
+		writel(rptr, &dma->reg->dma_rptr);
+	} else {
+		/* This may happen if no packets has been parsed */
+		dev_err_ratelimited(&pdev->dev, "rptr unchanged\n");
+		return IRQ_NONE;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t flexcard_dma_ovr(int irq, void *dev_id)
+{
+	struct platform_device *pdev = dev_id;
+	struct flexcard_dma *dma = platform_get_drvdata(pdev);
+	u32 stat;
+
+	/* check overflow flag */
+	stat = readl(&dma->reg->dma_stat);
+	if (!(stat & FLEXCARD_DMA_STAT_OFL))
+		return IRQ_NONE;
+
+	dev_err(&pdev->dev, "DMA buffer overflow\n");
+
+	writel(0x0, &dma->reg->dma_rptr);
+
+	/* reset overflow flag */
+	writel(FLEXCARD_DMA_STAT_OFL, &dma->reg->dma_stat);
+
+	return IRQ_HANDLED;
+}
+
+static int flexcard_dma_resource(struct platform_device *pdev)
+{
+	struct flexcard_dma *dma = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENXIO;
+
+	dma->reg = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!dma->reg) {
+		dev_err(&pdev->dev, "failed to map DMA register\n");
+		return -ENOMEM;
+	}
+
+	dma->irq = platform_get_irq(pdev, 0);
+	if (dma->irq < 0) {
+		dev_err(&pdev->dev, "failed to get CBL IRQ\n");
+		return -ENXIO;
+	}
+
+	dma->irq_ovr = platform_get_irq(pdev, 1);
+	if (dma->irq_ovr < 0) {
+		dev_err(&pdev->dev, "failed to get CO IRQ\n");
+		return -ENXIO;
+	}
+	return 0;
+}
+
+static int flexcard_dma_probe(struct platform_device *pdev)
+{
+	const struct mfd_cell *cell;
+	struct flexcard_dma *dma;
+	int ret;
+
+	cell = mfd_get_cell(pdev);
+	if (!cell)
+		return -ENODEV;
+
+	dma = devm_kzalloc(&pdev->dev, sizeof(*dma), GFP_KERNEL);
+	if (!dma)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, dma);
+
+	dma->buf = dma_alloc_coherent(&pdev->dev, DMA_TOTAL_BUF_SIZE,
+				      &dma->phys, GFP_KERNEL);
+	if (!dma->buf) {
+		dev_err(&pdev->dev, "could not allocate DMA memory\n");
+		return -ENOMEM;
+	}
+
+	ret = flexcard_dma_resource(pdev);
+	if (ret)
+		goto out_free_buf;
+
+	ret = flexcard_dma_setup(dma);
+	if (ret) {
+		dev_err(&pdev->dev, "could not setup Flexcard DMA: %d\n", ret);
+		goto out_free_buf;
+	}
+
+	ret = devm_request_threaded_irq(&pdev->dev, dma->irq, NULL,
+					flexcard_dma_isr, IRQF_ONESHOT,
+					"flexcard-CBL", pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "could not request Flexcard DMA CBL IRQ\n");
+		goto out_free_buf;
+	}
+
+	ret = devm_request_irq(&pdev->dev, dma->irq_ovr, flexcard_dma_ovr, 0,
+			  "flexcard-CO", pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "could not request Flexcard DMA CO IRQ\n");
+		goto out_free_irq;
+	}
+
+	writel(FLEXCARD_DMA_CTRL_DMA_ENA, &dma->reg->dma_ctrl);
+	writel(0x300, &dma->reg->dma_cbcr);
+
+	dev_info(&pdev->dev, "Flexcard DMA registered");
+
+	return 0;
+
+out_free_irq:
+	writel(0x0, &dma->reg->dma_ctrl);
+out_free_buf:
+	dma_free_coherent(&pdev->dev, DMA_TOTAL_BUF_SIZE,
+			  dma->buf, dma->phys);
+	return ret;
+}
+
+static int flexcard_dma_remove(struct platform_device *pdev)
+{
+	struct flexcard_dma *dma = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = flexcard_dma_stop(dma);
+	if (ret) {
+		dev_err(&pdev->dev, "could not stop DMA state machine\n");
+		return ret;
+	}
+
+	dma_free_coherent(&pdev->dev, DMA_TOTAL_BUF_SIZE,
+			  dma->buf, dma->phys);
+
+	return ret;
+}
+
+static struct platform_driver flexcard_dma_driver = {
+	.probe		= flexcard_dma_probe,
+	.remove		= flexcard_dma_remove,
+	.driver		= {
+		.name   = "flexcard-dma",
+	}
+};
+
+module_platform_driver(flexcard_dma_driver);
+
+MODULE_AUTHOR("Holger Dengler <dengler@linutronix.de>");
+MODULE_AUTHOR("Benedikt Spranger <b.spranger@linutronix.de>");
+MODULE_DESCRIPTION("Eberspaecher Flexcard PMC II DMA Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:flexcard-dma");
diff --git a/drivers/dma/flexcard/flexcard-dma.h b/drivers/dma/flexcard/flexcard-dma.h
new file mode 100644
index 0000000..6fc4ccf
--- /dev/null
+++ b/drivers/dma/flexcard/flexcard-dma.h
@@ -0,0 +1,218 @@
+/*
+ * Eberspächer Flexcard PMC II Carrier Board PCI Driver - DMA controller
+ *
+ * Copyright (c) 2014 - 2016, Linutronix GmbH
+ * Author: Benedikt Spranger <b.spranger@linutronix.de>
+ *         Holger Dengler <dengler@linutronix.de>
+ *
+ * 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.
+ */
+#ifndef __FLEXCARD_DMA_H
+#define __FLEXCARD_DMA_H
+
+#define FLEXCARD_DMA_BUF_SIZE		0x200000
+#define FLEXCARD_DMA_BUF_MASK		(FLEXCARD_DMA_BUF_SIZE - 1)
+
+#define FLEXCARD_DMA_CTRL_DMA_ENA	(1 << 0)
+#define FLEXCARD_DMA_CTRL_MAN_ENA	(1 << 1)
+#define FLEXCARD_DMA_CTRL_STOP_REQ	(1 << 16)
+#define FLEXCARD_DMA_CTRL_DMA_IDLE	(1 << 17)
+#define FLEXCARD_DMA_CTRL_RST_DMA	(1 << 31)
+
+#define FLEXCARD_DMA_STAT_BUSY		(1 << 15)
+#define FLEXCARD_DMA_STAT_OFL		(1 << 31)
+
+#define FLEXCARD_MAX_PAKET_SIZE		0x200
+
+#define FLEXCARD_BUF_HEADER_LEN_SHIFT	15
+#define FLEXCARD_BUF_HEADER_LEN_MASK	0xfe
+
+#define FLEXCARD_CANIF_OFFSET		0x20
+
+struct flexcard_dma_reg {
+	u32 dma_ctrl;
+	u32 dma_stat;
+	u32 r1[2];
+	u64 dma_cba;
+	u32 dma_cbs;
+	u32 dma_txr;
+	u32 dma_irer;
+	u32 dma_irsr;
+	u32 r2[10];
+	u32 dma_cbcr;
+	u32 dma_cblr;
+	u32 r3[2];
+	u32 dma_itcr;
+	u32 dma_itr;
+	u32 r4[2];
+	u32 dma_wptr;
+	u32 dma_rptr;
+	u32 r5[2];
+} __packed;
+
+struct flexcard_dma {
+	int irq;
+	int irq_ovr;
+	u32 rptr;
+	void *buf;
+	dma_addr_t phys;
+	int nr_eray;
+	struct flexcard_dma_reg __iomem *reg;
+};
+
+enum fc_packet_type {
+	FC_PACKET_TYPE_INFO = 1,
+	FC_PACKET_TYPE_FLEXRAY_FRAME = 2,
+	FC_PACKET_TYPE_ERROR = 3,
+	FC_PACKET_TYPE_STATUS = 4,
+	FC_PACKET_TYPE_TRIGGER = 5,
+	FC_PACKET_TYPE_TX_ACK = 6,
+	FC_PACKET_TYPE_NMV_VECTOR = 7,
+	FC_PACKET_TYPE_NOTIFICATION = 8,
+	FC_PACKET_TYPE_TRIGGER_EX = 9,
+	FC_PACKET_TYPE_CAN = 10,
+	FC_PACKET_TYPE_CAN_ERROR = 11,
+};
+
+struct fc_packet {
+	__u32 type;
+	__u32 p_packet;
+	__u32 p_next_packet;
+} __packed;
+
+struct fc_info_packet {
+	__u32 current_cycle;
+	__u32 timestamp;
+	__u32 offset_rate_correction;
+	__u32 pta_ccf_count;
+	__u32 cc;
+} __packed;
+
+struct fc_flexray_frame {
+	__u32 header;
+	__u32 header_crc;
+	__u32 pdata;
+	__u32 channel;
+	__u32 frame_crc;
+	__u32 timestamp;
+	__u32 cc;
+} __packed;
+
+struct fc_error_packet {
+	__u32 flag;
+	__u32 timestamp;
+	__u32 cycle_count;
+	__u64 additional_info;
+	__u32 cc;
+	__u32 reserved;
+} __packed;
+
+struct fc_status_packet {
+	__u32 flag;
+	__u32 timestamp;
+	__u32 cycle_count;
+	__u32 additional_info;
+	__u32 cc;
+	__u32 reserved[2];
+} __packed;
+
+struct fc_tx_ack_packet {
+	__u32 bufferid;
+	__u32 timestamp;
+	__u32 cycle_count;
+	__u32 header;
+	__u32 header_crc;
+	__u32 pdata;
+	__u32 channel;
+	__u32 cc;
+} __packed;
+
+struct fc_nm_vector_packet {
+	__u32 timestamp;
+	__u32 cycle_count;
+	__u32 nmv_vector_length;
+	__u32 nmv_vector[3];
+	__u32 cc;
+	__u32 reserved;
+} __packed;
+
+struct fc_notification_packet {
+	__u32 timestamp;
+	__u32 sequence_count;
+	__u32 reserved;
+} __packed;
+
+struct fc_trigger_ex_info_packet {
+	__u32 condition;
+	__u32 timestamp;
+	__u32 sequence_count;
+	__u32 reserved1;
+	__u64 performance_counter;
+	__u32 edge;
+	__u32 trigger_line;
+	__u32 reserved[4];
+} __packed;
+
+struct fc_can_packet {
+	__u32 id;
+	__u32 timestamp;
+	__u32 flags;
+	__u32 reserved;
+	__u32 cc;
+	__u8 data[8];
+} __packed;
+
+struct fc_can_error_packet {
+	__u32 type;
+	__u32 state;
+	__u32 timestamp;
+	__u32 rx_error_counter;
+	__u32 tx_error_counter;
+	__u32 cc;
+	__u32 reserved[2];
+} __packed;
+
+enum fc_can_cc_state {
+	fc_can_state_unknown = 0,
+	fc_can_state_config,
+	fc_can_state_normalActive,
+	fc_can_state_warning,
+	fc_can_state_error_passive,
+	fc_can_state_bus_off,
+};
+
+enum fc_can_error_type {
+	fc_can_error_none = 0,
+	fc_can_error_stuff,
+	fc_can_error_form,
+	fc_can_error_acknowledge,
+	fc_can_error_bit1,
+	fc_can_error_bit0,
+	fc_can_error_crc,
+	fc_can_error_parity,
+};
+
+union fc_packet_types {
+	struct fc_info_packet		info_packet;
+	struct fc_flexray_frame		flexray_frame;
+	struct fc_error_packet		error_packet;
+	struct fc_status_packet		status_packet;
+	struct fc_tx_ack_packet		tx_ack_packet;
+	struct fc_nm_vector_packet	nm_vector_packet;
+	struct fc_notification_packet	notification_packet;
+	struct fc_trigger_ex_info_packet ex_info_packet;
+	struct fc_can_packet		can_packet;
+	struct fc_can_error_packet	can_error_packet;
+};
+
+struct fc_packet_buf {
+	struct  fc_packet	header;
+	union   fc_packet_types	packet;
+} __packed;
+
+u32 flexcard_parse_packet(struct fc_packet_buf *pb, u32 avail,
+			  struct flexcard_dma *dma);
+
+#endif /* __FLEXCARD_DMA_H */
diff --git a/drivers/dma/flexcard/parser.c b/drivers/dma/flexcard/parser.c
new file mode 100644
index 0000000..2450229
--- /dev/null
+++ b/drivers/dma/flexcard/parser.c
@@ -0,0 +1,227 @@
+/*
+ * Eberspächer Flexcard PMC II Carrier Board PCI Driver - packet parser/mux
+ *
+ * Copyright (c) 2014 - 2016, Linutronix GmbH
+ * Author: Benedikt Spranger <b.spranger@linutronix.de>
+ *         Holger Dengler <dengler@linutronix.de>
+ *
+ * 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 <linux/device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <linux/mfd/flexcard.h>
+#include "flexcard-dma.h"
+
+static LIST_HEAD(rx_cb_list);
+static DEFINE_SPINLOCK(rx_cb_lock);
+
+struct fc_rx_cb {
+	struct list_head list;
+	int (*rx_cb)(void *priv, void *data, size_t len);
+	int cc;
+	void *priv;
+};
+
+/**
+ * flexcard_register_rx_cb() - Registers a callback for received packages
+ * @cc:		communication controller id
+ * @priv:	pointer to private data of the cc
+ * @rx_cp:	pionter to the receive callback
+ *
+ * Registers a callback for a communication controller specific handling for
+ * received packages. The callback is called by the generic parser, if the
+ * communication controller id inside of the received package matches the cc
+ * of the callback owner.
+ *
+ * Return: 0 is returned on success and a negative errno code for failure.
+ */
+int flexcard_register_rx_cb(int cc, void *priv,
+			    int (*rx_cb)(void *priv, void *data, size_t len))
+{
+	unsigned long flags;
+	struct fc_rx_cb *cb, *next;
+
+	if (!rx_cb)
+		return -EINVAL;
+
+	cb = kmalloc(sizeof(*cb), GFP_KERNEL);
+	if (!cb)
+		return -ENOMEM;
+
+	cb->cc = cc;
+	cb->priv = priv;
+	cb->rx_cb = rx_cb;
+
+	spin_lock_irqsave(&rx_cb_lock, flags);
+	list_for_each_entry(next, &rx_cb_list, list)
+		if (next->cc == cc)
+			goto out;
+
+	list_add_tail(&cb->list, &rx_cb_list);
+	spin_unlock_irqrestore(&rx_cb_lock, flags);
+
+	return 0;
+out:
+	spin_unlock_irqrestore(&rx_cb_lock, flags);
+	kfree(cb);
+
+	return -EBUSY;
+}
+EXPORT_SYMBOL_GPL(flexcard_register_rx_cb);
+
+/**
+ * flexcard_unregister_rx_cb() - Unregisters a callback for received packages
+ * @cc:		communication controller id
+ *
+ * Unregisters a callback for a communication controller specific handling for
+ * received packages.
+ *
+ * Return: 0 is returned on success and a negative errno code for failure.
+ */
+void flexcard_unregister_rx_cb(int cc)
+{
+	unsigned long flags;
+	struct fc_rx_cb *cur, *next;
+	int found = 0;
+
+	spin_lock_irqsave(&rx_cb_lock, flags);
+	list_for_each_entry_safe(cur, next, &rx_cb_list, list) {
+		if (cur->cc == cc) {
+			list_del(&cur->list);
+			kfree(cur);
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found)
+		pr_err("no callback registered for cc %d\n", cc);
+
+	spin_unlock_irqrestore(&rx_cb_lock, flags);
+}
+EXPORT_SYMBOL_GPL(flexcard_unregister_rx_cb);
+
+static int flexcard_queue_rx(int cc, void *buf, size_t len)
+{
+	struct fc_rx_cb *next;
+	unsigned long flags;
+	int ret = -ENODEV;
+
+	spin_lock_irqsave(&rx_cb_lock, flags);
+	list_for_each_entry(next, &rx_cb_list, list)
+		if (next->cc == cc)
+			ret = next->rx_cb(next->priv, buf, len);
+	spin_unlock_irqrestore(&rx_cb_lock, flags);
+
+	return ret;
+}
+
+static u32 flexcard_get_packet_len(u32 header)
+{
+	u32 len;
+
+	/*
+	 * header contains the number of transmitted 16bit words in bits 30-16.
+	 * if the number is odd the DMA engine padded with zero to 32bit.
+	 * calculate the number of transmitted bytes.
+	 */
+
+	len = le32_to_cpu(header);
+
+	len >>= FLEXCARD_BUF_HEADER_LEN_SHIFT;
+	len &= FLEXCARD_BUF_HEADER_LEN_MASK;
+
+	len = roundup(len, 4);
+
+	return len;
+}
+
+/**
+ * selfsync_cc - adjust the cc number for self-sync packages
+ * @dma:	pointer to dma structure
+ * @cc:		package cc
+ *
+ * Some Flexcards has support for self-synci bus configurations. With this
+ * feature it is possible to get a synchronized bus configuration with a
+ * single card.
+ * Indication for a self-sync package is eray_nr == 1 and cc == 1. The
+ * packages are always handled by communication controller 0.
+ */
+static inline u32 selfsync_cc(struct flexcard_dma *dma, u32 cc)
+{
+		if ((dma->nr_eray == 1) && (cc == 1))
+			return 0;
+		return cc;
+}
+
+u32 flexcard_parse_packet(struct fc_packet_buf *pb, u32 avail,
+			  struct flexcard_dma *dma)
+{
+	u32 l, cc, len = sizeof(struct fc_packet);
+	union fc_packet_types *pt = &pb->packet;
+
+	switch (le32_to_cpu(pb->header.type)) {
+	case FC_PACKET_TYPE_INFO:
+		len += sizeof(struct fc_info_packet);
+		cc = pt->info_packet.cc;
+		break;
+	case FC_PACKET_TYPE_ERROR:
+		len += sizeof(struct fc_error_packet);
+		cc = pt->error_packet.cc;
+		break;
+	case FC_PACKET_TYPE_STATUS:
+		len += sizeof(struct fc_status_packet);
+		cc = selfsync_cc(dma, pt->status_packet.cc);
+		break;
+	case FC_PACKET_TYPE_NMV_VECTOR:
+		len += sizeof(struct fc_nm_vector_packet);
+		cc = pt->nm_vector_packet.cc;
+		break;
+	case FC_PACKET_TYPE_NOTIFICATION:
+		len += sizeof(struct fc_notification_packet);
+		cc = 0;
+		break;
+	case FC_PACKET_TYPE_TRIGGER_EX:
+		len += sizeof(struct fc_trigger_ex_info_packet);
+		cc = 0;
+		break;
+	case FC_PACKET_TYPE_CAN:
+		len += sizeof(struct fc_can_packet);
+		cc = FLEXCARD_CANIF_OFFSET + pt->can_packet.cc;
+		break;
+	case FC_PACKET_TYPE_CAN_ERROR:
+		len += sizeof(struct fc_can_error_packet);
+		cc = FLEXCARD_CANIF_OFFSET + pt->can_error_packet.cc;
+		break;
+	case FC_PACKET_TYPE_FLEXRAY_FRAME:
+		len += sizeof(struct fc_flexray_frame);
+		pt->flexray_frame.pdata = len;
+		l = flexcard_get_packet_len(pt->flexray_frame.header);
+		len += l;
+		cc = pt->flexray_frame.cc;
+		break;
+	case FC_PACKET_TYPE_TX_ACK:
+		len += sizeof(struct fc_tx_ack_packet);
+		pt->tx_ack_packet.pdata = len;
+		l = flexcard_get_packet_len(pt->tx_ack_packet.header);
+		len += l;
+		cc = selfsync_cc(dma, pt->tx_ack_packet.cc);
+		break;
+	case FC_PACKET_TYPE_TRIGGER:
+	default:
+		pr_debug("pkt->type = %08x\n", pb->header.type);
+		return 0;
+	}
+
+	if (len > avail)
+		return 0;
+
+	flexcard_queue_rx(cc, pb, len);
+
+	return len;
+}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 490b435..cb87c27 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_DMA
 	select FLEXCARD_MISC
 	select FLEXCARD_PCLOCK
 	depends on PCI
diff --git a/include/linux/mfd/flexcard.h b/include/linux/mfd/flexcard.h
index 819c6ef..eeabc9e 100644
--- a/include/linux/mfd/flexcard.h
+++ b/include/linux/mfd/flexcard.h
@@ -109,4 +109,8 @@ struct flexcard_device {
 int flexcard_setup_irq(struct pci_dev *pdev);
 void flexcard_remove_irq(struct pci_dev *pdev);
 
+int flexcard_register_rx_cb(int cc, void *priv,
+			    int (*rx_cb)(void *priv, void *data, size_t len));
+void flexcard_unregister_rx_cb(int cc);
+
 #endif /* _LINUX_FLEXCARD_H */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [PATCH 09/12] misc: flexcard: add device attributes
  2016-12-14  0:11 ` [PATCH 09/12] misc: flexcard: add device attributes Holger Dengler
@ 2016-12-14  1:33   ` kbuild test robot
  2017-01-10 16:58   ` Greg Kroah-Hartman
  1 sibling, 0 replies; 30+ messages in thread
From: kbuild test robot @ 2016-12-14  1:33 UTC (permalink / raw)
  To: Holger Dengler
  Cc: kbuild-all, Lee Jones, Arnd Bergmann, Greg Kroah-Hartman,
	Vinod Koul, linux-kernel, dmaengine, Thomas Gleixner,
	Sebastian Siewior, Juergen Bubeck, Peter Mahler, Holger Dengler,
	Benedikt Spranger

[-- Attachment #1: Type: text/plain, Size: 1452 bytes --]

Hi Holger,

[auto build test ERROR on char-misc/char-misc-testing]
[also build test ERROR on v4.9]
[cannot apply to ljones-mfd/for-mfd-next next-20161213]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Holger-Dengler/Eberspaecher-Flexcard-PMC-II-base-support/20161214-082350
config: i386-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/misc/flexcard_misc.c: In function 'serialno_show':
>> drivers/misc/flexcard_misc.c:70:10: error: implicit declaration of function 'readq' [-Werror=implicit-function-declaration]
     fc_sn = readq(&priv->conf->fc_sn);
             ^~~~~
   cc1: some warnings being treated as errors

vim +/readq +70 drivers/misc/flexcard_misc.c

    64	static ssize_t serialno_show(struct device *dev,
    65				     struct device_attribute *attr, char *buf)
    66	{
    67		struct flexcard_misc *priv = dev_get_drvdata(dev);
    68		u64 fc_sn;
    69	
  > 70		fc_sn = readq(&priv->conf->fc_sn);
    71		return sprintf(buf, "%lld\n", fc_sn);
    72	}
    73	static DEVICE_ATTR_RO(serialno);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 56970 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 12/12] dma: Flexcard DMA ringbuffer demux driver
  2016-12-14  0:11 ` [PATCH 12/12] dma: Flexcard DMA ringbuffer demux driver Holger Dengler
@ 2016-12-14  1:54   ` kbuild test robot
  2016-12-15  4:38   ` Vinod Koul
  1 sibling, 0 replies; 30+ messages in thread
From: kbuild test robot @ 2016-12-14  1:54 UTC (permalink / raw)
  To: Holger Dengler
  Cc: kbuild-all, Lee Jones, Arnd Bergmann, Greg Kroah-Hartman,
	Vinod Koul, linux-kernel, dmaengine, Thomas Gleixner,
	Sebastian Siewior, Juergen Bubeck, Peter Mahler, Holger Dengler,
	Benedikt Spranger

[-- Attachment #1: Type: text/plain, Size: 1403 bytes --]

Hi Holger,

[auto build test ERROR on char-misc/char-misc-testing]
[also build test ERROR on v4.9]
[cannot apply to ljones-mfd/for-mfd-next next-20161213]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Holger-Dengler/Eberspaecher-Flexcard-PMC-II-base-support/20161214-082350
config: i386-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/dma/flexcard/core.c: In function 'flexcard_dma_setup':
>> drivers/dma/flexcard/core.c:92:2: error: implicit declaration of function 'writeq' [-Werror=implicit-function-declaration]
     writeq(dma->phys, &dma->reg->dma_cba);
     ^~~~~~
   cc1: some warnings being treated as errors

vim +/writeq +92 drivers/dma/flexcard/core.c

    86			return ret;
    87	
    88		writel(0x0, &dma->reg->dma_rptr);
    89		writel(0x0, &dma->reg->dma_wptr);
    90		writel(0x0, &dma->reg->dma_ctrl);
    91	
  > 92		writeq(dma->phys, &dma->reg->dma_cba);
    93		writel(FLEXCARD_DMA_BUF_SIZE, &dma->reg->dma_cbs);
    94	
    95		return ret;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 57027 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 04/12] mfd: flexcard: add interrupt support
  2016-12-14  0:11 ` [PATCH 04/12] mfd: flexcard: add interrupt support Holger Dengler
@ 2016-12-14  2:47   ` kbuild test robot
  2016-12-14  3:37   ` kbuild test robot
  1 sibling, 0 replies; 30+ messages in thread
From: kbuild test robot @ 2016-12-14  2:47 UTC (permalink / raw)
  To: Holger Dengler
  Cc: kbuild-all, Lee Jones, Arnd Bergmann, Greg Kroah-Hartman,
	Vinod Koul, linux-kernel, dmaengine, Thomas Gleixner,
	Sebastian Siewior, Juergen Bubeck, Peter Mahler, Holger Dengler,
	Benedikt Spranger

[-- Attachment #1: Type: text/plain, Size: 9301 bytes --]

Hi Holger,

[auto build test ERROR on char-misc/char-misc-testing]
[also build test ERROR on v4.9]
[cannot apply to ljones-mfd/for-mfd-next next-20161213]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Holger-Dengler/Eberspaecher-Flexcard-PMC-II-base-support/20161214-082350
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All error/warnings (new ones prefixed by >>):

   drivers/mfd/flexcard_irq.c: In function 'flexcard_demux':
>> drivers/mfd/flexcard_irq.c:111:3: error: implicit declaration of function 'generic_handle_irq' [-Werror=implicit-function-declaration]
      generic_handle_irq(cur);
      ^~~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c: In function 'flexcard_irq_ack':
>> drivers/mfd/flexcard_irq.c:119:33: error: implicit declaration of function 'irq_data_get_irq_chip_data' [-Werror=implicit-function-declaration]
     struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/mfd/flexcard_irq.c:119:33: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
>> drivers/mfd/flexcard_irq.c:120:51: error: dereferencing pointer to incomplete type 'struct irq_data'
     const struct fc_irq_tab *tp = &flexcard_irq_tab[d->hwirq];
                                                      ^~
   drivers/mfd/flexcard_irq.c: In function 'flexcard_irq_mask':
   drivers/mfd/flexcard_irq.c:128:33: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
     struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c: In function 'flexcard_irq_unmask':
   drivers/mfd/flexcard_irq.c:141:33: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
     struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c: At top level:
>> drivers/mfd/flexcard_irq.c:175:15: error: variable 'flexcard_irq_chip' has initializer but incomplete type
    static struct irq_chip flexcard_irq_chip = {
                  ^~~~~~~~
>> drivers/mfd/flexcard_irq.c:176:2: error: unknown field 'name' specified in initializer
     .name  = "flexcard_irq",
     ^
>> drivers/mfd/flexcard_irq.c:176:11: warning: excess elements in struct initializer
     .name  = "flexcard_irq",
              ^~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:176:11: note: (near initialization for 'flexcard_irq_chip')
>> drivers/mfd/flexcard_irq.c:177:2: error: unknown field 'irq_ack' specified in initializer
     .irq_ack = flexcard_irq_ack,
     ^
   drivers/mfd/flexcard_irq.c:177:13: warning: excess elements in struct initializer
     .irq_ack = flexcard_irq_ack,
                ^~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:177:13: note: (near initialization for 'flexcard_irq_chip')
>> drivers/mfd/flexcard_irq.c:178:2: error: unknown field 'irq_mask' specified in initializer
     .irq_mask = flexcard_irq_mask,
     ^
   drivers/mfd/flexcard_irq.c:178:14: warning: excess elements in struct initializer
     .irq_mask = flexcard_irq_mask,
                 ^~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:178:14: note: (near initialization for 'flexcard_irq_chip')
>> drivers/mfd/flexcard_irq.c:179:2: error: unknown field 'irq_unmask' specified in initializer
     .irq_unmask = flexcard_irq_unmask,
     ^
   drivers/mfd/flexcard_irq.c:179:16: warning: excess elements in struct initializer
     .irq_unmask = flexcard_irq_unmask,
                   ^~~~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:179:16: note: (near initialization for 'flexcard_irq_chip')
   drivers/mfd/flexcard_irq.c: In function 'flexcard_irq_domain_map':
>> drivers/mfd/flexcard_irq.c:187:2: error: implicit declaration of function 'irq_set_chip_and_handler_name' [-Werror=implicit-function-declaration]
     irq_set_chip_and_handler_name(irq, &flexcard_irq_chip,
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/mfd/flexcard_irq.c:188:11: error: 'handle_level_irq' undeclared (first use in this function)
              handle_level_irq, "flexcard");
              ^~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:188:11: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/mfd/flexcard_irq.c:189:2: error: implicit declaration of function 'irq_set_chip_data' [-Werror=implicit-function-declaration]
     irq_set_chip_data(irq, priv);
     ^~~~~~~~~~~~~~~~~
>> drivers/mfd/flexcard_irq.c:190:2: error: implicit declaration of function 'irq_modify_status' [-Werror=implicit-function-declaration]
     irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
     ^~~~~~~~~~~~~~~~~
>> drivers/mfd/flexcard_irq.c:190:25: error: 'IRQ_NOREQUEST' undeclared (first use in this function)
     irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
                            ^~~~~~~~~~~~~
>> drivers/mfd/flexcard_irq.c:190:41: error: 'IRQ_NOAUTOEN' undeclared (first use in this function)
     irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
                                            ^~~~~~~~~~~~
>> drivers/mfd/flexcard_irq.c:190:55: error: 'IRQ_NOPROBE' undeclared (first use in this function)
     irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
                                                          ^~~~~~~~~~~
   drivers/mfd/flexcard_irq.c: At top level:
>> drivers/mfd/flexcard_irq.c:175:24: error: storage size of 'flexcard_irq_chip' isn't known
    static struct irq_chip flexcard_irq_chip = {
                           ^~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/generic_handle_irq +111 drivers/mfd/flexcard_irq.c

   105	
   106		stat = readl(&priv->bar0->conf.irs) & VALID_DEVIRQ_MSK;
   107		while (stat) {
   108			slot = __ffs(stat);
   109			stat &= (1 << slot);
   110			cur = irq_linear_revmap(priv->irq_domain, slot);
 > 111			generic_handle_irq(cur);
   112			ret = IRQ_HANDLED;
   113		}
   114		return ret;
   115	}
   116	
   117	static void flexcard_irq_ack(struct irq_data *d)
   118	{
 > 119		struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
 > 120		const struct fc_irq_tab *tp = &flexcard_irq_tab[d->hwirq];
   121		void __iomem *p = (void __iomem *)priv->bar0 + tp->ackoffs;
   122	
   123		writel(tp->ack, p);
   124	}
   125	
   126	static void flexcard_irq_mask(struct irq_data *d)
   127	{
 > 128		struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
   129		const struct fc_irq_tab *tp = &flexcard_irq_tab[d->hwirq];
   130		void __iomem *p = (void __iomem *)priv->bar0 + tp->mskoffs;
   131		u32 *msk = (void *)priv + tp->mskcache;
   132	
   133		raw_spin_lock(&priv->irq_lock);
   134		*msk &= ~tp->msk;
   135		writel(*msk, p);
   136		raw_spin_unlock(&priv->irq_lock);
   137	}
   138	
   139	static void flexcard_irq_unmask(struct irq_data *d)
   140	{
 > 141		struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
   142		const struct fc_irq_tab *tp = &flexcard_irq_tab[d->hwirq];
   143		void __iomem *p = (void __iomem *)priv->bar0 + tp->mskoffs;
   144		u32 *msk = (void *)priv + tp->mskcache;
   145	
   146		raw_spin_lock(&priv->irq_lock);
   147		*msk |= tp->msk;
   148		writel(*msk, p);
   149		raw_spin_unlock(&priv->irq_lock);
   150	}
   151	
   152	static int flexcard_req_irq(struct pci_dev *pdev)
   153	{
   154		struct flexcard_device *priv = pci_get_drvdata(pdev);
   155		int ret;
   156	
   157		ret = pci_enable_msi(pdev);
   158		if (ret) {
   159			dev_warn(&pdev->dev, "could not enable MSI\n");
   160			/* shared PCI irq fallback */
   161			return request_irq(pdev->irq, flexcard_demux,
   162					   IRQF_NO_THREAD | IRQF_SHARED,
   163					   "flexcard", priv);
   164		}
   165		dev_info(&pdev->dev, "MSI enabled\n");
   166	
   167		ret = request_irq(pdev->irq, flexcard_demux, IRQF_NO_THREAD,
   168				  "flexcard", priv);
   169		if (ret)
   170			pci_disable_msi(pdev);
   171	
   172		return ret;
   173	}
   174	
 > 175	static struct irq_chip flexcard_irq_chip = {
 > 176		.name		= "flexcard_irq",
 > 177		.irq_ack	= flexcard_irq_ack,
 > 178		.irq_mask	= flexcard_irq_mask,
 > 179		.irq_unmask	= flexcard_irq_unmask,
   180	};
   181	
   182	static int flexcard_irq_domain_map(struct irq_domain *d, unsigned int irq,
   183					   irq_hw_number_t hw)
   184	{
   185		struct flexcard_device *priv = d->host_data;
   186	
 > 187		irq_set_chip_and_handler_name(irq, &flexcard_irq_chip,
 > 188					      handle_level_irq, "flexcard");
 > 189		irq_set_chip_data(irq, priv);
 > 190		irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
   191	
   192		return 0;
   193	}

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 59495 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 05/12] mfd: flexcard: add DMA interrupts
  2016-12-14  0:11 ` [PATCH 05/12] mfd: flexcard: add DMA interrupts Holger Dengler
@ 2016-12-14  3:08   ` kbuild test robot
  0 siblings, 0 replies; 30+ messages in thread
From: kbuild test robot @ 2016-12-14  3:08 UTC (permalink / raw)
  To: Holger Dengler
  Cc: kbuild-all, Lee Jones, Arnd Bergmann, Greg Kroah-Hartman,
	Vinod Koul, linux-kernel, dmaengine, Thomas Gleixner,
	Sebastian Siewior, Juergen Bubeck, Peter Mahler, Holger Dengler,
	Benedikt Spranger

[-- Attachment #1: Type: text/plain, Size: 10417 bytes --]

Hi Holger,

[auto build test ERROR on char-misc/char-misc-testing]
[also build test ERROR on v4.9]
[cannot apply to ljones-mfd/for-mfd-next next-20161213]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Holger-Dengler/Eberspaecher-Flexcard-PMC-II-base-support/20161214-082350
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   drivers/mfd/flexcard_irq.c: In function 'flexcard_demux':
   drivers/mfd/flexcard_irq.c:135:3: error: implicit declaration of function 'generic_handle_irq' [-Werror=implicit-function-declaration]
      generic_handle_irq(cur);
      ^~~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c: In function 'flexcard_irq_ack':
   drivers/mfd/flexcard_irq.c:143:33: error: implicit declaration of function 'irq_data_get_irq_chip_data' [-Werror=implicit-function-declaration]
     struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:143:33: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
   drivers/mfd/flexcard_irq.c:144:51: error: dereferencing pointer to incomplete type 'struct irq_data'
     const struct fc_irq_tab *tp = &flexcard_irq_tab[d->hwirq];
                                                      ^~
   drivers/mfd/flexcard_irq.c: In function 'flexcard_irq_mask':
   drivers/mfd/flexcard_irq.c:152:33: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
     struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c: In function 'flexcard_irq_unmask':
   drivers/mfd/flexcard_irq.c:165:33: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
     struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c: At top level:
   drivers/mfd/flexcard_irq.c:199:15: error: variable 'flexcard_irq_chip' has initializer but incomplete type
    static struct irq_chip flexcard_irq_chip = {
                  ^~~~~~~~
   drivers/mfd/flexcard_irq.c:200:2: error: unknown field 'name' specified in initializer
     .name  = "flexcard_irq",
     ^
   drivers/mfd/flexcard_irq.c:200:11: warning: excess elements in struct initializer
     .name  = "flexcard_irq",
              ^~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:200:11: note: (near initialization for 'flexcard_irq_chip')
   drivers/mfd/flexcard_irq.c:201:2: error: unknown field 'irq_ack' specified in initializer
     .irq_ack = flexcard_irq_ack,
     ^
   drivers/mfd/flexcard_irq.c:201:13: warning: excess elements in struct initializer
     .irq_ack = flexcard_irq_ack,
                ^~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:201:13: note: (near initialization for 'flexcard_irq_chip')
   drivers/mfd/flexcard_irq.c:202:2: error: unknown field 'irq_mask' specified in initializer
     .irq_mask = flexcard_irq_mask,
     ^
   drivers/mfd/flexcard_irq.c:202:14: warning: excess elements in struct initializer
     .irq_mask = flexcard_irq_mask,
                 ^~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:202:14: note: (near initialization for 'flexcard_irq_chip')
   drivers/mfd/flexcard_irq.c:203:2: error: unknown field 'irq_unmask' specified in initializer
     .irq_unmask = flexcard_irq_unmask,
     ^
   drivers/mfd/flexcard_irq.c:203:16: warning: excess elements in struct initializer
     .irq_unmask = flexcard_irq_unmask,
                   ^~~~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:203:16: note: (near initialization for 'flexcard_irq_chip')
   drivers/mfd/flexcard_irq.c: In function 'flexcard_irq_domain_map':
   drivers/mfd/flexcard_irq.c:211:2: error: implicit declaration of function 'irq_set_chip_and_handler_name' [-Werror=implicit-function-declaration]
     irq_set_chip_and_handler_name(irq, &flexcard_irq_chip,
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:212:11: error: 'handle_level_irq' undeclared (first use in this function)
              handle_level_irq, "flexcard");
              ^~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:212:11: note: each undeclared identifier is reported only once for each function it appears in
   drivers/mfd/flexcard_irq.c:213:2: error: implicit declaration of function 'irq_set_chip_data' [-Werror=implicit-function-declaration]
     irq_set_chip_data(irq, priv);
     ^~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:214:2: error: implicit declaration of function 'irq_modify_status' [-Werror=implicit-function-declaration]
     irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
     ^~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:214:25: error: 'IRQ_NOREQUEST' undeclared (first use in this function)
     irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
                            ^~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:214:41: error: 'IRQ_NOAUTOEN' undeclared (first use in this function)
     irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
                                            ^~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:214:55: error: 'IRQ_NOPROBE' undeclared (first use in this function)
     irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
                                                          ^~~~~~~~~~~
   drivers/mfd/flexcard_irq.c: At top level:
>> drivers/mfd/flexcard_irq.c:223:15: error: variable 'flexcard_dma_irq_chip' has initializer but incomplete type
    static struct irq_chip flexcard_dma_irq_chip = {
                  ^~~~~~~~
   drivers/mfd/flexcard_irq.c:224:2: error: unknown field 'name' specified in initializer
     .name  = "flexcard_dma_irq",
     ^
   drivers/mfd/flexcard_irq.c:224:11: warning: excess elements in struct initializer
     .name  = "flexcard_dma_irq",
              ^~~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:224:11: note: (near initialization for 'flexcard_dma_irq_chip')
   drivers/mfd/flexcard_irq.c:225:2: error: unknown field 'irq_ack' specified in initializer
     .irq_ack = flexcard_irq_ack,
     ^
   drivers/mfd/flexcard_irq.c:225:13: warning: excess elements in struct initializer
     .irq_ack = flexcard_irq_ack,
                ^~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:225:13: note: (near initialization for 'flexcard_dma_irq_chip')
   drivers/mfd/flexcard_irq.c:226:2: error: unknown field 'irq_mask' specified in initializer
     .irq_mask = flexcard_irq_mask,
     ^
   drivers/mfd/flexcard_irq.c:226:14: warning: excess elements in struct initializer
     .irq_mask = flexcard_irq_mask,
                 ^~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:226:14: note: (near initialization for 'flexcard_dma_irq_chip')
   drivers/mfd/flexcard_irq.c:227:2: error: unknown field 'irq_unmask' specified in initializer
     .irq_unmask = flexcard_irq_unmask,
     ^
   drivers/mfd/flexcard_irq.c:227:16: warning: excess elements in struct initializer
     .irq_unmask = flexcard_irq_unmask,
                   ^~~~~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:227:16: note: (near initialization for 'flexcard_dma_irq_chip')
   drivers/mfd/flexcard_irq.c: In function 'flexcard_dma_irq_domain_map':
   drivers/mfd/flexcard_irq.c:236:11: error: 'handle_level_irq' undeclared (first use in this function)
              handle_level_irq, "flexcard-dma");
              ^~~~~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:238:25: error: 'IRQ_NOREQUEST' undeclared (first use in this function)
     irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
                            ^~~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:238:41: error: 'IRQ_NOAUTOEN' undeclared (first use in this function)
     irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
                                            ^~~~~~~~~~~~
   drivers/mfd/flexcard_irq.c:238:55: error: 'IRQ_NOPROBE' undeclared (first use in this function)
     irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
                                                          ^~~~~~~~~~~
   drivers/mfd/flexcard_irq.c: At top level:
   drivers/mfd/flexcard_irq.c:199:24: error: storage size of 'flexcard_irq_chip' isn't known
    static struct irq_chip flexcard_irq_chip = {
                           ^~~~~~~~~~~~~~~~~
>> drivers/mfd/flexcard_irq.c:223:24: error: storage size of 'flexcard_dma_irq_chip' isn't known
    static struct irq_chip flexcard_dma_irq_chip = {
                           ^~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/flexcard_dma_irq_chip +223 drivers/mfd/flexcard_irq.c

   208	{
   209		struct flexcard_device *priv = d->host_data;
   210	
   211		irq_set_chip_and_handler_name(irq, &flexcard_irq_chip,
   212					      handle_level_irq, "flexcard");
   213		irq_set_chip_data(irq, priv);
 > 214		irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
   215	
   216		return 0;
   217	}
   218	
   219	static const struct irq_domain_ops flexcard_irq_domain_ops = {
   220		.map = flexcard_irq_domain_map,
   221	};
   222	
 > 223	static struct irq_chip flexcard_dma_irq_chip = {
   224		.name		= "flexcard_dma_irq",
   225		.irq_ack	= flexcard_irq_ack,
   226		.irq_mask	= flexcard_irq_mask,
   227		.irq_unmask	= flexcard_irq_unmask,
   228	};
   229	
   230	static int flexcard_dma_irq_domain_map(struct irq_domain *d, unsigned int irq,
   231					       irq_hw_number_t hw)
   232	{
   233		struct flexcard_device *priv = d->host_data;
   234	
   235		irq_set_chip_and_handler_name(irq, &flexcard_dma_irq_chip,
   236					      handle_level_irq, "flexcard-dma");
   237		irq_set_chip_data(irq, priv);
 > 238		irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
   239	
   240		return 0;
   241	}

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 59495 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 10/12] misc: Flexcard basic timestamp counter support
  2016-12-14  0:11 ` [PATCH 10/12] misc: Flexcard basic timestamp counter support Holger Dengler
@ 2016-12-14  3:28   ` kbuild test robot
  2016-12-14  8:46   ` Arnd Bergmann
  1 sibling, 0 replies; 30+ messages in thread
From: kbuild test robot @ 2016-12-14  3:28 UTC (permalink / raw)
  To: Holger Dengler
  Cc: kbuild-all, Lee Jones, Arnd Bergmann, Greg Kroah-Hartman,
	Vinod Koul, linux-kernel, dmaengine, Thomas Gleixner,
	Sebastian Siewior, Juergen Bubeck, Peter Mahler, Holger Dengler,
	Benedikt Spranger

[-- Attachment #1: Type: text/plain, Size: 3879 bytes --]

Hi Holger,

[auto build test ERROR on char-misc/char-misc-testing]
[also build test ERROR on v4.9]
[cannot apply to ljones-mfd/for-mfd-next next-20161213]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Holger-Dengler/Eberspaecher-Flexcard-PMC-II-base-support/20161214-082350
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All error/warnings (new ones prefixed by >>):

   drivers/misc/flexcard_posixclock.c: In function 'flexcard_clk_gettime':
>> drivers/misc/flexcard_posixclock.c:55:10: error: implicit declaration of function 'readl' [-Werror=implicit-function-declaration]
     upper = readl(clk->ts64);
             ^~~~~
   drivers/misc/flexcard_posixclock.c: In function 'flexcard_clk_settime':
>> drivers/misc/flexcard_posixclock.c:75:2: error: implicit declaration of function 'writel' [-Werror=implicit-function-declaration]
     writel(FLEXCARD_RST_TS, clk->reset);
     ^~~~~~
   drivers/misc/flexcard_posixclock.c: In function 'flexcard_clk_iomap':
>> drivers/misc/flexcard_posixclock.c:96:14: error: implicit declaration of function 'devm_ioremap' [-Werror=implicit-function-declaration]
     clk->ts64 = devm_ioremap(&pdev->dev, res->start, resource_size(res));
                 ^~~~~~~~~~~~
>> drivers/misc/flexcard_posixclock.c:96:12: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
     clk->ts64 = devm_ioremap(&pdev->dev, res->start, resource_size(res));
               ^
   drivers/misc/flexcard_posixclock.c:104:13: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
     clk->reset = devm_ioremap(&pdev->dev, res->start, resource_size(res));
                ^
   cc1: some warnings being treated as errors

vim +/readl +55 drivers/misc/flexcard_posixclock.c

    49	{
    50		struct flexcard_clk *clk = container_of(pc, struct flexcard_clk, clock);
    51		u64 now;
    52		u32 upper, rem;
    53	
    54	retry:
  > 55		upper = readl(clk->ts64);
    56		now = ((u64) upper << 32) | readl(clk->ts64 + 4);
    57		if (upper != readl(clk->ts64))
    58			goto retry;
    59	
    60		tp->tv_sec = div_u64_rem(now, 1000000, &rem);
    61		tp->tv_nsec = rem * 1000;
    62	
    63		return 0;
    64	}
    65	
    66	static int flexcard_clk_settime(struct posix_clock *pc,
    67					  const struct timespec *tp)
    68	{
    69		struct flexcard_clk *clk = container_of(pc, struct flexcard_clk, clock);
    70	
    71		/* The FlexCard posix clock could only be reset to 0 and not set */
    72		if (tp->tv_sec || tp->tv_nsec)
    73			return -EINVAL;
    74	
  > 75		writel(FLEXCARD_RST_TS, clk->reset);
    76	
    77		return 0;
    78	}
    79	
    80	static struct posix_clock_operations flexcard_clk_ops = {
    81		.owner		= THIS_MODULE,
    82		.clock_getres	= flexcard_clk_getres,
    83		.clock_gettime	= flexcard_clk_gettime,
    84		.clock_settime	= flexcard_clk_settime,
    85	};
    86	
    87	static int flexcard_clk_iomap(struct platform_device *pdev)
    88	{
    89		struct flexcard_clk *clk = platform_get_drvdata(pdev);
    90		struct resource *res;
    91	
    92		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    93		if (!res)
    94			return -ENXIO;
    95	
  > 96		clk->ts64 = devm_ioremap(&pdev->dev, res->start, resource_size(res));
    97		if (!clk->ts64)
    98			return -ENOMEM;
    99	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 59509 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 04/12] mfd: flexcard: add interrupt support
  2016-12-14  0:11 ` [PATCH 04/12] mfd: flexcard: add interrupt support Holger Dengler
  2016-12-14  2:47   ` kbuild test robot
@ 2016-12-14  3:37   ` kbuild test robot
  1 sibling, 0 replies; 30+ messages in thread
From: kbuild test robot @ 2016-12-14  3:37 UTC (permalink / raw)
  To: Holger Dengler
  Cc: kbuild-all, Lee Jones, Arnd Bergmann, Greg Kroah-Hartman,
	Vinod Koul, linux-kernel, dmaengine, Thomas Gleixner,
	Sebastian Siewior, Juergen Bubeck, Peter Mahler, Holger Dengler,
	Benedikt Spranger

[-- Attachment #1: Type: text/plain, Size: 5018 bytes --]

Hi Holger,

[auto build test ERROR on char-misc/char-misc-testing]
[also build test ERROR on v4.9]
[cannot apply to ljones-mfd/for-mfd-next next-20161213]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Holger-Dengler/Eberspaecher-Flexcard-PMC-II-base-support/20161214-082350
config: tile-allyesconfig (attached as .config)
compiler: tilegx-linux-gcc (GCC) 4.6.2
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=tile 

All errors (new ones prefixed by >>):

   drivers/mfd/flexcard_irq.c: In function 'flexcard_demux':
   drivers/mfd/flexcard_irq.c:111:3: error: implicit declaration of function 'generic_handle_irq'
   drivers/mfd/flexcard_irq.c: In function 'flexcard_irq_ack':
   drivers/mfd/flexcard_irq.c:119:9: error: implicit declaration of function 'irq_data_get_irq_chip_data'
   drivers/mfd/flexcard_irq.c:119:33: warning: initialization makes pointer from integer without a cast [enabled by default]
>> drivers/mfd/flexcard_irq.c:120:51: error: dereferencing pointer to incomplete type
   drivers/mfd/flexcard_irq.c: In function 'flexcard_irq_mask':
   drivers/mfd/flexcard_irq.c:128:33: warning: initialization makes pointer from integer without a cast [enabled by default]
   drivers/mfd/flexcard_irq.c:129:51: error: dereferencing pointer to incomplete type
   drivers/mfd/flexcard_irq.c: In function 'flexcard_irq_unmask':
   drivers/mfd/flexcard_irq.c:141:33: warning: initialization makes pointer from integer without a cast [enabled by default]
   drivers/mfd/flexcard_irq.c:142:51: error: dereferencing pointer to incomplete type
   drivers/mfd/flexcard_irq.c: At top level:
   drivers/mfd/flexcard_irq.c:175:15: error: variable 'flexcard_irq_chip' has initializer but incomplete type
   drivers/mfd/flexcard_irq.c:176:2: error: unknown field 'name' specified in initializer
   drivers/mfd/flexcard_irq.c:176:2: warning: excess elements in struct initializer [enabled by default]
   drivers/mfd/flexcard_irq.c:176:2: warning: (near initialization for 'flexcard_irq_chip') [enabled by default]
   drivers/mfd/flexcard_irq.c:177:2: error: unknown field 'irq_ack' specified in initializer
   drivers/mfd/flexcard_irq.c:177:2: warning: excess elements in struct initializer [enabled by default]
   drivers/mfd/flexcard_irq.c:177:2: warning: (near initialization for 'flexcard_irq_chip') [enabled by default]
   drivers/mfd/flexcard_irq.c:178:2: error: unknown field 'irq_mask' specified in initializer
   drivers/mfd/flexcard_irq.c:178:2: warning: excess elements in struct initializer [enabled by default]
   drivers/mfd/flexcard_irq.c:178:2: warning: (near initialization for 'flexcard_irq_chip') [enabled by default]
   drivers/mfd/flexcard_irq.c:179:2: error: unknown field 'irq_unmask' specified in initializer
   drivers/mfd/flexcard_irq.c:179:2: warning: excess elements in struct initializer [enabled by default]
   drivers/mfd/flexcard_irq.c:179:2: warning: (near initialization for 'flexcard_irq_chip') [enabled by default]
   drivers/mfd/flexcard_irq.c: In function 'flexcard_irq_domain_map':
   drivers/mfd/flexcard_irq.c:187:2: error: implicit declaration of function 'irq_set_chip_and_handler_name'
   drivers/mfd/flexcard_irq.c:188:11: error: 'handle_level_irq' undeclared (first use in this function)
   drivers/mfd/flexcard_irq.c:188:11: note: each undeclared identifier is reported only once for each function it appears in
   drivers/mfd/flexcard_irq.c:189:2: error: implicit declaration of function 'irq_set_chip_data'
   drivers/mfd/flexcard_irq.c:190:2: error: implicit declaration of function 'irq_modify_status'
   drivers/mfd/flexcard_irq.c:190:25: error: 'IRQ_NOREQUEST' undeclared (first use in this function)
   drivers/mfd/flexcard_irq.c:190:41: error: 'IRQ_NOAUTOEN' undeclared (first use in this function)
   drivers/mfd/flexcard_irq.c:190:55: error: 'IRQ_NOPROBE' undeclared (first use in this function)
   cc1: some warnings being treated as errors

vim +120 drivers/mfd/flexcard_irq.c

   105	
   106		stat = readl(&priv->bar0->conf.irs) & VALID_DEVIRQ_MSK;
   107		while (stat) {
   108			slot = __ffs(stat);
   109			stat &= (1 << slot);
   110			cur = irq_linear_revmap(priv->irq_domain, slot);
 > 111			generic_handle_irq(cur);
   112			ret = IRQ_HANDLED;
   113		}
   114		return ret;
   115	}
   116	
   117	static void flexcard_irq_ack(struct irq_data *d)
   118	{
   119		struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
 > 120		const struct fc_irq_tab *tp = &flexcard_irq_tab[d->hwirq];
   121		void __iomem *p = (void __iomem *)priv->bar0 + tp->ackoffs;
   122	
   123		writel(tp->ack, p);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 46516 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 01/12] mfd: Eberspaecher Flexcard PMC II Carrier Board support
  2016-12-14  0:11 ` [PATCH 01/12] mfd: Eberspaecher Flexcard PMC II Carrier Board support Holger Dengler
@ 2016-12-14  8:38   ` Arnd Bergmann
  2017-01-05 13:52     ` Holger Dengler
  0 siblings, 1 reply; 30+ messages in thread
From: Arnd Bergmann @ 2016-12-14  8:38 UTC (permalink / raw)
  To: Holger Dengler
  Cc: Lee Jones, Greg Kroah-Hartman, Vinod Koul, linux-kernel,
	dmaengine, Thomas Gleixner, Sebastian Siewior, Juergen Bubeck,
	Peter Mahler, Benedikt Spranger

On Wednesday, December 14, 2016 1:11:42 AM CET Holger Dengler wrote:
>
> diff --git a/include/uapi/linux/flexcard.h b/include/uapi/linux/flexcard.h
> new file mode 100644
> index 0000000..4e9f07b4
> --- /dev/null
> +++ b/include/uapi/linux/flexcard.h
> @@ -0,0 +1,64 @@

Why is this exported to user space?

> +
> +#include <linux/types.h>
> +
> +struct fc_version {
> +	__u8	dev;
> +	__u8	min;
> +	__u8	maj;
> +	__u8	reserved;
> +} __packed;

The __packed attribute is redundant here as all members
are just one byte anyway.

> +/* PCI BAR 0: Flexcard configuration */
> +struct fc_bar0_conf {
> +	__u32 r1;			/* 000 */
> +	struct fc_version fc_fw_ver;	/* 004 */
> +	struct fc_version fc_hw_ver;	/* 008 */
> +	__u32 r2[3];			/* 00c */
> +	__u64 fc_sn;			/* 018 */
> +	__u32 fc_uid;			/* 020 */
> +	__u32 r3[7];			/* 024 */
> +	__u32 fc_lic[6];		/* 040 */
> +	__u32 fc_slic[6];		/* 058 */
> +	__u32 trig_ctrl1;		/* 070 */
> +	__u32 r4;			/* 074 */
> +	__u32 trig_ctrl2;		/* 078 */
> +	__u32 r5[22];			/* 07c */
> +	__u32 amreg;			/* 0d4 */
> +	__u32 tiny_stat;		/* 0d8 */
> +	__u32 r6[5];			/* 0dc */
> +	__u32 can_dat_cnt;		/* 0f0 */
> +	__u32 can_err_cnt;		/* 0f4 */
> +	__u32 fc_data_cnt;		/* 0f8 */
> +	__u32 r7;			/* 0fc */
> +	__u32 fc_rocr;			/* 100 */
> +	__u32 r8;			/* 104 */
> +	__u32 pg_ctrl;			/* 108 */
> +	__u32 pg_term;			/* 10c */
> +	__u32 r9;			/* 110 */
> +	__u32 irs;			/* 114 */
> +	__u32 fr_tx_cnt;		/* 118 */
> +	__u32 irc;			/* 11c */
> +	__u64 pcnt;			/* 120 */
> +	__u32 r10;			/* 128 */
> +	__u32 nmv_cnt;			/* 12c */
> +	__u32 info_cnt;			/* 130 */
> +	__u32 stat_trg_cnt;		/* 134 */
> +	__u32 r11;			/* 138 */
> +	__u32 fr_rx_cnt;		/* 13c */
> +} __packed;

Here the __packed attribute is probably harmful, it prevents you
from accessing the members using 32-bit sized accesses and forces
bytewise accesses on some architectures, which tends to do the
wrong thing on MMIO.

	Arnd

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 08/12] misc: Flexcard misc device support
  2016-12-14  0:11 ` [PATCH 08/12] misc: Flexcard misc device support Holger Dengler
@ 2016-12-14  8:42   ` Arnd Bergmann
  2016-12-14  9:28     ` Holger Dengler
  0 siblings, 1 reply; 30+ messages in thread
From: Arnd Bergmann @ 2016-12-14  8:42 UTC (permalink / raw)
  To: Holger Dengler
  Cc: Lee Jones, Greg Kroah-Hartman, Vinod Koul, linux-kernel,
	dmaengine, Thomas Gleixner, Sebastian Siewior, Juergen Bubeck,
	Peter Mahler, Benedikt Spranger

On Wednesday, December 14, 2016 1:11:49 AM CET Holger Dengler wrote:
> 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 <b.spranger@linutronix.de>
> Signed-off-by: Holger Dengler <dengler@linutronix.de>
> cc: Arnd Bergmann <arnd@arndb.de>
> cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---
>  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
> 

Maybe this could fit better in drivers/uio/ than drivers/misc? It
seems to only export a memory mapped device.

	Arnd

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 10/12] misc: Flexcard basic timestamp counter support
  2016-12-14  0:11 ` [PATCH 10/12] misc: Flexcard basic timestamp counter support Holger Dengler
  2016-12-14  3:28   ` kbuild test robot
@ 2016-12-14  8:46   ` Arnd Bergmann
  2016-12-14  9:16     ` Thomas Gleixner
  1 sibling, 1 reply; 30+ messages in thread
From: Arnd Bergmann @ 2016-12-14  8:46 UTC (permalink / raw)
  To: Holger Dengler
  Cc: Lee Jones, Greg Kroah-Hartman, Vinod Koul, linux-kernel,
	dmaengine, Thomas Gleixner, Sebastian Siewior, Juergen Bubeck,
	Peter Mahler, Benedikt Spranger

On Wednesday, December 14, 2016 1:11:51 AM CET Holger Dengler wrote:
> The Eberspaecher Flexcard PMC II offers a Flexray network synchronized
> counter with a selectable resolution of 1us, 100ns or 10ns. Add basic
> support for the timestamp counter with 1us resolution, which is the
> standard Flexray bus resolution.
> 
> Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
> Signed-off-by: Holger Dengler <dengler@linutronix.de>
> cc: Arnd Bergmann <arnd@arndb.de>
> cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> 

Have you tried fitting this in the drivers/ptp/ framework rather
than having your own posix clock for it?

No idea if that works, it's just a thought I had.

	Arnd

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 10/12] misc: Flexcard basic timestamp counter support
  2016-12-14  8:46   ` Arnd Bergmann
@ 2016-12-14  9:16     ` Thomas Gleixner
  0 siblings, 0 replies; 30+ messages in thread
From: Thomas Gleixner @ 2016-12-14  9:16 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Holger Dengler, Lee Jones, Greg Kroah-Hartman, Vinod Koul,
	linux-kernel, dmaengine, Sebastian Siewior, Juergen Bubeck,
	Peter Mahler, Benedikt Spranger

On Wed, 14 Dec 2016, Arnd Bergmann wrote:
> On Wednesday, December 14, 2016 1:11:51 AM CET Holger Dengler wrote:
> > The Eberspaecher Flexcard PMC II offers a Flexray network synchronized
> > counter with a selectable resolution of 1us, 100ns or 10ns. Add basic
> > support for the timestamp counter with 1us resolution, which is the
> > standard Flexray bus resolution.
> > 
> > Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
> > Signed-off-by: Holger Dengler <dengler@linutronix.de>
> > cc: Arnd Bergmann <arnd@arndb.de>
> > cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > 
> 
> Have you tried fitting this in the drivers/ptp/ framework rather
> than having your own posix clock for it?

It has nothing to do with PTP. It's a completely seperate clock and cannot
be used for PTP style time synchronization.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 08/12] misc: Flexcard misc device support
  2016-12-14  8:42   ` Arnd Bergmann
@ 2016-12-14  9:28     ` Holger Dengler
  2017-01-10 16:59       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 30+ messages in thread
From: Holger Dengler @ 2016-12-14  9:28 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Lee Jones, Greg Kroah-Hartman, Vinod Koul, linux-kernel,
	dmaengine, Thomas Gleixner, Sebastian Siewior, Juergen Bubeck,
	Peter Mahler, Benedikt Spranger

[-- Attachment #1: Type: text/plain, Size: 1318 bytes --]

On 12/14/2016 09:42 AM, Arnd Bergmann wrote:
> On Wednesday, December 14, 2016 1:11:49 AM CET Holger Dengler wrote:
>> 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 <b.spranger@linutronix.de>
>> Signed-off-by: Holger Dengler <dengler@linutronix.de>
>> cc: Arnd Bergmann <arnd@arndb.de>
>> cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> ---
>>  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
>>
> 
> Maybe this could fit better in drivers/uio/ than drivers/misc? It
> seems to only export a memory mapped device.

You're right, this patch only introduce the memory mapping. But the next patch in series add also some attributes to the device, therfore we put it in drivers/misc. 

> 
> 	Arnd
> 

-- 
Gruß,
Holger Dengler
--
phone: +49 7556 25 999 14; fax: +49 7556 25 999 99


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 12/12] dma: Flexcard DMA ringbuffer demux driver
  2016-12-14  0:11 ` [PATCH 12/12] dma: Flexcard DMA ringbuffer demux driver Holger Dengler
  2016-12-14  1:54   ` kbuild test robot
@ 2016-12-15  4:38   ` Vinod Koul
  2016-12-19 10:54     ` Holger Dengler
  1 sibling, 1 reply; 30+ messages in thread
From: Vinod Koul @ 2016-12-15  4:38 UTC (permalink / raw)
  To: Holger Dengler
  Cc: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, linux-kernel,
	dmaengine, Thomas Gleixner, Sebastian Siewior, Juergen Bubeck,
	Peter Mahler, Benedikt Spranger

On Wed, Dec 14, 2016 at 01:11:53AM +0100, Holger Dengler wrote:
> The Flexcard interface design split packet receive and transmit. All
> received packets and card status information are multiplexed with a
> Flexcard specific protocol and handled through a DMA capable ringbuffer.
> The TX path has to poke each available component separate.
> 
> Add a Flexcard DMA ringbuffer driver and packet demultiplexer.

so the dma driver should only provide service and not do demuxing...

> +config FLEXCARD_DMA
> +	tristate "DMA support for Eberspaecher Flexcard PMC II Carrier Board"
> +	depends on MFD_FLEXCARD
> +	help
> +	  The Eberspaecher Flexcard PMC (PCI Mezzanine Card) II carrier
> +	  board support one DMA capable receive ringbuffer for all devices.
> +	  A card specific protocol is used to multiplex the received packets
> +	  through the ringbuffer. Enable DMA and Packet parser.
> +

This file is sorted alphabetically, so please add it it relavant place

> +#define DMA_TOTAL_BUF_SIZE		(2*FLEXCARD_DMA_BUF_SIZE)

space around * pls

> +#define FLEXCARD_DMA_BUF_SIZE		0x200000
> +#define FLEXCARD_DMA_BUF_MASK		(FLEXCARD_DMA_BUF_SIZE - 1)
> +
> +#define FLEXCARD_DMA_CTRL_DMA_ENA	(1 << 0)
> +#define FLEXCARD_DMA_CTRL_MAN_ENA	(1 << 1)
> +#define FLEXCARD_DMA_CTRL_STOP_REQ	(1 << 16)
> +#define FLEXCARD_DMA_CTRL_DMA_IDLE	(1 << 17)
> +#define FLEXCARD_DMA_CTRL_RST_DMA	(1 << 31)

BIT() and friends please

> +
> +#define FLEXCARD_DMA_STAT_BUSY		(1 << 15)
> +#define FLEXCARD_DMA_STAT_OFL		(1 << 31)
> +
> +#define FLEXCARD_MAX_PAKET_SIZE		0x200
> +
> +#define FLEXCARD_BUF_HEADER_LEN_SHIFT	15
> +#define FLEXCARD_BUF_HEADER_LEN_MASK	0xfe
> +
> +#define FLEXCARD_CANIF_OFFSET		0x20

Okay I have skipped over the parser and other stuff and still looking for
the dmaengine APIs. 

This driver _doesn't_ do that, and am not sure why.

Anyway, if this driver doesnt need dmaengine APIs it doesnt belong in
drivers/dma/. Otherwise please port to dmanegine APIs, possibly use parser
as a client. You cna use virt-channels as well for managing the transfers.

So I am not considering this submission

Thanks
-- 
~Vinod

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 12/12] dma: Flexcard DMA ringbuffer demux driver
  2016-12-15  4:38   ` Vinod Koul
@ 2016-12-19 10:54     ` Holger Dengler
  0 siblings, 0 replies; 30+ messages in thread
From: Holger Dengler @ 2016-12-19 10:54 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Lee Jones, Arnd Bergmann, Greg Kroah-Hartman, linux-kernel,
	dmaengine, Thomas Gleixner, Sebastian Siewior, Juergen Bubeck,
	Peter Mahler, Benedikt Spranger

[-- Attachment #1: Type: text/plain, Size: 3102 bytes --]

On 12/15/2016 05:38 AM, Vinod Koul wrote:
> On Wed, Dec 14, 2016 at 01:11:53AM +0100, Holger Dengler wrote:
>> The Flexcard interface design split packet receive and transmit. All
>> received packets and card status information are multiplexed with a
>> Flexcard specific protocol and handled through a DMA capable ringbuffer.
>> The TX path has to poke each available component separate.
>>
>> Add a Flexcard DMA ringbuffer driver and packet demultiplexer.
> 
> so the dma driver should only provide service and not do demuxing...

The Flexcard can be equipped with multiple functional modules (so called Tinys). Unfortunately, the RX traffic of all Tinys is handled by the base card in a single DMA-ringbuffer. No separate channels, no scatter-gather-lists. So RX-demuxing must be done by one single instance per base card. The TX-path is _not_ handled via DMA, the data goes directly to the Tiny registers.

>> +#define FLEXCARD_DMA_STAT_BUSY		(1 << 15)
>> +#define FLEXCARD_DMA_STAT_OFL		(1 << 31)
>> +
>> +#define FLEXCARD_MAX_PAKET_SIZE		0x200
>> +
>> +#define FLEXCARD_BUF_HEADER_LEN_SHIFT	15
>> +#define FLEXCARD_BUF_HEADER_LEN_MASK	0xfe
>> +
>> +#define FLEXCARD_CANIF_OFFSET		0x20
> 
> Okay I have skipped over the parser and other stuff and still looking for
> the dmaengine APIs. 
> 
> This driver _doesn't_ do that, and am not sure why.

The main reason, why we do not used the dmaengine interfaces, is, that the Flexcard DMA engine is not as flexible as normal DMA engines are. It is only used for the receive path, it does not support separate channels per Tiny and it uses a single ring-buffer instead of scatter-gather-lists. If we would use the dmaengine interfaces, we would end up with a solution, that accepts only one client per card, and the client must always be the parser (because of the demuxing). Therefore, I do not see any advantage in using the dmaengine interfaces.

> Anyway, if this driver doesnt need dmaengine APIs it doesnt belong in
> drivers/dma/. Otherwise please port to dmanegine APIs, possibly use parser
> as a client. You cna use virt-channels as well for managing the transfers.

Ok, I can follow your argumentation, that the driver for the Flexcard "DMA" does not belong to drivers/dma. In our second post [1], we had it in drivers/mfd, but Lee mentioned, that it is not a mfd driver and asked us to move it to drivers/dma [2]. But if it is neither a mfd nor a dmaengine driver, what kind of driver is it? What is the right place for this driver? (Maybe the naming of the driver is too confusing. Although the Flexcard use DMA (from a technically point of view), this function is more a RX-demux-engine...)

@Lee: 
with Vinods comments, the information above and (optionally) a renaming, do you see any possibility to re-include it in drivers/mfd?

[1] http://www.spinics.net/lists/kernel/msg1954282.html
[2] http://www.spinics.net/lists/kernel/msg1957525.html

> 
> So I am not considering this submission
> 
> Thanks
> 
-- 
Gruß,
Holger Dengler
--
phone: +49 7556 25 999 14; fax: +49 7556 25 999 99


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 00/12] Eberspaecher Flexcard PMC II base support
  2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
                   ` (11 preceding siblings ...)
  2016-12-14  0:11 ` [PATCH 12/12] dma: Flexcard DMA ringbuffer demux driver Holger Dengler
@ 2017-01-04  9:43 ` Lee Jones
  12 siblings, 0 replies; 30+ messages in thread
From: Lee Jones @ 2017-01-04  9:43 UTC (permalink / raw)
  To: Holger Dengler
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Vinod Koul, linux-kernel,
	dmaengine, Thomas Gleixner, Sebastian Siewior, Juergen Bubeck,
	Peter Mahler

On Wed, 14 Dec 2016, Holger Dengler wrote:

> 
> The Eberspaecher Flexcard PMC II is a PMC (PCI Mezzanine Card) II
> carrier board. The carrier board can take up to 4 exchangeable physical
> layer boards for CAN, FlexRay or Ethernet.
> This patchset adds support for the common infrastructure of the carrier
> board.
> 
> This patch series apply on v4.9.
> 
> First post:  http://www.spinics.net/lists/netdev/msg246290.html
> Second post: http://www.spinics.net/lists/kernel/msg1954275.html
> 
> According to the comments regarding our first posting, the MFD driver
> patchset has been split up into separate functional parts.
> 
> According to the comments regarding our second port, we moved the
> separated driver to their particular subsystems. All other comments
> are also reflected.
> 
> The timer functionality was wrongly named as clocksource in the second post,
> although it is a posix_clock. We renamed it and moved it together with the
> misc_device funtions to drivers/misc/. If someone know a better place for
> the posix_clock, please let me know.
> 
> The irq part of the mfd driver has been mainly reworked (thanks to Thomas
> and Sebastian for their input). The irq-demux is now implementet without a
> loop and the irq_chips share the irq-table and functions.
> 
> Holger Dengler (12):
>   mfd: Eberspaecher Flexcard PMC II Carrier Board support
>   mfd: flexcard: add flexcard misc mfd-cell
>   mfd: flexcard: add posix clock mfd-cell
>   mfd: flexcard: add interrupt support
>   mfd: flexcard: add DMA interrupts
>   mfd: flexcard: add DMA device
>   mfd: flexcard: add UIO IRQ devices
>   misc: Flexcard misc device support
>   misc: flexcard: add device attributes
>   misc: Flexcard basic timestamp counter support
>   misc: flexcard: Support timestamp trigger selection
>   dma: Flexcard DMA ringbuffer demux driver
> 
>  drivers/dma/Kconfig                 |   9 +
>  drivers/dma/Makefile                |   1 +
>  drivers/dma/flexcard/Makefile       |   2 +
>  drivers/dma/flexcard/core.c         | 292 ++++++++++++++++++++++
>  drivers/dma/flexcard/flexcard-dma.h | 218 +++++++++++++++++
>  drivers/dma/flexcard/parser.c       | 227 +++++++++++++++++

>  drivers/mfd/Kconfig                 |  14 ++
>  drivers/mfd/Makefile                |   3 +
>  drivers/mfd/flexcard_core.c         | 476 ++++++++++++++++++++++++++++++++++++
>  drivers/mfd/flexcard_irq.c          | 305 +++++++++++++++++++++++
>  include/linux/mfd/flexcard.h        | 116 +++++++++

Place all of this in one patch to aid review.

>  drivers/misc/Kconfig                |  15 ++
>  drivers/misc/Makefile               |   2 +
>  drivers/misc/flexcard_misc.c        | 361 +++++++++++++++++++++++++++
>  drivers/misc/flexcard_posixclock.c  | 295 ++++++++++++++++++++++
>  include/uapi/linux/Kbuild           |   1 +
>  include/uapi/linux/flexcard.h       |  80 ++++++
>  17 files changed, 2417 insertions(+)
>  create mode 100644 drivers/dma/flexcard/Makefile
>  create mode 100644 drivers/dma/flexcard/core.c
>  create mode 100644 drivers/dma/flexcard/flexcard-dma.h
>  create mode 100644 drivers/dma/flexcard/parser.c
>  create mode 100644 drivers/mfd/flexcard_core.c
>  create mode 100644 drivers/mfd/flexcard_irq.c
>  create mode 100644 drivers/misc/flexcard_misc.c
>  create mode 100644 drivers/misc/flexcard_posixclock.c
>  create mode 100644 include/linux/mfd/flexcard.h
>  create mode 100644 include/uapi/linux/flexcard.h
> 

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 01/12] mfd: Eberspaecher Flexcard PMC II Carrier Board support
  2016-12-14  8:38   ` Arnd Bergmann
@ 2017-01-05 13:52     ` Holger Dengler
  0 siblings, 0 replies; 30+ messages in thread
From: Holger Dengler @ 2017-01-05 13:52 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Lee Jones, Greg Kroah-Hartman, Vinod Koul, linux-kernel,
	dmaengine, Thomas Gleixner, Sebastian Siewior, Juergen Bubeck,
	Peter Mahler, Benedikt Spranger


[-- Attachment #1.1: Type: text/plain, Size: 2868 bytes --]

On 12/14/2016 09:38 AM, Arnd Bergmann wrote:
> On Wednesday, December 14, 2016 1:11:42 AM CET Holger Dengler wrote:
>>
>> diff --git a/include/uapi/linux/flexcard.h b/include/uapi/linux/flexcard.h
>> new file mode 100644
>> index 0000000..4e9f07b4
>> --- /dev/null
>> +++ b/include/uapi/linux/flexcard.h
>> @@ -0,0 +1,64 @@
> 
> Why is this exported to user space?

The registers of bar0 can be accessed from userspace via mmap and the structures in this header file describe the register layout in bar0.

>> +
>> +#include <linux/types.h>
>> +
>> +struct fc_version {
>> +	__u8	dev;
>> +	__u8	min;
>> +	__u8	maj;
>> +	__u8	reserved;
>> +} __packed;
> 
> The __packed attribute is redundant here as all members
> are just one byte anyway.

Both structures (struct fc_version and struct fc_bar0_conf) describe the layout of the registers in bar0. Therefore it must be guaranteed (on all architectures) that the compiler don't insert any spare-parts in the structures. My current understanding is, that the __packed attribute has to be used exactly for such a case. But I will check this again and if it is not required, I'll remove it.

> 
>> +/* PCI BAR 0: Flexcard configuration */
>> +struct fc_bar0_conf {
>> +	__u32 r1;			/* 000 */
>> +	struct fc_version fc_fw_ver;	/* 004 */
>> +	struct fc_version fc_hw_ver;	/* 008 */
>> +	__u32 r2[3];			/* 00c */
>> +	__u64 fc_sn;			/* 018 */
>> +	__u32 fc_uid;			/* 020 */
>> +	__u32 r3[7];			/* 024 */
>> +	__u32 fc_lic[6];		/* 040 */
>> +	__u32 fc_slic[6];		/* 058 */
>> +	__u32 trig_ctrl1;		/* 070 */
>> +	__u32 r4;			/* 074 */
>> +	__u32 trig_ctrl2;		/* 078 */
>> +	__u32 r5[22];			/* 07c */
>> +	__u32 amreg;			/* 0d4 */
>> +	__u32 tiny_stat;		/* 0d8 */
>> +	__u32 r6[5];			/* 0dc */
>> +	__u32 can_dat_cnt;		/* 0f0 */
>> +	__u32 can_err_cnt;		/* 0f4 */
>> +	__u32 fc_data_cnt;		/* 0f8 */
>> +	__u32 r7;			/* 0fc */
>> +	__u32 fc_rocr;			/* 100 */
>> +	__u32 r8;			/* 104 */
>> +	__u32 pg_ctrl;			/* 108 */
>> +	__u32 pg_term;			/* 10c */
>> +	__u32 r9;			/* 110 */
>> +	__u32 irs;			/* 114 */
>> +	__u32 fr_tx_cnt;		/* 118 */
>> +	__u32 irc;			/* 11c */
>> +	__u64 pcnt;			/* 120 */
>> +	__u32 r10;			/* 128 */
>> +	__u32 nmv_cnt;			/* 12c */
>> +	__u32 info_cnt;			/* 130 */
>> +	__u32 stat_trg_cnt;		/* 134 */
>> +	__u32 r11;			/* 138 */
>> +	__u32 fr_rx_cnt;		/* 13c */
>> +} __packed;
> 
> Here the __packed attribute is probably harmful, it prevents you
> from accessing the members using 32-bit sized accesses and forces
> bytewise accesses on some architectures, which tends to do the
> wrong thing on MMIO.

Is this also true, if the base address for this struct is always 32bit-alligned (because it is the base address of bar0)?

> 
> 	Arnd
> 

-- 
Gruß,
Holger Dengler
--
phone: +49 7556 25 999 14; fax: +49 7556 25 999 99


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 09/12] misc: flexcard: add device attributes
  2016-12-14  0:11 ` [PATCH 09/12] misc: flexcard: add device attributes Holger Dengler
  2016-12-14  1:33   ` kbuild test robot
@ 2017-01-10 16:58   ` Greg Kroah-Hartman
  1 sibling, 0 replies; 30+ messages in thread
From: Greg Kroah-Hartman @ 2017-01-10 16:58 UTC (permalink / raw)
  To: Holger Dengler
  Cc: Lee Jones, Arnd Bergmann, Vinod Koul, linux-kernel, dmaengine,
	Thomas Gleixner, Sebastian Siewior, Juergen Bubeck, Peter Mahler,
	Benedikt Spranger

On Wed, Dec 14, 2016 at 01:11:50AM +0100, Holger Dengler wrote:
> Add device attributes for common flexcard information access. The
> attribiutes are read-only execpt "uid" (user ID register).
> The "uid" attribute can also be used to change the user-defined ID of a
> Flexcard.
> 
> Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
> Signed-off-by: Holger Dengler <dengler@linutronix.de>
> cc: Arnd Bergmann <arnd@arndb.de>
> cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---
>  drivers/misc/flexcard_misc.c | 196 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 196 insertions(+)

You didn't document your new sysfs files in Documentation/ABI/ ?

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 08/12] misc: Flexcard misc device support
  2016-12-14  9:28     ` Holger Dengler
@ 2017-01-10 16:59       ` Greg Kroah-Hartman
  0 siblings, 0 replies; 30+ messages in thread
From: Greg Kroah-Hartman @ 2017-01-10 16:59 UTC (permalink / raw)
  To: Holger Dengler
  Cc: Arnd Bergmann, Lee Jones, Vinod Koul, linux-kernel, dmaengine,
	Thomas Gleixner, Sebastian Siewior, Juergen Bubeck, Peter Mahler,
	Benedikt Spranger

On Wed, Dec 14, 2016 at 10:28:25AM +0100, Holger Dengler wrote:
> On 12/14/2016 09:42 AM, Arnd Bergmann wrote:
> > On Wednesday, December 14, 2016 1:11:49 AM CET Holger Dengler wrote:
> >> 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 <b.spranger@linutronix.de>
> >> Signed-off-by: Holger Dengler <dengler@linutronix.de>
> >> cc: Arnd Bergmann <arnd@arndb.de>
> >> cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> >> ---
> >>  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
> >>
> > 
> > Maybe this could fit better in drivers/uio/ than drivers/misc? It
> > seems to only export a memory mapped device.
> 
> You're right, this patch only introduce the memory mapping. But the
> next patch in series add also some attributes to the device, therfore
> we put it in drivers/misc. 

That's fine, it should still be a uio driver as that's what it does.
You can have sysfs files for a UIO device, right?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2017-01-10 16:58 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-14  0:11 [PATCH 00/12] Eberspaecher Flexcard PMC II base support Holger Dengler
2016-12-14  0:11 ` [PATCH 01/12] mfd: Eberspaecher Flexcard PMC II Carrier Board support Holger Dengler
2016-12-14  8:38   ` Arnd Bergmann
2017-01-05 13:52     ` Holger Dengler
2016-12-14  0:11 ` [PATCH 02/12] mfd: flexcard: add flexcard misc mfd-cell Holger Dengler
2016-12-14  0:11 ` [PATCH 03/12] mfd: flexcard: add posix clock mfd-cell Holger Dengler
2016-12-14  0:11 ` [PATCH 04/12] mfd: flexcard: add interrupt support Holger Dengler
2016-12-14  2:47   ` kbuild test robot
2016-12-14  3:37   ` kbuild test robot
2016-12-14  0:11 ` [PATCH 05/12] mfd: flexcard: add DMA interrupts Holger Dengler
2016-12-14  3:08   ` kbuild test robot
2016-12-14  0:11 ` [PATCH 06/12] mfd: flexcard: add DMA device Holger Dengler
2016-12-14  0:11 ` [PATCH 07/12] mfd: flexcard: add UIO IRQ devices Holger Dengler
2016-12-14  0:11 ` [PATCH 08/12] misc: Flexcard misc device support Holger Dengler
2016-12-14  8:42   ` Arnd Bergmann
2016-12-14  9:28     ` Holger Dengler
2017-01-10 16:59       ` Greg Kroah-Hartman
2016-12-14  0:11 ` [PATCH 09/12] misc: flexcard: add device attributes Holger Dengler
2016-12-14  1:33   ` kbuild test robot
2017-01-10 16:58   ` Greg Kroah-Hartman
2016-12-14  0:11 ` [PATCH 10/12] misc: Flexcard basic timestamp counter support Holger Dengler
2016-12-14  3:28   ` kbuild test robot
2016-12-14  8:46   ` Arnd Bergmann
2016-12-14  9:16     ` Thomas Gleixner
2016-12-14  0:11 ` [PATCH 11/12] misc: flexcard: Support timestamp trigger selection Holger Dengler
2016-12-14  0:11 ` [PATCH 12/12] dma: Flexcard DMA ringbuffer demux driver Holger Dengler
2016-12-14  1:54   ` kbuild test robot
2016-12-15  4:38   ` Vinod Koul
2016-12-19 10:54     ` Holger Dengler
2017-01-04  9:43 ` [PATCH 00/12] Eberspaecher Flexcard PMC II base support Lee Jones

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).