devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] Introduce PTX1K Boot FPGA driver
@ 2016-10-07 15:21 Pantelis Antoniou
       [not found] ` <1475853724-22557-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Mark Rutland, devicetree, Jean Delvare, linux-hwmon,
	linux-watchdog, Georgi Vlaev, Frank Rowand, Pantelis Antoniou,
	linux-kernel, JawaharBalaji Thirumalaisamy, Wim Van Sebroeck,
	Rob Herring, linux-mtd, Brian Norris, David Woodhouse,
	Guenter Roeck

Add Juniper's PTX1K Boot FPGA driver. Those FPGAs
are present in Juniper's PTX series of routers.

The MFD driver provices watchdog/mtd/hwmon devices.

There are full device tree binding documents for the
master mfd driver and for the slave driver.

This patchset is against mainline as of today: v4.8-9431-g3477d16
and is dependent on the "Juniper prerequisites" and
"Juniper infrastructure" patchsets sent earlier.

Georgi Vlaev (7):
  mfd: Add PTX1K I2CS BootFPGA MFD driver
  mfd: dt-bindings: Add bindings for the Juniper PTX1K Boot FPGA
  watchdog: Add PTX1K I2CS BootFPGA watchdog driver.
  watchdog: ptx1kbf-wdt: Add ptx1kbf device tree bindings
  mtd: ptx1kbf: Add PTX1K BootFPGA MTD driver
  mtd: ptx1kbf: Bindings for Juniper's PTX1K Boot FPGA
  hwmon: ptx1kbf: Add PTX1K I2CS BootFPGA sensor driver

 .../devicetree/bindings/mfd/jnx-ptx1k-bootfpga.txt |  34 ++
 .../devicetree/bindings/mtd/ptx1kbf-mtd.txt        |  23 +
 .../bindings/watchdog/jnx-ptx1kbf-wdt.txt          |  17 +
 drivers/hwmon/Kconfig                              |  17 +
 drivers/hwmon/Makefile                             |   1 +
 drivers/hwmon/jnx_ptx1kbf_hwmon.c                  | 123 ++++
 drivers/mfd/Kconfig                                |  11 +
 drivers/mfd/Makefile                               |   1 +
 drivers/mfd/ptx1k-bootfpga.c                       | 462 ++++++++++++++
 drivers/mtd/devices/Kconfig                        |  10 +
 drivers/mtd/devices/Makefile                       |   1 +
 drivers/mtd/devices/jnx_ptx1kbf_mtd.c              | 677 +++++++++++++++++++++
 drivers/watchdog/Kconfig                           |  15 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/jnx_ptx1kbf_wdt.c                 | 229 +++++++
 include/linux/mfd/ptx1k-bootfpga.h                 |  93 +++
 16 files changed, 1715 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/jnx-ptx1k-bootfpga.txt
 create mode 100644 Documentation/devicetree/bindings/mtd/ptx1kbf-mtd.txt
 create mode 100644 Documentation/devicetree/bindings/watchdog/jnx-ptx1kbf-wdt.txt
 create mode 100644 drivers/hwmon/jnx_ptx1kbf_hwmon.c
 create mode 100644 drivers/mfd/ptx1k-bootfpga.c
 create mode 100644 drivers/mtd/devices/jnx_ptx1kbf_mtd.c
 create mode 100644 drivers/watchdog/jnx_ptx1kbf_wdt.c
 create mode 100644 include/linux/mfd/ptx1k-bootfpga.h

-- 
1.9.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH 1/7] mfd: Add PTX1K I2CS BootFPGA MFD driver
       [not found] ` <1475853724-22557-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
@ 2016-10-07 15:21   ` Pantelis Antoniou
  2016-10-07 15:21   ` [PATCH 2/7] mfd: dt-bindings: Add bindings for the Juniper PTX1K Boot FPGA Pantelis Antoniou
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Rob Herring, Mark Rutland, Frank Rowand, David Woodhouse,
	Brian Norris, Wim Van Sebroeck, Jean Delvare, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	linux-hwmon-u79uwXL29TY76Z2rM5mHXA

From: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>

The driver allows access to the BootFPGA logic of the I2CS FPGA
@0xfed5000 from the LPC bus. The driver exports debugfs entries
for manipulating registers and device attrs for reading board and
FPGA IDs and switching the active BIOS flash. The client devices
created by the MFD driver depend on the PCB and FPGA version
numbers. PTX1K (etch1) RE boards support only watchdog clients.
Warn on using engineering releases (FPGA version = 0xEE) and
disable clients on revisions known to cause problems.

- watchdog - jnx_ptx1kbf_wdt
- mtd - jnx_ptx1kbf_mtd (etch2)
- hwmon - jnx_ptx1kbf_hwmon (etch2)

Signed-off-by: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
Signed-off-by: Guenter Roeck <groeck-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
Signed-off-by: JawaharBalaji Thirumalaisamy <jawaharb-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
[Ported from Juniper kernel]
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
---
 drivers/mfd/Kconfig                |  11 +
 drivers/mfd/Makefile               |   1 +
 drivers/mfd/ptx1k-bootfpga.c       | 462 +++++++++++++++++++++++++++++++++++++
 include/linux/mfd/ptx1k-bootfpga.h |  93 ++++++++
 4 files changed, 567 insertions(+)
 create mode 100644 drivers/mfd/ptx1k-bootfpga.c
 create mode 100644 include/linux/mfd/ptx1k-bootfpga.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 82493d5..a2564ba 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1417,6 +1417,17 @@ config MFD_JUNIPER_I2CS
 	  This driver can be built as a module. If built as a module it will be
 	  called "jnx_i2cs"
 
+config MFD_JUNIPER_PTX1KBF
+	tristate "Juniper PTX1K RCB I2CS BootFPGA"
+	depends on JNX_PTX1K_RCB
+	select MFD_CORE
+	help
+	  Select this to enable the I2CS Boot FPGA multi-function kernel driver.
+	  This FPGA is present on the PTX1K RCB.
+
+	  This driver can be built as a module. If built as a module it will be
+	  called "ptx1k-bootfpga"
+
 config MFD_TWL4030_AUDIO
 	bool "TI TWL4030 Audio"
 	depends on TWL4030_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 215d9cf..1661b82 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -153,6 +153,7 @@ obj-$(CONFIG_MFD_JUNIPER_SAM)	+= sam-core.o
 obj-$(CONFIG_MFD_JUNIPER_EXT_CPLD) += ptxpmb-ext-cpld-core.o
 obj-$(CONFIG_MFD_JUNIPER_CBC)	+= cbc-core.o
 obj-$(CONFIG_MFD_JUNIPER_I2CS)	+= jnx-i2cs-core.o
+obj-$(CONFIG_MFD_JUNIPER_PTX1KBF) += ptx1k-bootfpga.o
 obj-$(CONFIG_MFD_DB8500_PRCMU)	+= db8500-prcmu.o
 # ab8500-core need to come after db8500-prcmu (which provides the channel)
 obj-$(CONFIG_AB8500_CORE)	+= ab8500-core.o ab8500-sysctrl.o
