All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] Introduce Juniper I2CS FPGA driver
@ 2016-10-07 15:20 Pantelis Antoniou
  2016-10-07 15:21   ` Pantelis Antoniou
                   ` (9 more replies)
  0 siblings, 10 replies; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:20 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree, linux-kernel, linux-gpio, linux-i2c, linux-leds,
	linux-hwmon

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

The MFD driver provices i2c/gpio/leds/hwmon devices.

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

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.

Avirup Banerjee (1):
  hwmon: Add driver for Fan Tray on Juniper I2CS FGPA

Georgi Vlaev (8):
  mfd: Add Juniper I2CS MFD driver
  mfd: dt-bindings: Add bindings for the Juniper I2CS MFD
  i2c/muxes: Juniper I2CS RE mux
  i2c: i2c-mux-i2cs: Add device tree bindings
  gpio: gpio-i2cs: Document bindings of I2CS FPGA GPIO block
  leds: i2cs: Add I2CS FPGA leds driver
  leds: Add binding for Juniper's I2CS FPGA
  hwmon: i2cs-fan: Add hwmon dts binding documentation

Guenter Roeck (1):
  gpio: i2cs: Juniper I2CS to GPIO pin mapping driver

 .../devicetree/bindings/gpio/jnx,gpio-i2cs.txt     |  43 ++
 .../devicetree/bindings/hwmon/i2cs-fan.txt         |  19 +
 .../devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt   |  27 ++
 .../devicetree/bindings/leds/leds-i2cs.txt         |  34 ++
 Documentation/devicetree/bindings/mfd/jnx-i2cs.txt |  68 +++
 drivers/gpio/Kconfig                               |  11 +
 drivers/gpio/Makefile                              |   1 +
 drivers/gpio/gpio-jnx-i2cs.c                       | 523 +++++++++++++++++++++
 drivers/hwmon/Kconfig                              |  11 +
 drivers/hwmon/Makefile                             |   1 +
 drivers/hwmon/jnx-fan.c                            | 471 +++++++++++++++++++
 drivers/i2c/muxes/Kconfig                          |  10 +
 drivers/i2c/muxes/Makefile                         |   1 +
 drivers/i2c/muxes/i2c-mux-i2cs.c                   | 155 ++++++
 drivers/leds/Kconfig                               |   9 +
 drivers/leds/Makefile                              |   1 +
 drivers/leds/leds-jnx-i2cs.c                       | 219 +++++++++
 drivers/mfd/Kconfig                                |  17 +
 drivers/mfd/Makefile                               |   1 +
 drivers/mfd/jnx-i2cs-core.c                        | 118 +++++
 include/linux/mfd/jnx-i2cs-core.h                  |  96 ++++
 include/linux/platform_data/jnx-i2cs-fan.h         |  13 +
 22 files changed, 1849 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/jnx,gpio-i2cs.txt
 create mode 100644 Documentation/devicetree/bindings/hwmon/i2cs-fan.txt
 create mode 100644 Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
 create mode 100644 Documentation/devicetree/bindings/leds/leds-i2cs.txt
 create mode 100644 Documentation/devicetree/bindings/mfd/jnx-i2cs.txt
 create mode 100644 drivers/gpio/gpio-jnx-i2cs.c
 create mode 100644 drivers/hwmon/jnx-fan.c
 create mode 100644 drivers/i2c/muxes/i2c-mux-i2cs.c
 create mode 100644 drivers/leds/leds-jnx-i2cs.c
 create mode 100644 drivers/mfd/jnx-i2cs-core.c
 create mode 100644 include/linux/mfd/jnx-i2cs-core.h
 create mode 100644 include/linux/platform_data/jnx-i2cs-fan.h

-- 
1.9.1

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

* [PATCH 01/10] mfd: Add Juniper I2CS MFD driver
@ 2016-10-07 15:21   ` Pantelis Antoniou
  0 siblings, 0 replies; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree, linux-kernel, linux-gpio, linux-i2c, linux-leds,
	linux-hwmon

From: Georgi Vlaev <gvlaev@juniper.net>

Add Juniper's I2CS FPGA MFD driver.

This driver is bare-bones and only provides a method for the
instantiation of the following subdevices.

- I2C mux driver (i2c-mux-i2cs)
- LEDS driver (leds-jnx-i2cs)
- GPIO driver (gpio-jnx-i2cs)
- HWMON driver (i2cs-fan-hwmon)

Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
Signed-off-by: Guenter Roeck <groeck@juniper.net>
Signed-off-by: JawaharBalaji Thirumalaisamy <jawaharb@juniper.net>
[Ported from Juniper kernel]
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
---
 drivers/mfd/Kconfig               |  17 ++++++
 drivers/mfd/Makefile              |   1 +
 drivers/mfd/jnx-i2cs-core.c       | 118 ++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/jnx-i2cs-core.h |  96 +++++++++++++++++++++++++++++++
 4 files changed, 232 insertions(+)
 create mode 100644 drivers/mfd/jnx-i2cs-core.c
 create mode 100644 include/linux/mfd/jnx-i2cs-core.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6107f7a..82493d5 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1400,6 +1400,23 @@ config MFD_JUNIPER_CBC
 	  This driver can be built as a module. If built as a module it will be
 	  called "cbc-core"
 
+config MFD_JUNIPER_I2CS
+	tristate "Juniper I2CS FPGA"
+	depends on JNX_PTX1K_RCB || PTXPMB_COMMON || JNX_SYSTEM
+	select MFD_CORE
+	select REGMAP_I2C
+	select GPIO_JNX_I2CS
+	select I2C_MUX_I2CS
+	select LEDS_JNX_I2CS
+	depends on I2C=y
+	default y
+	help
+	  Select this to enable the I2CS FPGA multi-function kernel driver.
+	  This FPGA is present on almost any Juniper Networks card.
+
+	  This driver can be built as a module. If built as a module it will be
+	  called "jnx_i2cs"
+
 config MFD_TWL4030_AUDIO
 	bool "TI TWL4030 Audio"
 	depends on TWL4030_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 0ea6dc6..215d9cf 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -152,6 +152,7 @@ obj-$(CONFIG_MFD_JUNIPER_CPLD)	+= ptxpmb-cpld-core.o
 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_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/jnx-i2cs-core.c b/drivers/mfd/jnx-i2cs-core.c
new file mode 100644
index 0000000..d279a73
--- /dev/null
+++ b/drivers/mfd/jnx-i2cs-core.c
@@ -0,0 +1,118 @@
+/*
+ * drivers/mfd/jnx-i2cs-core.c
+ *
+ * Copyright (c) 2014, Juniper Networks
+ * Author: Georgi Vlaev <gvlaev@juniper.net>
+ *
+ * The I2C Slave FPGA (I2CS) - found on almost any Juniper card.
+ *
+ * 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/module.h>
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/mfd/jnx-i2cs-core.h>
+
+static int jnx_i2cs_probe(struct i2c_client *i2c,
+			  const struct i2c_device_id *id)
+{
+	struct device *dev = &i2c->dev;
+	struct jnx_i2cs_platform_data *pdata = dev_get_platdata(dev);
+	struct device_node *child, *np = dev->of_node;
+	struct mfd_cell *cells;
+	int ncells, ret;
+
+	if (np) {
+		ncells = of_get_child_count(np);
+		if (ncells == 0) {
+			dev_err(dev, "No child specified for %s\n", np->name);
+			return -EINVAL;
+		}
+
+		cells = devm_kzalloc(dev, ncells * sizeof(*cells), GFP_KERNEL);
+		if (!cells)
+			return -ENOMEM;
+
+		ncells = 0;
+		for_each_available_child_of_node(dev->of_node, child) {
+			const char *s;
+
+			s = of_get_property(child, "compatible", NULL);
+			if (!s) {
+				dev_err(dev,
+					"Missing compatible property for %s\n",
+					child->name);
+				return -EINVAL;
+			}
+
+			cells[ncells].name = child->name;
+			cells[ncells].of_compatible = s;
+			ncells++;
+		}
+		if (ncells == 0) {
+			dev_err(dev, "No active child for %s\n", np->name);
+			return -EINVAL;
+		}
+	} else if (pdata) {
+		cells = pdata->cells;
+		ncells = pdata->ncells;
+	} else {
+		return -ENODEV;
+	}
+
+	ret = mfd_add_devices(dev, i2c_adapter_id(i2c->adapter),
+			      cells, ncells, NULL, 0, NULL);
+
+	return ret;
+}
+
+static int jnx_i2cs_remove(struct i2c_client *i2c)
+{
+	mfd_remove_devices(&i2c->dev);
+
+	return 0;
+}
+
+static const struct of_device_id jnx_i2cs_of_match[] = {
+	{ .compatible = "jnx,i2cs-rcb" },
+	{ .compatible = "jnx,i2cs-fpc" },
+	{ .compatible = "jnx,i2cs-sib" },
+	{ .compatible = "jnx,i2cs-fan" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, jnx_i2cs_of_match);
+
+static const struct i2c_device_id jnx_i2cs_id[] = {
+	{ "jnx_i2cs_rcb", 0 },
+	{ "jnx_i2cs_fpc", 0 },
+	{ "jnx_i2cs_sib", 0 },
+	{ "jnx_i2cs_fan", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, jnx_i2cs_id);
+
+static struct i2c_driver jnx_i2cs_driver = {
+	.driver = {
+		.name = "jnx_i2cs",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(jnx_i2cs_of_match),
+	},
+	.probe    = jnx_i2cs_probe,
+	.remove   = jnx_i2cs_remove,
+	.id_table = jnx_i2cs_id,
+};
+
+module_i2c_driver(jnx_i2cs_driver);
+
+MODULE_DESCRIPTION("Juniper I2CS MFD core driver");
+MODULE_AUTHOR("Georgi Vlaev <gvlaev@juniper.net>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/jnx-i2cs-core.h b/include/linux/mfd/jnx-i2cs-core.h
new file mode 100644
index 0000000..5e63aab
--- /dev/null
+++ b/include/linux/mfd/jnx-i2cs-core.h
@@ -0,0 +1,96 @@
+/*
+ * I2CS FPGA (jnx-i2cs-core) registers
+ *
+ * Copyright (C) 2014 Juniper Networks
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __JNX_I2CS_CORE_H__
+#define __JNX_I2CS_CORE_H__
+
+/* SIB I2CS registers */
+#define I2CS_SCRATCH		0x00
+#define I2CS_VERSION		0x01
+#define I2CS_MASTER_STATUS	0x02
+#define I2CS_MASTER_TIMEOUT	0x03
+#define I2CS_MASTER_FORCE	0x04
+#define I2CS_I2C0_STATUS	0x05
+#define I2CS_I2C1_STATUS	0x06
+#define I2CS_I2C_RESET		0x07
+#define I2CS_DATECODE		0x0f
+#define I2CS_INT_STATUS		0x10
+#define I2CS_INT_ENABLE		0x11
+#define I2CS_FRU_LED		0x12
+#define I2CS_MISC_IO		0x13
+#define I2CS_BUTTON_STATUS	0x14
+#define I2CS_BUTTON_ENABLE	0x15
+#define I2CS_GPIO_OE		0x16
+#define I2CS_GPIO_OUT		0x17
+#define I2CS_GPIO_IN		0x18
+#define I2CS_SERIAL_CONFIG0	0x19
+#define I2CS_SERIAL_CONFIG1	0x1a
+#define I2CS_MII_CONFIG		0x1b
+#define I2CS_MII_ADDR		0x1c
+#define I2CS_MII_DATA0		0x1d
+#define I2CS_MII_DATA1		0x1e
+#define I2CS_MII_DATA2		0x1f
+#define I2CS_PWR_CONTROL	0x20
+#define I2CS_PWR_UP_STATUS	0x21
+#define I2CS_PWR_DIS_STATUS	0x22
+#define I2CS_PWR_DIS_CAUSE	0x23
+#define I2CS_PWR_VFAIL_STATUS	0x24
+#define I2CS_PWR_VFAIL_CAUSE	0x25
+#define I2CS_PWR_TRIM_UP_A	0x26
+#define I2CS_PWR_TRIM_UP_B	0x27
+#define I2CS_PWR_TRIM_DN_A	0x28
+#define I2CS_PWR_TRIM_DN_B	0x29
+#define I2CS_PWR_VFAIL_STATUS_B	0x2a
+#define I2CS_PWR_VFAIL_CAUSE_B	0x2b
+#define I2CS_SCB		0x2c
+#define I2CS_RESET_I2CS_REG	0x2d
+#define I2CS_RESET_CONTROL	0x40
+#define I2CS_SIB_ID_PORT_STATUS	0x41
+#define I2CS_SIB_PCIE_GEN	0x42
+#define I2CS_TF_LTC		0x43
+#define I2CS_POWER_RST_HSWAP	0x44
+#define I2CS_SIB_EN		0x45
+#define I2CS_SIB_SPARE		0x46
+#define I2CS_TF_PCIE_INT_STAT	0x47
+#define I2CS_TF_PCIE_INT_EN	0x48
+#define I2CS_SIB_MISC_0		0x49
+#define I2CS_SIB_MISC_1		0x4a
+#define I2CS_LINK_STATUS_0	0x4b
+#define I2CS_LINK_STATUS_1	0x4c
+#define I2CS_LINK_STATUS_2	0x4d
+#define I2CS_LINK_STATUS_3	0x4e
+#define I2CS_LINK_STATUS_4	0x4f
+#define I2CS_LINK_STATUS_5	0x50
+#define I2CS_LINK_STATUS_6	0x51
+#define I2CS_LINK_STATUS_7	0x52
+#define I2CS_LINK_STATUS_8	0x53
+#define I2CS_LINK_STATUS_9	0x54
+#define I2CS_LINK_STATUS_10	0x55
+#define I2CS_LINK_STATUS_11	0x56
+#define I2CS_LINK_STATUS_12	0x57
+#define I2CS_LINK_STATUS_13	0x58
+#define I2CS_LINK_STATUS_14	0x59
+#define I2CS_LINK_STATUS_15	0x5a
+#define I2CS_LINK_STATUS_16	0x5b
+#define I2CS_LINK_STATUS_17	0x5c
+#define I2CS_PWR_VFAIL_IGNORE_SNG	0x5d
+#define I2CS_SPARE		0x5e
+#define I2CS_SPARE_OE		0x5f
+#define I2CS_MAX_REGISTER	I2CS_SPARE_OE
+
+struct mfd_cell;
+
+struct jnx_i2cs_platform_data {
+	int ncells;
+	struct mfd_cell *cells;
+};
+
+#endif /*__JNX_I2CS_CORE_H__*/
-- 
1.9.1

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

* [PATCH 01/10] mfd: Add Juniper I2CS MFD driver
@ 2016-10-07 15:21   ` Pantelis Antoniou
  0 siblings, 0 replies; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-gpio-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-leds-u79uwXL29TY76Z2rM5mHXA,
	linux-hwmon-u79uwXL29TY76Z2rM5mHXA

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

Add Juniper's I2CS FPGA MFD driver.

This driver is bare-bones and only provides a method for the
instantiation of the following subdevices.

- I2C mux driver (i2c-mux-i2cs)
- LEDS driver (leds-jnx-i2cs)
- GPIO driver (gpio-jnx-i2cs)
- HWMON driver (i2cs-fan-hwmon)

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               |  17 ++++++
 drivers/mfd/Makefile              |   1 +
 drivers/mfd/jnx-i2cs-core.c       | 118 ++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/jnx-i2cs-core.h |  96 +++++++++++++++++++++++++++++++
 4 files changed, 232 insertions(+)
 create mode 100644 drivers/mfd/jnx-i2cs-core.c
 create mode 100644 include/linux/mfd/jnx-i2cs-core.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6107f7a..82493d5 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1400,6 +1400,23 @@ config MFD_JUNIPER_CBC
 	  This driver can be built as a module. If built as a module it will be
 	  called "cbc-core"
 
+config MFD_JUNIPER_I2CS
+	tristate "Juniper I2CS FPGA"
+	depends on JNX_PTX1K_RCB || PTXPMB_COMMON || JNX_SYSTEM
+	select MFD_CORE
+	select REGMAP_I2C
+	select GPIO_JNX_I2CS
+	select I2C_MUX_I2CS
+	select LEDS_JNX_I2CS
+	depends on I2C=y
+	default y
+	help
+	  Select this to enable the I2CS FPGA multi-function kernel driver.
+	  This FPGA is present on almost any Juniper Networks card.
+
+	  This driver can be built as a module. If built as a module it will be
+	  called "jnx_i2cs"
+
 config MFD_TWL4030_AUDIO
 	bool "TI TWL4030 Audio"
 	depends on TWL4030_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 0ea6dc6..215d9cf 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -152,6 +152,7 @@ obj-$(CONFIG_MFD_JUNIPER_CPLD)	+= ptxpmb-cpld-core.o
 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_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/jnx-i2cs-core.c b/drivers/mfd/jnx-i2cs-core.c