diff --git a/drivers/mfd/ptx1k-bootfpga.c b/drivers/mfd/ptx1k-bootfpga.c
new file mode 100644
index 0000000..5ab2ed2
--- /dev/null
+++ b/drivers/mfd/ptx1k-bootfpga.c
@@ -0,0 +1,462 @@
+/*
+ * Juniper Networks PTX1K RCB I2CS Boot FPGA multi-function core driver
+ *
+ * Copyright (C) 2014 Juniper Networks. All rights reserved.
+ * Author: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/acpi.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/ptx1k-bootfpga.h>
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#endif
+
+struct ptx1kbf_core {
+	struct device	*dev;
+	void __iomem	*base;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *dir;
+	u8 addr;				/* any register offsset */
+	struct debugfs_blob_wrapper blob;	/* regspace page blob */
+#endif
+};
+
+static struct resource ptx1kbf_resources[] = {
+	{
+		.start	= 0,
+		.end	= 0xff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct mfd_cell ptx1kbf_cells[] = {
+	{
+		.name = "jnx-ptx1kbf-wdt",
+		.num_resources = ARRAY_SIZE(ptx1kbf_resources),
+		.resources = ptx1kbf_resources,
+		.of_compatible = "jnx,ptx1kbf-wdt",
+	}, {
+		.name = "jnx-ptx1kbf-mtd",
+		.num_resources = ARRAY_SIZE(ptx1kbf_resources),
+		.resources = ptx1kbf_resources,
+		.of_compatible = "jnx,ptx1kbf-mtd",
+	}, {
+		.name = "jnx-ptx1kbf-hwmon",
+		.num_resources = ARRAY_SIZE(ptx1kbf_resources),
+		.resources = ptx1kbf_resources,
+		.of_compatible = "jnx,ptx1kbf-hwmon",
+	},
+};
+
+/* ptx1k-bootfpga debugfs */
+#ifdef CONFIG_DEBUG_FS
+/* debugfs: set/get register offset */
+static int bf_debugfs_addr_print(struct seq_file *s, void *p)
+{
+	struct ptx1kbf_core *bf = (struct ptx1kbf_core *)s->private;
+
+	seq_printf(s, "0x%02X\n", bf->addr);
+
+	return 0;
+}
+
+static int bf_debugfs_addr_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, bf_debugfs_addr_print, inode->i_private);
+}
+
+static ssize_t bf_debugfs_addr_write(struct file *file,
+	const char __user *user_buf, size_t count, loff_t *ppos)
+{
+	struct ptx1kbf_core *bf =
+		((struct seq_file *)(file->private_data))->private;
+	unsigned long addr;
+	int err;
+
+	err = kstrtoul_from_user(user_buf, count, 0, &addr);
+	if (err)
+		return err;
+
+	if (addr > ptx1kbf_resources[0].end) {
+		dev_err(bf->dev, "register offset out of range\n");
+		return -EINVAL;
+	}
+	bf->addr = addr;
+
+	return count;
+}
+
+static const struct file_operations bf_debugfs_addr_fops = {
+	.open = bf_debugfs_addr_open,
+	.write = bf_debugfs_addr_write,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+/* debugfs: set/get register value */
+static int bf_debugfs_val_print(struct seq_file *s, void *p)
+{
+	struct ptx1kbf_core *bf = (struct ptx1kbf_core *)s->private;
+
+	seq_printf(s, "0x%02X\n", ioread8(bf->base + bf->addr));
+
+	return 0;
+}
+
+static int bf_debugfs_val_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, bf_debugfs_val_print, inode->i_private);
+}
+
+static ssize_t bf_debugfs_val_write(struct file *file,
+	const char __user *user_buf, size_t count, loff_t *ppos)
+{
+	struct ptx1kbf_core *bf =
+		((struct seq_file *)(file->private_data))->private;
+	unsigned long value;
+	int err;
+
+	err = kstrtoul_from_user(user_buf, count, 0, &value);
+	if (err)
+		return err;
+
+	iowrite8(value & 0xff, bf->base + bf->addr);
+
+	return count;
+}
+
+static const struct file_operations bf_debugfs_val_fops = {
+	.open = bf_debugfs_val_open,
+	.write = bf_debugfs_val_write,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int bf_debugfs_init(struct ptx1kbf_core *bf)
+{
+	struct dentry *file;
+
+	bf->dir = debugfs_create_dir("ptx1k-bootfpga", NULL);
+	if (!bf->dir)
+		return -ENOMEM;
+
+/* Register dump */
+	bf->blob.size = resource_size(&ptx1kbf_resources[0]);
+	bf->blob.data = bf->base;
+
+	file = debugfs_create_blob("reg-dump", S_IFREG | S_IRUSR, bf->dir,
+				   &bf->blob);
+	if (!file)
+		goto err;
+
+/* Any register @base */
+	file = debugfs_create_file("reg-address", (S_IRUGO | S_IWUSR),
+		bf->dir, bf, &bf_debugfs_addr_fops);
+	if (!file)
+		goto err;
+
+	file = debugfs_create_file("reg-value", (S_IRUGO | S_IWUSR),
+		bf->dir, bf, &bf_debugfs_val_fops);
+	if (!file)
+		goto err;
+
+	return 0;
+err:
+	debugfs_remove_recursive(bf->dir);
+	dev_err(bf->dev, "failed to create debugfs entries.\n");
+
+	return -ENOMEM;
+}
+
+static void bf_debugfs_remove(struct ptx1kbf_core *bf)
+{
+	debugfs_remove_recursive(bf->dir);
+}
+#endif /* CONFIG_DEBUG_FS */
+
+/* Export FPGA board revisions and status as device attrs */
+static ssize_t bf_reg_show(struct device *dev, char *buf, u8 reg)
+{
+	struct ptx1kbf_core *bf = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%02x\n", ioread8(bf->base + reg));
+}
+
+static ssize_t bf_version_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	return bf_reg_show(dev, buf, BOOT_FPGA_VERSION);
+}
+
+static ssize_t bf_board_id_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	return bf_reg_show(dev, buf, BOOT_FPGA_BOARD_ID);
+}
+
+static ssize_t bf_jspec_version_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	return bf_reg_show(dev, buf, BOOT_FPGA_JSPEC_VERSION);
+}
+
+static ssize_t bf_pcb_version_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	return bf_reg_show(dev, buf, BOOT_FPGA_PCB_VERSION);
+}
+
+static ssize_t bf_chassis_type_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	return bf_reg_show(dev, buf, BOOT_FPGA_CHASSIS_TYPE);
+}
+
+/* active_flash: (BIOS) Switch bethween FlashA and FlashB */
+static ssize_t bf_active_flash_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct ptx1kbf_core *bf = dev_get_drvdata(dev);
+	u8 reg = ioread8(bf->base + BOOT_FPGA_BOOT_CONTROL);
+
+	return sprintf(buf, "%u\n", (u8)(reg & BC_FLASH_SELECT) >> 4);
+}
+
+static ssize_t bf_active_flash_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct ptx1kbf_core *bf = dev_get_drvdata(dev);
+	unsigned long val;
+	int err;
+	u8 reg;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	if (val > 1)
+		return -EINVAL;
+
+	reg = ioread8(bf->base + BOOT_FPGA_BOOT_CONTROL);
+	reg &= ~BC_FLASH_SELECT;
+	reg |= (u8)((val << 4) & BC_FLASH_SELECT);
+	iowrite8(reg, bf->base + BOOT_FPGA_BOOT_CONTROL);
+
+	return count;
+}
+
+static DEVICE_ATTR(version, S_IRUGO, bf_version_show, NULL);
+static DEVICE_ATTR(board_id, S_IRUGO, bf_board_id_show, NULL);
+static DEVICE_ATTR(jspec_version, S_IRUGO, bf_jspec_version_show, NULL);
+static DEVICE_ATTR(pcb_version, S_IRUGO, bf_pcb_version_show, NULL);
+static DEVICE_ATTR(chassis_type, S_IRUGO, bf_chassis_type_show, NULL);
+static DEVICE_ATTR(active_flash, S_IRUGO | S_IWUSR, bf_active_flash_show,
+		bf_active_flash_store);
+
+static struct attribute *bf_attrs[] = {
+	&dev_attr_version.attr,
+	&dev_attr_board_id.attr,
+	&dev_attr_jspec_version.attr,
+	&dev_attr_pcb_version.attr,
+	&dev_attr_chassis_type.attr,
+	&dev_attr_active_flash.attr,
+	NULL,
+};
+
+static struct attribute_group bf_attr_group = {
+	.attrs = bf_attrs,
+};
+
+/* Check if scratch regs are usable */
+static int bf_scratch_test(struct ptx1kbf_core *bf)
+{
+	u8 i, ii;
+
+	for (i = 0; i < 0xff; i++) {
+		iowrite8(i, bf->base + BOOT_FPGA_SCRATCH1);
+		ii = ioread8(bf->base + BOOT_FPGA_SCRATCH1);
+		if (ii != i) {
+			dev_err(bf->dev, "Scratch(1) write failed: %02x->%02x",
+				i, ii);
+			return -EIO;
+		}
+	}
+
+	for (i = 0; i < 0xff; i++) {
+		iowrite8(i, bf->base + BOOT_FPGA_SCRATCH2);
+		ii = ioread8(bf->base + BOOT_FPGA_SCRATCH2);
+		if (ii != i) {
+			dev_err(bf->dev, "Scratch(2) write failed: %02x->%02x",
+				i, ii);
+			return -EIO;
+		}
+	}
+
+	iowrite8(0, bf->base + BOOT_FPGA_SCRATCH1);
+	iowrite8(0, bf->base + BOOT_FPGA_SCRATCH2);
+
+	return 0;
+}
+
+static int ptx1kbf_probe(struct platform_device *pdev)
+{
+	static struct ptx1kbf_core *bf;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	int err, ncells = 0;
+	u8 pcb_version, fpga_version;
+
+	bf = devm_kzalloc(dev, sizeof(struct ptx1kbf_core), GFP_KERNEL);
+	if (!bf)
+		return -ENOMEM;
+
+	bf->dev = dev;
+	dev_set_drvdata(dev, bf);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	bf->base = devm_ioremap_nocache(dev, res->start, resource_size(res));
+	if (IS_ERR(bf->base))
+		return -EADDRNOTAVAIL;
+
+	/* Get the FPGA & PCB versions to filter supported features */
+	fpga_version = ioread8(bf->base + BOOT_FPGA_VERSION),
+	pcb_version = ioread8(bf->base + BOOT_FPGA_PCB_VERSION);
+
+	dev_info(dev, "FPGA version: 0x%02X, PCB version: 0x%02X\n",
+		 fpga_version, pcb_version);
+
+	/* Exit if scratch loop fails */
+	err = bf_scratch_test(bf);
+	if (err)
+		return err;
+
+	/*
+	 * Support matrix.
+	 * PCB version #0 (ETCH1) = Spartan XC3S400AN
+	 * PCB version #1 (ETCH2) = Spartan XC3S700AN
+	 *
+	 * PCB version #0 supported devices
+	 *	- watchdog (FPGA version >= 0x0E)
+	 *	- hwmon & mtd unsupported due to FPGA limitations
+	 *
+	 * PCB version #1 supported devices
+	 *	- watchdog (FPGA version >= 0x0E)
+	 *	- mtd devices (FPGA version > 0x0E)
+	 *	- hwmon (FPGA version > 0x0F ?)
+	 *
+	 * FPGA version 0xEE is "engineering release", warn on usage.
+	 * FPGA version 0xC0 and < 0x0E are unsupported.
+	 */
+
+	/* Engineering release - allow it to run for testing/debug */
+	if (fpga_version == 0xEE) {
+		dev_warn(dev,
+			"0x%02X is engineering release, consider FPGA update",
+			fpga_version);
+	}
+
+	if (fpga_version != 0xC0 && fpga_version >= 0x0E) {
+		/* wdt - any pcb, fpga >= 0x0E && !0xC0 */
+		ncells = 1;
+
+		/* mtd - pcb > 0, fpga >= 0x0F
+		 * Versions bellow 0x0F may cause damage of the flash (!)
+		 */
+		if (pcb_version > 0 && fpga_version > 0x0E)
+			ncells = 2;
+
+		/* hwmon - pcb > 0, fpga > 0x0F (assumption) */
+		if (pcb_version > 0 && fpga_version > 0x0F)
+			ncells = 3;
+
+		err = mfd_add_devices(dev, pdev->id, ptx1kbf_cells,
+				      ncells, res, 0, NULL);
+		if (err)
+			return err;
+	} else {
+		/* Unsupported - known to cause problems: 0xC0, < 0x0E */
+		dev_err(dev,
+			"0x%02X is unsupported version, consider FPGA update",
+			fpga_version);
+	}
+
+	err = sysfs_create_group(&dev->kobj, &bf_attr_group);
+	if (err) {
+		sysfs_remove_group(&dev->kobj, &bf_attr_group);
+		goto err_mfd;
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	bf_debugfs_init(bf);
+#endif
+
+	return 0;
+
+err_mfd:
+	mfd_remove_devices(&pdev->dev);
+
+	return err;
+}
+
+static int ptx1kbf_remove(struct platform_device *pdev)
+{
+#ifdef CONFIG_DEBUG_FS
+	struct ptx1kbf_core *bf = dev_get_drvdata(&pdev->dev);
+
+	bf_debugfs_remove(bf);
+#endif
+	sysfs_remove_group(&pdev->dev.kobj, &bf_attr_group);
+	mfd_remove_devices(&pdev->dev);
+	return 0;
+}
+
+static const struct of_device_id ptx1kbf_of_ids[] = {
+	{ .compatible = "jnx,ptx1k-bootfpga" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ptx1kbf_of_ids);
+
+static struct platform_driver ptx1kbf_driver = {
+	.driver		= {
+		.name	= "ptx1k-bootfpga",
+		.of_match_table = ptx1kbf_of_ids,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ptx1kbf_probe,
+	.remove		= ptx1kbf_remove,
+};
+
+module_platform_driver(ptx1kbf_driver);
+
+MODULE_DESCRIPTION("Juniper Networks PTX1K RCB I2CS Boot FPGA Driver");
+MODULE_AUTHOR("Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ptx1k-bootfpga");
diff --git a/include/linux/mfd/ptx1k-bootfpga.h b/include/linux/mfd/ptx1k-bootfpga.h
new file mode 100644
index 0000000..6a40c95
--- /dev/null
+++ b/include/linux/mfd/ptx1k-bootfpga.h
@@ -0,0 +1,93 @@
+/*
+ * PTX1K I2CS Boot FPGA registers
+ *
+ * Copyright (C) 2014 Juniper Networks. All rights reserved.
+ * Author: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __PTX1K_BOOTFPGA_H__
+#define __PTX1K_BOOTFPGA_H__
+
+#include <linux/bitops.h>
+
+#define BOOT_FPGA_SCRATCH1			0x00
+#define BOOT_FPGA_SCRATCH2			0x01
+#define BOOT_FPGA_VERSION			0x02
+#define BOOT_FPGA_JSPEC_VERSION			0x03
+#define BOOT_FPGA_PCB_VERSION			0x04
+#define BOOT_FPGA_BOARD_ID			0x05
+#define BOOT_FPGA_RESET_REASON1			0x06
+#define BOOT_FPGA_RESET_REASON2			0x07
+#define BOOT_FPGA_RESET_CONTROL_AND_STATUS1	0x08
+#define BOOT_FPGA_RESET_CONTROL_AND_STATUS2	0x09
+#define BOOT_FPGA_RESET_CONTROL_AND_STATUS3	0x0a
+#define BOOT_FPGA_BOOT_CONTROL			0x0b
+#define BOOT_FPGA_WATCHDOG_TIMER_THRESHOLD	0x0c
+#define BOOT_FPGA_ERROR_STATUS1			0x0d
+#define BOOT_FPGA_ERROR_STATUS2			0x0e
+#define BOOT_FPGA_ERROR_STATUS3			0x0f
+#define BOOT_FPGA_IRQ_ENABLE1			0x10
+#define BOOT_FPGA_IRQ_STATUS1			0x11
+#define BOOT_FPGA_IRQ_ENABLE2			0x12
+#define BOOT_FPGA_IRQ_STATUS2			0x13
+#define BOOT_FPGA_CHASSIS_TYPE			0x14
+#define BOOT_FPGA_POST_CODE			0x15
+#define BOOT_FPGA_MISC_CONTROL			0x16
+#define BOOT_FPGA_MISC_STATUS			0x17
+#define BOOT_FPGA_CPU_TEMP_MSB			0x18
+#define BOOT_FPGA_CPU_TEMP_LSB			0x19
+#define BOOT_FPGA_PCH_TEMP_MSB			0x1a
+#define BOOT_FPGA_PCH_TEMP_LSB			0x1b
+#define BOOT_FPGA_DIMM1_TEMP_MSB		0x1c
+#define BOOT_FPGA_DIMM1_TEMP_LSB		0x1d
+#define BOOT_FPGA_DIMM2_TEMP_MSB		0x1e
+#define BOOT_FPGA_DIMM2_TEMP_LSB		0x1f
+
+#define BOOT_FPGA_SFPP_USB_SSD_PWR_CONTROL	0x20
+#define BOOT_FPGA_FPGA_ID			0x21
+#define BOOT_FPGA_SPI_FLASH_CONTROL_AND_STATUS	0x22
+#define BOOT_FPGA_PCH_NMI_SLEEP_RT_STATUS	0x23
+#define BOOT_FPGA_PCH_NMI_SLEEP_LATCHED_STATUS	0x24
+
+#define BOOT_FPGA_FLASH_IF_ADDR(a)		(0xe0 + (a))
+#define BOOT_FPGA_FLASH_IF_BYTE_COUNT(a)	(0xe4 + (a))
+#define BOOT_FPGA_FLASH_IF_CONTROL(a)		(0xe8 + (a))
+#define BOOT_FPGA_FLASH_IF_STATUS(a)		(0xec + (a))
+#define BOOT_FPGA_FLASH_IF_WRITE_BUF_ADDR_MSB	0xf0
+#define BOOT_FPGA_FLASH_IF_WRITE_BUF_ADDR_LSB	0xf1
+#define BOOT_FPGA_FLASH_IF_WRITE_BUF_DATA	0xf2
+#define BOOT_FPGA_FLASH_IF_READ_BUF_ADDR_MSB	0xf3
+#define BOOT_FPGA_FLASH_IF_READ_BUF_ADDR_LSB	0xf4
+#define BOOT_FPGA_FLASH_IF_READ_BUF_DATA	0xf5
+
+#define BOOT_FPGA_RU_CONFIG_CONTROL_STATUS	0xf6
+#define BOOT_FPGA_RU_CONFIG_STATUS_DATA_MSB	0xf7
+#define BOOT_FPGA_RU_CONFIG_STATUS_DATA_LSB	0xf8
+#define BOOT_FPGA_RU_CONFIG_ADDR_23_DOWNTO_16	0xf9
+#define BOOT_FPGA_RU_CONFIG_ADDR_15_DOWNTO_8	0xfa
+#define BOOT_FPGA_RU_CONFIG_ADDR_7_DOWNTO_0	0xfb
+
+#define RR1_SW		BIT(7)	/* SW initiated reset */
+#define RR1_WDOG	BIT(6)	/* Watchdog induced reset */
+#define RR1_MSTR	BIT(5)	/* System host (Master RE) initiated reset */
+#define RR1_BUTTON	BIT(4)	/* Front panel button reset */
+#define RR1_POWER_CYCLE	BIT(3)	/* Natural power cycle */
+#define RR1_POWER_FAIL	BIT(2)	/* Power fail */
+#define RR1_THERM_TRIP	BIT(1)	/* CPU thermal trip */
+#define RR1_PCH		BIT(0)	/* PCH initiated reset, e.g TCO timer expiry */
+
+#define RR2_MSMI_FATAL		BIT(3)	/* CPU MSMI# fatal reset */
+#define RR2_CATERR_IERR		BIT(2)	/* CPU CATERR_IERR# induced reset */
+#define RR2_XDP			BIT(1)	/* XDP request reset */
+#define RR2_AUTO_POWER_OFF	BIT(0)	/* Auto power off */
+
+#define BC_WDT_ENA		BIT(6)	/* Watchdog timer enable */
+#define BC_FLASH_SELECT		BIT(4)	/* Flash select enable/status */
+#define WTT_THRESHOLD_MASK	0x3f
+
+#endif /*__PTX1K_BOOTFPGA_H__*/
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 2/7] mfd: dt-bindings: Add bindings for the Juniper PTX1K Boot FPGA
       [not found] ` <1475853724-22557-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
  2016-10-07 15:21   ` [PATCH 1/7] mfd: Add PTX1K I2CS BootFPGA MFD driver Pantelis Antoniou
@ 2016-10-07 15:21   ` Pantelis Antoniou
  2016-10-07 15:22   ` [PATCH 3/7] watchdog: Add PTX1K I2CS BootFPGA watchdog driver Pantelis Antoniou
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Rob Herring, Mark Rutland, Frank Rowand, David Woodhouse,
	Brian Norris, Wim Van Sebroeck, Jean Delvare, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	linux-hwmon-u79uwXL29TY76Z2rM5mHXA

From: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>

Add device tree bindings for the Juniper PTX1K Boot FPGA MFD driver.

Signed-off-by: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
[Ported from Juniper kernel]
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
---
 .../devicetree/bindings/mfd/jnx-ptx1k-bootfpga.txt | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/jnx-ptx1k-bootfpga.txt

diff --git a/Documentation/devicetree/bindings/mfd/jnx-ptx1k-bootfpga.txt b/Documentation/devicetree/bindings/mfd/jnx-ptx1k-bootfpga.txt
new file mode 100644
index 0000000..596dec7
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/jnx-ptx1k-bootfpga.txt
@@ -0,0 +1,34 @@
+* Device tree bindings for Juniper's PTX1K boot FPGA MFD driver
+
+The device supports a hardware watchdog, a flash MTD device and
+a hwmon sensor device. The bindings of those drivers are described
+in the jnx-ptx1kbf-wdt, jnx-ptx1kbf-mtd and jnx-ptx1kbf-hwmon documents.
+
+Required properties:
+
+- compatible:		"ptx1k-bootfpga"
+
+- reg:			contains offset/length value for device state control
+			registers space.
+
+Example:
+
+bootfpga@10000 {
+	compatible = "jnx,ptx1k-bootfpga";
+	reg = <0x10000 0x100>;
+
+	wdt {
+		compatible = "jnx,ptx1kbf-wdt";
+		/* no properties required */
+	};
+
+	mtd {
+		compatible = "jnx,ptx1kbf-mtd";
+		/* use the full device */
+	};
+
+	hwmon {
+		compatible = "jnx,ptx1kbf-hwmon";
+		/* no properties required */
+	};
+};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 3/7] watchdog: Add PTX1K I2CS BootFPGA watchdog driver.
       [not found] ` <1475853724-22557-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
  2016-10-07 15:21   ` [PATCH 1/7] mfd: Add PTX1K I2CS BootFPGA MFD driver Pantelis Antoniou
  2016-10-07 15:21   ` [PATCH 2/7] mfd: dt-bindings: Add bindings for the Juniper PTX1K Boot FPGA Pantelis Antoniou
@ 2016-10-07 15:22   ` Pantelis Antoniou
  2016-10-07 15:22   ` [PATCH 4/7] watchdog: ptx1kbf-wdt: Add ptx1kbf device tree bindings Pantelis Antoniou
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:22 UTC (permalink / raw)
  To: Lee Jones
  Cc: Rob Herring, Mark Rutland, Frank Rowand, David Woodhouse,
	Brian Norris, Wim Van Sebroeck, Jean Delvare, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	linux-hwmon-u79uwXL29TY76Z2rM5mHXA

From: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>

This driver allows using the I2CS watchdog on PTX1K. The
BootFPGA implements a watchdog that allows setting timeout
from predefined set of values from 15 msec to 491 sec.

Signed-off-by: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
Signed-off-by: Guenter Roeck <groeck-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
Signed-off-by: JawaharBalaji Thirumalaisamy <jawaharb-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
[Ported from Juniper kernel]
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
---
 drivers/watchdog/Kconfig           |  15 +++
 drivers/watchdog/Makefile          |   1 +
 drivers/watchdog/jnx_ptx1kbf_wdt.c | 229 +++++++++++++++++++++++++++++++++++++
 3 files changed, 245 insertions(+)
 create mode 100644 drivers/watchdog/jnx_ptx1kbf_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 2554f47..a3761eb 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1033,6 +1033,21 @@ config IT87_WDT
 	  To compile this driver as a module, choose M here: the module will
 	  be called it87_wdt.
 
+config JNX_PTX1KBF_WDT
+	tristate "Juniper Networks PTX1000 I2CS BootFPGA Watchdog"
+	depends on X86 && MFD_JUNIPER_PTX1KBF
+	---help---
+	  This is the driver for the watchdog timer built-in on the Juniper
+	  Networks PTX1000 I2CS/BootFPGA and acessible from the LPC bus. The
+	  BootFPGA watchdog allows several predefined thresholds, so this
+	  driver will select a value close to these static values: 15 ms,
+	  30 ms, 60 ms, 120 ms, 240 ms, 480 ms, 960 ms, 1920 ms, 3840 ms,
+	  7680 ms, 15360 ms, 30720 ms, 61440 ms, 122880 ms, 245760 ms and
+	  516096 ms.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called jnx_ptx1kbf_wdt.
+
 config HP_WATCHDOG
 	tristate "HP ProLiant iLO2+ Hardware Watchdog Timer"
 	depends on X86 && PCI
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 942b795..f9fafdf 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -111,6 +111,7 @@ endif
 obj-$(CONFIG_IT8712F_WDT) += it8712f_wdt.o
 obj-$(CONFIG_IT87_WDT) += it87_wdt.o
 obj-$(CONFIG_JNX_PTXPMB_WDT) += ptxpmb_wdt.o
+obj-$(CONFIG_JNX_PTX1KBF_WDT) += jnx_ptx1kbf_wdt.o
 obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o
 obj-$(CONFIG_KEMPLD_WDT) += kempld_wdt.o
 obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
diff --git a/drivers/watchdog/jnx_ptx1kbf_wdt.c b/drivers/watchdog/jnx_ptx1kbf_wdt.c
new file mode 100644
index 0000000..7d3e0b7
--- /dev/null
+++ b/drivers/watchdog/jnx_ptx1kbf_wdt.c
@@ -0,0 +1,229 @@
+/*
+ * Juniper Networks PTX1K RCB I2CS Boot FPGA watchdog driver
+ *
+ * Copyright (C) 2014 Juniper Networks. All rights reserved.
+ * Author: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/watchdog.h>
+#include <linux/mfd/ptx1k-bootfpga.h>
+
+#define WDT_MIN_TIMEOUT		1
+#define WDT_MAX_TIMEOUT		491
+#define WDT_DEFAULT_TIMEOUT	60	/* default heartbeat in seconds */
+
+#define DRVNAME "jnx-ptx1kbf-wdt"
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+
+#define MSW_NOWAYOUT __MODULE_STRING(WATCHDOG_NOWAYOUT)
+MODULE_PARM_DESC(nowayout,
+		 "Cannot be stopped once started (def=" MSW_NOWAYOUT ")");
+
+struct ptx1kbf_wdt {
+	void __iomem *base;
+	struct watchdog_device wdt_dev;
+};
+
+/*
+ * The BOOT_FPGA_WATCHDOG_TIMER_THRESHOLD register defines the watchdog
+ * timer thresholds in ms: 0x0 = 15 ms, 0x1 = 30 ms, ...  0xD = 122880 ms,
+ * 0xE = 245760 ms, 0xF = 492520 ms, or value = (2^index * 15)
+ */
+static int ptx1kbf_index_to_timeout(u8 reg)
+{
+	return ((1 << (reg & WTT_THRESHOLD_MASK)) * 15) / 1000;
+}
+
+static u8 ptx1kbf_timeout_to_index(unsigned int timeout)
+{
+	return fls(timeout * 1000 / 15) & WTT_THRESHOLD_MASK;
+}
+
+static int ptx1kbf_wdt_set_timeout(struct watchdog_device *wdt_dev,
+				   unsigned int timeout)
+{
+	struct ptx1kbf_wdt *wdt = watchdog_get_drvdata(wdt_dev);
+	u8 reg, index;
+
+	if (timeout > WDT_MAX_TIMEOUT)
+		return -EINVAL;
+
+	index = ptx1kbf_timeout_to_index(timeout);
+
+	reg = ioread8(wdt->base + BOOT_FPGA_WATCHDOG_TIMER_THRESHOLD);
+	reg &= ~WTT_THRESHOLD_MASK;
+	reg |= index;
+	iowrite8(reg, wdt->base + BOOT_FPGA_WATCHDOG_TIMER_THRESHOLD);
+
+	/* Set the actual timeout supported by the watchdog */
+	wdt->wdt_dev.timeout = ptx1kbf_index_to_timeout(index);
+
+	return 0;
+}
+
+static int ptx1kbf_wdt_ping(struct watchdog_device *wdt_dev)
+{
+	return ptx1kbf_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
+}
+
+static int ptx1kbf_wdt_start(struct watchdog_device *wdt_dev)
+{
+	struct ptx1kbf_wdt *wdt = watchdog_get_drvdata(wdt_dev);
+	int ret;
+	u8 reg;
+
+	ret = ptx1kbf_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
+	if (ret < 0)
+		return ret;
+
+	reg = ioread8(wdt->base + BOOT_FPGA_BOOT_CONTROL);
+	reg |= BC_WDT_ENA;
+	iowrite8(reg, wdt->base + BOOT_FPGA_BOOT_CONTROL);
+
+	return 0;
+}
+
+static int ptx1kbf_wdt_stop(struct watchdog_device *wdt_dev)
+{
+	struct ptx1kbf_wdt *wdt = watchdog_get_drvdata(wdt_dev);
+	u8 reg;
+
+	reg = ioread8(wdt->base + BOOT_FPGA_BOOT_CONTROL);
+	reg &= ~BC_WDT_ENA;
+	iowrite8(reg, wdt->base + BOOT_FPGA_BOOT_CONTROL);
+
+	return 0;
+}
+
+static struct watchdog_info ptx1kbf_wdt_info = {
+	.options	= WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
+			  WDIOF_MAGICCLOSE,
+	.identity	= "PTX1K BootFPGA Watchdog",
+	.firmware_version = 0,
+};
+
+static const struct watchdog_ops ptx1kbf_wdt_ops = {
+	.owner = THIS_MODULE,
+	.start = ptx1kbf_wdt_start,
+	.stop = ptx1kbf_wdt_stop,
+	.ping = ptx1kbf_wdt_ping,
+	.set_timeout = ptx1kbf_wdt_set_timeout,
+};
+
+static int ptx1kbf_wdt_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct resource *res;
+	struct ptx1kbf_wdt *wdt;
+	u8 reset_reason1, reset_reason2;
+	unsigned int timeout;
+
+	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+	if (!wdt)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	wdt->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(wdt->base))
+		return PTR_ERR(wdt->base);
+
+	platform_set_drvdata(pdev, wdt);
+	wdt->wdt_dev.info = &ptx1kbf_wdt_info;
+	wdt->wdt_dev.ops = &ptx1kbf_wdt_ops;
+	wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT;
+	wdt->wdt_dev.max_timeout = WDT_MAX_TIMEOUT;
+	wdt->wdt_dev.timeout = WDT_DEFAULT_TIMEOUT;
+	wdt->wdt_dev.parent = &pdev->dev;
+
+	reset_reason1 = ioread8(wdt->base + BOOT_FPGA_RESET_REASON1);
+	reset_reason2 = ioread8(wdt->base + BOOT_FPGA_RESET_REASON2);
+	if (reset_reason1 & RR1_MSTR)
+		wdt->wdt_dev.bootstatus |= WDIOF_EXTERN1;
+	else if (reset_reason1 & RR1_BUTTON)
+		wdt->wdt_dev.bootstatus |= WDIOF_EXTERN2;
+	else if (reset_reason1 & RR1_WDOG)
+		wdt->wdt_dev.bootstatus |= WDIOF_CARDRESET;
+	else if (reset_reason1 & RR1_POWER_FAIL)
+		wdt->wdt_dev.bootstatus |= WDIOF_POWERUNDER;
+	else if (reset_reason1 & RR1_THERM_TRIP)
+		wdt->wdt_dev.bootstatus |= WDIOF_OVERHEAT;
+	else if (reset_reason1 & RR2_AUTO_POWER_OFF)
+		wdt->wdt_dev.bootstatus |= WDIOF_FANFAULT;
+
+	/* Report the FPGA/WDT version */
+	ptx1kbf_wdt_info.firmware_version =
+				ioread8(wdt->base + BOOT_FPGA_VERSION);
+
+	/*
+	 * The PTX1K BIOS configures the timeout when the FPGA watchdog
+	 * is enabled. Index values < 0x07 set thresholds bellow 1s,
+	 * so we can ignore them
+	 */
+	timeout = ptx1kbf_index_to_timeout(ioread8(wdt->base +
+				BOOT_FPGA_WATCHDOG_TIMER_THRESHOLD));
+
+	watchdog_init_timeout(&wdt->wdt_dev, timeout, &pdev->dev);
+	watchdog_set_nowayout(&wdt->wdt_dev, nowayout);
+	watchdog_set_drvdata(&wdt->wdt_dev, wdt);
+
+	/* Stop the watchdog if BIOS has enabled it */
+	ptx1kbf_wdt_stop(&wdt->wdt_dev);
+
+	ret = watchdog_register_device(&wdt->wdt_dev);
+	if (ret)
+		return ret;
+
+	dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)",
+		 wdt->wdt_dev.timeout, nowayout);
+
+	return 0;
+}
+
+static int ptx1kbf_wdt_remove(struct platform_device *pdev)
+{
+	struct ptx1kbf_wdt *wdt = platform_get_drvdata(pdev);
+
+	watchdog_unregister_device(&wdt->wdt_dev);
+
+	return 0;
+}
+
+static const struct of_device_id ptx1kbf_wdt_of_ids[] = {
+	{ .compatible = "jnx,ptx1kbf-wdt", NULL },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ptx1kbf_wdt_of_ids);
+
+static struct platform_driver ptx1kbf_wdt_driver = {
+	.probe	= ptx1kbf_wdt_probe,
+	.remove = ptx1kbf_wdt_remove,
+	.driver = {
+		.name = DRVNAME,
+		.owner = THIS_MODULE,
+		.of_match_table = ptx1kbf_wdt_of_ids,
+	},
+};
+
+module_platform_driver(ptx1kbf_wdt_driver);
+
+MODULE_DESCRIPTION("Juniper Networks PTX1K RCB I2CS Boot FPGA watchdog driver");
+MODULE_AUTHOR("Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRVNAME);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 4/7] watchdog: ptx1kbf-wdt: Add ptx1kbf device tree bindings
       [not found] ` <1475853724-22557-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
                     ` (2 preceding siblings ...)
  2016-10-07 15:22   ` [PATCH 3/7] watchdog: Add PTX1K I2CS BootFPGA watchdog driver Pantelis Antoniou
@ 2016-10-07 15:22   ` Pantelis Antoniou
  2016-10-07 15:22   ` [PATCH 5/7] mtd: ptx1kbf: Add PTX1K BootFPGA MTD driver Pantelis Antoniou
  2016-10-10 20:32   ` [PATCH 0/7] Introduce PTX1K Boot FPGA driver Rob Herring
  5 siblings, 0 replies; 9+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:22 UTC (permalink / raw)
  To: Lee Jones
  Cc: Rob Herring, Mark Rutland, Frank Rowand, David Woodhouse,
	Brian Norris, Wim Van Sebroeck, Jean Delvare, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	linux-hwmon-u79uwXL29TY76Z2rM5mHXA

From: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>

Add binding document for the watchdog driver of PTX1K Boot FPGA.

Signed-off-by: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
[Ported from Juniper kernel]
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
---
 .../devicetree/bindings/watchdog/jnx-ptx1kbf-wdt.txt    | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/jnx-ptx1kbf-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/jnx-ptx1kbf-wdt.txt b/Documentation/devicetree/bindings/watchdog/jnx-ptx1kbf-wdt.txt
new file mode 100644
index 0000000..0aa8086
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/jnx-ptx1kbf-wdt.txt
@@ -0,0 +1,17 @@
+Juniper's PTX1K Boot FPGA watchdog driver
+
+Required properties:
+
+- compatible:	Should be "jnx,ptx1kbf-wdt"
+
+Optional properties:
+
+- reg : Specifies base physical address and size of the registers. It is
+  optional since the MFD parent driver supplies it, but can be overridden.
+
+Example:
+
+wdt {
+	compatible = "jnx,ptx1kbf-wdt";
+	/* no properties defined */
+};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 5/7] mtd: ptx1kbf: Add PTX1K BootFPGA MTD driver
       [not found] ` <1475853724-22557-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
                     ` (3 preceding siblings ...)
  2016-10-07 15:22   ` [PATCH 4/7] watchdog: ptx1kbf-wdt: Add ptx1kbf device tree bindings Pantelis Antoniou
@ 2016-10-07 15:22   ` Pantelis Antoniou
  2016-10-10 20:32   ` [PATCH 0/7] Introduce PTX1K Boot FPGA driver Rob Herring
  5 siblings, 0 replies; 9+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:22 UTC (permalink / raw)
  To: Lee Jones
  Cc: Rob Herring, Mark Rutland, Frank Rowand, David Woodhouse,
	Brian Norris, Wim Van Sebroeck, Jean Delvare, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	linux-hwmon-u79uwXL29TY76Z2rM5mHXA

From: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>

This patch adds a MTD driver for configuration updates of the
Xilinx Spartan 3AN based FPGAs on the PTX1K RE boards. The
driver is client of the ptx1k-bootfpga driver.

Signed-off-by: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
[Ported from Juniper kernel]
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
---
 drivers/mtd/devices/Kconfig           |  10 +
 drivers/mtd/devices/Makefile          |   1 +
 drivers/mtd/devices/jnx_ptx1kbf_mtd.c | 677 ++++++++++++++++++++++++++++++++++
 3 files changed, 688 insertions(+)
 create mode 100644 drivers/mtd/devices/jnx_ptx1kbf_mtd.c

diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index f5a9032..25a1c4a 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -155,6 +155,16 @@ config MTD_SAM_FLASH
 	  This driver can also be built as a module. When it is so the name of
 	  the module is flash-sam.
 
+config MTD_JNX_PTX1KBF
+	tristate "Juniper I2CS BootFPGA MTD driver"
+	depends on MFD_JUNIPER_PTX1KBF
+	help
+	  This enables the MTD driver for the Juniper I2CS BootFPGA.
+	  The driver is used to perform software upgrades of the RE's
+	  Spartan 3AN XC3S50AN, XC3S200AN, XCS400AN, XC3S700AN and
+	  XC3S1400AN based I2CS. The I2CS BootFPGA must implement the
+	  remote upgrade software interface.
+
 config JNX_PMB_NVRAM
 	tristate "Juniper FPC PMB NVRAM Driver"
 	depends on (PTXPMB_COMMON || JNX_PTX_NGPMB)
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 7556311..e1adfa5 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_MTD_ST_SPI_FSM)    += st_spi_fsm.o
 obj-$(CONFIG_MTD_POWERNV_FLASH)	+= powernv_flash.o
 
 obj-$(CONFIG_MTD_SAM_FLASH)	+= sam-flash.o