new file mode 100644
index 0000000..d279a73
--- /dev/null
+++ b/drivers/mfd/jnx-i2cs-core.c
@@ -0,0 +1,118 @@
+/*
+ * drivers/mfd/jnx-i2cs-core.c
+ *
+ * Copyright (c) 2014, Juniper Networks
+ * Author: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
+ *
+ * The I2C Slave FPGA (I2CS) - found on almost any Juniper card.
+ *
+ * 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/module.h>
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/mfd/jnx-i2cs-core.h>
+
+static int jnx_i2cs_probe(struct i2c_client *i2c,
+			  const struct i2c_device_id *id)
+{
+	struct device *dev = &i2c->dev;
+	struct jnx_i2cs_platform_data *pdata = dev_get_platdata(dev);
+	struct device_node *child, *np = dev->of_node;
+	struct mfd_cell *cells;
+	int ncells, ret;
+
+	if (np) {
+		ncells = of_get_child_count(np);
+		if (ncells == 0) {
+			dev_err(dev, "No child specified for %s\n", np->name);
+			return -EINVAL;
+		}
+
+		cells = devm_kzalloc(dev, ncells * sizeof(*cells), GFP_KERNEL);
+		if (!cells)
+			return -ENOMEM;
+
+		ncells = 0;
+		for_each_available_child_of_node(dev->of_node, child) {
+			const char *s;
+
+			s = of_get_property(child, "compatible", NULL);
+			if (!s) {
+				dev_err(dev,
+					"Missing compatible property for %s\n",
+					child->name);
+				return -EINVAL;
+			}
+
+			cells[ncells].name = child->name;
+			cells[ncells].of_compatible = s;
+			ncells++;
+		}
+		if (ncells == 0) {
+			dev_err(dev, "No active child for %s\n", np->name);
+			return -EINVAL;
+		}
+	} else if (pdata) {
+		cells = pdata->cells;
+		ncells = pdata->ncells;
+	} else {
+		return -ENODEV;
+	}
+
+	ret = mfd_add_devices(dev, i2c_adapter_id(i2c->adapter),
+			      cells, ncells, NULL, 0, NULL);
+
+	return ret;
+}
+
+static int jnx_i2cs_remove(struct i2c_client *i2c)
+{
+	mfd_remove_devices(&i2c->dev);
+
+	return 0;
+}
+
+static const struct of_device_id jnx_i2cs_of_match[] = {
+	{ .compatible = "jnx,i2cs-rcb" },
+	{ .compatible = "jnx,i2cs-fpc" },
+	{ .compatible = "jnx,i2cs-sib" },
+	{ .compatible = "jnx,i2cs-fan" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, jnx_i2cs_of_match);
+
+static const struct i2c_device_id jnx_i2cs_id[] = {
+	{ "jnx_i2cs_rcb", 0 },
+	{ "jnx_i2cs_fpc", 0 },
+	{ "jnx_i2cs_sib", 0 },
+	{ "jnx_i2cs_fan", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, jnx_i2cs_id);
+
+static struct i2c_driver jnx_i2cs_driver = {
+	.driver = {
+		.name = "jnx_i2cs",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(jnx_i2cs_of_match),
+	},
+	.probe    = jnx_i2cs_probe,
+	.remove   = jnx_i2cs_remove,
+	.id_table = jnx_i2cs_id,
+};
+
+module_i2c_driver(jnx_i2cs_driver);
+
+MODULE_DESCRIPTION("Juniper I2CS MFD core driver");
+MODULE_AUTHOR("Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/jnx-i2cs-core.h b/include/linux/mfd/jnx-i2cs-core.h
new file mode 100644
index 0000000..5e63aab
--- /dev/null
+++ b/include/linux/mfd/jnx-i2cs-core.h
@@ -0,0 +1,96 @@
+/*
+ * I2CS FPGA (jnx-i2cs-core) registers
+ *
+ * Copyright (C) 2014 Juniper Networks
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __JNX_I2CS_CORE_H__
+#define __JNX_I2CS_CORE_H__
+
+/* SIB I2CS registers */
+#define I2CS_SCRATCH		0x00
+#define I2CS_VERSION		0x01
+#define I2CS_MASTER_STATUS	0x02
+#define I2CS_MASTER_TIMEOUT	0x03
+#define I2CS_MASTER_FORCE	0x04
+#define I2CS_I2C0_STATUS	0x05
+#define I2CS_I2C1_STATUS	0x06
+#define I2CS_I2C_RESET		0x07
+#define I2CS_DATECODE		0x0f
+#define I2CS_INT_STATUS		0x10
+#define I2CS_INT_ENABLE		0x11
+#define I2CS_FRU_LED		0x12
+#define I2CS_MISC_IO		0x13
+#define I2CS_BUTTON_STATUS	0x14
+#define I2CS_BUTTON_ENABLE	0x15
+#define I2CS_GPIO_OE		0x16
+#define I2CS_GPIO_OUT		0x17
+#define I2CS_GPIO_IN		0x18
+#define I2CS_SERIAL_CONFIG0	0x19
+#define I2CS_SERIAL_CONFIG1	0x1a
+#define I2CS_MII_CONFIG		0x1b
+#define I2CS_MII_ADDR		0x1c
+#define I2CS_MII_DATA0		0x1d
+#define I2CS_MII_DATA1		0x1e
+#define I2CS_MII_DATA2		0x1f
+#define I2CS_PWR_CONTROL	0x20
+#define I2CS_PWR_UP_STATUS	0x21
+#define I2CS_PWR_DIS_STATUS	0x22
+#define I2CS_PWR_DIS_CAUSE	0x23
+#define I2CS_PWR_VFAIL_STATUS	0x24
+#define I2CS_PWR_VFAIL_CAUSE	0x25
+#define I2CS_PWR_TRIM_UP_A	0x26
+#define I2CS_PWR_TRIM_UP_B	0x27
+#define I2CS_PWR_TRIM_DN_A	0x28
+#define I2CS_PWR_TRIM_DN_B	0x29
+#define I2CS_PWR_VFAIL_STATUS_B	0x2a
+#define I2CS_PWR_VFAIL_CAUSE_B	0x2b
+#define I2CS_SCB		0x2c
+#define I2CS_RESET_I2CS_REG	0x2d
+#define I2CS_RESET_CONTROL	0x40
+#define I2CS_SIB_ID_PORT_STATUS	0x41
+#define I2CS_SIB_PCIE_GEN	0x42
+#define I2CS_TF_LTC		0x43
+#define I2CS_POWER_RST_HSWAP	0x44
+#define I2CS_SIB_EN		0x45
+#define I2CS_SIB_SPARE		0x46
+#define I2CS_TF_PCIE_INT_STAT	0x47
+#define I2CS_TF_PCIE_INT_EN	0x48
+#define I2CS_SIB_MISC_0		0x49
+#define I2CS_SIB_MISC_1		0x4a
+#define I2CS_LINK_STATUS_0	0x4b
+#define I2CS_LINK_STATUS_1	0x4c
+#define I2CS_LINK_STATUS_2	0x4d
+#define I2CS_LINK_STATUS_3	0x4e
+#define I2CS_LINK_STATUS_4	0x4f
+#define I2CS_LINK_STATUS_5	0x50
+#define I2CS_LINK_STATUS_6	0x51
+#define I2CS_LINK_STATUS_7	0x52
+#define I2CS_LINK_STATUS_8	0x53
+#define I2CS_LINK_STATUS_9	0x54
+#define I2CS_LINK_STATUS_10	0x55
+#define I2CS_LINK_STATUS_11	0x56
+#define I2CS_LINK_STATUS_12	0x57
+#define I2CS_LINK_STATUS_13	0x58
+#define I2CS_LINK_STATUS_14	0x59
+#define I2CS_LINK_STATUS_15	0x5a
+#define I2CS_LINK_STATUS_16	0x5b
+#define I2CS_LINK_STATUS_17	0x5c
+#define I2CS_PWR_VFAIL_IGNORE_SNG	0x5d
+#define I2CS_SPARE		0x5e
+#define I2CS_SPARE_OE		0x5f
+#define I2CS_MAX_REGISTER	I2CS_SPARE_OE
+
+struct mfd_cell;
+
+struct jnx_i2cs_platform_data {
+	int ncells;
+	struct mfd_cell *cells;
+};
+
+#endif /*__JNX_I2CS_CORE_H__*/
-- 
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] 30+ messages in thread

* [PATCH 02/10] mfd: dt-bindings: Add bindings for the Juniper I2CS MFD
  2016-10-07 15:20 [PATCH 00/10] Introduce Juniper I2CS FPGA driver Pantelis Antoniou
  2016-10-07 15:21   ` Pantelis Antoniou
@ 2016-10-07 15:21 ` Pantelis Antoniou
  2016-10-10 20:23   ` Rob Herring
  2016-10-07 15:21   ` Pantelis Antoniou
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree, linux-kernel, linux-gpio, linux-i2c, linux-leds,
	linux-hwmon

From: Georgi Vlaev <gvlaev@juniper.net>

Add device tree bindings for the Juniper I2CS MFD driver.

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

diff --git a/Documentation/devicetree/bindings/mfd/jnx-i2cs.txt b/Documentation/devicetree/bindings/mfd/jnx-i2cs.txt
new file mode 100644
index 0000000..0ec103b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/jnx-i2cs.txt
@@ -0,0 +1,68 @@
+Device-Tree bindings for Juniper Networks I2CS FPGA MFD
+
+Required properties:
+- compatible - Must be one of:
+	"jnx,i2cs-rcb"	(Routing Engine or Control Board FRUs)
+	"jnx,i2cs-fpc"	(Flexible Port Concentrator FRUs)
+	"jnx,i2cs-sib"	(Switching Interface Board FRUs)
+	"jnx,i2cs-fan"	(Fan Tray FRUs)
+
+Optional properties:
+
+Depending on the FRU, the I2CS MFD has varied group of sub-devices:
+
+Device                   Description
+------                   -----------
+jnx,i2cs-gpio		: Virtual gpio mapping driver
+jnx,i2cs-fan-hwmon	: hwmon driver for fan trays
+jnx,i2c-mux-i2cs	: I2C Mux driver for FPC FRUs
+jnx,leds-i2cs		: Led driver
+
+All these optional nodes are described in their respective binding
+documents.
+
+Example node:
+
+i2cs@54 {
+	compatible = "jnx,i2cs-fpc";
+	reg = <0x54>;
+	#address-cells = <0>;
+	#size-cells = <0>;
+
+	fpc2_mux {
+		compatible = "jnx,i2c-mux-i2cs";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		fpc2i2c0: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+	};
+
+	fpc2_gpiomap: gpio-jnx-i2cs {
+		compatible = "jnx,gpio-i2cs";
+		reg = <0x54>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+
+		/*
+		 * Map bits [0-3] of reg 0x21 as gpio inputs, bits [4-7]
+		 * as gpio outputs
+		 */
+		i2c-gpio-map = <0x21 0x0f>;
+	};
+
+	leds-jnx-i2cs {
+		compatible = "jnx,leds-i2cs";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		sib8-active {
+			reg = <0>;
+			linux,default-trigger = "sib8-active";
+		};
+	};
+};
-- 
1.9.1

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

* [PATCH 03/10] i2c/muxes: Juniper I2CS RE mux
@ 2016-10-07 15:21   ` Pantelis Antoniou
  0 siblings, 0 replies; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree, linux-kernel, linux-gpio, linux-i2c, linux-leds,
	linux-hwmon

From: Georgi Vlaev <gvlaev@juniper.net>

Add support for Juniper I2C Slave RE multiplexer driver.

This I2C multiplexer driver allows the RE to access some of
the FPC I2C buses. It's compatible only with the FPC variant of the
I2CS.

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/i2c/muxes/Kconfig        |  10 +++
 drivers/i2c/muxes/Makefile       |   1 +
 drivers/i2c/muxes/i2c-mux-i2cs.c | 155 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 166 insertions(+)
 create mode 100644 drivers/i2c/muxes/i2c-mux-i2cs.c

diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index f45a9cb..c95380d 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -30,6 +30,16 @@ config I2C_MUX_GPIO
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mux-gpio.
 
+config I2C_MUX_I2CS
+	tristate "Juniper I2C Slave MFD client RE multiplexer"
+	depends on MFD_JUNIPER_I2CS
+	help
+	  Select this to enable the Juniper I2C Slave RE multiplexer driver
+	  on the relevant Juniper platforms.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-mux-i2cs.
+
 config I2C_MUX_PCA9541
 	tristate "NXP PCA9541 I2C Master Selector"
 	help
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
index 78d8cba..45b4287 100644
--- a/drivers/i2c/muxes/Makefile
+++ b/drivers/i2c/muxes/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE)	+= i2c-arb-gpio-challenge.o
 obj-$(CONFIG_I2C_DEMUX_PINCTRL)		+= i2c-demux-pinctrl.o
 
 obj-$(CONFIG_I2C_MUX_GPIO)	+= i2c-mux-gpio.o
+obj-$(CONFIG_I2C_MUX_I2CS)	+= i2c-mux-i2cs.o
 obj-$(CONFIG_I2C_MUX_PCA9541)	+= i2c-mux-pca9541.o
 obj-$(CONFIG_I2C_MUX_PCA954x)	+= i2c-mux-pca954x.o
 obj-$(CONFIG_I2C_MUX_PINCTRL)	+= i2c-mux-pinctrl.o
diff --git a/drivers/i2c/muxes/i2c-mux-i2cs.c b/drivers/i2c/muxes/i2c-mux-i2cs.c
new file mode 100644
index 0000000..c498a44
--- /dev/null
+++ b/drivers/i2c/muxes/i2c-mux-i2cs.c
@@ -0,0 +1,155 @@
+/*
+ * Juniper Networks I2CS RE mux driver
+ *
+ * Copyright (C) 2012, 2013, 2014 Juniper Networks. All rights reserved.
+ *
+ * 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/init.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/i2c-mux.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/jnx-i2cs-core.h>
+
+#define MISC_IO_RE_EN	0x01
+
+/*
+ * Read/write to mux register.
+ *   Don't use i2c_transfer()/i2c_smbus_xfer()
+ *   for this as they will try to lock adapter a second time
+ */
+static int i2cs_mux_read_byte(struct i2c_client *client,
+				  u8 offset, u8 *val)
+{
+	struct i2c_msg msg[2];
+
+	msg[0].addr = client->addr;
+	msg[0].flags = 0;
+	msg[0].len = 1;
+	msg[0].buf = &offset;
+
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len = 1;
+	msg[1].buf = val;
+
+	return client->adapter->algo->master_xfer(client->adapter, msg, 2);
+}
+
+static int i2cs_mux_write_byte(struct i2c_client *client, u8 offset, u8 val)
+{
+	struct i2c_msg msg;
+	char buf[2];
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.len = 2;
+	buf[0] = offset;
+	buf[1] = val;
+	msg.buf = buf;
+
+	return client->adapter->algo->master_xfer(client->adapter, &msg, 1);
+}
+
+static int i2cs_mux_select(struct i2c_mux_core *muxc, u32 chan)
+{
+	int ret;
+	u8 val = 0;
+	struct i2c_client *client = i2c_mux_priv(muxc);
+
+	ret = i2cs_mux_read_byte(client, I2CS_MISC_IO, &val);
+	if (ret < 0)
+		return ret;
+
+	val |= MISC_IO_RE_EN;
+	ret = i2cs_mux_write_byte(client, I2CS_MISC_IO, val);
+
+	return ret;
+}
+
+static int i2cs_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
+{
+	int ret;
+	u8 val = 0;
+	struct i2c_client *client = i2c_mux_priv(muxc);
+
+	ret = i2cs_mux_read_byte(client, I2CS_MISC_IO, &val);
+	if (ret < 0)
+		return ret;
+
+	val &= ~MISC_IO_RE_EN;
+	ret = i2cs_mux_write_byte(client, I2CS_MISC_IO, val);
+
+	return 0;
+}
+
+static int i2cs_mux_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct i2c_client *client;
+	struct i2c_mux_core *muxc;
+	int ret;
+
+	if (!dev->parent)
+		return -ENODEV;
+
+	client = i2c_verify_client(dev->parent);
+	if (!client)
+		return -ENODEV;
+
+	muxc = i2c_mux_alloc(client->adapter, &client->dev, 1, 0, 0,
+				i2cs_mux_select, i2cs_mux_deselect);
+	if (!muxc)
+		return -ENOMEM;
+	muxc->priv = client;
+
+	ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, muxc);
+
+	return 0;
+}
+
+static int i2cs_mux_remove(struct platform_device *pdev)
+{
+	i2c_mux_del_adapters(platform_get_drvdata(pdev));
+
+	return 0;
+}
+
+static const struct of_device_id i2cs_mux_of_match[] = {
+	{ .compatible = "jnx,i2c-mux-i2cs", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, i2cs_mux_of_match);
+
+static struct platform_driver i2cs_mux_driver = {
+	.driver = {
+		.name = "i2c-mux-i2cs",
+		.owner  = THIS_MODULE,
+		.of_match_table = of_match_ptr(i2cs_mux_of_match),
+	},
+	.probe = i2cs_mux_probe,
+	.remove = i2cs_mux_remove,
+};
+module_platform_driver(i2cs_mux_driver);
+
+MODULE_DESCRIPTION("Juniper Networks I2CS RE Mux driver");
+MODULE_AUTHOR("Georgi Vlaev <gvlaev@juniper.net>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:i2c-mux-i2cs");
-- 
1.9.1

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

* [PATCH 03/10] i2c/muxes: Juniper I2CS RE mux
@ 2016-10-07 15:21   ` Pantelis Antoniou
  0 siblings, 0 replies; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-gpio-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-leds-u79uwXL29TY76Z2rM5mHXA,
	linux-hwmon-u79uwXL29TY76Z2rM5mHXA

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

Add support for Juniper I2C Slave RE multiplexer driver.

This I2C multiplexer driver allows the RE to access some of
the FPC I2C buses. It's compatible only with the FPC variant of the
I2CS.

Signed-off-by: Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
Signed-off-by: Guenter Roeck <groeck-3r7Miqu9kMnR7s880joybQ@public.gmane.org>
[Ported from Juniper kernel]
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
---
 drivers/i2c/muxes/Kconfig        |  10 +++
 drivers/i2c/muxes/Makefile       |   1 +
 drivers/i2c/muxes/i2c-mux-i2cs.c | 155 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 166 insertions(+)
 create mode 100644 drivers/i2c/muxes/i2c-mux-i2cs.c

diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index f45a9cb..c95380d 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -30,6 +30,16 @@ config I2C_MUX_GPIO
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mux-gpio.
 
+config I2C_MUX_I2CS
+	tristate "Juniper I2C Slave MFD client RE multiplexer"
+	depends on MFD_JUNIPER_I2CS
+	help
+	  Select this to enable the Juniper I2C Slave RE multiplexer driver
+	  on the relevant Juniper platforms.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-mux-i2cs.
+
 config I2C_MUX_PCA9541
 	tristate "NXP PCA9541 I2C Master Selector"
 	help
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
index 78d8cba..45b4287 100644
--- a/drivers/i2c/muxes/Makefile
+++ b/drivers/i2c/muxes/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE)	+= i2c-arb-gpio-challenge.o
 obj-$(CONFIG_I2C_DEMUX_PINCTRL)		+= i2c-demux-pinctrl.o
 
 obj-$(CONFIG_I2C_MUX_GPIO)	+= i2c-mux-gpio.o
+obj-$(CONFIG_I2C_MUX_I2CS)	+= i2c-mux-i2cs.o
 obj-$(CONFIG_I2C_MUX_PCA9541)	+= i2c-mux-pca9541.o
 obj-$(CONFIG_I2C_MUX_PCA954x)	+= i2c-mux-pca954x.o
 obj-$(CONFIG_I2C_MUX_PINCTRL)	+= i2c-mux-pinctrl.o
diff --git a/drivers/i2c/muxes/i2c-mux-i2cs.c b/drivers/i2c/muxes/i2c-mux-i2cs.c
new file mode 100644
index 0000000..c498a44
--- /dev/null
+++ b/drivers/i2c/muxes/i2c-mux-i2cs.c
@@ -0,0 +1,155 @@
+/*
+ * Juniper Networks I2CS RE mux driver
+ *
+ * Copyright (C) 2012, 2013, 2014 Juniper Networks. All rights reserved.
+ *
+ * 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/init.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/i2c-mux.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/jnx-i2cs-core.h>
+
+#define MISC_IO_RE_EN	0x01
+
+/*
+ * Read/write to mux register.
+ *   Don't use i2c_transfer()/i2c_smbus_xfer()
+ *   for this as they will try to lock adapter a second time
+ */
+static int i2cs_mux_read_byte(struct i2c_client *client,
+				  u8 offset, u8 *val)
+{
+	struct i2c_msg msg[2];
+
+	msg[0].addr = client->addr;
+	msg[0].flags = 0;
+	msg[0].len = 1;
+	msg[0].buf = &offset;
+
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len = 1;
+	msg[1].buf = val;
+
+	return client->adapter->algo->master_xfer(client->adapter, msg, 2);
+}
+
+static int i2cs_mux_write_byte(struct i2c_client *client, u8 offset, u8 val)
+{
+	struct i2c_msg msg;
+	char buf[2];
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.len = 2;
+	buf[0] = offset;
+	buf[1] = val;
+	msg.buf = buf;
+
+	return client->adapter->algo->master_xfer(client->adapter, &msg, 1);
+}
+
+static int i2cs_mux_select(struct i2c_mux_core *muxc, u32 chan)
+{
+	int ret;
+	u8 val = 0;
+	struct i2c_client *client = i2c_mux_priv(muxc);
+
+	ret = i2cs_mux_read_byte(client, I2CS_MISC_IO, &val);
+	if (ret < 0)
+		return ret;
+
+	val |= MISC_IO_RE_EN;
+	ret = i2cs_mux_write_byte(client, I2CS_MISC_IO, val);
+
+	return ret;
+}
+
+static int i2cs_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
+{
+	int ret;
+	u8 val = 0;
+	struct i2c_client *client = i2c_mux_priv(muxc);
+
+	ret = i2cs_mux_read_byte(client, I2CS_MISC_IO, &val);
+	if (ret < 0)
+		return ret;
+
+	val &= ~MISC_IO_RE_EN;
+	ret = i2cs_mux_write_byte(client, I2CS_MISC_IO, val);
+
+	return 0;
+}
+
+static int i2cs_mux_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct i2c_client *client;
+	struct i2c_mux_core *muxc;
+	int ret;
+
+	if (!dev->parent)
+		return -ENODEV;
+
+	client = i2c_verify_client(dev->parent);
+	if (!client)
+		return -ENODEV;
+
+	muxc = i2c_mux_alloc(client->adapter, &client->dev, 1, 0, 0,
+				i2cs_mux_select, i2cs_mux_deselect);
+	if (!muxc)
+		return -ENOMEM;
+	muxc->priv = client;
+
+	ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, muxc);
+
+	return 0;
+}
+
+static int i2cs_mux_remove(struct platform_device *pdev)
+{
+	i2c_mux_del_adapters(platform_get_drvdata(pdev));
+
+	return 0;
+}
+
+static const struct of_device_id i2cs_mux_of_match[] = {
+	{ .compatible = "jnx,i2c-mux-i2cs", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, i2cs_mux_of_match);
+
+static struct platform_driver i2cs_mux_driver = {
+	.driver = {
+		.name = "i2c-mux-i2cs",
+		.owner  = THIS_MODULE,
+		.of_match_table = of_match_ptr(i2cs_mux_of_match),
+	},
+	.probe = i2cs_mux_probe,
+	.remove = i2cs_mux_remove,
+};
+module_platform_driver(i2cs_mux_driver);
+
+MODULE_DESCRIPTION("Juniper Networks I2CS RE Mux driver");
+MODULE_AUTHOR("Georgi Vlaev <gvlaev-3r7Miqu9kMnR7s880joybQ@public.gmane.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:i2c-mux-i2cs");
-- 
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] 30+ messages in thread

* [PATCH 04/10] i2c: i2c-mux-i2cs: Add device tree bindings
  2016-10-07 15:20 [PATCH 00/10] Introduce Juniper I2CS FPGA driver Pantelis Antoniou
                   ` (2 preceding siblings ...)
  2016-10-07 15:21   ` Pantelis Antoniou
@ 2016-10-07 15:21 ` Pantelis Antoniou
  2016-10-10 15:48     ` Peter Rosin
  2016-10-10 20:25   ` Rob Herring
  2016-10-07 15:21 ` [PATCH 05/10] gpio: i2cs: Juniper I2CS to GPIO pin mapping driver Pantelis Antoniou
                   ` (5 subsequent siblings)
  9 siblings, 2 replies; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree, linux-kernel, linux-gpio, linux-i2c, linux-leds,
	linux-hwmon

From: Georgi Vlaev <gvlaev@juniper.net>

Add binding document for the i2c mux driver of Juniper's I2CS FPGA.

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

diff --git a/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt b/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
new file mode 100644
index 0000000..03d917f
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
@@ -0,0 +1,27 @@
+* Juniper I2C Mux on I2CS
+
+	I2C mux driver for switching the RE access to the FPC i2c bus.
+	Compatible with the FPC variant of the I2CS.
+
+Required properties:
+
+  - compatible: "jnx,i2cs-mux-i2cs".
+
+The following required properties are defined externally:
+
+  - Standard I2C mux properties. See i2c-mux.txt in this directory.
+  - I2C child bus nodes. See i2c-mux.txt in this directory.
+
+Example:
+
+fpc0_mux {
+	compatible = "jnx,i2c-mux-i2cs";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	fpc0i2c0: i2c@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0>;
+	};
+};
-- 
1.9.1

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

* [PATCH 05/10] gpio: i2cs: Juniper I2CS to GPIO pin mapping driver
  2016-10-07 15:20 [PATCH 00/10] Introduce Juniper I2CS FPGA driver Pantelis Antoniou
                   ` (3 preceding siblings ...)
  2016-10-07 15:21 ` [PATCH 04/10] i2c: i2c-mux-i2cs: Add device tree bindings Pantelis Antoniou
@ 2016-10-07 15:21 ` Pantelis Antoniou
  2016-10-21  8:41     ` Linus Walleij
  2016-10-07 15:21 ` [PATCH 06/10] gpio: gpio-i2cs: Document bindings of I2CS FPGA GPIO block Pantelis Antoniou
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree, linux-kernel, linux-gpio, linux-i2c, linux-leds,
	linux-hwmon

From: Guenter Roeck <groeck@juniper.net>

This driver maps I2C slave register bits to GPIO pins. Registers
are supposed to be 8 bit wide. Interrupt support is optional.

The driver is implemented as client of the I2CS MFD driver.

Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
Signed-off-by: Guenter Roeck <groeck@juniper.net>
Signed-off-by: JawaharBalaji Thirumalaisamy <jawaharb@juniper.net>
[Ported from Juniper kernel]
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
---
 drivers/gpio/Kconfig         |  11 +
 drivers/gpio/Makefile        |   1 +
 drivers/gpio/gpio-jnx-i2cs.c | 523 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 535 insertions(+)
 create mode 100644 drivers/gpio/gpio-jnx-i2cs.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ef8f408..34840e9 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -746,6 +746,17 @@ config GPIO_ADNP
 	  enough to represent all pins, but the driver will assume a
 	  register layout for 64 pins (8 registers).
 
+config GPIO_JNX_I2CS
+	tristate "Juniper I2C slave GPIO driver"
+	depends on I2C
+	depends on MFD_JUNIPER_I2CS
+	help
+	  This driver maps I2C slave register bits to GPIO pins.
+	  Mapping is configured through devicetree data.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called gpio-jnx-i2cs.
+
 config GPIO_MAX7300
 	tristate "Maxim MAX7300 GPIO expander"
 	select GPIO_MAX730X
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 825c2636..06d5d51 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_GPIO_ICH)		+= gpio-ich.o
 obj-$(CONFIG_GPIO_IOP)		+= gpio-iop.o
 obj-$(CONFIG_GPIO_IT87)		+= gpio-it87.o
 obj-$(CONFIG_GPIO_JANZ_TTL)	+= gpio-janz-ttl.o
+obj-$(CONFIG_GPIO_JNX_I2CS)	+= gpio-jnx-i2cs.o
 obj-$(CONFIG_GPIO_KEMPLD)	+= gpio-kempld.o
 obj-$(CONFIG_ARCH_KS8695)	+= gpio-ks8695.o
 obj-$(CONFIG_GPIO_INTEL_MID)	+= gpio-intel-mid.o