+obj-$(CONFIG_MTD_JNX_PTX1KBF)	+= jnx_ptx1kbf_mtd.o
 obj-$(CONFIG_JNX_PMB_NVRAM)     += jnx_pmb_nvram.o
 
 CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/jnx_ptx1kbf_mtd.c b/drivers/mtd/devices/jnx_ptx1kbf_mtd.c
new file mode 100644
index 0000000..3bc17be
--- /dev/null
+++ b/drivers/mtd/devices/jnx_ptx1kbf_mtd.c
@@ -0,0 +1,677 @@
+/*
+ * Juniper Networks PTX1K RCB I2CS Boot FPGA MTD driver
+ * FPGA upgrades of the Spartan3AN/XC3S700 based I2CS.
+ *
+ * Copyright (C) 2015 Juniper Networks. All rights reserved.
+ * Author: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mfd/ptx1k-bootfpga.h>
+
+#define DEFAULT_BUSY_TIMEOUT	5	/* default timeout (msec) */
+#define PAGE_BUFFER_TXFER	400	/* page->sram transfer (usec) */
+
+/* FLASH_IF_CONTROL commands */
+#define CONTROL_READ_SID	0x80
+#define CONTROL_READ_DID	0x04
+#define CONTROL_READ_STATUS	0x08
+#define CONTROL_SECTOR_ERASE	0x20
+#define CONTROL_PAGE_ERASE	0x40
+#define CONTROL_PAGE_WRITE	0x02
+#define CONTROL_PAGE_READ	0x01
+#define CONTROL_SP_READ		0x02
+#define CONTROL_SP_WRITE	0x08
+#define CONTROL_SP_UALL		0x01
+
+/* FLASH_IF_STATUS bits */
+#define STATUS_BUSY		BIT(0)
+#define STATUS_ILLEGAL_WRITE	BIT(1)
+#define STATUS_ILLEGAL_ERASE	BIT(2)
+#define STATUS_ILLEGAL (STATUS_ILLEGAL_WRITE | STATUS_ILLEGAL_ERASE)
+#define STATUS_POWER_2_ADDR	BIT(3)
+#define STATUS_SID_I2CS		0x1F /* I2CS Spartan3AN FPGA */
+
+/* RU_CONFIG_CONTROL_STATUS bits */
+#define RU_CCS_USER_IMAGE	BIT(7)
+#define RU_CCS_RECONFIG		BIT(5)
+
+#define MASK_SPARE_PAGE		0x1f
+#define MASK_SPARE_SECTOR	0x1fff
+
+#define SECTOR_UNPROTECT	0x00
+#define SECTOR_PROTECT		0xff
+
+struct bfmtd_info {
+	const char *name;
+	u8 device_id;		/* flash id as reported by the fpga */
+	size_t flash_size;	/* total flash size */
+	size_t page_size;	/* read/write page size */
+	size_t sector_size;	/* erase sector size */
+	size_t nr_pages;	/* total number of pages */
+	size_t nr_sectors;	/* total number of sectors */
+	size_t writesize;	/* write size */
+	size_t writebufsize;	/* internal fpga sram buffer size (bytes) */
+	size_t spare_size;	/* additional bytes per page in 'default' mode*/
+	/*
+	 * Timeouts are defined in the Xilinx "In-System Flash (ISF) Upgrade
+	 * User Guide". Our values will add 20% on top of ISF ones
+	 */
+	u16 page_erase_tmo;	/* page erase timeout (msec) */
+	u16 sector_erase_tmo;	/* sector erase timeout (msec) */
+	u16 buffer_program_tmo;	/* sram buffer program timeout (msec) */
+};
+
+/*
+ * Definitions in power-of-2 addressing mode.
+ * Reconfigure sizes if default mode is detected.
+ */
+static struct bfmtd_info bfmtd_info_db[] = {
+	{
+		.name = "XC3S50AN",
+		.device_id = 0x22,
+		.flash_size = 256 * 512,
+		.page_size = 256,
+		.nr_pages = 512,
+		.nr_sectors = 4,
+		.sector_size = 256 * 128,
+		.writesize = 1,
+		.writebufsize = 256,
+		.spare_size = 8,
+		.page_erase_tmo = 38,
+		.sector_erase_tmo = 3000,
+		.buffer_program_tmo = 5,
+	},
+	{
+		.name = "XC3S200AN/XC3S400AN",
+		.device_id = 0x24,
+		.flash_size = 256 * 2048,
+		.page_size = 256,
+		.nr_pages = 2048,
+		.nr_sectors = 8,
+		.sector_size = 256 * 256,
+		.writesize = 1,
+		.writebufsize = 256,
+		.spare_size = 8,
+		.page_erase_tmo = 38,
+		.sector_erase_tmo = 6000,
+		.buffer_program_tmo = 5,
+	},
+	{
+		.name = "XC3S700AN",
+		.device_id = 0x25,
+		.flash_size = 256 * 4096,
+		.page_size = 256,
+		.nr_pages = 4096,
+		.nr_sectors = 16,
+		.sector_size = 256 * 256,
+		.writesize = 1,
+		.writebufsize = 256,
+		.spare_size = 8,
+		.page_erase_tmo = 42,
+		.sector_erase_tmo = 6000,
+		.buffer_program_tmo = 8,
+	},
+	{
+		.name = "XC3S1400AN",
+		.device_id = 0x26,
+		.flash_size = 512 * 4096,
+		.page_size = 512,
+		.nr_pages = 4096,
+		.nr_sectors = 16,
+		.sector_size = 512 * 256,
+		.writesize = 1,
+		.writebufsize = 512,
+		.spare_size = 8,
+		.page_erase_tmo = 42,
+		.sector_erase_tmo = 6000,
+		.buffer_program_tmo = 8,
+	},
+};
+
+struct bf_mtd {
+	void __iomem *base;
+	struct device *dev;
+	struct mtd_info mtd;
+	struct bfmtd_info *info;
+	struct mutex lock;
+};
+
+/*
+ * bfmtd_busy_wait()
+ *	Wait for busy[0] flag in the FLASH_IF_STATUS register
+ */
+static int bfmtd_busy_wait(struct bf_mtd *bfmtd, unsigned long max_wait)
+{
+	u8 status;
+	unsigned long timeout = jiffies + msecs_to_jiffies(max_wait);
+
+	udelay(50);
+	do {
+		status = ioread8(bfmtd->base + BOOT_FPGA_FLASH_IF_STATUS(3));
+		if (!(status & STATUS_BUSY))
+			return 0;
+
+		if (status & STATUS_ILLEGAL)
+			return -EACCES;
+
+		usleep_range(50, 100);
+	} while (time_before(jiffies, timeout));
+
+	return -ETIMEDOUT;
+}
+
+/*
+ * bfmtd_read_status()
+ *	Read FLASH_IF_STATUS regsters
+ */
+static int bfmtd_read_status(struct bf_mtd *bfmtd, u8 control_cmd,
+				u8 status_index)
+{
+	int ret;
+
+	iowrite8(control_cmd,
+		 bfmtd->base + BOOT_FPGA_FLASH_IF_CONTROL(3));
+
+	ret = bfmtd_busy_wait(bfmtd, DEFAULT_BUSY_TIMEOUT);
+	if (ret)
+		return ret;
+
+	return ioread8(bfmtd->base +
+			BOOT_FPGA_FLASH_IF_STATUS(status_index));
+}
+
+/* Device ID */
+static inline int bfmtd_read_did(struct bf_mtd *bfmtd)
+{
+	return bfmtd_read_status(bfmtd, CONTROL_READ_DID, 1);
+}
+
+/* Silicon ID */
+static inline int bfmtd_read_sid(struct bf_mtd *bfmtd)
+{
+	return bfmtd_read_status(bfmtd, CONTROL_READ_SID, 2);
+}
+
+/* ^2 addressing mode */
+static inline int bfmtd_read_p2addr(struct bf_mtd *bfmtd)
+{
+	return bfmtd_read_status(bfmtd, CONTROL_READ_STATUS, 3);
+}
+
+/*
+ * bfmtd_calc_flash_addr()
+ *
+ * We have to support 2 different addressing schemes.
+ * The page_size can be 256, 264, 512, 528.
+ * The page_size in the default addressing mode are 264 and 528.
+ * The same is valid for the sector addresses.
+ * Calculate the page/sector address from the page_size/sectro_size.
+ *
+ * Example (XC3S700AN):
+ * Page#	Default addressing	Power of 2 addressing
+ * 0		0x000 - 0x107		0x000 - 0xFF
+ * 1		0x200 - 0x307		0x100 - 0x1FF
+ * 2		0x400 - 0x507		0x200 - 0x2FF
+ */
+static u32 bfmtd_calc_flash_addr(u32 addr, u32 size, u32 mask)
+{
+	/* spare = 0,8,16 for pages and 0,1024,2048,4096 for sectors */
+	u32 spare = size & mask;
+
+	if (!spare) /* power-of-2 mode */
+		return addr & ~(size - 1);
+
+	/* default mode, use spare to get the page/sector address */
+	addr /= size;
+	addr *= (spare << 6);
+
+	return addr;
+}
+
+/*
+ * bfmtd_read_page()
+ *	Transfer a page from the flash into the sram buffer
+ */
+static int bfmtd_read_page(struct bf_mtd *bfmtd, u32 addr, u8 *buf,
+				size_t len)
+{
+	int ret;
+	u32 page_addr, page_ofs;
+	u16 buff_addr;
+	size_t retlen, page_size =  bfmtd->info->page_size;
+
+	if (len > page_size)
+		len = page_size;
+
+	page_ofs = addr % page_size;
+	retlen = len - page_ofs;
+
+	if (!retlen || addr + retlen > bfmtd->info->flash_size)
+		return -EINVAL;
+
+	ret = bfmtd_busy_wait(bfmtd, DEFAULT_BUSY_TIMEOUT);
+	if (ret)
+		return ret;
+
+	/* Calculate the page address */
+	page_addr = bfmtd_calc_flash_addr(addr, page_size, MASK_SPARE_PAGE);
+
+	/* Set page address, byte count and trigger write */
+	iowrite32(be32_to_cpu(page_addr),
+		bfmtd->base + BOOT_FPGA_FLASH_IF_ADDR(0));
+	/* byte count (N), denotes (N + 1) */
+	iowrite32(be32_to_cpu(len - 1),
+		bfmtd->base + BOOT_FPGA_FLASH_IF_BYTE_COUNT(0));
+	iowrite8(CONTROL_PAGE_READ,
+		bfmtd->base + BOOT_FPGA_FLASH_IF_CONTROL(3));
+
+	/* Wait the fpga the fetch the page into the sram buffer (400 usec) */
+	ret = bfmtd_busy_wait(bfmtd, DEFAULT_BUSY_TIMEOUT);
+	if (ret)
+		return ret;
+
+	for (buff_addr = page_ofs; buff_addr < len; buff_addr++) {
+		iowrite16(be16_to_cpu(buff_addr),
+			bfmtd->base + BOOT_FPGA_FLASH_IF_READ_BUF_ADDR_MSB);
+		*buf = ioread8(bfmtd->base + BOOT_FPGA_FLASH_IF_READ_BUF_DATA);
+		buf++;
+	}
+
+	return retlen;
+}
+
+/*
+ * bfmtd_is_protected()
+ *	Check if the sector @addr is protected
+ */
+static int bfmtd_is_protected(struct bf_mtd *bfmtd, u32 addr)
+{
+	u8 protected_sectors[16];
+	int n_sector, ret = 0;
+	u16 buff_addr;
+
+	if (addr > bfmtd->info->flash_size)
+		return -EINVAL;
+
+	n_sector = addr / bfmtd->info->sector_size;
+
+	/* Read the protected sector array */
+	iowrite8(CONTROL_SP_READ,
+		bfmtd->base + BOOT_FPGA_FLASH_IF_CONTROL(2));
+
+	ret = bfmtd_busy_wait(bfmtd, DEFAULT_BUSY_TIMEOUT);
+	if (ret)
+		return ret;
+
+	for (buff_addr = 0; buff_addr < bfmtd->info->nr_sectors; buff_addr++) {
+		iowrite16(be16_to_cpu(buff_addr),
+			bfmtd->base + BOOT_FPGA_FLASH_IF_READ_BUF_ADDR_MSB);
+		protected_sectors[buff_addr] =
+			ioread8(bfmtd->base + BOOT_FPGA_FLASH_IF_READ_BUF_DATA);
+	}
+
+	if (protected_sectors[n_sector] == SECTOR_PROTECT) {
+		dev_err(bfmtd->dev, "Sector #%d is protected\n", n_sector);
+		return -EACCES;
+	}
+
+	return 0;
+}
+
+/*
+ * bfmtd_erase_region()
+ *	Erase pages or sectors.
+ *	Note: The control (0xa5a5a5a5) words are written on page boundary.
+ */
+static int bfmtd_erase_region(struct bf_mtd *bfmtd, u32 addr)
+{
+	struct mtd_info *mtd = &bfmtd->mtd;
+	u32 flash_addr, mask, timeout;
+	u8 cmd;
+	int ret;
+
+	if (addr > bfmtd->info->flash_size)
+		return -EINVAL;
+
+	ret = bfmtd_is_protected(bfmtd, addr);
+	if (ret)
+		return ret;
+
+	ret = bfmtd_busy_wait(bfmtd, DEFAULT_BUSY_TIMEOUT);
+	if (ret)
+		return ret;
+
+	/* sector/page erase mode ? */
+	if (bfmtd->info->page_size == mtd->erasesize) {
+		mask = MASK_SPARE_PAGE;
+		timeout = bfmtd->info->page_erase_tmo;
+		cmd = CONTROL_PAGE_ERASE;
+	} else {
+		mask = MASK_SPARE_SECTOR;
+		timeout = bfmtd->info->sector_erase_tmo;
+		cmd = CONTROL_SECTOR_ERASE;
+	}
+
+	/* Calculate the page/sector address */
+	flash_addr = bfmtd_calc_flash_addr(addr, mtd->erasesize, mask);
+
+	/* Set page/sector address, byte count and trigger erase */
+	iowrite32(be32_to_cpu(flash_addr),
+		bfmtd->base + BOOT_FPGA_FLASH_IF_ADDR(0));
+	iowrite8(cmd, bfmtd->base + BOOT_FPGA_FLASH_IF_CONTROL(3));
+
+	/* Wait the fpga the flush the buffer */
+	ret = bfmtd_busy_wait(bfmtd, timeout);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * bfmtd_write_page()
+ *	Write a page content in the sram buffer and then to flash device
+ */
+static int bfmtd_write_page(struct bf_mtd *bfmtd, u32 addr, const u8 *buf,
+				size_t len)
+{
+	int ret;
+	u32 page_addr, page_ofs;
+	u16 buff_addr;
+	size_t retlen, page_size =  bfmtd->info->page_size;
+
+	if (len > page_size)
+		len = page_size;
+
+	page_ofs = addr % page_size;
+	retlen = len - page_ofs;
+
+	if (!retlen || addr + retlen > bfmtd->info->flash_size)
+		return -EINVAL;
+
+	ret = bfmtd_busy_wait(bfmtd, DEFAULT_BUSY_TIMEOUT);
+	if (ret)
+		return ret;
+
+	/* Fill the internal fpga buffer */
+	for (buff_addr = page_ofs; buff_addr < len; buff_addr++) {
+		iowrite16(be16_to_cpu(buff_addr),
+			bfmtd->base + BOOT_FPGA_FLASH_IF_WRITE_BUF_ADDR_MSB);
+		iowrite8(*buf, bfmtd->base + BOOT_FPGA_FLASH_IF_WRITE_BUF_DATA);
+		buf++;
+	}
+
+	/* Calculate the page address */
+	page_addr = bfmtd_calc_flash_addr(addr, page_size, MASK_SPARE_PAGE);
+
+	/* Set page address, byte count and trigger write */
+	iowrite32(be32_to_cpu(page_addr),
+		bfmtd->base + BOOT_FPGA_FLASH_IF_ADDR(0));
+	iowrite32(be32_to_cpu(len - 1),
+		bfmtd->base + BOOT_FPGA_FLASH_IF_BYTE_COUNT(0));
+	iowrite8(CONTROL_PAGE_WRITE,
+		bfmtd->base + BOOT_FPGA_FLASH_IF_CONTROL(3));
+
+	/* Wait the fpga the flush the buffer */
+	ret = bfmtd_busy_wait(bfmtd, bfmtd->info->buffer_program_tmo);
+	if (ret)
+		return ret;
+
+	return retlen;
+}
+
+/*
+ * bfmtd_read()
+ *	MTD read
+ */
+static int bfmtd_read(struct mtd_info *mtd, loff_t from, size_t len,
+			size_t *retlen, u8 *buf)
+{
+	struct bf_mtd *bfmtd = container_of(mtd, struct bf_mtd, mtd);
+	int ret, read = 0;
+
+	mutex_lock(&bfmtd->lock);
+	while (len) {
+		ret = bfmtd_read_page(bfmtd, from, buf, len);
+		if (ret < 0) {
+			dev_err(bfmtd->dev, "RD @0x%llx, size %ld failed (%d)",
+					from, len, ret);
+			mutex_unlock(&bfmtd->lock);
+			return ret;
+		}
+		read += ret;
+		len -= ret;
+		from += ret;
+		buf += ret;
+	}
+	mutex_unlock(&bfmtd->lock);
+
+	*retlen = read;
+
+	return 0;
+}
+
+/*
+ * bfmtd_write()
+ *	MTD write
+ */
+static int bfmtd_write(struct mtd_info *mtd, loff_t to, size_t len,
+				size_t *retlen, const u8 *buf)
+{
+	struct bf_mtd *bfmtd = container_of(mtd, struct bf_mtd, mtd);
+	int ret, written = 0;
+
+	mutex_lock(&bfmtd->lock);
+	while (len) {
+		ret = bfmtd_write_page(bfmtd, to, buf, len);
+		if (ret < 0) {
+			dev_err(bfmtd->dev, "WR @0x%llx, size %ld failed (%d)",
+					to, len, ret);
+			mutex_unlock(&bfmtd->lock);
+			return ret;
+		}
+		written += ret;
+		len -= ret;
+		to += ret;
+		buf += ret;
+	}
+	mutex_unlock(&bfmtd->lock);
+
+	*retlen = written;
+
+	return 0;
+}
+
+/*
+ * bfmtd_erase()
+ *	MTD erase
+ */
+static int bfmtd_erase(struct mtd_info *mtd, struct erase_info *ei)
+{
+	struct bf_mtd *bfmtd = container_of(mtd, struct bf_mtd, mtd);
+	u32  start_addr, end_addr, addr;
+	int len, ret = 0;
+
+	len = ei->len;
+	start_addr =  ei->addr;
+	end_addr = start_addr + len - 1;
+
+	ei->state = MTD_ERASE_DONE;
+	addr = start_addr;
+	mutex_lock(&bfmtd->lock);
+	while (addr < end_addr) {
+		ret = bfmtd_erase_region(bfmtd, addr);
+		if (ret < 0) {
+			dev_err(bfmtd->dev, "Erase @0x%x, size %d failed (%d)",
+					addr, mtd->erasesize, ret);
+			ei->state = MTD_ERASE_FAILED;
+			break;
+		}
+		addr += mtd->erasesize;
+	}
+	mutex_unlock(&bfmtd->lock);
+
+	mtd_erase_callback(ei);
+
+	return ret;
+}
+
+static int bfmtd_init_mtd(struct bf_mtd *bfmtd)
+{
+	struct mtd_info *mtd;
+	struct bfmtd_info *info = NULL;
+	int ret, i;
+
+	ret = bfmtd_read_sid(bfmtd);
+	if (ret < 0)
+		return ret;
+
+	if (ret != STATUS_SID_I2CS) {
+		dev_err(bfmtd->dev, "Unsupported silicon id: %u", ret);
+		return -ENODEV;
+	}
+
+	ret = bfmtd_read_did(bfmtd);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(bfmtd_info_db); i++) {
+		if (bfmtd_info_db[i].device_id == ret) {
+			info = &bfmtd_info_db[i];
+			break;
+		}
+	}
+
+	if (!info) {
+		dev_err(bfmtd->dev, "Unsupported device id: %u", ret);
+		return -ENODEV;
+	}
+
+	ret = bfmtd_read_p2addr(bfmtd);
+	if (ret < 0)
+		return ret;
+
+	/* Reconfigure sizes if not in "power-of-2" addressing mode */
+	if (!(ret & STATUS_POWER_2_ADDR)) {
+		info->page_size += info->spare_size;
+		info->writebufsize = info->page_size;
+		info->flash_size = info->page_size * info->nr_pages;
+		info->sector_size = info->flash_size / info->nr_sectors;
+	}
+
+	dev_info(bfmtd->dev, "%s configuration flash in \'%s\' addressing mode\n",
+			info->name,
+			(ret & STATUS_POWER_2_ADDR) ? "power-of-2" : "default");
+
+	ret = ioread8(bfmtd->base + BOOT_FPGA_RU_CONFIG_CONTROL_STATUS);
+	dev_info(bfmtd->dev, "active FPGA configuration: %s\n",
+			(ret & RU_CCS_USER_IMAGE) ? "user" : "golden");
+
+	bfmtd->info = info;
+	mtd = &bfmtd->mtd;
+	mtd->name = dev_name(bfmtd->dev);
+	mtd->type = MTD_NORFLASH;
+	mtd->flags = MTD_CAP_NORFLASH;
+	mtd->erasesize = info->page_size;
+	mtd->writesize = info->writesize;
+	mtd->writebufsize = info->writebufsize;
+	mtd->size = info->flash_size;
+	mtd->_erase = bfmtd_erase;
+	mtd->_read = bfmtd_read;
+	mtd->_write = bfmtd_write;
+
+	return 0;
+}
+
+static int bfmtd_probe(struct platform_device *pdev)
+{
+	struct mtd_part_parser_data ppdata = {};
+	struct bf_mtd *bfmtd;
+	struct resource *mem;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	bfmtd = devm_kzalloc(dev, sizeof(*bfmtd), GFP_KERNEL);
+	if (!bfmtd)
+		return -ENOMEM;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(dev, "Failed to get platform mmio resource\n");
+		return -ENOENT;
+	}
+
+	bfmtd->base = devm_ioremap_nocache(dev, mem->start, resource_size(mem));
+	if (IS_ERR(bfmtd->base)) {
+		dev_err(dev, "Failed to ioremap mmio memory\n");
+		return PTR_ERR(bfmtd->base);
+	}
+
+	bfmtd->dev = dev;
+	ret = bfmtd_init_mtd(bfmtd);
+	if (ret)
+		return ret;
+
+	ret = mtd_device_parse_register(&bfmtd->mtd, NULL, &ppdata, NULL, 0);
+	if (ret) {
+		dev_err(dev, "Failed to register MTD device (%d)\n", ret);
+		return ret;
+	}
+
+	mutex_init(&bfmtd->lock);
+
+	platform_set_drvdata(pdev, bfmtd);
+
+	return ret;
+}
+
+static int bfmtd_remove(struct platform_device *pdev)
+{
+	struct bf_mtd *bfmtd = platform_get_drvdata(pdev);
+
+	mtd_device_unregister(&bfmtd->mtd);
+
+	return 0;
+}
+
+static const struct of_device_id ptx1kbf_mtd_ids[] = {
+	{ .compatible = "jnx,ptx1kbf-mtd", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ptx1kbf_mtd_ids);
+
+static struct platform_driver bfmtd_driver = {
+	.probe  = bfmtd_probe,
+	.remove = bfmtd_remove,
+	.driver = {
+		.name = "jnx-ptx1kbf-mtd",
+		.owner = THIS_MODULE,
+		.of_match_table = ptx1kbf_mtd_ids,
+	},
+};
+
+module_platform_driver(bfmtd_driver);
+
+MODULE_DESCRIPTION("Juniper Networks PTX1K RCB I2CS Boot FPGA MTD driver");
+MODULE_AUTHOR("Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:jnx-ptx1kbf-mtd");
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 6/7] mtd: ptx1kbf: Bindings for Juniper's PTX1K Boot FPGA
  2016-10-07 15:21 [PATCH 0/7] Introduce PTX1K Boot FPGA driver Pantelis Antoniou
       [not found] ` <1475853724-22557-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
@ 2016-10-07 15:22 ` Pantelis Antoniou
  2016-10-07 15:22 ` [PATCH 7/7] hwmon: ptx1kbf: Add PTX1K I2CS BootFPGA sensor driver Pantelis Antoniou
  2 siblings, 0 replies; 9+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:22 UTC (permalink / raw)
  To: Lee Jones
  Cc: Mark Rutland, devicetree, Jean Delvare, linux-hwmon,
	linux-watchdog, Georgi Vlaev, Frank Rowand, Pantelis Antoniou,
	linux-kernel, JawaharBalaji Thirumalaisamy, Wim Van Sebroeck,
	Rob Herring, linux-mtd, Brian Norris, David Woodhouse,
	Guenter Roeck

From: Georgi Vlaev <gvlaev@juniper.net>

Add binding document for Junipers Flash IP block present
in the PTX1K Boot FPGA on PTX series of routers.

Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
[Ported from Juniper kernel]
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
---
 .../devicetree/bindings/mtd/ptx1kbf-mtd.txt        | 23 ++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/ptx1kbf-mtd.txt

diff --git a/Documentation/devicetree/bindings/mtd/ptx1kbf-mtd.txt b/Documentation/devicetree/bindings/mtd/ptx1kbf-mtd.txt
new file mode 100644
index 0000000..4e25060
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/ptx1kbf-mtd.txt
@@ -0,0 +1,23 @@
+Flash device on a PTX1K Boot FPGA
+
+These flash chips are found in the PTX series of Juniper routers.
+
+Required properties:
+- compatible : must be "jnx,flash-sam"
+
+Optional properties:
+- reg : memory address for the flash chip, note that this is not
+required since usually the device is a subdevice of the SAM MFD
+driver which fills in the register fields.
+
+For the rest of the properties, see mtd-physmap.txt.
+
+The device tree may optionally contain sub-nodes describing partitions of the
+address space. See partition.txt for more detail.
+
+Example:
+
+ptx1kbf_mtd {
+	compatible = "jnx,ptx1kbf-mtd";
+	/* usually the whole flash is used */
+};
-- 
1.9.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH 7/7] hwmon: ptx1kbf: Add PTX1K I2CS BootFPGA sensor driver
  2016-10-07 15:21 [PATCH 0/7] Introduce PTX1K Boot FPGA driver Pantelis Antoniou
       [not found] ` <1475853724-22557-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
  2016-10-07 15:22 ` [PATCH 6/7] mtd: ptx1kbf: Bindings for Juniper's PTX1K Boot FPGA Pantelis Antoniou
@ 2016-10-07 15:22 ` Pantelis Antoniou
  2 siblings, 0 replies; 9+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:22 UTC (permalink / raw)
  To: Lee Jones
  Cc: Rob Herring, Mark Rutland, Frank Rowand, David Woodhouse,
	Brian Norris, Wim Van Sebroeck, Jean Delvare, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree, linux-kernel, linux-mtd, linux-watchdog, linux-hwmon

From: Georgi Vlaev <gvlaev@juniper.net>

The drivers allows reading CPU, PCH and DIMM modules teperatures
from the I2CS FPGA via the SMLink1 to the PCH.

Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
Signed-off-by: Guenter Roeck <groeck@juniper.net>
[Ported from Juniper kernel]
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
---
 drivers/hwmon/Kconfig             |  17 ++++++
 drivers/hwmon/Makefile            |   1 +
 drivers/hwmon/jnx_ptx1kbf_hwmon.c | 123 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 141 insertions(+)
 create mode 100644 drivers/hwmon/jnx_ptx1kbf_hwmon.c

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index b9348d2..5b66c7b 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -674,6 +674,23 @@ config SENSORS_JNX_FAN
 	  This driver can also be built as a module.  If so, the module
 	  will be called jnx-fan.
 
+config SENSORS_JNX_PTX1KBF
+	tristate "Juniper Networks PTX1000 I2CS BootFPGA thermal sensors"
+	depends on MFD_JUNIPER_PTX1KBF
+	help
+	  If you say yes here you get support for the hardware
+	  monitoring features of the Juniper Networks PTX1000 I2CS BootFPGA
+	  on the LPC bus. The CPU's digital thermal sensor can be read over
+	  the PECI interface. PECI is connected to the PCH and the PCH's
+	  Management Engine (ME) can be configured to poll CPU and DIMM
+	  temperatures over the PECI interface. Then, it is possible for an
+	  external I2C master (in the I2CS FPGA) to read CPU, DIMM and PCH
+	  temperatures from the PCH over SMLink1 (which is connected to the board
+	  I2C tree).
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called jnx_ptx1kbf_hwmon.
+
 config SENSORS_POWR1220
 	tristate "Lattice POWR1220 Power Monitoring"
 	depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index eea631e..a3dedef 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_SENSORS_INA3221)	+= ina3221.o
 obj-$(CONFIG_SENSORS_IT87)	+= it87.o
 obj-$(CONFIG_SENSORS_JC42)	+= jc42.o
 obj-$(CONFIG_SENSORS_JNX_FAN)   += jnx-fan.o