diff --git a/drivers/gpio/gpio-jnx-i2cs.c b/drivers/gpio/gpio-jnx-i2cs.c
new file mode 100644
index 0000000..3a87b6a
--- /dev/null
+++ b/drivers/gpio/gpio-jnx-i2cs.c
@@ -0,0 +1,523 @@
+/*
+ * I2C -> GPIO mapping driver
+ * Copyright (c) 2013 Juniper Networks
+ *
+ * Derived from gpio-adnp.c
+ * Copyright (C) 2011-2012 Avionic Design GmbH
+ *
+ * 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/gpio.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+struct i2c_gpio_map {
+	u8 reg;		/* register offset			*/
+	u8 direction;	/* direction (in/out) for each bit	*/
+	u8 value;	/* cached value				*/
+	u8 irq_enable;
+	u8 irq_level;
+	u8 irq_rise;
+	u8 irq_fall;
+	u8 irq_high;
+	u8 irq_low;
+};
+
+struct i2cs_gpio {
+	struct i2c_client *client;	/* platform's device parent client */
+	struct device *dev;		/* our device */
+	struct gpio_chip gpio;
+	int irq;
+
+	struct mutex i2c_lock;
+
+	struct irq_domain *domain;
+	struct mutex irq_lock;
+
+	struct delayed_work work;
+
+	int num_regs;
+	struct i2c_gpio_map *map;
+};
+
+static inline struct i2cs_gpio *to_i2cs_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct i2cs_gpio, gpio);
+}
+
+static int i2cs_gpio_read_byte_data(struct i2c_client *client, u8 reg)
+{
+	int val, retries;
+
+	/*
+	 * i2c slave reads fail once in a while for no obvious reason.
+	 * Retry on any error code.
+	 */
+	for (retries = 0; retries < 10; retries++) {
+		val = i2c_smbus_read_byte_data(client, reg);
+		if (val >= 0)
+			break;
+	}
+	return val;
+}
+
+static int i2cs_gpio_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+	struct i2cs_gpio *i2cs_gpio = to_i2cs_gpio(chip);
+	struct i2c_gpio_map *map = &i2cs_gpio->map[offset >> 3];
+	struct i2c_client *client = i2cs_gpio->client;
+	u8 pos = offset & 7;
+	u8 reg = map->reg;
+	int val;
+
+	val = i2cs_gpio_read_byte_data(client, reg);
+	if (val < 0)
+		return val;
+
+	map->value = val;
+
+	return !!(val & BIT(pos));
+}
+
+static void __i2cs_gpio_gpio_set(struct i2cs_gpio *i2cs_gpio,
+				 unsigned int offset, int value)
+{
+	struct i2c_gpio_map *map = &i2cs_gpio->map[offset >> 3];
+	struct i2c_client *client = i2cs_gpio->client;
+	u8 pos = offset & 7;
+	u8 reg = map->reg;
+	int val;
+
+	val = i2cs_gpio_read_byte_data(client, reg);
+	if (val < 0)
+		return;
+
+	if (value)
+		val |= BIT(pos);
+	else
+		val &= ~BIT(pos);
+
+	map->value = val;
+	i2c_smbus_write_byte_data(client, reg, val);
+}
+
+static void i2cs_gpio_gpio_set(struct gpio_chip *chip,
+			       unsigned int offset, int value)
+{
+	struct i2cs_gpio *i2cs_gpio = to_i2cs_gpio(chip);
+
+	mutex_lock(&i2cs_gpio->i2c_lock);
+	__i2cs_gpio_gpio_set(i2cs_gpio, offset, value);
+	mutex_unlock(&i2cs_gpio->i2c_lock);
+}
+
+static int i2cs_gpio_gpio_direction_input(struct gpio_chip *chip,
+					  unsigned int offset)
+{
+	struct i2cs_gpio *i2cs_gpio = to_i2cs_gpio(chip);
+	struct i2c_gpio_map *map = &i2cs_gpio->map[offset >> 3];
+	u8 pos = offset & 7;
+
+	/*
+	 * Direction is determined by devicetree data and can not be
+	 * overwritten.
+	 */
+	return (map->direction & BIT(pos)) ? 0 : -EACCES;
+}
+
+static int i2cs_gpio_gpio_direction_output(struct gpio_chip *chip,
+					   unsigned int offset, int value)
+{
+	struct i2cs_gpio *i2cs_gpio = to_i2cs_gpio(chip);
+	struct i2c_gpio_map *map = &i2cs_gpio->map[offset >> 3];
+	u8 pos = offset & 7;
+
+	/*
+	 * Direction is determined by devicetree data and can not be
+	 * overwritten.
+	 */
+	return (map->direction & BIT(pos)) ? -EACCES : 0;
+}
+
+static int i2cs_gpio_gpio_setup(struct i2cs_gpio *i2cs_gpio,
+				unsigned int num_gpios)
+{
+	struct gpio_chip *chip = &i2cs_gpio->gpio;
+	struct i2c_client *client = i2cs_gpio->client;
+	char *name;
+
+	name = devm_kzalloc(i2cs_gpio->dev, 64, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+
+	scnprintf(name, 64, "%s-%d-%02x", dev_name(i2cs_gpio->dev),
+		  i2c_adapter_id(client->adapter), client->addr);
+
+	chip->direction_input = i2cs_gpio_gpio_direction_input;
+	chip->direction_output = i2cs_gpio_gpio_direction_output;
+	chip->get = i2cs_gpio_gpio_get;
+	chip->set = i2cs_gpio_gpio_set;
+	chip->can_sleep = 1;
+
+	chip->base = -1;
+	chip->ngpio = num_gpios;
+	chip->label = name;
+	chip->parent = i2cs_gpio->dev;
+	chip->of_node = chip->parent->of_node;
+	chip->owner = THIS_MODULE;
+
+	return 0;
+}
+
+static void i2cs_gpio_irq_work(struct i2cs_gpio *i2cs_gpio)
+{
+	unsigned int i;
+
+	for (i = 0; i < i2cs_gpio->num_regs; i++) {
+		struct i2c_gpio_map *map = &i2cs_gpio->map[i];
+		unsigned int base = i << 3, bit;
+		unsigned long pending;
+		u8 changed, level;
+
+		/* Don't read from i2c bus if interrupts are disabled */
+		if (!map->irq_enable)
+			continue;
+
+		level = i2cs_gpio_read_byte_data(i2cs_gpio->client, map->reg);
+		if (level < 0)
+			continue;
+
+		/* determine if bit changed levels */
+		changed = level ^ map->value;
+
+		/* compute edge-triggered interrupts */
+		pending = changed & ((map->irq_fall & ~level) |
+				     (map->irq_rise & level));
+
+		/* add in level-triggered interrupts */
+		pending |= (map->irq_high & level) |
+			   (map->irq_low & ~level);
+
+		/* mask out disabled interrupts */
+		pending &= map->irq_enable;
+
+		for_each_set_bit(bit, &pending, 8) {
+			unsigned int virq;
+
+			virq = irq_find_mapping(i2cs_gpio->domain, base + bit);
+			handle_nested_irq(virq);
+		}
+		map->value = level;
+	}
+}
+
+static irqreturn_t i2cs_gpio_irq_handler(int irq, void *data)
+{
+	i2cs_gpio_irq_work(data);
+
+	return IRQ_HANDLED;
+}
+
+static void i2cs_gpio_worker(struct work_struct *work)
+{
+	struct i2cs_gpio *i2cs_gpio;
+
+	i2cs_gpio = container_of(work, struct i2cs_gpio, work.work);
+	i2cs_gpio_irq_work(i2cs_gpio);
+	schedule_delayed_work(&i2cs_gpio->work, msecs_to_jiffies(100));
+}
+
+static int i2cs_gpio_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+	struct i2cs_gpio *i2cs_gpio = to_i2cs_gpio(chip);
+
+	return irq_create_mapping(i2cs_gpio->domain, offset);
+}
+
+static void i2cs_gpio_irq_mask(struct irq_data *data)
+{
+	struct i2cs_gpio *i2cs_gpio = irq_data_get_irq_chip_data(data);
+	struct i2c_gpio_map *map = &i2cs_gpio->map[data->hwirq >> 3];
+	unsigned int pos = data->hwirq & 7;
+
+	map->irq_enable &= ~BIT(pos);
+}
+
+static void i2cs_gpio_irq_unmask(struct irq_data *data)
+{
+	struct i2cs_gpio *i2cs_gpio = irq_data_get_irq_chip_data(data);
+	struct i2c_gpio_map *map = &i2cs_gpio->map[data->hwirq >> 3];
+	unsigned int pos = data->hwirq & 7;
+
+	map->irq_enable |= BIT(pos);
+}
+
+static int i2cs_gpio_irq_set_type(struct irq_data *data, unsigned int type)
+{
+	struct i2cs_gpio *i2cs_gpio = irq_data_get_irq_chip_data(data);
+	struct i2c_gpio_map *map = &i2cs_gpio->map[data->hwirq >> 3];
+	unsigned int pos = data->hwirq & 7;
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		map->irq_rise |= BIT(pos);
+	else
+		map->irq_rise &= ~BIT(pos);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		map->irq_fall |= BIT(pos);
+	else
+		map->irq_fall &= ~BIT(pos);
+
+	if (type & IRQ_TYPE_LEVEL_HIGH)
+		map->irq_high |= BIT(pos);
+	else
+		map->irq_high &= ~BIT(pos);
+
+	if (type & IRQ_TYPE_LEVEL_LOW)
+		map->irq_low |= BIT(pos);
+	else
+		map->irq_low &= ~BIT(pos);
+
+	return 0;
+}
+
+static void i2cs_gpio_irq_bus_lock(struct irq_data *data)
+{
+	struct i2cs_gpio *i2cs_gpio = irq_data_get_irq_chip_data(data);
+
+	mutex_lock(&i2cs_gpio->irq_lock);
+}
+
+static void i2cs_gpio_irq_bus_unlock(struct irq_data *data)
+{
+	struct i2cs_gpio *i2cs_gpio = irq_data_get_irq_chip_data(data);
+
+	mutex_unlock(&i2cs_gpio->irq_lock);
+}
+
+static struct irq_chip i2cs_gpio_irq_chip = {
+	.name = "jnx-gpio-i2cs",
+	.irq_mask = i2cs_gpio_irq_mask,
+	.irq_unmask = i2cs_gpio_irq_unmask,
+	.irq_set_type = i2cs_gpio_irq_set_type,
+	.irq_bus_lock = i2cs_gpio_irq_bus_lock,
+	.irq_bus_sync_unlock = i2cs_gpio_irq_bus_unlock,
+};
+
+static int i2cs_gpio_irq_map(struct irq_domain *domain, unsigned int irq,
+			     irq_hw_number_t hwirq)
+{
+	irq_set_chip_data(irq, domain->host_data);
+	irq_set_chip(irq, &i2cs_gpio_irq_chip);
+	irq_set_nested_thread(irq, true);
+	irq_set_noprobe(irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops i2cs_gpio_irq_domain_ops = {
+	.map = i2cs_gpio_irq_map,
+	.xlate = irq_domain_xlate_twocell,
+};
+
+static int i2cs_gpio_irq_setup(struct i2cs_gpio *i2cs_gpio)
+{
+	struct i2c_client *client = i2cs_gpio->client;
+	struct gpio_chip *chip = &i2cs_gpio->gpio;
+	int i, val, err;
+
+	mutex_init(&i2cs_gpio->irq_lock);
+
+	/* Cache initial register values */
+	for (i = 0; i < i2cs_gpio->num_regs; i++) {
+		struct i2c_gpio_map *map = &i2cs_gpio->map[i];
+
+		val = i2cs_gpio_read_byte_data(client, map->reg);
+		if (val < 0) {
+			dev_err(i2cs_gpio->dev,
+				"Failed to read register 0x%x: %d\n",
+				map->reg, val);
+			return val;
+		}
+		map->value = val;
+	}
+
+	i2cs_gpio->domain = irq_domain_add_linear(chip->of_node, chip->ngpio,
+						&i2cs_gpio_irq_domain_ops,
+						i2cs_gpio);
+
+	INIT_DELAYED_WORK(&i2cs_gpio->work, i2cs_gpio_worker);
+
+	if (i2cs_gpio->irq) {
+		err = request_threaded_irq(i2cs_gpio->irq, NULL,
+					   i2cs_gpio_irq_handler,
+					   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					   dev_name(chip->parent), i2cs_gpio);
+		if (err) {
+			dev_err(chip->parent, "can't request IRQ#%d: %d\n",
+				i2cs_gpio->irq, err);
+			goto error;
+		}
+	} else {
+		schedule_delayed_work(&i2cs_gpio->work, HZ / 10);
+	}
+
+	chip->to_irq = i2cs_gpio_gpio_to_irq;
+	return 0;
+
+error:
+	irq_domain_remove(i2cs_gpio->domain);
+	return err;
+}
+
+static void i2cs_gpio_irq_teardown(struct i2cs_gpio *i2cs_gpio)
+{
+	unsigned int irq, i;
+
+	if (i2cs_gpio->irq)
+		free_irq(i2cs_gpio->irq, i2cs_gpio);
+	else
+		cancel_delayed_work_sync(&i2cs_gpio->work);
+
+	for (i = 0; i < i2cs_gpio->gpio.ngpio; i++) {
+		irq = irq_find_mapping(i2cs_gpio->domain, i);
+		if (irq > 0)
+			irq_dispose_mapping(irq);
+	}
+
+	irq_domain_remove(i2cs_gpio->domain);
+}
+
+static int i2cs_gpio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct i2c_client *client;
+	struct i2cs_gpio *i2cs_gpio;
+	struct property *prop;
+	int num_regs;
+	int i, err;
+
+	if (!dev->parent)
+		return -ENODEV;
+
+	client = i2c_verify_client(dev->parent);
+	if (!client)
+		return -ENODEV;
+
+	i2cs_gpio = devm_kzalloc(dev, sizeof(*i2cs_gpio), GFP_KERNEL);
+	if (!i2cs_gpio)
+		return -ENOMEM;
+
+	prop = of_find_property(np, "i2c-gpio-map", &num_regs);
+	if (!prop)
+		return -EINVAL;
+	num_regs /= sizeof(u32);
+	if (!num_regs || (num_regs & 1))
+		return -EINVAL;
+	num_regs /= 2;
+
+	/*
+	 * If irq_of_parse_and_map() fails (returns 0), assume that
+	 * no interrupts are configured and that we need to poll instead.
+	 * We don't support deferred probes for this driver.
+	 */
+	i2cs_gpio->irq = irq_of_parse_and_map(np, 0);
+	i2cs_gpio->dev = dev;
+	i2cs_gpio->num_regs = num_regs;
+	i2cs_gpio->map = devm_kzalloc(dev,
+				      num_regs * sizeof(struct i2c_gpio_map),
+				      GFP_KERNEL);
+	if (!i2cs_gpio->map)
+		return -ENOMEM;
+
+	for (i = 0; i < num_regs; i++) {
+		struct i2c_gpio_map *map = &i2cs_gpio->map[i];
+		u32 val;
+
+		err = of_property_read_u32_index(np, "i2c-gpio-map", i * 2,
+						 &val);
+		if (err)
+			return err;
+		if (val > 0xff)
+			return -EINVAL;
+		map->reg = val;
+
+		err = of_property_read_u32_index(np, "i2c-gpio-map", i * 2 + 1,
+						 &val);
+		if (err)
+			return err;
+		if (val > 0xff)
+			return -EINVAL;
+		map->direction = val;
+	}
+
+	mutex_init(&i2cs_gpio->i2c_lock);
+	i2cs_gpio->client = client;
+
+	err = i2cs_gpio_gpio_setup(i2cs_gpio, num_regs << 3);
+	if (err < 0)
+		return err;
+
+	if (of_find_property(np, "interrupt-controller", NULL)) {
+		err = i2cs_gpio_irq_setup(i2cs_gpio);
+		if (err < 0)
+			return err;
+	}
+
+	err = gpiochip_add(&i2cs_gpio->gpio);
+	if (err < 0)
+		goto teardown;
+
+	platform_set_drvdata(pdev, i2cs_gpio);
+	return 0;
+
+teardown:
+	if (of_find_property(np, "interrupt-controller", NULL))
+		i2cs_gpio_irq_teardown(i2cs_gpio);
+
+	return err;
+}
+
+static int i2cs_gpio_remove(struct platform_device *pdev)
+{
+	struct i2cs_gpio *i2cs_gpio = platform_get_drvdata(pdev);
+	struct device_node *np = pdev->dev.of_node;
+
+	gpiochip_remove(&i2cs_gpio->gpio);
+
+	if (of_find_property(np, "interrupt-controller", NULL))
+		i2cs_gpio_irq_teardown(i2cs_gpio);
+
+	return 0;
+}
+
+static const struct of_device_id i2cs_gpio_of_match[] = {
+	{ .compatible = "jnx,gpio-i2cs", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, i2cs_gpio_of_match);
+
+static struct platform_driver i2cs_gpio_driver = {
+	.driver = {
+		.name = "gpio-jnx-i2cs",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(i2cs_gpio_of_match),
+	},
+	.probe = i2cs_gpio_probe,
+	.remove = i2cs_gpio_remove,
+};
+module_platform_driver(i2cs_gpio_driver);
+
+MODULE_DESCRIPTION("Juniper Networks I2C to GPIO mapping driver");
+MODULE_AUTHOR("Guenter Roeck <groeck@juniper.net>");
+MODULE_LICENSE("GPL");
-- 
1.9.1

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

* [PATCH 06/10] gpio: gpio-i2cs: Document bindings of I2CS FPGA GPIO block
  2016-10-07 15:20 [PATCH 00/10] Introduce Juniper I2CS FPGA driver Pantelis Antoniou
                   ` (4 preceding siblings ...)
  2016-10-07 15:21 ` [PATCH 05/10] gpio: i2cs: Juniper I2CS to GPIO pin mapping driver Pantelis Antoniou
@ 2016-10-07 15:21 ` Pantelis Antoniou
  2016-10-21  8:59     ` Linus Walleij
  2016-10-07 15:21 ` [PATCH 07/10] leds: i2cs: Add I2CS FPGA leds driver Pantelis Antoniou
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree, linux-kernel, linux-gpio, linux-i2c, linux-leds,
	linux-hwmon

From: Georgi Vlaev <gvlaev@juniper.net>

Add device tree bindings document for the GPIO driver of
Juniper's I2CS FPGA.

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

diff --git a/Documentation/devicetree/bindings/gpio/jnx,gpio-i2cs.txt b/Documentation/devicetree/bindings/gpio/jnx,gpio-i2cs.txt
new file mode 100644
index 0000000..835b7fb4
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/jnx,gpio-i2cs.txt
@@ -0,0 +1,43 @@
+Juniper I2CS FPGA GPIO presence block
+
+This is virtual gpio driver, that maps each bit of the I2CS FPGA to
+a gpio. It's used as a compatibility replacement for FRUs that use
+I2CS FPGA to report presence, control and report power status in
+the Juniper's driver infra that uses gpios. Compatible with any I2CS.
+
+Required properties:
+
+Required properties:
+- compatible: "jnx,gpio-i2cs"
+
+- reg:
+    Address on the I2C bus of the I2CS FPGA
+
+- gpio-controller: Marks the device node as a gpio controller.
+
+- interrupt-controller: Marks the device node as an interrupt
+			controller.
+
+- i2c-gpio-map: Map of "I2CS register" and "direction". The registers
+	are 8 bit wide, each bit of the register is mapped to either
+	input or output depending on the bits of the "direction". If
+	the bit in the direction is 1, then that bit from the I2CS
+	register is mapped to gpio input, otherwise to gpio output.
+
+- #gpio-cells : Should be two.  The first cell is the pin number and
+	the second cell is used to specify the gpio polarity:
+	0 = active high
+	1 = active low
+
+Optional properties:
+
+Example:
+
+cb0_slave: i2c-slave@54 {
+	compatible = "jnx,gpio-i2cs";
+	reg = <0x54>;
+	#gpio-cells = <2>;
+	gpio-controller;
+	interrupt-controller;
+	i2c-gpio-map = <0x21 0xff>;	/* power status (bit 6) */
+};
-- 
1.9.1

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

* [PATCH 07/10] leds: i2cs: Add I2CS FPGA leds driver
  2016-10-07 15:20 [PATCH 00/10] Introduce Juniper I2CS FPGA driver Pantelis Antoniou
                   ` (5 preceding siblings ...)
  2016-10-07 15:21 ` [PATCH 06/10] gpio: gpio-i2cs: Document bindings of I2CS FPGA GPIO block Pantelis Antoniou
@ 2016-10-07 15:21 ` Pantelis Antoniou
  2016-10-10  9:41   ` Jacek Anaszewski
  2016-10-07 15:21   ` Pantelis Antoniou
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree, linux-kernel, linux-gpio, linux-i2c, linux-leds,
	linux-hwmon

From: Georgi Vlaev <gvlaev@juniper.net>

Add support for the FRU faceplate status LEDs (OK, FAIL,
ACTIVE, STANDBY) controlled by the Juniper I2CS FPGA. This
driver is a jnx-i2cs-core client.

Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
[Ported from Juniper kernel]
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
---
 drivers/leds/Kconfig         |   9 ++
 drivers/leds/Makefile        |   1 +
 drivers/leds/leds-jnx-i2cs.c | 219 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 229 insertions(+)
 create mode 100644 drivers/leds/leds-jnx-i2cs.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 7a628c6..45c6612 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -659,6 +659,15 @@ config LEDS_MLXCPLD
 	  This option enabled support for the LEDs on the Mellanox
 	  boards. Say Y to enabled these.
 
+config LEDS_JNX_I2CS
+	tristate "LED support for the Juniper Networks I2CS FPGA"
+	depends on LEDS_CLASS && I2C
+	select REGMAP_I2C
+	help
+	  This option enables support for the FRU faceplate status
+	  LEDs (OK, FAIL, ACTIVE, STANDBY) controlled by the Juniper
+	  I2CS FPGA.
+
 comment "LED Triggers"
 source "drivers/leds/trigger/Kconfig"
 
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 3965070..1ce2d0b 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_LEDS_IS31FL319X)		+= leds-is31fl319x.o
 obj-$(CONFIG_LEDS_IS31FL32XX)		+= leds-is31fl32xx.o
 obj-$(CONFIG_LEDS_PM8058)		+= leds-pm8058.o
 obj-$(CONFIG_LEDS_MLXCPLD)		+= leds-mlxcpld.o
+obj-$(CONFIG_LEDS_JNX_I2CS)		+= leds-jnx-i2cs.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
diff --git a/drivers/leds/leds-jnx-i2cs.c b/drivers/leds/leds-jnx-i2cs.c
new file mode 100644
index 0000000..c2d7274
--- /dev/null
+++ b/drivers/leds/leds-jnx-i2cs.c
@@ -0,0 +1,219 @@
+/*
+ * Juniper Networks I2CS FPGA LEDs driver
+ *
+ * Copyright (C) 2016 Juniper Networks
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/of.h>
+#include <linux/delay.h>
+#include <linux/leds.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/jnx-i2cs-core.h>
+
+#define FRU_LEDS	4 /* Total LEDs (active, fail, ok, standby) */
+#define HW_BLINK_LEDS	3 /* LEDs with hw blink cap (standby not supported) */
+
+/*
+ * I2CS fru_led [0x12]
+ *
+ * bit 6   | bit 5    | bit 4   |...                        | bit 0
+ * blink_ok|blink_fail|blink_act|led_standby|led_ok|led_fail|led_act
+ */
+
+/* TODO: Use the regmap from the parent MFD */
+static struct regmap_config i2cs_leds_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = I2CS_SPARE_OE,
+};
+
+struct i2cs_led {
+	struct led_classdev lc;
+	struct regmap *regmap;
+	struct work_struct work;
+	int blink;
+	int on;
+	int bit;
+};
+
+struct i2cs_led_data {
+	int num_leds;
+	struct i2cs_led *leds;
+};
+
+static void jnx_i2cs_leds_work(struct work_struct *work)
+{
+	struct i2cs_led *led = container_of(work, struct i2cs_led, work);
+
+	int mask = (BIT(led->bit) << 4) | BIT(led->bit);
+	int value = ((led->blink << led->bit) << 4) | (led->on << led->bit);
+
+	regmap_update_bits(led->regmap, I2CS_FRU_LED, mask, value & 0x7f);
+}
+
+static void jnx_i2cs_leds_brightness_set(struct led_classdev *lc,
+				 enum led_brightness brightness)
+{
+	struct i2cs_led *led = container_of(lc, struct i2cs_led, lc);
+
+	led->on = (brightness != LED_OFF);
+	led->blink = 0; /* always turn off hw blink on brightness_set() */
+	schedule_work(&led->work);
+}
+
+static int jnx_i2cs_leds_blink_set(struct led_classdev *lc,
+				   unsigned long *delay_on,
+				   unsigned long *delay_off)
+{
+	struct i2cs_led *led = container_of(lc, struct i2cs_led, lc);
+
+	led->blink = (*delay_on > 0);
+	led->on = led->blink; /* 'on' bit should be set if blinking */
+	schedule_work(&led->work);
+
+	return 0;
+}
+
+static int jnx_i2cs_leds_init_one(struct device *dev, struct device_node *np,
+				  struct i2cs_led_data *ild,
+				  struct regmap *regmap, int num)
+{
+	struct i2cs_led *led;
+	const char *string;
+	bool hw_blink;
+	int ret;
+	u32 reg;
+
+	ret = of_property_read_u32(np, "reg", &reg);
+	if (ret || reg >= FRU_LEDS)
+		return -ENODEV;
+
+	led = &ild->leds[num];
+	led->bit = reg;
+	led->regmap = regmap;
+
+	if (!of_property_read_string(np, "label", &string))
+		led->lc.name = string;
+	else
+		led->lc.name = np->name;
+
+	if (!of_property_read_string(np, "linux,default-trigger", &string))
+		led->lc.default_trigger = string;
+
+	led->lc.brightness = LED_OFF;
+	led->lc.brightness_set = jnx_i2cs_leds_brightness_set;
+	if (led->bit <= HW_BLINK_LEDS) {
+		hw_blink = of_property_read_bool(np, "hw-blink");
+		if (hw_blink)
+			led->lc.blink_set = jnx_i2cs_leds_blink_set;
+	}
+
+	ret = devm_led_classdev_register(dev, &led->lc);
+	if (ret)
+		return ret;
+
+	INIT_WORK(&led->work, jnx_i2cs_leds_work);
+
+	return 0;
+}
+
+static int jnx_i2cs_leds_of_init(struct device *dev, struct i2cs_led_data *ild)
+{
+	struct device_node *child, *np = dev->of_node;
+	struct regmap *regmap;
+	struct i2c_client *client;
+	int ret, num_leds, i = 0;
+
+	if (!dev->parent)
+		return -ENODEV;
+
+	client = i2c_verify_client(dev->parent);
+	if (!client)
+		return -ENODEV;
+
+	regmap = devm_regmap_init_i2c(client, &i2cs_leds_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "Failed to allocate register map\n");
+		return PTR_ERR(regmap);
+	}
+
+	num_leds = of_get_child_count(np);
+	if (!num_leds || num_leds > FRU_LEDS)
+		return -ENODEV;
+
+	ild->num_leds = num_leds;
+	ild->leds = devm_kzalloc(dev, sizeof(struct i2cs_led) * num_leds,
+				 GFP_KERNEL);
+	if (!ild->leds)
+		return -ENOMEM;
+
+	for_each_child_of_node(np, child) {
+		ret = jnx_i2cs_leds_init_one(dev, child, ild, regmap, i++);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int jnx_i2cs_leds_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct i2cs_led_data *ild;
+	int ret;
+
+	ild = devm_kzalloc(dev, sizeof(*ild), GFP_KERNEL);
+	if (!ild)
+		return -ENOMEM;
+
+	ret = jnx_i2cs_leds_of_init(dev, ild);
+	if (ret < 0)
+		return ret;
+
+	platform_set_drvdata(pdev, ild);
+
+	return 0;
+}
+
+static int jnx_i2cs_leds_remove(struct platform_device *pdev)
+{
+	struct i2cs_led_data *ild = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < ild->num_leds; i++) {
+		devm_led_classdev_unregister(&pdev->dev, &ild->leds[i].lc);
+		cancel_work_sync(&ild->leds[i].work);
+	}
+
+	return 0;
+}
+
+static const struct of_device_id jnx_i2cs_leds_match[] = {
+	{ .compatible = "jnx,leds-i2cs", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, jnx_i2cs_leds_match);
+
+static struct platform_driver jnx_i2cs_leds_driver = {
+	.driver = {
+		.name  = "leds-i2cs",
+		.of_match_table = jnx_i2cs_leds_match,
+	},
+	.probe = jnx_i2cs_leds_probe,
+	.remove = jnx_i2cs_leds_remove,
+};
+
+module_platform_driver(jnx_i2cs_leds_driver);
+
+MODULE_DESCRIPTION("Juniper Networks I2CS leds driver");
+MODULE_AUTHOR("Georgi Vlaev <gvlaev@juniper.net>");
+MODULE_LICENSE("GPL");
-- 
1.9.1

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

* [PATCH 08/10] leds: Add binding for Juniper's I2CS FPGA
@ 2016-10-07 15:21   ` Pantelis Antoniou
  0 siblings, 0 replies; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree, linux-kernel, linux-gpio, linux-i2c, linux-leds,
	linux-hwmon

From: Georgi Vlaev <gvlaev@juniper.net>

Document bindings for the I2CS FPGA leds.

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

diff --git a/Documentation/devicetree/bindings/leds/leds-i2cs.txt b/Documentation/devicetree/bindings/leds/leds-i2cs.txt
new file mode 100644
index 0000000..100e584
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-i2cs.txt
@@ -0,0 +1,34 @@
+Juniper I2CS LED driver.
+
+This is present in Juniper platforms that use a I2CS Slave FPGA.
+
+Required properties:
+  - compatible: must be "jnx,leds-i2cs"
+  - #address-cells : must be 1.
+  - #size-cells : must be 0.
+
+Each led is represented as a sub-node of the jnx,leds-i2cs device.
+
+LED sub-node properties:
+- label : (optional) see Documentation/devicetree/bindings/leds/common.txt
+- reg : number of LED
+- linux,default-trigger : (optional)
+   see Documentation/devicetree/bindings/leds/common.txt
+
+Example:
+
+leds_fpc0: leds-jnx-i2cs {
+	compatible = "jnx,leds-i2cs";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	fpc0-fail {
+		reg = <1>;
+		linux,default-trigger = "fpc0-fail";
+	};
+
+	fpc0-ok {
+		reg = <2>;
+		linux,default-trigger = "fpc0-ok";
+	};
+};
-- 
1.9.1

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

* [PATCH 08/10] leds: Add binding for Juniper's I2CS FPGA
@ 2016-10-07 15:21   ` Pantelis Antoniou
  0 siblings, 0 replies; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-gpio-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-leds-u79uwXL29TY76Z2rM5mHXA,
	linux-hwmon-u79uwXL29TY76Z2rM5mHXA

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

Document bindings for the I2CS FPGA leds.

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/leds/leds-i2cs.txt         | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/leds/leds-i2cs.txt

diff --git a/Documentation/devicetree/bindings/leds/leds-i2cs.txt b/Documentation/devicetree/bindings/leds/leds-i2cs.txt
new file mode 100644
index 0000000..100e584
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-i2cs.txt
@@ -0,0 +1,34 @@
+Juniper I2CS LED driver.
+
+This is present in Juniper platforms that use a I2CS Slave FPGA.
+
+Required properties:
+  - compatible: must be "jnx,leds-i2cs"
+  - #address-cells : must be 1.
+  - #size-cells : must be 0.
+
+Each led is represented as a sub-node of the jnx,leds-i2cs device.
+
+LED sub-node properties:
+- label : (optional) see Documentation/devicetree/bindings/leds/common.txt
+- reg : number of LED
+- linux,default-trigger : (optional)
+   see Documentation/devicetree/bindings/leds/common.txt
+
+Example:
+
+leds_fpc0: leds-jnx-i2cs {
+	compatible = "jnx,leds-i2cs";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	fpc0-fail {
+		reg = <1>;
+		linux,default-trigger = "fpc0-fail";
+	};
+
+	fpc0-ok {
+		reg = <2>;
+		linux,default-trigger = "fpc0-ok";
+	};
+};
-- 
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] 30+ messages in thread

* [PATCH 09/10] hwmon: Add driver for Fan Tray on Juniper I2CS FGPA
  2016-10-07 15:20 [PATCH 00/10] Introduce Juniper I2CS FPGA driver Pantelis Antoniou
                   ` (7 preceding siblings ...)
  2016-10-07 15:21   ` Pantelis Antoniou
@ 2016-10-07 15:21 ` Pantelis Antoniou
  2016-10-07 15:21 ` [PATCH 10/10] hwmon: i2cs-fan: Add hwmon dts binding documentation Pantelis Antoniou
  9 siblings, 0 replies; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree, linux-kernel, linux-gpio, linux-i2c, linux-leds,
	linux-hwmon

From: Avirup Banerjee <abanerjee@juniper.net>

Add a hwmon driver for Fan Trays using Juniper's I2CS FPGA.

Signed-off-by: Avirup Banerjee <abanerjee@juniper.net>
Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
Signed-off-by: Guenter Roeck <groeck@juniper.net>
Signed-off-by: JawaharBalaji Thirumalaisamy <jawaharb@juniper.net>
[Ported from Juniper kernel]
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
---
 drivers/hwmon/Kconfig                      |  11 +
 drivers/hwmon/Makefile                     |   1 +
 drivers/hwmon/jnx-fan.c                    | 471 +++++++++++++++++++++++++++++
 include/linux/platform_data/jnx-i2cs-fan.h |  13 +
 4 files changed, 496 insertions(+)
 create mode 100644 drivers/hwmon/jnx-fan.c
 create mode 100644 include/linux/platform_data/jnx-i2cs-fan.h

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 45cef3d..b9348d2 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -663,6 +663,17 @@ config SENSORS_JC42
 	  This driver can also be built as a module.  If so, the module
 	  will be called jc42.
 
+config SENSORS_JNX_FAN
+	tristate "Juniper Fan Tray driver"
+	depends on I2C && MFD_JUNIPER_I2CS
+	select REGMAP_I2C
+	help
+	  If you say yes here you get support for the Juniper Networks
+	  Fan Tray Driver.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called jnx-fan.
+
 config SENSORS_POWR1220
 	tristate "Lattice POWR1220 Power Monitoring"
 	depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index aecf4ba..eea631e 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_SENSORS_INA2XX)	+= ina2xx.o
 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_JZ4740)	+= jz4740-hwmon.o
 obj-$(CONFIG_SENSORS_K8TEMP)	+= k8temp.o
 obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