+obj-$(CONFIG_SENSORS_JNX_PTX1KBF)	+= jnx_ptx1kbf_hwmon.o
 obj-$(CONFIG_SENSORS_JZ4740)	+= jz4740-hwmon.o
 obj-$(CONFIG_SENSORS_K8TEMP)	+= k8temp.o
 obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
diff --git a/drivers/hwmon/jnx_ptx1kbf_hwmon.c b/drivers/hwmon/jnx_ptx1kbf_hwmon.c
new file mode 100644
index 0000000..a9d6562
--- /dev/null
+++ b/drivers/hwmon/jnx_ptx1kbf_hwmon.c
@@ -0,0 +1,123 @@
+/*
+ * Juniper Networks PTX1K RCB I2CS Boot FPGA hwmon driver
+ *
+ * Copyright (C) 2014 Juniper Networks. All rights reserved.
+ * Author: Georgi Vlaev <gvlaev@juniper.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/mfd/ptx1k-bootfpga.h>
+
+#define DRVNAME "jnx-ptx1kbf-hwmon"
+
+struct bf_hwmon {
+	void __iomem *base;
+};
+
+static const char *const bf_temp_label[] = {
+	"CPU", "PCH", "DIMM1", "DIMM2"
+};
+
+static ssize_t bf_show_temp(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct bf_hwmon *hwmon = dev_get_drvdata(dev);
+	int channel = to_sensor_dev_attr(attr)->index;
+
+	return sprintf(buf, "%d\n", be16_to_cpu(ioread16(hwmon->base +
+				BOOT_FPGA_CPU_TEMP_MSB + (channel * 2))));
+}
+
+static ssize_t bf_show_label(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	int channel = to_sensor_dev_attr(attr)->index;
+
+	return sprintf(buf, "%s\n", bf_temp_label[channel]);
+}
+
+/* CPU Temp */
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, bf_show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, bf_show_label, NULL, 0);
+/* PCH Temp */
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, bf_show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, bf_show_label, NULL, 1);
+/* DIMM1 Temp */
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, bf_show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, bf_show_label, NULL, 2);
+/* DIMM2 Temp */
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, bf_show_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, bf_show_label, NULL, 3);
+
+static struct attribute *bf_attrs[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_label.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_label.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_label.dev_attr.attr,
+	&sensor_dev_attr_temp4_input.dev_attr.attr,
+	&sensor_dev_attr_temp4_label.dev_attr.attr,
+	NULL
+};
+
+ATTRIBUTE_GROUPS(bf);
+
+static int bf_hwmon_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device *hwmon_dev;
+	struct bf_hwmon *hwmon;
+	struct resource *mem;
+
+	hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL);
+	if (!hwmon)
+		return -ENOMEM;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "Failed to get platform mmio resource\n");
+		return -ENOENT;
+	}
+
+	hwmon->base = devm_ioremap_nocache(dev, mem->start, resource_size(mem));
+	if (IS_ERR(hwmon->base)) {
+		dev_err(dev, "Failed to ioremap mmio memory\n");
+		return PTR_ERR(hwmon->base);
+	}
+
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, "jnx_ptx1kbf",
+							   hwmon, bf_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static struct platform_driver bf_hwmon_driver = {
+	.probe  = bf_hwmon_probe,
+	.driver = {
+		.name = DRVNAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+module_platform_driver(bf_hwmon_driver);
+
+MODULE_DESCRIPTION("Juniper Networks PTX1K RCB I2CS Boot FPGA hwmon driver");
+MODULE_AUTHOR("Georgi Vlaev <gvlaev@juniper.net>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRVNAME);
-- 
1.9.1

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

* Re: [PATCH 0/7] Introduce PTX1K Boot FPGA driver
       [not found] ` <1475853724-22557-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
                     ` (4 preceding siblings ...)
  2016-10-07 15:22   ` [PATCH 5/7] mtd: ptx1kbf: Add PTX1K BootFPGA MTD driver Pantelis Antoniou
@ 2016-10-10 20:32   ` Rob Herring
  5 siblings, 0 replies; 9+ messages in thread
From: Rob Herring @ 2016-10-10 20:32 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Lee Jones, Mark Rutland, Frank Rowand, David Woodhouse,
	Brian Norris, Wim Van Sebroeck, Jean Delvare, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	linux-hwmon-u79uwXL29TY76Z2rM5mHXA

On Fri, Oct 07, 2016 at 06:21:57PM +0300, Pantelis Antoniou wrote:
> Add Juniper's PTX1K Boot FPGA driver. Those FPGAs
> are present in Juniper's PTX series of routers.
> 
> The MFD driver provices watchdog/mtd/hwmon devices.
> 
> There are full device tree binding documents for the
> master mfd driver and for the slave driver.
> 
> This patchset is against mainline as of today: v4.8-9431-g3477d16
> and is dependent on the "Juniper prerequisites" and
> "Juniper infrastructure" patchsets sent earlier.

You've exceeded the number of patches I'm willing to review at once for 
one person and I'm tired of making the same comments. So fix anything 
I've already mentioned elsewhere and send this series again.

Rob
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2016-10-10 20:32 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-07 15:21 [PATCH 0/7] Introduce PTX1K Boot FPGA driver Pantelis Antoniou
     [not found] ` <1475853724-22557-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
2016-10-07 15:21   ` [PATCH 1/7] mfd: Add PTX1K I2CS BootFPGA MFD driver Pantelis Antoniou
2016-10-07 15:21   ` [PATCH 2/7] mfd: dt-bindings: Add bindings for the Juniper PTX1K Boot FPGA Pantelis Antoniou
2016-10-07 15:22   ` [PATCH 3/7] watchdog: Add PTX1K I2CS BootFPGA watchdog driver Pantelis Antoniou
2016-10-07 15:22   ` [PATCH 4/7] watchdog: ptx1kbf-wdt: Add ptx1kbf device tree bindings Pantelis Antoniou
2016-10-07 15:22   ` [PATCH 5/7] mtd: ptx1kbf: Add PTX1K BootFPGA MTD driver Pantelis Antoniou
2016-10-10 20:32   ` [PATCH 0/7] Introduce PTX1K Boot FPGA driver Rob Herring
2016-10-07 15:22 ` [PATCH 6/7] mtd: ptx1kbf: Bindings for Juniper's PTX1K Boot FPGA Pantelis Antoniou
2016-10-07 15:22 ` [PATCH 7/7] hwmon: ptx1kbf: Add PTX1K I2CS BootFPGA sensor driver Pantelis Antoniou

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).