diff --git a/drivers/hwmon/jnx-fan.c b/drivers/hwmon/jnx-fan.c
new file mode 100644
index 0000000..d04e3ce
--- /dev/null
+++ b/drivers/hwmon/jnx-fan.c
@@ -0,0 +1,471 @@
+/*
+ * hwmon: Driver for Juniper Fan Tray Controller
+ *
+ * Copyright (c) 2014 Juniper Networks. All rights reserved.
+ * Author: Avirup Banerjee <abanerjee@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/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_data/jnx-i2cs-fan.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define DRIVER_NAME "i2cs_fan_hwmon"
+
+/*
+ * Fan fpga register offsets
+ */
+
+#define I2CS_FAN_ADEC_VER                   0x01
+#define I2CS_FAN_SELECT                     0x40
+#define I2CS_FAN_SPEED_CTRL                 0x41
+#define I2CS_FAN_MAX_TACH                   0x42
+#define I2CS_FAN_MIN_TACH                   0x43
+#define I2CS_FAN_TACH                       0x44
+#define I2CS_FAN_INT_SRC                    0x45
+#define I2CS_FAN_INT_MASK                   0x46
+#define I2CS_FAN_INT_1_7                    0x47
+#define I2CS_FAN_INT_8_14                   0x48
+#define I2CS_FAN_SPARE_FAN_INT_15_22        0x49
+#define I2CS_FAN_MODE_AND_TEST              0x4A
+#define I2CS_FAN_HW_DEBUG_1                 0x4B
+#define I2CS_FAN_HW_DEBUG_2                 0x4C
+#define I2CS_FAN_SW_FAN_POWER_SPEED_FAIL    0x4D
+#define I2CS_FAN_ADEC_MASK_WAIT_SECOND      0x4F
+#define I2CS_FAN_RESET_WAIT_CONTROL         0x50
+#define I2CS_FAN_BOARD_STAT_1               0x51
+#define I2CS_FAN_BOARD_STAT_2               0x52
+#define I2CS_FAN_OK_THRESHOLD               0x53
+#define I2CS_FAN_SPARE                      0x54
+#define I2CS_FAN_SPARE_OE                   0x55
+
+#define FAN_TACH_FACTOR                     120
+#define NUM_FANS_PER_TRAY                   14
+
+struct jnx_fan_data {
+	struct regmap *regmap;
+	struct device *hwmon_dev;
+	struct mutex update_lock;
+	int fan_index;
+	int num_fans;
+	int factor;
+};
+
+static int jnx_fan_select(struct jnx_fan_data *data, int index)
+{
+	/* Return if fan has already been selected */
+	if (data->fan_index == index)
+		return 0;
+
+	data->fan_index = index;
+
+	return regmap_write(data->regmap, I2CS_FAN_SELECT, index);
+}
+
+static int jnx_fan_read_reg(struct jnx_fan_data *data, u8 reg, int index)
+{
+	unsigned int value;
+	int ret;
+
+	mutex_lock(&data->update_lock);
+
+	ret = jnx_fan_select(data, index);
+	if (ret < 0)
+		goto done;
+
+	ret = regmap_read(data->regmap, reg, &value);
+	if (ret < 0)
+		goto done;
+	ret = value;
+
+done:
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static int jnx_fan_write_reg(struct jnx_fan_data *data, u8 reg,
+			     unsigned int value, int index)
+{
+	int ret;
+
+	mutex_lock(&data->update_lock);
+	ret = jnx_fan_select(data, index);
+	if (ret < 0)
+		goto done;
+
+	ret = regmap_write(data->regmap, reg, value);
+
+done:
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static ssize_t jnx_fan_set_pwm(struct device *dev,
+			       struct device_attribute *da,
+			       const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct jnx_fan_data *data = dev_get_drvdata(dev);
+	unsigned long val;
+	int ret;
+
+	if (kstrtoul(buf, 10, &val) < 0)
+		return -EINVAL;
+	if (val > 255)
+		return -EINVAL;
+
+	ret = jnx_fan_write_reg(data, I2CS_FAN_SPEED_CTRL, val, attr->index);
+	return ret ? ret : count;
+}
+
+static ssize_t jnx_fan_show_pwm(struct device *dev,
+				struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct jnx_fan_data *data = dev_get_drvdata(dev);
+	int ret;
+
+	ret = jnx_fan_read_reg(data, I2CS_FAN_SPEED_CTRL, attr->index);
+	if (ret < 0)
+		return ret;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
+}
+
+static ssize_t jnx_fan_show(struct device *dev, struct device_attribute *da,
+			    char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
+	struct jnx_fan_data *data = dev_get_drvdata(dev);
+	int ret;
+
+	ret = jnx_fan_read_reg(data, attr->nr, attr->index);
+	if (ret < 0)
+		return ret;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", ret * data->factor);
+}
+
+static ssize_t jnx_fan_set(struct device *dev, struct device_attribute *da,
+			   const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
+	struct jnx_fan_data *data = dev_get_drvdata(dev);
+	unsigned long val;
+	int ret;
+
+	if (kstrtoul(buf, 10, &val) < 0)
+		return -EINVAL;
+
+	DIV_ROUND_CLOSEST(val, data->factor);
+	clamp_val(val, 0, 255);
+
+	ret = jnx_fan_write_reg(data, attr->nr, val, attr->index);
+	return ret ? ret : count;
+}
+
+static umode_t jnx_fan_is_visible(struct kobject *kobj, struct attribute *a,
+				  int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct jnx_fan_data *data = dev_get_drvdata(dev);
+	unsigned int index = n % 14;
+
+	if (index < data->num_fans)
+		return a->mode;
+
+	return 0;
+}
+
+static struct regmap_config jnx_fan_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = I2CS_FAN_SPARE_OE,
+};
+
+/* Fan speed */
+static SENSOR_DEVICE_ATTR_2(fan1_input,  S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 1);
+static SENSOR_DEVICE_ATTR_2(fan2_input,  S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 2);
+static SENSOR_DEVICE_ATTR_2(fan3_input,  S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 3);
+static SENSOR_DEVICE_ATTR_2(fan4_input,  S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 4);
+static SENSOR_DEVICE_ATTR_2(fan5_input,  S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 5);
+static SENSOR_DEVICE_ATTR_2(fan6_input,  S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 6);
+static SENSOR_DEVICE_ATTR_2(fan7_input,  S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 7);
+static SENSOR_DEVICE_ATTR_2(fan8_input,  S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 8);
+static SENSOR_DEVICE_ATTR_2(fan9_input,  S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 9);
+static SENSOR_DEVICE_ATTR_2(fan10_input, S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 10);
+static SENSOR_DEVICE_ATTR_2(fan11_input, S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 11);
+static SENSOR_DEVICE_ATTR_2(fan12_input, S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 12);
+static SENSOR_DEVICE_ATTR_2(fan13_input, S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 13);
+static SENSOR_DEVICE_ATTR_2(fan14_input, S_IRUGO, jnx_fan_show, NULL,
+			    I2CS_FAN_TACH, 14);
+
+/* PWM values */
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 2);
+static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 3);
+static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 4);
+static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 5);
+static SENSOR_DEVICE_ATTR(pwm6, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 6);
+static SENSOR_DEVICE_ATTR(pwm7, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 7);
+static SENSOR_DEVICE_ATTR(pwm8, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 8);
+static SENSOR_DEVICE_ATTR(pwm9, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 9);
+static SENSOR_DEVICE_ATTR(pwm10, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 10);
+static SENSOR_DEVICE_ATTR(pwm11, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 11);
+static SENSOR_DEVICE_ATTR(pwm12, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 12);
+static SENSOR_DEVICE_ATTR(pwm13, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 13);
+static SENSOR_DEVICE_ATTR(pwm14, S_IWUSR | S_IRUGO, jnx_fan_show_pwm,
+			  jnx_fan_set_pwm, 14);
+
+/* Fan Thresholds */
+
+/* Min */
+static SENSOR_DEVICE_ATTR_2(fan1_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 1);
+static SENSOR_DEVICE_ATTR_2(fan2_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 2);
+static SENSOR_DEVICE_ATTR_2(fan3_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 3);
+static SENSOR_DEVICE_ATTR_2(fan4_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 4);
+static SENSOR_DEVICE_ATTR_2(fan5_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 5);
+static SENSOR_DEVICE_ATTR_2(fan6_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 6);
+static SENSOR_DEVICE_ATTR_2(fan7_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 7);
+static SENSOR_DEVICE_ATTR_2(fan8_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 8);
+static SENSOR_DEVICE_ATTR_2(fan9_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 9);
+static SENSOR_DEVICE_ATTR_2(fan10_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 10);
+static SENSOR_DEVICE_ATTR_2(fan11_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 11);
+static SENSOR_DEVICE_ATTR_2(fan12_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 12);
+static SENSOR_DEVICE_ATTR_2(fan13_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 13);
+static SENSOR_DEVICE_ATTR_2(fan14_min, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MIN_TACH, 14);
+/* Max */
+static SENSOR_DEVICE_ATTR_2(fan1_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 1);
+static SENSOR_DEVICE_ATTR_2(fan2_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 2);
+static SENSOR_DEVICE_ATTR_2(fan3_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 3);
+static SENSOR_DEVICE_ATTR_2(fan4_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 4);
+static SENSOR_DEVICE_ATTR_2(fan5_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 5);
+static SENSOR_DEVICE_ATTR_2(fan6_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 6);
+static SENSOR_DEVICE_ATTR_2(fan7_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 7);
+static SENSOR_DEVICE_ATTR_2(fan8_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 8);
+static SENSOR_DEVICE_ATTR_2(fan9_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 9);
+static SENSOR_DEVICE_ATTR_2(fan10_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 10);
+static SENSOR_DEVICE_ATTR_2(fan11_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 11);
+static SENSOR_DEVICE_ATTR_2(fan12_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 12);
+static SENSOR_DEVICE_ATTR_2(fan13_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 13);
+static SENSOR_DEVICE_ATTR_2(fan14_max, S_IWUSR | S_IRUGO, jnx_fan_show,
+			    jnx_fan_set, I2CS_FAN_MAX_TACH, 14);
+
+static struct attribute *jnx_fan_attrs[] = {
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_input.dev_attr.attr,
+	&sensor_dev_attr_fan4_input.dev_attr.attr,
+	&sensor_dev_attr_fan5_input.dev_attr.attr,
+	&sensor_dev_attr_fan6_input.dev_attr.attr,
+	&sensor_dev_attr_fan7_input.dev_attr.attr,
+	&sensor_dev_attr_fan8_input.dev_attr.attr,
+	&sensor_dev_attr_fan9_input.dev_attr.attr,
+	&sensor_dev_attr_fan10_input.dev_attr.attr,
+	&sensor_dev_attr_fan11_input.dev_attr.attr,
+	&sensor_dev_attr_fan12_input.dev_attr.attr,
+	&sensor_dev_attr_fan13_input.dev_attr.attr,
+	&sensor_dev_attr_fan14_input.dev_attr.attr,
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_pwm2.dev_attr.attr,
+	&sensor_dev_attr_pwm3.dev_attr.attr,
+	&sensor_dev_attr_pwm4.dev_attr.attr,
+	&sensor_dev_attr_pwm5.dev_attr.attr,
+	&sensor_dev_attr_pwm6.dev_attr.attr,
+	&sensor_dev_attr_pwm7.dev_attr.attr,
+	&sensor_dev_attr_pwm8.dev_attr.attr,
+	&sensor_dev_attr_pwm9.dev_attr.attr,
+	&sensor_dev_attr_pwm10.dev_attr.attr,
+	&sensor_dev_attr_pwm11.dev_attr.attr,
+	&sensor_dev_attr_pwm12.dev_attr.attr,
+	&sensor_dev_attr_pwm13.dev_attr.attr,
+	&sensor_dev_attr_pwm14.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan3_min.dev_attr.attr,
+	&sensor_dev_attr_fan4_min.dev_attr.attr,
+	&sensor_dev_attr_fan5_min.dev_attr.attr,
+	&sensor_dev_attr_fan6_min.dev_attr.attr,
+	&sensor_dev_attr_fan7_min.dev_attr.attr,
+	&sensor_dev_attr_fan8_min.dev_attr.attr,
+	&sensor_dev_attr_fan9_min.dev_attr.attr,
+	&sensor_dev_attr_fan10_min.dev_attr.attr,
+	&sensor_dev_attr_fan11_min.dev_attr.attr,
+	&sensor_dev_attr_fan12_min.dev_attr.attr,
+	&sensor_dev_attr_fan13_min.dev_attr.attr,
+	&sensor_dev_attr_fan14_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_max.dev_attr.attr,
+	&sensor_dev_attr_fan2_max.dev_attr.attr,
+	&sensor_dev_attr_fan3_max.dev_attr.attr,
+	&sensor_dev_attr_fan4_max.dev_attr.attr,
+	&sensor_dev_attr_fan5_max.dev_attr.attr,
+	&sensor_dev_attr_fan6_max.dev_attr.attr,
+	&sensor_dev_attr_fan7_max.dev_attr.attr,
+	&sensor_dev_attr_fan8_max.dev_attr.attr,
+	&sensor_dev_attr_fan9_max.dev_attr.attr,
+	&sensor_dev_attr_fan10_max.dev_attr.attr,
+	&sensor_dev_attr_fan11_max.dev_attr.attr,
+	&sensor_dev_attr_fan12_max.dev_attr.attr,
+	&sensor_dev_attr_fan13_max.dev_attr.attr,
+	&sensor_dev_attr_fan14_max.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group jnx_fan_group = {
+	.attrs = jnx_fan_attrs,
+	.is_visible = jnx_fan_is_visible,
+};
+__ATTRIBUTE_GROUPS(jnx_fan);
+
+static int jnx_fan_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct i2cs_fan_platform_data *pdata = dev_get_platdata(dev);
+	struct i2c_client *client;
+	struct jnx_fan_data *data;
+
+	if (!dev->parent)
+		return -ENODEV;
+
+	client = i2c_verify_client(dev->parent);
+	if (!client)
+		return -ENODEV;
+
+	data = devm_kzalloc(dev, sizeof(struct jnx_fan_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->regmap = devm_regmap_init_i2c(client, &jnx_fan_regmap_config);
+	if (IS_ERR(data->regmap)) {
+		dev_err(dev, "failed to allocate register map\n");
+		return PTR_ERR(data->regmap);
+	}
+
+	if (pdata) {
+		data->num_fans = pdata->num_fans;
+		data->factor = pdata->factor;
+	} else {
+		data->num_fans = NUM_FANS_PER_TRAY;
+		data->factor = FAN_TACH_FACTOR;
+	}
+
+	if (dev->of_node) {
+		of_property_read_u32(dev->of_node,
+				     "num-fans", &data->num_fans);
+		of_property_read_u32(dev->of_node,
+				     "tach-factor", &data->factor);
+	}
+
+	data->fan_index = -1;
+	mutex_init(&data->update_lock);
+
+	platform_set_drvdata(pdev, data);
+
+	data->hwmon_dev = hwmon_device_register_with_groups(dev->parent,
+							    "i2cs_fan", data,
+							    jnx_fan_groups);
+	return PTR_ERR_OR_ZERO(data->hwmon_dev);
+}
+
+static int jnx_fan_remove(struct platform_device *pdev)
+{
+	struct jnx_fan_data *data = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(data->hwmon_dev);
+
+	return 0;
+}
+
+static const struct of_device_id jnx_fan_of_match[] = {
+	{ .compatible = "jnx,i2cs-fan-hwmon", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, jnx_fan_of_match);
+
+static struct platform_driver jnx_fan_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = of_match_ptr(jnx_fan_of_match),
+	},
+	.probe = jnx_fan_probe,
+	.remove = jnx_fan_remove,
+};
+
+module_platform_driver(jnx_fan_driver);
+
+MODULE_AUTHOR("Avirup Banerjee <abanerjee@juniper.net>");
+MODULE_DESCRIPTION("JNPR FAN driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/include/linux/platform_data/jnx-i2cs-fan.h b/include/linux/platform_data/jnx-i2cs-fan.h
new file mode 100644
index 0000000..b3fc8c2
--- /dev/null
+++ b/include/linux/platform_data/jnx-i2cs-fan.h
@@ -0,0 +1,13 @@
+/*
+ * i2cs-fan.h
+ */
+
+#ifndef I2CS_FAN_H
+#define I2CS_FAN_H
+
+struct i2cs_fan_platform_data {
+	int num_fans;	/* Number of fans in tray		*/
+	int factor;	/* fan speed multiplication factor	*/
+};
+
+#endif /* I2CS_FAN_H */
-- 
1.9.1

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

* [PATCH 10/10] hwmon: i2cs-fan: Add hwmon dts binding documentation
  2016-10-07 15:20 [PATCH 00/10] Introduce Juniper I2CS FPGA driver Pantelis Antoniou
                   ` (8 preceding siblings ...)
  2016-10-07 15:21 ` [PATCH 09/10] hwmon: Add driver for Fan Tray on Juniper I2CS FGPA Pantelis Antoniou
@ 2016-10-07 15:21 ` Pantelis Antoniou
  2016-10-10 20:29   ` Rob Herring
  9 siblings, 1 reply; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-07 15:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, Pantelis Antoniou,
	devicetree, linux-kernel, linux-gpio, linux-i2c, linux-leds,
	linux-hwmon

From: Georgi Vlaev <gvlaev@juniper.net>

Adds the I2CS Fan Tray hwmon device tree node documentation.

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

diff --git a/Documentation/devicetree/bindings/hwmon/i2cs-fan.txt b/Documentation/devicetree/bindings/hwmon/i2cs-fan.txt
new file mode 100644
index 0000000..4ef880c
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/i2cs-fan.txt
@@ -0,0 +1,19 @@
+Hwmon driver for Juniper fan trays on I2CS Slave FPGA
+
+Required properties:
+
+- compatible: "i2cs-fan-hwmon"
+
+Optional properties:
+
+- num-fans: fans per tray (default 14)
+
+- tach-factor: TACH count scaling factor (default 120)
+
+Example:
+
+fan-hwmon {
+	compatible = "jnx,i2cs-fan-hwmon";
+	num-fans = <6>;
+	tach-factor = <33>;
+};
-- 
1.9.1

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

* Re: [PATCH 07/10] leds: i2cs: Add I2CS FPGA leds driver
  2016-10-07 15:21 ` [PATCH 07/10] leds: i2cs: Add I2CS FPGA leds driver Pantelis Antoniou
@ 2016-10-10  9:41   ` Jacek Anaszewski
  0 siblings, 0 replies; 30+ messages in thread
From: Jacek Anaszewski @ 2016-10-10  9:41 UTC (permalink / raw)
  To: Pantelis Antoniou, Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jean Delvare,
	Peter Rosin, Avirup Banerjee, Georgi Vlaev, Guenter Roeck,
	JawaharBalaji Thirumalaisamy, devicetree, linux-kernel,
	linux-gpio, linux-i2c, linux-leds, linux-hwmon

Hi Pantelis,

Thanks for the patch. Please find my comments in the code below.

On 10/07/2016 05:21 PM, Pantelis Antoniou wrote:
> From: Georgi Vlaev <gvlaev@juniper.net>
>
> Add support for the FRU faceplate status LEDs (OK, FAIL,
> ACTIVE, STANDBY) controlled by the Juniper I2CS FPGA. This
> driver is a jnx-i2cs-core client.
>
> Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
> [Ported from Juniper kernel]
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> ---
>  drivers/leds/Kconfig         |   9 ++
>  drivers/leds/Makefile        |   1 +
>  drivers/leds/leds-jnx-i2cs.c | 219 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 229 insertions(+)
>  create mode 100644 drivers/leds/leds-jnx-i2cs.c
>
> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
> index 7a628c6..45c6612 100644
> --- a/drivers/leds/Kconfig
> +++ b/drivers/leds/Kconfig
> @@ -659,6 +659,15 @@ config LEDS_MLXCPLD
>  	  This option enabled support for the LEDs on the Mellanox
>  	  boards. Say Y to enabled these.
>
> +config LEDS_JNX_I2CS
> +	tristate "LED support for the Juniper Networks I2CS FPGA"
> +	depends on LEDS_CLASS && I2C
> +	select REGMAP_I2C
> +	help
> +	  This option enables support for the FRU faceplate status
> +	  LEDs (OK, FAIL, ACTIVE, STANDBY) controlled by the Juniper
> +	  I2CS FPGA.
> +
>  comment "LED Triggers"
>  source "drivers/leds/trigger/Kconfig"
>
> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
> index 3965070..1ce2d0b 100644
> --- a/drivers/leds/Makefile
> +++ b/drivers/leds/Makefile
> @@ -71,6 +71,7 @@ obj-$(CONFIG_LEDS_IS31FL319X)		+= leds-is31fl319x.o
>  obj-$(CONFIG_LEDS_IS31FL32XX)		+= leds-is31fl32xx.o
>  obj-$(CONFIG_LEDS_PM8058)		+= leds-pm8058.o
>  obj-$(CONFIG_LEDS_MLXCPLD)		+= leds-mlxcpld.o
> +obj-$(CONFIG_LEDS_JNX_I2CS)		+= leds-jnx-i2cs.o
>
>  # LED SPI Drivers
>  obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
> diff --git a/drivers/leds/leds-jnx-i2cs.c b/drivers/leds/leds-jnx-i2cs.c
> new file mode 100644
> index 0000000..c2d7274
> --- /dev/null
> +++ b/drivers/leds/leds-jnx-i2cs.c
> @@ -0,0 +1,219 @@
> +/*
> + * Juniper Networks I2CS FPGA LEDs driver
> + *
> + * Copyright (C) 2016 Juniper Networks
> + * 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.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/regmap.h>
> +#include <linux/of.h>
> +#include <linux/delay.h>
> +#include <linux/leds.h>
> +#include <linux/i2c.h>
> +#include <linux/platform_device.h>
> +#include <linux/mfd/jnx-i2cs-core.h>

Please arrange include directives in alphabetical order.

> +#define FRU_LEDS	4 /* Total LEDs (active, fail, ok, standby) */
> +#define HW_BLINK_LEDS	3 /* LEDs with hw blink cap (standby not supported) */
> +
> +/*
> + * I2CS fru_led [0x12]
> + *
> + * bit 6   | bit 5    | bit 4   |...                        | bit 0
> + * blink_ok|blink_fail|blink_act|led_standby|led_ok|led_fail|led_act
> + */
> +
> +/* TODO: Use the regmap from the parent MFD */

Isn't it a good moment to address that?

> +static struct regmap_config i2cs_leds_regmap_config = {
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.max_register = I2CS_SPARE_OE,
> +};
> +
> +struct i2cs_led {
> +	struct led_classdev lc;

Most drivers use led_cdev or cdev name for it.
It is more informative and improves readability.

> +	struct regmap *regmap;
> +	struct work_struct work;
> +	int blink;
> +	int on;
> +	int bit;
> +};
> +
> +struct i2cs_led_data {
> +	int num_leds;
> +	struct i2cs_led *leds;
> +};
> +
> +static void jnx_i2cs_leds_work(struct work_struct *work)
> +{
> +	struct i2cs_led *led = container_of(work, struct i2cs_led, work);
> +
> +	int mask = (BIT(led->bit) << 4) | BIT(led->bit);
> +	int value = ((led->blink << led->bit) << 4) | (led->on << led->bit);
> +
> +	regmap_update_bits(led->regmap, I2CS_FRU_LED, mask, value & 0x7f);
> +}

If you used brightness_set_blocking op instead of brightness_set,
then you could get rid of the in-driver work queue.

> +
> +static void jnx_i2cs_leds_brightness_set(struct led_classdev *lc,
> +				 enum led_brightness brightness)
> +{
> +	struct i2cs_led *led = container_of(lc, struct i2cs_led, lc);
> +
> +	led->on = (brightness != LED_OFF);
> +	led->blink = 0; /* always turn off hw blink on brightness_set() */

Some time ago we changed brightness setting semantics when blinking
is on. Now setting any brightness > 0 shouldn't disable blinking.
Following commit provides the details:

7cfe749fad51 ("leds: core: Fix brightness setting upon hardware blinking 
enabled")

It seems that the hardware supports only one brightness level.
In such a case I'd return immediately if the LED is on and
brightness to be set is 1.

> +	schedule_work(&led->work);
> +}
> +
> +static int jnx_i2cs_leds_blink_set(struct led_classdev *lc,
> +				   unsigned long *delay_on,
> +				   unsigned long *delay_off)
> +{
> +	struct i2cs_led *led = container_of(lc, struct i2cs_led, lc);
> +
> +	led->blink = (*delay_on > 0);

blink_set op should fail if hardware doesn't support delay_on
or delay_off periods. I lets the LED core to apply software blink
fallback.

> +	led->on = led->blink; /* 'on' bit should be set if blinking */
> +	schedule_work(&led->work);
> +
> +	return 0;
> +}
> +
> +static int jnx_i2cs_leds_init_one(struct device *dev, struct device_node *np,
> +				  struct i2cs_led_data *ild,
> +				  struct regmap *regmap, int num)
> +{
> +	struct i2cs_led *led;
> +	const char *string;
> +	bool hw_blink;
> +	int ret;
> +	u32 reg;
> +
> +	ret = of_property_read_u32(np, "reg", &reg);
> +	if (ret || reg >= FRU_LEDS)
> +		return -ENODEV;
> +
> +	led = &ild->leds[num];
> +	led->bit = reg;
> +	led->regmap = regmap;
> +
> +	if (!of_property_read_string(np, "label", &string))
> +		led->lc.name = string;
> +	else
> +		led->lc.name = np->name;
> +
> +	if (!of_property_read_string(np, "linux,default-trigger", &string))
> +		led->lc.default_trigger = string;
> +
> +	led->lc.brightness = LED_OFF;
> +	led->lc.brightness_set = jnx_i2cs_leds_brightness_set;

You need also:

led->lc.max_brightness = 1;

> +	if (led->bit <= HW_BLINK_LEDS) {
> +		hw_blink = of_property_read_bool(np, "hw-blink");
> +		if (hw_blink)
> +			led->lc.blink_set = jnx_i2cs_leds_blink_set;
> +	}
> +
> +	ret = devm_led_classdev_register(dev, &led->lc);
> +	if (ret)
> +		return ret;
> +
> +	INIT_WORK(&led->work, jnx_i2cs_leds_work);
> +
> +	return 0;
> +}
> +
> +static int jnx_i2cs_leds_of_init(struct device *dev, struct i2cs_led_data *ild)
> +{
> +	struct device_node *child, *np = dev->of_node;
> +	struct regmap *regmap;
> +	struct i2c_client *client;
> +	int ret, num_leds, i = 0;
> +
> +	if (!dev->parent)
> +		return -ENODEV;
> +
> +	client = i2c_verify_client(dev->parent);
> +	if (!client)
> +		return -ENODEV;
> +
> +	regmap = devm_regmap_init_i2c(client, &i2cs_leds_regmap_config);
> +	if (IS_ERR(regmap)) {
> +		dev_err(dev, "Failed to allocate register map\n");
> +		return PTR_ERR(regmap);
> +	}
> +
> +	num_leds = of_get_child_count(np);
> +	if (!num_leds || num_leds > FRU_LEDS)
> +		return -ENODEV;
> +
> +	ild->num_leds = num_leds;
> +	ild->leds = devm_kzalloc(dev, sizeof(struct i2cs_led) * num_leds,
> +				 GFP_KERNEL);
> +	if (!ild->leds)
> +		return -ENOMEM;
> +
> +	for_each_child_of_node(np, child) {
> +		ret = jnx_i2cs_leds_init_one(dev, child, ild, regmap, i++);
> +		if (ret)
> +			return ret;

of_node_put(child) should be called on error to avoid memory leak.

> +	}
> +
> +	return 0;
> +}
> +
> +static int jnx_i2cs_leds_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct i2cs_led_data *ild;
> +	int ret;
> +
> +	ild = devm_kzalloc(dev, sizeof(*ild), GFP_KERNEL);
> +	if (!ild)
> +		return -ENOMEM;
> +
> +	ret = jnx_i2cs_leds_of_init(dev, ild);
> +	if (ret < 0)
> +		return ret;
> +
> +	platform_set_drvdata(pdev, ild);
> +
> +	return 0;
> +}
> +
> +static int jnx_i2cs_leds_remove(struct platform_device *pdev)
> +{
> +	struct i2cs_led_data *ild = platform_get_drvdata(pdev);
> +	int i;
> +
> +	for (i = 0; i < ild->num_leds; i++) {
> +		devm_led_classdev_unregister(&pdev->dev, &ild->leds[i].lc);

This is redundant.

> +		cancel_work_sync(&ild->leds[i].work);
> +	}
> +
> +	return 0;
> +}

This function will be redundant after removing work queue.

> +static const struct of_device_id jnx_i2cs_leds_match[] = {
> +	{ .compatible = "jnx,leds-i2cs", },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, jnx_i2cs_leds_match);
> +
> +static struct platform_driver jnx_i2cs_leds_driver = {
> +	.driver = {
> +		.name  = "leds-i2cs",
> +		.of_match_table = jnx_i2cs_leds_match,
> +	},
> +	.probe = jnx_i2cs_leds_probe,
> +	.remove = jnx_i2cs_leds_remove,
> +};
> +
> +module_platform_driver(jnx_i2cs_leds_driver);
> +
> +MODULE_DESCRIPTION("Juniper Networks I2CS leds driver");
> +MODULE_AUTHOR("Georgi Vlaev <gvlaev@juniper.net>");
> +MODULE_LICENSE("GPL");
>


-- 
Best regards,
Jacek Anaszewski

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

* Re: [PATCH 08/10] leds: Add binding for Juniper's I2CS FPGA
  2016-10-07 15:21   ` Pantelis Antoniou
  (?)
@ 2016-10-10  9:41   ` Jacek Anaszewski
  -1 siblings, 0 replies; 30+ messages in thread
From: Jacek Anaszewski @ 2016-10-10  9:41 UTC (permalink / raw)
  To: Pantelis Antoniou, Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jean Delvare,
	Peter Rosin, Avirup Banerjee, Georgi Vlaev, Guenter Roeck,
	JawaharBalaji Thirumalaisamy, devicetree, linux-kernel,
	linux-gpio, linux-i2c, linux-leds, linux-hwmon

Hi Pantelis,

On 10/07/2016 05:21 PM, Pantelis Antoniou wrote:
> From: Georgi Vlaev <gvlaev@juniper.net>
>
> Document bindings for the I2CS FPGA leds.
>
> Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
> [Ported from Juniper kernel]
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> ---
>  .../devicetree/bindings/leds/leds-i2cs.txt         | 34 ++++++++++++++++++++++
>  1 file changed, 34 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/leds/leds-i2cs.txt
>
> diff --git a/Documentation/devicetree/bindings/leds/leds-i2cs.txt b/Documentation/devicetree/bindings/leds/leds-i2cs.txt
> new file mode 100644
> index 0000000..100e584
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/leds/leds-i2cs.txt
> @@ -0,0 +1,34 @@
> +Juniper I2CS LED driver.
> +
> +This is present in Juniper platforms that use a I2CS Slave FPGA.
> +
> +Required properties:
> +  - compatible: must be "jnx,leds-i2cs"

s/compatible:/compatible :/

Also treat the description as a regular sentence, i.e. begin it
with a capital letter and put a dot at the end.

> +  - #address-cells : must be 1.
> +  - #size-cells : must be 0.

s/must/Must/

> +Each led is represented as a sub-node of the jnx,leds-i2cs device.
> +
> +LED sub-node properties:
> +- label : (optional) see Documentation/devicetree/bindings/leds/common.txt
> +- reg : number of LED
> +- linux,default-trigger : (optional)
> +   see Documentation/devicetree/bindings/leds/common.txt

Driver uses also "hw-blink" property. Please document it here, but
add also a prefix:

jnx,hw-blink

Also "jnx" entry should be added to 
Documentation/devicetree/bindings/vendor-prefixes.txt.

> +Example:
> +
> +leds_fpc0: leds-jnx-i2cs {
> +	compatible = "jnx,leds-i2cs";
> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +
> +	fpc0-fail {
> +		reg = <1>;

It would be good to provide also an example of "label"
property to suggest LED class device name according to
the LED class device naming convention.
See Documentation/leds/leds-class.txt for details.

> +		linux,default-trigger = "fpc0-fail";
> +	};
> +
> +	fpc0-ok {
> +		reg = <2>;
> +		linux,default-trigger = "fpc0-ok";
> +	};
> +};
>


-- 
Best regards,
Jacek Anaszewski

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

* Re: [PATCH 03/10] i2c/muxes: Juniper I2CS RE mux
  2016-10-07 15:21   ` Pantelis Antoniou
@ 2016-10-10 15:29     ` Peter Rosin
  -1 siblings, 0 replies; 30+ messages in thread
From: Peter Rosin @ 2016-10-10 15:29 UTC (permalink / raw)
  To: Pantelis Antoniou, Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Avirup Banerjee, Georgi Vlaev, Guenter Roeck,
	JawaharBalaji Thirumalaisamy, devicetree, linux-kernel,
	linux-gpio, linux-i2c, linux-leds, linux-hwmon

On 2016-10-07 17:21, Pantelis Antoniou wrote:
> From: Georgi Vlaev <gvlaev@juniper.net>
> 
> Add support for Juniper I2C Slave RE multiplexer driver.
> 
> This I2C multiplexer driver allows the RE to access some of
> the FPC I2C buses. It's compatible only with the FPC variant of the
> I2CS.
> 
> 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/i2c/muxes/Kconfig        |  10 +++
>  drivers/i2c/muxes/Makefile       |   1 +
>  drivers/i2c/muxes/i2c-mux-i2cs.c | 155 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 166 insertions(+)
>  create mode 100644 drivers/i2c/muxes/i2c-mux-i2cs.c
> 
> diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
> index f45a9cb..c95380d 100644
> --- a/drivers/i2c/muxes/Kconfig
> +++ b/drivers/i2c/muxes/Kconfig
> @@ -30,6 +30,16 @@ config I2C_MUX_GPIO
>  	  This driver can also be built as a module.  If so, the module
>  	  will be called i2c-mux-gpio.
>  
> +config I2C_MUX_I2CS
> +	tristate "Juniper I2C Slave MFD client RE multiplexer"
> +	depends on MFD_JUNIPER_I2CS
> +	help
> +	  Select this to enable the Juniper I2C Slave RE multiplexer driver
> +	  on the relevant Juniper platforms.
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called i2c-mux-i2cs.
> +
>  config I2C_MUX_PCA9541
>  	tristate "NXP PCA9541 I2C Master Selector"
>  	help
> diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
> index 78d8cba..45b4287 100644
> --- a/drivers/i2c/muxes/Makefile
> +++ b/drivers/i2c/muxes/Makefile
> @@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE)	+= i2c-arb-gpio-challenge.o
>  obj-$(CONFIG_I2C_DEMUX_PINCTRL)		+= i2c-demux-pinctrl.o
>  
>  obj-$(CONFIG_I2C_MUX_GPIO)	+= i2c-mux-gpio.o
> +obj-$(CONFIG_I2C_MUX_I2CS)	+= i2c-mux-i2cs.o
>  obj-$(CONFIG_I2C_MUX_PCA9541)	+= i2c-mux-pca9541.o
>  obj-$(CONFIG_I2C_MUX_PCA954x)	+= i2c-mux-pca954x.o
>  obj-$(CONFIG_I2C_MUX_PINCTRL)	+= i2c-mux-pinctrl.o
> diff --git a/drivers/i2c/muxes/i2c-mux-i2cs.c b/drivers/i2c/muxes/i2c-mux-i2cs.c

Please name the file i2c-mux-jnx-i2cs.c. Or something else a bit more
specific.

> new file mode 100644
> index 0000000..c498a44
> --- /dev/null
> +++ b/drivers/i2c/muxes/i2c-mux-i2cs.c
> @@ -0,0 +1,155 @@
> +/*
> + * Juniper Networks I2CS RE mux driver
> + *
> + * Copyright (C) 2012, 2013, 2014 Juniper Networks. All rights reserved.
> + *
> + * 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/init.h>

init?

> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/i2c.h>
> +#include <linux/i2c-mux.h>
> +#include <linux/regmap.h>

regmap?

> +#include <linux/platform_device.h>
> +#include <linux/mfd/jnx-i2cs-core.h>
> +
> +#define MISC_IO_RE_EN	0x01
> +
> +/*
> + * Read/write to mux register.
> + *   Don't use i2c_transfer()/i2c_smbus_xfer()
> + *   for this as they will try to lock adapter a second time
> + */

If this is the only concern, you should consider making this
gate mux-locked instead of parent-locked. Then you can avoid
all these unlocked games. But there are caveats, so you better
read Documentation/i2c/i2c-topology for the details before
you change.

> +static int i2cs_mux_read_byte(struct i2c_client *client,
> +				  u8 offset, u8 *val)
> +{
> +	struct i2c_msg msg[2];
> +
> +	msg[0].addr = client->addr;
> +	msg[0].flags = 0;
> +	msg[0].len = 1;
> +	msg[0].buf = &offset;
> +
> +	msg[1].addr = client->addr;
> +	msg[1].flags = I2C_M_RD;
> +	msg[1].len = 1;
> +	msg[1].buf = val;
> +
> +	return client->adapter->algo->master_xfer(client->adapter, msg, 2);

If you still want to be parent-locked, use __i2c_transfer. In
either case, consider adding code that handles the case of no
algo->master_xfer (some i2c adapters only support
algo->smbus_xfer).

> +}
> +
> +static int i2cs_mux_write_byte(struct i2c_client *client, u8 offset, u8 val)
> +{
> +	struct i2c_msg msg;
> +	char buf[2];
> +
> +	msg.addr = client->addr;
> +	msg.flags = 0;
> +	msg.len = 2;
> +	buf[0] = offset;
> +	buf[1] = val;
> +	msg.buf = buf;
> +
> +	return client->adapter->algo->master_xfer(client->adapter, &msg, 1);
> +}
> +
> +static int i2cs_mux_select(struct i2c_mux_core *muxc, u32 chan)
> +{
> +	int ret;
> +	u8 val = 0;
> +	struct i2c_client *client = i2c_mux_priv(muxc);
> +
> +	ret = i2cs_mux_read_byte(client, I2CS_MISC_IO, &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	val |= MISC_IO_RE_EN;
> +	ret = i2cs_mux_write_byte(client, I2CS_MISC_IO, val);
> +

To me, it sounds as if I2CS_MISC_IO is a register with more than
one bit and that you are open to nasty races here. You probably
need to interact with the mfd parent and arrange some locking.

> +	return ret;
> +}
> +
> +static int i2cs_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
> +{
> +	int ret;
> +	u8 val = 0;
> +	struct i2c_client *client = i2c_mux_priv(muxc);
> +
> +	ret = i2cs_mux_read_byte(client, I2CS_MISC_IO, &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	val &= ~MISC_IO_RE_EN;
> +	ret = i2cs_mux_write_byte(client, I2CS_MISC_IO, val);
> +
> +	return 0;
> +}
> +
> +static int i2cs_mux_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct i2c_client *client;
> +	struct i2c_mux_core *muxc;
> +	int ret;
> +
> +	if (!dev->parent)
> +		return -ENODEV;
> +
> +	client = i2c_verify_client(dev->parent);
> +	if (!client)
> +		return -ENODEV;
> +
> +	muxc = i2c_mux_alloc(client->adapter, &client->dev, 1, 0, 0,
> +				i2cs_mux_select, i2cs_mux_deselect);

You only have one child adapter, making this a gate. Please use
the I2C_MUX_GATE flag which should be available in 4.9. This also
affects the preferred devicetree, see comment on that patch.

> +	if (!muxc)
> +		return -ENOMEM;
> +	muxc->priv = client;
> +
> +	ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
> +	if (ret)
> +		return ret;
> +
> +	platform_set_drvdata(pdev, muxc);
> +
> +	return 0;
> +}
> +
> +static int i2cs_mux_remove(struct platform_device *pdev)
> +{
> +	i2c_mux_del_adapters(platform_get_drvdata(pdev));
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id i2cs_mux_of_match[] = {
> +	{ .compatible = "jnx,i2c-mux-i2cs", },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, i2cs_mux_of_match);
> +
> +static struct platform_driver i2cs_mux_driver = {
> +	.driver = {
> +		.name = "i2c-mux-i2cs",
> +		.owner  = THIS_MODULE,

Drop this line.

Cheers,
Peter

> +		.of_match_table = of_match_ptr(i2cs_mux_of_match),
> +	},
> +	.probe = i2cs_mux_probe,
> +	.remove = i2cs_mux_remove,
> +};
> +module_platform_driver(i2cs_mux_driver);
> +
> +MODULE_DESCRIPTION("Juniper Networks I2CS RE Mux driver");
> +MODULE_AUTHOR("Georgi Vlaev <gvlaev@juniper.net>");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:i2c-mux-i2cs");
> 

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

* Re: [PATCH 03/10] i2c/muxes: Juniper I2CS RE mux
@ 2016-10-10 15:29     ` Peter Rosin
  0 siblings, 0 replies; 30+ messages in thread
From: Peter Rosin @ 2016-10-10 15:29 UTC (permalink / raw)
  To: Pantelis Antoniou, Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Avirup Banerjee, Georgi Vlaev, Guenter Roeck,
	JawaharBalaji Thirumalaisamy, devicetree, linux-kernel,
	linux-gpio, linux-i2c, linux-leds, linux-hwmon

On 2016-10-07 17:21, Pantelis Antoniou wrote:
> From: Georgi Vlaev <gvlaev@juniper.net>
> 
> Add support for Juniper I2C Slave RE multiplexer driver.
> 
> This I2C multiplexer driver allows the RE to access some of
> the FPC I2C buses. It's compatible only with the FPC variant of the
> I2CS.
> 
> 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/i2c/muxes/Kconfig        |  10 +++
>  drivers/i2c/muxes/Makefile       |   1 +
>  drivers/i2c/muxes/i2c-mux-i2cs.c | 155 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 166 insertions(+)
>  create mode 100644 drivers/i2c/muxes/i2c-mux-i2cs.c
> 
> diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
> index f45a9cb..c95380d 100644
> --- a/drivers/i2c/muxes/Kconfig
> +++ b/drivers/i2c/muxes/Kconfig
> @@ -30,6 +30,16 @@ config I2C_MUX_GPIO
>  	  This driver can also be built as a module.  If so, the module
>  	  will be called i2c-mux-gpio.
>  
> +config I2C_MUX_I2CS
> +	tristate "Juniper I2C Slave MFD client RE multiplexer"
> +	depends on MFD_JUNIPER_I2CS
> +	help
> +	  Select this to enable the Juniper I2C Slave RE multiplexer driver
> +	  on the relevant Juniper platforms.
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called i2c-mux-i2cs.
> +
>  config I2C_MUX_PCA9541
>  	tristate "NXP PCA9541 I2C Master Selector"
>  	help
> diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
> index 78d8cba..45b4287 100644
> --- a/drivers/i2c/muxes/Makefile
> +++ b/drivers/i2c/muxes/Makefile
> @@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE)	+= i2c-arb-gpio-challenge.o
>  obj-$(CONFIG_I2C_DEMUX_PINCTRL)		+= i2c-demux-pinctrl.o
>  
>  obj-$(CONFIG_I2C_MUX_GPIO)	+= i2c-mux-gpio.o
> +obj-$(CONFIG_I2C_MUX_I2CS)	+= i2c-mux-i2cs.o
>  obj-$(CONFIG_I2C_MUX_PCA9541)	+= i2c-mux-pca9541.o
>  obj-$(CONFIG_I2C_MUX_PCA954x)	+= i2c-mux-pca954x.o
>  obj-$(CONFIG_I2C_MUX_PINCTRL)	+= i2c-mux-pinctrl.o
> diff --git a/drivers/i2c/muxes/i2c-mux-i2cs.c b/drivers/i2c/muxes/i2c-mux-i2cs.c

Please name the file i2c-mux-jnx-i2cs.c. Or something else a bit more
specific.

> new file mode 100644
> index 0000000..c498a44
> --- /dev/null
> +++ b/drivers/i2c/muxes/i2c-mux-i2cs.c
> @@ -0,0 +1,155 @@
> +/*
> + * Juniper Networks I2CS RE mux driver
> + *
> + * Copyright (C) 2012, 2013, 2014 Juniper Networks. All rights reserved.
> + *
> + * 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/init.h>

init?

> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/i2c.h>
> +#include <linux/i2c-mux.h>
> +#include <linux/regmap.h>

regmap?

> +#include <linux/platform_device.h>
> +#include <linux/mfd/jnx-i2cs-core.h>
> +
> +#define MISC_IO_RE_EN	0x01
> +
> +/*
> + * Read/write to mux register.
> + *   Don't use i2c_transfer()/i2c_smbus_xfer()
> + *   for this as they will try to lock adapter a second time
> + */

If this is the only concern, you should consider making this
gate mux-locked instead of parent-locked. Then you can avoid
all these unlocked games. But there are caveats, so you better
read Documentation/i2c/i2c-topology for the details before
you change.

> +static int i2cs_mux_read_byte(struct i2c_client *client,
> +				  u8 offset, u8 *val)
> +{
> +	struct i2c_msg msg[2];
> +
> +	msg[0].addr = client->addr;
> +	msg[0].flags = 0;
> +	msg[0].len = 1;
> +	msg[0].buf = &offset;
> +
> +	msg[1].addr = client->addr;
> +	msg[1].flags = I2C_M_RD;
> +	msg[1].len = 1;
> +	msg[1].buf = val;
> +
> +	return client->adapter->algo->master_xfer(client->adapter, msg, 2);

If you still want to be parent-locked, use __i2c_transfer. In
either case, consider adding code that handles the case of no
algo->master_xfer (some i2c adapters only support
algo->smbus_xfer).

> +}
> +
> +static int i2cs_mux_write_byte(struct i2c_client *client, u8 offset, u8 val)
> +{
> +	struct i2c_msg msg;
> +	char buf[2];
> +
> +	msg.addr = client->addr;
> +	msg.flags = 0;
> +	msg.len = 2;
> +	buf[0] = offset;
> +	buf[1] = val;
> +	msg.buf = buf;
> +
> +	return client->adapter->algo->master_xfer(client->adapter, &msg, 1);
> +}
> +
> +static int i2cs_mux_select(struct i2c_mux_core *muxc, u32 chan)
> +{
> +	int ret;
> +	u8 val = 0;
> +	struct i2c_client *client = i2c_mux_priv(muxc);
> +
> +	ret = i2cs_mux_read_byte(client, I2CS_MISC_IO, &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	val |= MISC_IO_RE_EN;
> +	ret = i2cs_mux_write_byte(client, I2CS_MISC_IO, val);
> +

To me, it sounds as if I2CS_MISC_IO is a register with more than
one bit and that you are open to nasty races here. You probably
need to interact with the mfd parent and arrange some locking.

> +	return ret;
> +}
> +
> +static int i2cs_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
> +{
> +	int ret;
> +	u8 val = 0;
> +	struct i2c_client *client = i2c_mux_priv(muxc);
> +
> +	ret = i2cs_mux_read_byte(client, I2CS_MISC_IO, &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	val &= ~MISC_IO_RE_EN;
> +	ret = i2cs_mux_write_byte(client, I2CS_MISC_IO, val);
> +
> +	return 0;
> +}
> +
> +static int i2cs_mux_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct i2c_client *client;
> +	struct i2c_mux_core *muxc;
> +	int ret;
> +
> +	if (!dev->parent)
> +		return -ENODEV;
> +
> +	client = i2c_verify_client(dev->parent);
> +	if (!client)
> +		return -ENODEV;
> +
> +	muxc = i2c_mux_alloc(client->adapter, &client->dev, 1, 0, 0,
> +				i2cs_mux_select, i2cs_mux_deselect);

You only have one child adapter, making this a gate. Please use
the I2C_MUX_GATE flag which should be available in 4.9. This also
affects the preferred devicetree, see comment on that patch.

> +	if (!muxc)
> +		return -ENOMEM;
> +	muxc->priv = client;
> +
> +	ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
> +	if (ret)
> +		return ret;
> +
> +	platform_set_drvdata(pdev, muxc);
> +
> +	return 0;
> +}
> +
> +static int i2cs_mux_remove(struct platform_device *pdev)
> +{
> +	i2c_mux_del_adapters(platform_get_drvdata(pdev));
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id i2cs_mux_of_match[] = {
> +	{ .compatible = "jnx,i2c-mux-i2cs", },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, i2cs_mux_of_match);
> +
> +static struct platform_driver i2cs_mux_driver = {
> +	.driver = {
> +		.name = "i2c-mux-i2cs",
> +		.owner  = THIS_MODULE,

Drop this line.

Cheers,
Peter

> +		.of_match_table = of_match_ptr(i2cs_mux_of_match),
> +	},
> +	.probe = i2cs_mux_probe,
> +	.remove = i2cs_mux_remove,
> +};
> +module_platform_driver(i2cs_mux_driver);
> +
> +MODULE_DESCRIPTION("Juniper Networks I2CS RE Mux driver");
> +MODULE_AUTHOR("Georgi Vlaev <gvlaev@juniper.net>");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:i2c-mux-i2cs");
> 

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

* Re: [PATCH 04/10] i2c: i2c-mux-i2cs: Add device tree bindings
  2016-10-07 15:21 ` [PATCH 04/10] i2c: i2c-mux-i2cs: Add device tree bindings Pantelis Antoniou
@ 2016-10-10 15:48     ` Peter Rosin
  2016-10-10 20:25   ` Rob Herring
  1 sibling, 0 replies; 30+ messages in thread
From: Peter Rosin @ 2016-10-10 15:48 UTC (permalink / raw)
  To: Pantelis Antoniou, Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Avirup Banerjee, Georgi Vlaev, Guenter Roeck,
	JawaharBalaji Thirumalaisamy, devicetree, linux-kernel,
	linux-gpio, linux-i2c, linux-leds, linux-hwmon

On 2016-10-07 17:21, Pantelis Antoniou wrote:
> From: Georgi Vlaev <gvlaev@juniper.net>
> 
> Add binding document for the i2c mux driver of Juniper's I2CS FPGA.
> 
> Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
> [Ported from Juniper kernel]
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> ---
>  .../devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt   | 27 ++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
> 
> diff --git a/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt b/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
> new file mode 100644
> index 0000000..03d917f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
> @@ -0,0 +1,27 @@
> +* Juniper I2C Mux on I2CS
> +
> +	I2C mux driver for switching the RE access to the FPC i2c bus.
> +	Compatible with the FPC variant of the I2CS.
> +
> +Required properties:
> +
> +  - compatible: "jnx,i2cs-mux-i2cs".

jnx,i2c-mux-i2cs

> +
> +The following required properties are defined externally:
> +
> +  - Standard I2C mux properties. See i2c-mux.txt in this directory.

To accommodate changes pending for 4.9, change "mux" to "gate" in
this line...

> +  - I2C child bus nodes. See i2c-mux.txt in this directory.

This line is wrong since the child nodes themselves are optional in
i2c-gate.txt (and i2c-mux.txt). I guess you can just drop it since
the child nodes are mentioned in i2c-gate.txt (and i2c-mux.txt).

> +
> +Example:
> +
> +fpc0_mux {
> +	compatible = "jnx,i2c-mux-i2cs";
> +	#address-cells = <1>;
> +	#size-cells = <0>;

...drop these two...

> +
> +	fpc0i2c0: i2c@0 {

...change i2c@0 to i2c-gate...

> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		reg = <0>;

...and drop reg.

Cheers,
Peter

> +	};
> +};
> 

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

* Re: [PATCH 04/10] i2c: i2c-mux-i2cs: Add device tree bindings
@ 2016-10-10 15:48     ` Peter Rosin
  0 siblings, 0 replies; 30+ messages in thread
From: Peter Rosin @ 2016-10-10 15:48 UTC (permalink / raw)
  To: Pantelis Antoniou, Lee Jones
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Avirup Banerjee, Georgi Vlaev, Guenter Roeck,
	JawaharBalaji Thirumalaisamy, devicetree, linux-kernel,
	linux-gpio, linux-i2c, linux-leds, linux-hwmon

On 2016-10-07 17:21, Pantelis Antoniou wrote:
> From: Georgi Vlaev <gvlaev@juniper.net>
> 
> Add binding document for the i2c mux driver of Juniper's I2CS FPGA.
> 
> Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
> [Ported from Juniper kernel]
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> ---
>  .../devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt   | 27 ++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
> 
> diff --git a/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt b/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
> new file mode 100644
> index 0000000..03d917f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
> @@ -0,0 +1,27 @@
> +* Juniper I2C Mux on I2CS
> +
> +	I2C mux driver for switching the RE access to the FPC i2c bus.
> +	Compatible with the FPC variant of the I2CS.
> +
> +Required properties:
> +
> +  - compatible: "jnx,i2cs-mux-i2cs".

jnx,i2c-mux-i2cs

> +
> +The following required properties are defined externally:
> +
> +  - Standard I2C mux properties. See i2c-mux.txt in this directory.

To accommodate changes pending for 4.9, change "mux" to "gate" in
this line...

> +  - I2C child bus nodes. See i2c-mux.txt in this directory.

This line is wrong since the child nodes themselves are optional in
i2c-gate.txt (and i2c-mux.txt). I guess you can just drop it since
the child nodes are mentioned in i2c-gate.txt (and i2c-mux.txt).

> +
> +Example:
> +
> +fpc0_mux {
> +	compatible = "jnx,i2c-mux-i2cs";
> +	#address-cells = <1>;
> +	#size-cells = <0>;

...drop these two...

> +
> +	fpc0i2c0: i2c@0 {

...change i2c@0 to i2c-gate...

> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		reg = <0>;

...and drop reg.

Cheers,
Peter

> +	};
> +};
> 


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

* Re: [PATCH 02/10] mfd: dt-bindings: Add bindings for the Juniper I2CS MFD
  2016-10-07 15:21 ` [PATCH 02/10] mfd: dt-bindings: Add bindings for the Juniper I2CS MFD Pantelis Antoniou
@ 2016-10-10 20:23   ` Rob Herring
  2016-10-17 19:10     ` Pantelis Antoniou
  0 siblings, 1 reply; 30+ messages in thread
From: Rob Herring @ 2016-10-10 20:23 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Lee Jones, Linus Walleij, Alexandre Courbot, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, devicetree,
	linux-kernel, linux-gpio, linux-i2c, linux-leds, linux-hwmon

On Fri, Oct 07, 2016 at 06:21:01PM +0300, Pantelis Antoniou wrote:
> From: Georgi Vlaev <gvlaev@juniper.net>
> 
> Add device tree bindings for the Juniper I2CS MFD driver.
> 
> Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
> [Ported from Juniper kernel]
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> ---
>  Documentation/devicetree/bindings/mfd/jnx-i2cs.txt | 68 ++++++++++++++++++++++
>  1 file changed, 68 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/jnx-i2cs.txt
> 
> diff --git a/Documentation/devicetree/bindings/mfd/jnx-i2cs.txt b/Documentation/devicetree/bindings/mfd/jnx-i2cs.txt
> new file mode 100644
> index 0000000..0ec103b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/jnx-i2cs.txt
> @@ -0,0 +1,68 @@
> +Device-Tree bindings for Juniper Networks I2CS FPGA MFD
> +
> +Required properties:
> +- compatible - Must be one of:
> +	"jnx,i2cs-rcb"	(Routing Engine or Control Board FRUs)
> +	"jnx,i2cs-fpc"	(Flexible Port Concentrator FRUs)
> +	"jnx,i2cs-sib"	(Switching Interface Board FRUs)
> +	"jnx,i2cs-fan"	(Fan Tray FRUs)
> +
> +Optional properties:
> +
> +Depending on the FRU, the I2CS MFD has varied group of sub-devices:
> +
> +Device                   Description
> +------                   -----------
> +jnx,i2cs-gpio		: Virtual gpio mapping driver
> +jnx,i2cs-fan-hwmon	: hwmon driver for fan trays
> +jnx,i2c-mux-i2cs	: I2C Mux driver for FPC FRUs
> +jnx,leds-i2cs		: Led driver
> +
> +All these optional nodes are described in their respective binding
> +documents.
> +
> +Example node:
> +
> +i2cs@54 {
> +	compatible = "jnx,i2cs-fpc";
> +	reg = <0x54>;
> +	#address-cells = <0>;
> +	#size-cells = <0>;
> +
> +	fpc2_mux {

Generic node names please.

mux { 

> +		compatible = "jnx,i2c-mux-i2cs";
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		fpc2i2c0: i2c@0 {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			reg = <0>;
> +		};
> +	};
> +
> +	fpc2_gpiomap: gpio-jnx-i2cs {

gpio@54 {

> +		compatible = "jnx,gpio-i2cs";
> +		reg = <0x54>;
> +		#gpio-cells = <2>;
> +		gpio-controller;
> +		interrupt-controller;
> +
> +		/*
> +		 * Map bits [0-3] of reg 0x21 as gpio inputs, bits [4-7]
> +		 * as gpio outputs
> +		 */
> +		i2c-gpio-map = <0x21 0x0f>;
> +	};
> +
> +	leds-jnx-i2cs {

leds {

> +		compatible = "jnx,leds-i2cs";
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		sib8-active {
> +			reg = <0>;
> +			linux,default-trigger = "sib8-active";
> +		};
> +	};
> +};
> -- 
> 1.9.1
> 

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

* Re: [PATCH 04/10] i2c: i2c-mux-i2cs: Add device tree bindings
  2016-10-07 15:21 ` [PATCH 04/10] i2c: i2c-mux-i2cs: Add device tree bindings Pantelis Antoniou
  2016-10-10 15:48     ` Peter Rosin
@ 2016-10-10 20:25   ` Rob Herring
  1 sibling, 0 replies; 30+ messages in thread
From: Rob Herring @ 2016-10-10 20:25 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Lee Jones, Linus Walleij, Alexandre Courbot, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, devicetree,
	linux-kernel, linux-gpio, linux-i2c, linux-leds, linux-hwmon

On Fri, Oct 07, 2016 at 06:21:03PM +0300, Pantelis Antoniou wrote:
> From: Georgi Vlaev <gvlaev@juniper.net>
> 
> Add binding document for the i2c mux driver of Juniper's I2CS FPGA.
> 
> Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
> [Ported from Juniper kernel]
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> ---
>  .../devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt   | 27 ++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
> 
> diff --git a/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt b/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
> new file mode 100644
> index 0000000..03d917f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
> @@ -0,0 +1,27 @@
> +* Juniper I2C Mux on I2CS
> +
> +	I2C mux driver for switching the RE access to the FPC i2c bus.

What is RE?

> +	Compatible with the FPC variant of the I2CS.
> +
> +Required properties:
> +
> +  - compatible: "jnx,i2cs-mux-i2cs".
> +
> +The following required properties are defined externally:
> +
> +  - Standard I2C mux properties. See i2c-mux.txt in this directory.
> +  - I2C child bus nodes. See i2c-mux.txt in this directory.
> +
> +Example:
> +
> +fpc0_mux {
> +	compatible = "jnx,i2c-mux-i2cs";
> +	#address-cells = <1>;
> +	#size-cells = <0>;

Needs some address? 

> +
> +	fpc0i2c0: i2c@0 {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		reg = <0>;
> +	};
> +};
> -- 
> 1.9.1
> 

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

* Re: [PATCH 10/10] hwmon: i2cs-fan: Add hwmon dts binding documentation
  2016-10-07 15:21 ` [PATCH 10/10] hwmon: i2cs-fan: Add hwmon dts binding documentation Pantelis Antoniou
@ 2016-10-10 20:29   ` Rob Herring
  2016-10-17 19:12     ` Pantelis Antoniou
  0 siblings, 1 reply; 30+ messages in thread
From: Rob Herring @ 2016-10-10 20:29 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Lee Jones, Linus Walleij, Alexandre Courbot, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, devicetree,
	linux-kernel, linux-gpio, linux-i2c, linux-leds, linux-hwmon

On Fri, Oct 07, 2016 at 06:21:09PM +0300, Pantelis Antoniou wrote:
> From: Georgi Vlaev <gvlaev@juniper.net>
> 
> Adds the I2CS Fan Tray hwmon device tree node documentation.
> 
> Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
> [Ported from Juniper kernel]
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> ---
>  Documentation/devicetree/bindings/hwmon/i2cs-fan.txt | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/hwmon/i2cs-fan.txt
> 
> diff --git a/Documentation/devicetree/bindings/hwmon/i2cs-fan.txt b/Documentation/devicetree/bindings/hwmon/i2cs-fan.txt
> new file mode 100644
> index 0000000..4ef880c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/i2cs-fan.txt
> @@ -0,0 +1,19 @@
> +Hwmon driver for Juniper fan trays on I2CS Slave FPGA

This is a h/w description, not a driver.

> +
> +Required properties:
> +
> +- compatible: "i2cs-fan-hwmon"

I doubt any fan control h/w has "hwmon" in the name.

> +
> +Optional properties:
> +
> +- num-fans: fans per tray (default 14)
> +
> +- tach-factor: TACH count scaling factor (default 120)

vendor prefixes needed.

> +
> +Example:
> +
> +fan-hwmon {
> +	compatible = "jnx,i2cs-fan-hwmon";
> +	num-fans = <6>;
> +	tach-factor = <33>;
> +};
> -- 
> 1.9.1
> 

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

* Re: [PATCH 02/10] mfd: dt-bindings: Add bindings for the Juniper I2CS MFD
  2016-10-10 20:23   ` Rob Herring
@ 2016-10-17 19:10     ` Pantelis Antoniou
  0 siblings, 0 replies; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-17 19:10 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lee Jones, Linus Walleij, Alexandre Courbot, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, devicetree,
	linux-kernel, linux-gpio, linux-i2c, linux-leds, linux-hwmon

Hi Rob,

> On Oct 10, 2016, at 23:23 , Rob Herring <robh@kernel.org> wrote:
> 
> On Fri, Oct 07, 2016 at 06:21:01PM +0300, Pantelis Antoniou wrote:
>> From: Georgi Vlaev <gvlaev@juniper.net>
>> 
>> Add device tree bindings for the Juniper I2CS MFD driver.
>> 
>> Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
>> [Ported from Juniper kernel]
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
>> ---
>> Documentation/devicetree/bindings/mfd/jnx-i2cs.txt | 68 ++++++++++++++++++++++
>> 1 file changed, 68 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/mfd/jnx-i2cs.txt
>> 
>> diff --git a/Documentation/devicetree/bindings/mfd/jnx-i2cs.txt b/Documentation/devicetree/bindings/mfd/jnx-i2cs.txt
>> new file mode 100644
>> index 0000000..0ec103b
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mfd/jnx-i2cs.txt
>> @@ -0,0 +1,68 @@
>> +Device-Tree bindings for Juniper Networks I2CS FPGA MFD
>> +
>> +Required properties:
>> +- compatible - Must be one of:
>> +	"jnx,i2cs-rcb"	(Routing Engine or Control Board FRUs)
>> +	"jnx,i2cs-fpc"	(Flexible Port Concentrator FRUs)
>> +	"jnx,i2cs-sib"	(Switching Interface Board FRUs)
>> +	"jnx,i2cs-fan"	(Fan Tray FRUs)
>> +
>> +Optional properties:
>> +
>> +Depending on the FRU, the I2CS MFD has varied group of sub-devices:
>> +
>> +Device                   Description
>> +------                   -----------
>> +jnx,i2cs-gpio		: Virtual gpio mapping driver
>> +jnx,i2cs-fan-hwmon	: hwmon driver for fan trays
>> +jnx,i2c-mux-i2cs	: I2C Mux driver for FPC FRUs
>> +jnx,leds-i2cs		: Led driver
>> +
>> +All these optional nodes are described in their respective binding
>> +documents.
>> +
>> +Example node:
>> +
>> +i2cs@54 {
>> +	compatible = "jnx,i2cs-fpc";
>> +	reg = <0x54>;
>> +	#address-cells = <0>;
>> +	#size-cells = <0>;
>> +
>> +	fpc2_mux {
> 
> Generic node names please.
> 

OK.

> mux { 
> 
>> +		compatible = "jnx,i2c-mux-i2cs";
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +
>> +		fpc2i2c0: i2c@0 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <0>;
>> +		};
>> +	};
>> +
>> +	fpc2_gpiomap: gpio-jnx-i2cs {
> 
> gpio@54 {
> 
OK

>> +		compatible = "jnx,gpio-i2cs";
>> +		reg = <0x54>;
>> +		#gpio-cells = <2>;
>> +		gpio-controller;
>> +		interrupt-controller;
>> +
>> +		/*
>> +		 * Map bits [0-3] of reg 0x21 as gpio inputs, bits [4-7]
>> +		 * as gpio outputs
>> +		 */
>> +		i2c-gpio-map = <0x21 0x0f>;
>> +	};
>> +
>> +	leds-jnx-i2cs {
> 
> leds {
> 

OK.

>> +		compatible = "jnx,leds-i2cs";
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +
>> +		sib8-active {
>> +			reg = <0>;
>> +			linux,default-trigger = "sib8-active";
>> +		};
>> +	};
>> +};
>> -- 
>> 1.9.1

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

* Re: [PATCH 04/10] i2c: i2c-mux-i2cs: Add device tree bindings
  2016-10-10 15:48     ` Peter Rosin
  (?)
@ 2016-10-17 19:11     ` Pantelis Antoniou
  -1 siblings, 0 replies; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-17 19:11 UTC (permalink / raw)
  To: Peter Rosin
  Cc: Lee Jones, Linus Walleij, Alexandre Courbot, Rob Herring,
	Mark Rutland, Frank Rowand, Wolfram Sang, Richard Purdie,
	Jacek Anaszewski, Jean Delvare, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, devicetree,
	linux-kernel, linux-gpio, linux-i2c, linux-leds, linux-hwmon

Hi Rob,

> On Oct 10, 2016, at 18:48 , Peter Rosin <peda@axentia.se> wrote:
> 
> On 2016-10-07 17:21, Pantelis Antoniou wrote:
>> From: Georgi Vlaev <gvlaev@juniper.net>
>> 
>> Add binding document for the i2c mux driver of Juniper's I2CS FPGA.
>> 
>> Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
>> [Ported from Juniper kernel]
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
>> ---
>> .../devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt   | 27 ++++++++++++++++++++++
>> 1 file changed, 27 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
>> 
>> diff --git a/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt b/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
>> new file mode 100644
>> index 0000000..03d917f
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/i2c/jnx,i2c-mux-i2cs.txt
>> @@ -0,0 +1,27 @@
>> +* Juniper I2C Mux on I2CS
>> +
>> +	I2C mux driver for switching the RE access to the FPC i2c bus.
>> +	Compatible with the FPC variant of the I2CS.
>> +
>> +Required properties:
>> +
>> +  - compatible: "jnx,i2cs-mux-i2cs".
> 
> jnx,i2c-mux-i2cs
> 

OK.

>> +
>> +The following required properties are defined externally:
>> +
>> +  - Standard I2C mux properties. See i2c-mux.txt in this directory.
> 
> To accommodate changes pending for 4.9, change "mux" to "gate" in
> this line…
> 

OK, interesting.


>> +  - I2C child bus nodes. See i2c-mux.txt in this directory.
> 
> This line is wrong since the child nodes themselves are optional in
> i2c-gate.txt (and i2c-mux.txt). I guess you can just drop it since
> the child nodes are mentioned in i2c-gate.txt (and i2c-mux.txt).
> 

OK then.

>> +
>> +Example:
>> +
>> +fpc0_mux {
>> +	compatible = "jnx,i2c-mux-i2cs";
>> +	#address-cells = <1>;
>> +	#size-cells = <0>;
> 
> ...drop these two...
> 
>> +
>> +	fpc0i2c0: i2c@0 {
> 
> ...change i2c@0 to i2c-gate...
> 
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		reg = <0>;
> 
> ...and drop reg.
> 
> Cheers,
> Peter
> 

OK on all.

>> +	};
>> +};

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

* Re: [PATCH 10/10] hwmon: i2cs-fan: Add hwmon dts binding documentation
  2016-10-10 20:29   ` Rob Herring
@ 2016-10-17 19:12     ` Pantelis Antoniou
  0 siblings, 0 replies; 30+ messages in thread
From: Pantelis Antoniou @ 2016-10-17 19:12 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lee Jones, Linus Walleij, Alexandre Courbot, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, devicetree,
	linux-kernel, linux-gpio, linux-i2c, linux-leds, linux-hwmon


> On Oct 10, 2016, at 23:29 , Rob Herring <robh@kernel.org> wrote:
> 
> On Fri, Oct 07, 2016 at 06:21:09PM +0300, Pantelis Antoniou wrote:
>> From: Georgi Vlaev <gvlaev@juniper.net>
>> 
>> Adds the I2CS Fan Tray hwmon device tree node documentation.
>> 
>> Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
>> [Ported from Juniper kernel]
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
>> ---
>> Documentation/devicetree/bindings/hwmon/i2cs-fan.txt | 19 +++++++++++++++++++
>> 1 file changed, 19 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/hwmon/i2cs-fan.txt
>> 
>> diff --git a/Documentation/devicetree/bindings/hwmon/i2cs-fan.txt b/Documentation/devicetree/bindings/hwmon/i2cs-fan.txt
>> new file mode 100644
>> index 0000000..4ef880c
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/hwmon/i2cs-fan.txt
>> @@ -0,0 +1,19 @@
>> +Hwmon driver for Juniper fan trays on I2CS Slave FPGA
> 
> This is a h/w description, not a driver.
> 
>> +
>> +Required properties:
>> +
>> +- compatible: "i2cs-fan-hwmon"
> 
> I doubt any fan control h/w has "hwmon" in the name.
> 
>> +
>> +Optional properties:
>> +
>> +- num-fans: fans per tray (default 14)
>> +
>> +- tach-factor: TACH count scaling factor (default 120)
> 
> vendor prefixes needed.
> 
>> +
>> +Example:
>> +
>> +fan-hwmon {
>> +	compatible = "jnx,i2cs-fan-hwmon";
>> +	num-fans = <6>;
>> +	tach-factor = <33>;
>> +};
>> -- 
>> 1.9.1

OK on all three.

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

* Re: [PATCH 05/10] gpio: i2cs: Juniper I2CS to GPIO pin mapping driver
  2016-10-07 15:21 ` [PATCH 05/10] gpio: i2cs: Juniper I2CS to GPIO pin mapping driver Pantelis Antoniou
@ 2016-10-21  8:41     ` Linus Walleij
  0 siblings, 0 replies; 30+ messages in thread
From: Linus Walleij @ 2016-10-21  8:41 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Lee Jones, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, devicetree,
	linux-kernel, linux-gpio, linux-i2c, linux-leds, linux-hwmon

On Fri, Oct 7, 2016 at 5:21 PM, Pantelis Antoniou
<pantelis.antoniou@konsulko.com> wrote:

> From: Guenter Roeck <groeck@juniper.net>
>
> This driver maps I2C slave register bits to GPIO pins. Registers
> are supposed to be 8 bit wide. Interrupt support is optional.
>
> The driver is implemented as client of the I2CS MFD driver.
>
> Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
> Signed-off-by: Guenter Roeck <groeck@juniper.net>
> Signed-off-by: JawaharBalaji Thirumalaisamy <jawaharb@juniper.net>
> [Ported from Juniper kernel]
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>

This driver again has the same review comments as the two first
ones, GPIOLIB_IRQCHIP etc. Revise accordingly and repost
and I will look at it again.

(Interestingly this one uses BIT() properly.)

Yours,
Linus Walleij

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

* Re: [PATCH 05/10] gpio: i2cs: Juniper I2CS to GPIO pin mapping driver
@ 2016-10-21  8:41     ` Linus Walleij
  0 siblings, 0 replies; 30+ messages in thread
From: Linus Walleij @ 2016-10-21  8:41 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Lee Jones, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, devicetree,
	linux-kernel, linux-gpio, linux-i2c@vger.kernel.org

On Fri, Oct 7, 2016 at 5:21 PM, Pantelis Antoniou
<pantelis.antoniou@konsulko.com> wrote:

> From: Guenter Roeck <groeck@juniper.net>
>
> This driver maps I2C slave register bits to GPIO pins. Registers
> are supposed to be 8 bit wide. Interrupt support is optional.
>
> The driver is implemented as client of the I2CS MFD driver.
>
> Signed-off-by: Georgi Vlaev <gvlaev@juniper.net>
> Signed-off-by: Guenter Roeck <groeck@juniper.net>
> Signed-off-by: JawaharBalaji Thirumalaisamy <jawaharb@juniper.net>
> [Ported from Juniper kernel]
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>

This driver again has the same review comments as the two first
ones, GPIOLIB_IRQCHIP etc. Revise accordingly and repost
and I will look at it again.

(Interestingly this one uses BIT() properly.)

Yours,
Linus Walleij

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

* Re: [PATCH 06/10] gpio: gpio-i2cs: Document bindings of I2CS FPGA GPIO block
  2016-10-07 15:21 ` [PATCH 06/10] gpio: gpio-i2cs: Document bindings of I2CS FPGA GPIO block Pantelis Antoniou
@ 2016-10-21  8:59     ` Linus Walleij
  0 siblings, 0 replies; 30+ messages in thread
From: Linus Walleij @ 2016-10-21  8:59 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Lee Jones, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, devicetree,
	linux-kernel, linux-gpio, linux-i2c, linux-leds, linux-hwmon

On Fri, Oct 7, 2016 at 5:21 PM, Pantelis Antoniou
<pantelis.antoniou@konsulko.com> wrote:

> +This is virtual gpio driver, that maps each bit of the I2CS FPGA to
> +a gpio. It's used as a compatibility replacement for FRUs that use
> +I2CS FPGA to report presence, control and report power status in
> +the Juniper's driver infra that uses gpios. Compatible with any I2CS.

What does "virtual" mean?

I regularly NACK patches that try to shoehorn stuff into
GPIO not because they are actually GPIO hardware drivers or
general purpose at all, but because it is convenient. Don't do this.

> +- i2c-gpio-map: Map of "I2CS register" and "direction". The registers
> +       are 8 bit wide, each bit of the register is mapped to either
> +       input or output depending on the bits of the "direction". If
> +       the bit in the direction is 1, then that bit from the I2CS
> +       register is mapped to gpio input, otherwise to gpio output.

Does this mean that the hardware is synthesized so that some lines
are hardwired as input and some hardwired as output?

That again does not sound like "general purpose" at all.

I think this happens in other hardware and should be a generic
binding like

gpio-lines-input-only = <0>, <4>;
gpio-lines-output-only = <7>, <8>;

And no bitmasking, use the local offset, parse and construct the
mask.

Yours,
Linus Walleij

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

* Re: [PATCH 06/10] gpio: gpio-i2cs: Document bindings of I2CS FPGA GPIO block
@ 2016-10-21  8:59     ` Linus Walleij
  0 siblings, 0 replies; 30+ messages in thread
From: Linus Walleij @ 2016-10-21  8:59 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Lee Jones, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, Wolfram Sang, Richard Purdie, Jacek Anaszewski,
	Jean Delvare, Peter Rosin, Avirup Banerjee, Georgi Vlaev,
	Guenter Roeck, JawaharBalaji Thirumalaisamy, devicetree,
	linux-kernel, linux-gpio, linux-i2c@vger.kernel.org

On Fri, Oct 7, 2016 at 5:21 PM, Pantelis Antoniou
<pantelis.antoniou@konsulko.com> wrote:

> +This is virtual gpio driver, that maps each bit of the I2CS FPGA to
> +a gpio. It's used as a compatibility replacement for FRUs that use
> +I2CS FPGA to report presence, control and report power status in
> +the Juniper's driver infra that uses gpios. Compatible with any I2CS.

What does "virtual" mean?

I regularly NACK patches that try to shoehorn stuff into
GPIO not because they are actually GPIO hardware drivers or
general purpose at all, but because it is convenient. Don't do this.

> +- i2c-gpio-map: Map of "I2CS register" and "direction". The registers
> +       are 8 bit wide, each bit of the register is mapped to either
> +       input or output depending on the bits of the "direction". If
> +       the bit in the direction is 1, then that bit from the I2CS
> +       register is mapped to gpio input, otherwise to gpio output.

Does this mean that the hardware is synthesized so that some lines
are hardwired as input and some hardwired as output?

That again does not sound like "general purpose" at all.

I think this happens in other hardware and should be a generic
binding like

gpio-lines-input-only = <0>, <4>;
gpio-lines-output-only = <7>, <8>;

And no bitmasking, use the local offset, parse and construct the
mask.

Yours,
Linus Walleij

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

end of thread, other threads:[~2016-10-21  8:59 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-07 15:20 [PATCH 00/10] Introduce Juniper I2CS FPGA driver Pantelis Antoniou
2016-10-07 15:21 ` [PATCH 01/10] mfd: Add Juniper I2CS MFD driver Pantelis Antoniou
2016-10-07 15:21   ` Pantelis Antoniou
2016-10-07 15:21 ` [PATCH 02/10] mfd: dt-bindings: Add bindings for the Juniper I2CS MFD Pantelis Antoniou
2016-10-10 20:23   ` Rob Herring
2016-10-17 19:10     ` Pantelis Antoniou
2016-10-07 15:21 ` [PATCH 03/10] i2c/muxes: Juniper I2CS RE mux Pantelis Antoniou
2016-10-07 15:21   ` Pantelis Antoniou
2016-10-10 15:29   ` Peter Rosin
2016-10-10 15:29     ` Peter Rosin
2016-10-07 15:21 ` [PATCH 04/10] i2c: i2c-mux-i2cs: Add device tree bindings Pantelis Antoniou
2016-10-10 15:48   ` Peter Rosin
2016-10-10 15:48     ` Peter Rosin
2016-10-17 19:11     ` Pantelis Antoniou
2016-10-10 20:25   ` Rob Herring
2016-10-07 15:21 ` [PATCH 05/10] gpio: i2cs: Juniper I2CS to GPIO pin mapping driver Pantelis Antoniou
2016-10-21  8:41   ` Linus Walleij
2016-10-21  8:41     ` Linus Walleij
2016-10-07 15:21 ` [PATCH 06/10] gpio: gpio-i2cs: Document bindings of I2CS FPGA GPIO block Pantelis Antoniou
2016-10-21  8:59   ` Linus Walleij
2016-10-21  8:59     ` Linus Walleij
2016-10-07 15:21 ` [PATCH 07/10] leds: i2cs: Add I2CS FPGA leds driver Pantelis Antoniou
2016-10-10  9:41   ` Jacek Anaszewski
2016-10-07 15:21 ` [PATCH 08/10] leds: Add binding for Juniper's I2CS FPGA Pantelis Antoniou
2016-10-07 15:21   ` Pantelis Antoniou
2016-10-10  9:41   ` Jacek Anaszewski
2016-10-07 15:21 ` [PATCH 09/10] hwmon: Add driver for Fan Tray on Juniper I2CS FGPA Pantelis Antoniou
2016-10-07 15:21 ` [PATCH 10/10] hwmon: i2cs-fan: Add hwmon dts binding documentation Pantelis Antoniou
2016-10-10 20:29   ` Rob Herring
2016-10-17 19:12     ` Pantelis Antoniou

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.