All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/7] Add support for the Turris Mox router
@ 2018-08-08 15:26 Marek Behún
  2018-08-08 15:27 ` [PATCH v1 1/7] From: Ken Ma <make@marvell.com> Marek Behún
                   ` (6 more replies)
  0 siblings, 7 replies; 25+ messages in thread
From: Marek Behún @ 2018-08-08 15:26 UTC (permalink / raw)
  To: linux-arm-kernel

This adds preliminary support for the Turris Mox SOHO router developed by CZ.NIC
to mainline kernel.

The first patch fixes the corresponding pinctrl driver.

The second patch adds a new type of bus called "moxtet" to the kernel, via which
the different Mox modules can be found and configured.

The third patch adds support for GPIOs found on the module with SFP cage. These
GPIOs are configured via the "moxtet" bus.

The fourth and fifth patches add support for watchdog found on Armada 37xx SOCs.

The sixth patch fixes a weird bug I keep encountering in the mvneta driver on
Armada 3720 SOCs. This may be deleted or changed in the future version of this
patchset depending on what the networking guys will think about this.

The seventh patch adds Turris Mox device tree.

Marek

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

* [PATCH v1 1/7] From: Ken Ma <make@marvell.com>
  2018-08-08 15:26 [PATCH v1 0/7] Add support for the Turris Mox router Marek Behún
@ 2018-08-08 15:27 ` Marek Behún
  2018-08-08 16:49   ` Andrew Lunn
  2018-08-08 15:27 ` [PATCH v1 2/7] drivers: mfd: Add support for Moxtet bus Marek Behún
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 25+ messages in thread
From: Marek Behún @ 2018-08-08 15:27 UTC (permalink / raw)
  To: linux-arm-kernel

pinctrl: armada-37xx: Correct mpp definitions

This patch corrects below mpp definitions:
 - The sdio_sb group is composed of 6 pins and not 5;
 - The rgmii group contains pins mpp2[17:6] and not mpp2[19:6];
 - Pin of group "pmic0" is mpp1[6] but not mpp1[16];
 - Pin of group "pmic1" is mpp1[7] but not mpp1[17];
 - A new group "smi" is added in A0 with 2 pins - mpp2[19:18], its
   bitmask is bit4;
 - Group "pcie1" has 3 pins in A0 - mpp2[5:3], its bit mask is
   bit5 | bit9 | bit10 but not bit4;
 - Group "ptp" has 3 pins in A0 as Z1, but its bitmask is changed to
   bit11 | bit12 | bit13.

Signed-off-by: Marek Behun <marek.behun@nic.cz>

diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index 53cf800688e9..95abadee8542 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -157,8 +157,8 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = {
 	PIN_GRP_GPIO("pwm1", 12, 1, BIT(4), "pwm"),
 	PIN_GRP_GPIO("pwm2", 13, 1, BIT(5), "pwm"),
 	PIN_GRP_GPIO("pwm3", 14, 1, BIT(6), "pwm"),
-	PIN_GRP_GPIO("pmic1", 17, 1, BIT(7), "pmic"),
-	PIN_GRP_GPIO("pmic0", 16, 1, BIT(8), "pmic"),
+	PIN_GRP_GPIO("pmic1", 7, 1, BIT(7), "pmic"),
+	PIN_GRP_GPIO("pmic0", 6, 1, BIT(8), "pmic"),
 	PIN_GRP_GPIO("i2c2", 2, 2, BIT(9), "i2c"),
 	PIN_GRP_GPIO("i2c1", 0, 2, BIT(10), "i2c"),
 	PIN_GRP_GPIO("spi_cs1", 17, 1, BIT(12), "spi"),
@@ -182,8 +182,9 @@ static struct armada_37xx_pin_group armada_37xx_sb_groups[] = {
 	PIN_GRP_GPIO("usb2_drvvbus1", 1, 1, BIT(1), "drvbus"),
 	PIN_GRP_GPIO("sdio_sb", 24, 6, BIT(2), "sdio"),
 	PIN_GRP_GPIO("rgmii", 6, 12, BIT(3), "mii"),
-	PIN_GRP_GPIO("pcie1", 3, 2, BIT(4), "pcie"),
-	PIN_GRP_GPIO("ptp", 20, 3, BIT(5), "ptp"),
+	PIN_GRP_GPIO("smi", 18, 2, BIT(4), "smi"),
+	PIN_GRP_GPIO("pcie1", 3, 3, BIT(5) | BIT(9) | BIT(10), "pcie"),
+	PIN_GRP_GPIO("ptp", 20, 3, BIT(11) | BIT(12) | BIT(13), "ptp"),
 	PIN_GRP("ptp_clk", 21, 1, BIT(6), "ptp", "mii"),
 	PIN_GRP("ptp_trig", 22, 1, BIT(7), "ptp", "mii"),
 	PIN_GRP_GPIO_3("mii_col", 23, 1, BIT(8) | BIT(14), 0, BIT(8), BIT(14),
-- 
2.16.4

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

* [PATCH v1 2/7] drivers: mfd: Add support for Moxtet bus
  2018-08-08 15:26 [PATCH v1 0/7] Add support for the Turris Mox router Marek Behún
  2018-08-08 15:27 ` [PATCH v1 1/7] From: Ken Ma <make@marvell.com> Marek Behún
@ 2018-08-08 15:27 ` Marek Behún
  2018-08-08 15:32   ` Marek Behún
  2018-08-08 15:27 ` [PATCH v1 3/7] drivers: gpio: Add support for Turris Mox SFP GPIOs Marek Behún
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 25+ messages in thread
From: Marek Behún @ 2018-08-08 15:27 UTC (permalink / raw)
  To: linux-arm-kernel

On the Turris Mox router there can be connected different modules to
the main CPU board, currently a module with a SFP cage, a module with
MiniPCIe connector, a 4-port switch module and a 8-port switch module,
for example:
  [CPU]-[PCIe]-[8-port switch]-[8-port switch]-[SFP]

Each of this modules has an input and output shift register, and these
are connected via SPI to CPU board.

Via this SPI connection we are able to discover which modules are
connected and we can also read/write some configuration to the modules.
Fromi/to each module 8 bits can be read (of which lower 4 bits identify
the module) and written.

For example from the module with a SFP cage we can read the LOS,
TX-FAULT and MOD-DEF0 signals, while we can write TX-DISABLE and
RATE-SELECT signals.

Other modules may support something else.

This driver creates a new bus type, called "moxtet". For each Mox module
it finds via SPI, it creates a new device on the moxtet bus so that
drivers can be written for them, for example a gpio driver for the
module with a SFP cage.

The topology of how Mox modules are connected can then be read by
listing /sys/bus/moxtet/devices.

Signed-off-by: Marek Behun <marek.behun@nic.cz>

 create mode 100644 Documentation/devicetree/bindings/mfd/moxtet.txt
 create mode 100644 drivers/mfd/moxtet.c
 create mode 100644 include/linux/mfd/moxtet.h

diff --git a/Documentation/devicetree/bindings/mfd/moxtet.txt b/Documentation/devicetree/bindings/mfd/moxtet.txt
new file mode 100644
index 000000000000..02b96fbd5ddd
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/moxtet.txt
@@ -0,0 +1,36 @@
+Turris Mox module configuration bus (over SPI)
+
+Required properties:
+ - compatible		: Should be "cznic,moxtet".
+ - #address-cells	: Has to be 1
+ - #size-cells		: Has to be 0
+For other required and optional properties of SPI slave
+nodes please refer to ../spi/spi-bus.txt.
+
+Required properties of subnodes:
+ - reg			: Should be position on the Moxtet bus
+ - moxtet,id		: Should be ID of the Moxtet device connected
+
+The driver finds the devices connected to the bus by itself, but it may be
+needed to reference some of them from other parts of the device tree. In that
+case the devices can be defined as subnodes of the moxtet node.
+
+Example:
+
+	moxtet at 1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "cznic,moxtet";
+		reg = <1>;
+		spi-max-frequency = <1000000>;
+		spi-cpol;
+		spi-cpha;
+
+		moxtet_sfp: moxtet-sfp at 0 {
+			compatible = "cznic,moxtet-sfp";
+			gpio-controller;
+			#gpio-cells;
+			reg = <0>;
+			moxtet,id = <1>;
+		}
+	};
diff --git a/MAINTAINERS b/MAINTAINERS
index 7cebd5bba8a8..27ca12e8309a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1378,6 +1378,13 @@ F:	drivers/clocksource/timer-prima2.c
 F:	drivers/clocksource/timer-atlas7.c
 N:	[^a-z]sirf
 
+ARM/CZ.NIC TURRIS MOX SUPPORT
+M:	Marek Behun <marek.behun@nic.cz>
+W:	http://mox.turris.cz
+S:	Maintained
+F:	include/mfd/moxtet.h
+F:	drivers/mfd/moxtet.c
+
 ARM/EBSA110 MACHINE SUPPORT
 M:	Russell King <linux@armlinux.org.uk>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b860eb5aa194..395d8b15f8a8 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -784,6 +784,16 @@ config MFD_MAX8998
 	  additional drivers must be enabled in order to use the functionality
 	  of the device.
 
+config MFD_MOXTET
+	tristate "CZ.NIC Turris Mox module configuration bus"
+	depends on SPI_MASTER && OF
+	help
+	  Say yes here to add support for the module configuration bus found
+	  on CZ.NIC's Turris Mox. This is needed for the ability to read
+	  in what order the modules are connected and to get/set some of
+	  their settings. For example the GPIOs on Mox SFP module are
+	  configured through this bus.
+
 config MFD_MT6397
 	tristate "MediaTek MT6397 PMIC Support"
 	select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index e9fd20dba18d..1401863e27b1 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -147,6 +147,7 @@ max8925-objs			:= max8925-core.o max8925-i2c.o
 obj-$(CONFIG_MFD_MAX8925)	+= max8925.o
 obj-$(CONFIG_MFD_MAX8997)	+= max8997.o max8997-irq.o
 obj-$(CONFIG_MFD_MAX8998)	+= max8998.o max8998-irq.o
+obj-$(CONFIG_MFD_MOXTET)	+= moxtet.o
 
 pcf50633-objs			:= pcf50633-core.o pcf50633-irq.o
 obj-$(CONFIG_MFD_PCF50633)	+= pcf50633.o
diff --git a/drivers/mfd/moxtet.c b/drivers/mfd/moxtet.c
new file mode 100644
index 000000000000..62b36308d51a
--- /dev/null
+++ b/drivers/mfd/moxtet.c
@@ -0,0 +1,497 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Turris Mox module configuration bus driver
+ *
+ * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+ */
+
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/moxtet.h>
+
+static ssize_t
+module_id_show(struct device *dev, struct device_attribute *a, char *buf)
+{
+	struct moxtet_device *mdev = to_moxtet_device(dev);
+
+	return sprintf(buf, "0x%x\n", mdev->id);
+}
+static DEVICE_ATTR_RO(module_id);
+
+static ssize_t
+module_name_show(struct device *dev, struct device_attribute *a, char *buf)
+{
+	struct moxtet_device *mdev = to_moxtet_device(dev);
+
+	return sprintf(buf, "%s\n", turris_mox_module_name(mdev->id));
+}
+static DEVICE_ATTR_RO(module_name);
+
+static ssize_t
+input_value_show(struct device *dev, struct device_attribute *a, char *buf)
+{
+	int ret;
+
+	ret = moxtet_device_read(dev);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "0x%x\n", ret);
+}
+static DEVICE_ATTR_RO(input_value);
+
+static ssize_t
+output_value_show(struct device *dev, struct device_attribute *a, char *buf)
+{
+	int ret;
+
+	ret = moxtet_device_written(dev);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "0x%x\n", ret);
+}
+
+static ssize_t
+output_value_store(struct device *dev, struct device_attribute *a,
+		   const char *buf, size_t count)
+{
+	unsigned long val;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &val);
+	if (ret < 0)
+		return ret;
+
+	if (val > 0xff)
+		return -ERANGE;
+
+	ret = moxtet_device_write(dev, val);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+static DEVICE_ATTR_RW(output_value);
+
+static struct attribute *moxtet_dev_attrs[] = {
+	&dev_attr_module_id.attr,
+	&dev_attr_module_name.attr,
+	&dev_attr_input_value.attr,
+	&dev_attr_output_value.attr,
+	NULL,
+};
+
+static const struct attribute_group moxtet_dev_group = {
+	.attrs = moxtet_dev_attrs,
+};
+
+static const struct attribute_group *moxtet_dev_groups[] = {
+	&moxtet_dev_group,
+	NULL,
+};
+
+static int moxtet_match(struct device *dev, struct device_driver *drv)
+{
+	struct moxtet_device *mdev = to_moxtet_device(dev);
+	struct moxtet_driver *tdrv = to_moxtet_driver(drv);
+	const enum turris_mox_module_id *t;
+
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	for (t = tdrv->id_table; *t; ++t)
+		if (*t == mdev->id)
+			return 1;
+
+	return 0;
+}
+
+struct bus_type moxtet_bus_type = {
+	.name		= "moxtet",
+	.dev_groups	= moxtet_dev_groups,
+	.match		= moxtet_match,
+};
+EXPORT_SYMBOL_GPL(moxtet_bus_type);
+
+int __moxtet_register_driver(struct module *owner,
+			     struct moxtet_driver *mdrv)
+{
+	mdrv->driver.owner = owner;
+	mdrv->driver.bus = &moxtet_bus_type;
+	return driver_register(&mdrv->driver);
+}
+EXPORT_SYMBOL_GPL(__moxtet_register_driver);
+
+static int moxtet_dev_check(struct device *dev, void *data)
+{
+	struct moxtet_device *mdev = to_moxtet_device(dev);
+	struct moxtet_device *new_dev = data;
+
+	if (mdev->moxtet == new_dev->moxtet && mdev->id == new_dev->id &&
+	    mdev->idx == new_dev->idx)
+		return -EBUSY;
+	return 0;
+}
+
+static void moxtet_dev_release(struct device *dev)
+{
+	struct moxtet_device *mdev = to_moxtet_device(dev);
+
+	put_device(mdev->moxtet->dev);
+	kfree(mdev);
+}
+
+static struct moxtet_device *
+moxtet_alloc_device(struct moxtet *moxtet)
+{
+	struct moxtet_device *dev;
+
+	if (!get_device(moxtet->dev))
+		return NULL;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		put_device(moxtet->dev);
+		return NULL;
+	}
+
+	dev->moxtet = moxtet;
+	dev->dev.parent = moxtet->dev;
+	dev->dev.bus = &moxtet_bus_type;
+	dev->dev.release = moxtet_dev_release;
+
+	device_initialize(&dev->dev);
+
+	return dev;
+}
+
+static int moxtet_add_device(struct moxtet_device *dev)
+{
+	static DEFINE_MUTEX(add_mutex);
+	int ret;
+
+	if (dev->idx >= TURRIS_MOX_MAX_MODULES || dev->id > 0xf)
+		return -EINVAL;
+
+	dev_set_name(&dev->dev, "moxtet-%s.%u",
+		     turris_mox_module_name(dev->id), dev->idx);
+
+	mutex_lock(&add_mutex);
+
+	ret = bus_for_each_dev(&moxtet_bus_type, NULL, dev,
+			       moxtet_dev_check);
+	if (ret)
+		goto done;
+
+	ret = device_add(&dev->dev);
+	if (ret < 0)
+		dev_err(dev->moxtet->dev, "can't add %s, status %d\n",
+			dev_name(dev->moxtet->dev), ret);
+
+done:
+	mutex_unlock(&add_mutex);
+	return ret;
+}
+
+static int __unregister(struct device *dev, void *null)
+{
+	if (dev->of_node) {
+		of_node_clear_flag(dev->of_node, OF_POPULATED);
+		of_node_put(dev->of_node);
+	}
+
+	device_unregister(dev);
+
+	return 0;
+}
+
+static struct moxtet_device *
+of_register_moxtet_device(struct moxtet *moxtet, struct device_node *nc)
+{
+	struct moxtet_device *dev;
+	u32 val;
+	int ret;
+
+	dev = moxtet_alloc_device(moxtet);
+	if (!dev) {
+		dev_err(moxtet->dev,
+			"Moxtet device alloc error for %pOF\n", nc);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ret = of_property_read_u32(nc, "reg", &val);
+	if (ret || val >= TURRIS_MOX_MAX_MODULES) {
+		dev_err(moxtet->dev, "%pOF has no valid 'reg' property (%d)\n",
+			nc, ret);
+		goto err_put;
+	}
+	dev->idx = val;
+
+	ret = of_property_read_u32(nc, "moxtet,id", &val);
+	if (ret || val > 0xf) {
+		dev_err(moxtet->dev,
+			"%pOF has no valid 'moxtet,id' property (%d)\n", nc,
+			ret);
+		goto err_put;
+	}
+	dev->id = val;
+
+	if (moxtet->modules[dev->idx] != dev->id) {
+		dev_err(moxtet->dev,
+			"%pOF requested Moxtet device ID 0x%x, 0x%x found\n",
+			nc, dev->id, moxtet->modules[dev->idx]);
+		goto err_put;
+	}
+
+	of_node_get(nc);
+	dev->dev.of_node = nc;
+
+	ret = moxtet_add_device(dev);
+	if (ret) {
+		dev_err(moxtet->dev,
+			"Moxtet device register error for %pOF\n", nc);
+		of_node_put(nc);
+		goto err_put;
+	}
+
+	return dev;
+
+err_put:
+	put_device(&dev->dev);
+	return ERR_PTR(ret);
+}
+
+static void of_register_moxtet_devices(struct moxtet *moxtet)
+{
+	struct moxtet_device *dev;
+	struct device_node *nc;
+
+	if (!moxtet->dev->of_node)
+		return;
+
+	for_each_available_child_of_node(moxtet->dev->of_node, nc) {
+		if (of_node_test_and_set_flag(nc, OF_POPULATED))
+			continue;
+		dev = of_register_moxtet_device(moxtet, nc);
+		if (IS_ERR(dev)) {
+			dev_warn(moxtet->dev,
+				 "Failed to create Moxtet device for %pOF\n",
+				 nc);
+			of_node_clear_flag(nc, OF_POPULATED);
+		}
+	}
+}
+
+static void
+moxtet_register_devices_from_topology(struct moxtet *moxtet)
+{
+	struct moxtet_device *dev;
+	int i, ret;
+
+	for (i = 0; i < moxtet->count; ++i) {
+		dev = moxtet_alloc_device(moxtet);
+		if (!dev) {
+			dev_err(moxtet->dev, "Moxtet device %u alloc error\n",
+				i, moxtet->modules[i]);
+			continue;
+		}
+
+		dev->idx = i;
+		dev->id = moxtet->modules[i];
+
+		ret = moxtet_add_device(dev);
+		if (ret && ret != -EBUSY) {
+			dev_err(moxtet->dev,
+				"Moxtet device %u register error: %i\n", i,
+				moxtet->modules[i], ret);
+		}
+	}
+}
+
+static int moxtet_find_topology(struct moxtet *moxtet)
+{
+	u8 buf[TURRIS_MOX_MAX_MODULES];
+	int i, ret;
+
+	ret = spi_read(to_spi_device(moxtet->dev), buf, TURRIS_MOX_MAX_MODULES);
+	if (ret < 0)
+		return ret;
+
+	if (buf[0] == TURRIS_MOX_CPU_ID_EMMC) {
+		dev_info(moxtet->dev, "Found eMMC Turris Mox CPU module\n");
+	} else if (buf[0] == TURRIS_MOX_CPU_ID_SD) {
+		dev_info(moxtet->dev, "Found SD Turris Mox CPU module\n");
+	} else {
+		dev_err(moxtet->dev, "Invalid Turris Mox CPU module 0x%02x\n",
+			buf[0]);
+		return -ENODEV;
+	}
+
+	moxtet->count = 0;
+
+	for (i = 1; i < TURRIS_MOX_MAX_MODULES; ++i) {
+		int module_id;
+
+		if (buf[i] == 0xff)
+			break;
+
+		module_id = buf[i] & 0xf;
+
+		moxtet->modules[i-1] = module_id;
+		++moxtet->count;
+
+		switch (module_id) {
+		case TURRIS_MOX_MODULE_SFP:
+			dev_info(moxtet->dev, "SFP module found\n");
+			break;
+		case TURRIS_MOX_MODULE_PCI:
+			dev_info(moxtet->dev, "PCIe module found\n");
+			break;
+		case TURRIS_MOX_MODULE_TOPAZ:
+			dev_info(moxtet->dev, "Topaz Switch module found\n");
+			break;
+		case TURRIS_MOX_MODULE_PERIDOT:
+			dev_info(moxtet->dev, "Peridot Switch module found\n");
+			break;
+		default:
+			dev_info(moxtet->dev,
+				 "Unknown Moxtet module found (ID 0x%02x)\n",
+				 module_id);
+		}
+	}
+
+	return 0;
+}
+
+int moxtet_device_read(struct device *dev)
+{
+	struct moxtet_device *mdev = to_moxtet_device(dev);
+	struct moxtet *moxtet = mdev->moxtet;
+	u8 buf[TURRIS_MOX_MAX_MODULES];
+	struct spi_transfer xfer = {
+		.rx_buf = buf,
+		.tx_buf = moxtet->tx,
+		.len = moxtet->count + 1
+	};
+	int ret;
+
+	if (mdev->idx >= moxtet->count)
+		return -EINVAL;
+
+	mutex_lock(&moxtet->lock);
+
+	ret = spi_sync_transfer(to_spi_device(moxtet->dev), &xfer, 1);
+
+	mutex_unlock(&moxtet->lock);
+
+	if (ret < 0)
+		return ret;
+
+	return buf[mdev->idx + 1] >> 4;
+}
+EXPORT_SYMBOL_GPL(moxtet_device_read);
+
+int moxtet_device_write(struct device *dev, u8 val)
+{
+	struct moxtet_device *mdev = to_moxtet_device(dev);
+	struct moxtet *moxtet = mdev->moxtet;
+	int ret;
+
+	if (mdev->idx >= moxtet->count)
+		return -EINVAL;
+
+	mutex_lock(&moxtet->lock);
+
+	moxtet->tx[moxtet->count - mdev->idx] = val;
+
+	ret = spi_write(to_spi_device(moxtet->dev), moxtet->tx,
+			moxtet->count + 1);
+
+	mutex_unlock(&moxtet->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(moxtet_device_write);
+
+int moxtet_device_written(struct device *dev)
+{
+	struct moxtet_device *mdev = to_moxtet_device(dev);
+	struct moxtet *moxtet = mdev->moxtet;
+
+	if (mdev->idx >= moxtet->count)
+		return -EINVAL;
+
+	return moxtet->tx[moxtet->count - mdev->idx];
+}
+EXPORT_SYMBOL_GPL(moxtet_device_written);
+
+static int moxtet_probe(struct spi_device *spi)
+{
+	struct moxtet *moxtet;
+	int ret;
+
+	ret = spi_setup(spi);
+	if (ret < 0)
+		return ret;
+
+	moxtet = devm_kzalloc(&spi->dev, sizeof(struct moxtet),
+			      GFP_KERNEL);
+	if (!moxtet)
+		return -ENOMEM;
+
+	moxtet->dev = &spi->dev;
+	spi_set_drvdata(spi, moxtet);
+
+	mutex_init(&moxtet->lock);
+
+	ret = moxtet_find_topology(moxtet);
+	if (ret < 0)
+		return ret;
+
+	of_register_moxtet_devices(moxtet);
+	moxtet_register_devices_from_topology(moxtet);
+
+	return 0;
+}
+
+static int moxtet_remove(struct spi_device *spi)
+{
+	struct moxtet *moxtet = spi_get_drvdata(spi);
+	int dummy;
+
+	dummy = device_for_each_child(moxtet->dev, NULL, __unregister);
+
+	mutex_destroy(&moxtet->lock);
+
+	return 0;
+}
+
+static const struct of_device_id moxtet_dt_ids[] = {
+	{ .compatible = "cznic,moxtet" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, moxtet_dt_ids);
+
+static struct spi_driver moxtet_driver = {
+	.driver = {
+		.name		= "moxtet",
+		.of_match_table = moxtet_dt_ids,
+	},
+	.probe		= moxtet_probe,
+	.remove		= moxtet_remove,
+};
+module_spi_driver(moxtet_driver);
+
+static int __init moxtet_init(void)
+{
+	return bus_register(&moxtet_bus_type);
+}
+
+postcore_initcall(moxtet_init);
+
+MODULE_AUTHOR("Marek Behun <marek.behun@nic.cz>");
+MODULE_DESCRIPTION("CZ.NIC's Turris Mox module configuration bus");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/moxtet.h b/include/linux/mfd/moxtet.h
new file mode 100644
index 000000000000..f818039c2c2e
--- /dev/null
+++ b/include/linux/mfd/moxtet.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Turris Mox module configuration bus driver
+ *
+ * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+ */
+
+#ifndef __LINUX_MFD_MOXTET_H
+#define __LINUX_MFD_MOXTET_H
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+#define TURRIS_MOX_MAX_MODULES	10
+
+enum turris_mox_cpu_module_id {
+	TURRIS_MOX_CPU_ID_EMMC	= 0x00,
+	TURRIS_MOX_CPU_ID_SD	= 0x10,
+};
+
+enum turris_mox_module_id {
+	TURRIS_MOX_MODULE_SFP		= 0x01,
+	TURRIS_MOX_MODULE_PCI		= 0x02,
+	TURRIS_MOX_MODULE_TOPAZ		= 0x03,
+	TURRIS_MOX_MODULE_PERIDOT	= 0x04,
+};
+
+static inline const char *turris_mox_module_name(unsigned int id)
+{
+	switch (id) {
+	case TURRIS_MOX_MODULE_SFP:
+		return "sfp";
+	case TURRIS_MOX_MODULE_PCI:
+		return "pci";
+	case TURRIS_MOX_MODULE_TOPAZ:
+		return "topaz";
+	case TURRIS_MOX_MODULE_PERIDOT:
+		return "peridot";
+	default:
+		return "unknown";
+	}
+}
+
+extern struct bus_type moxtet_type;
+
+struct moxtet {
+	struct device	*dev;
+	struct mutex	lock;
+	u8		modules[TURRIS_MOX_MAX_MODULES];
+	int		count;
+	u8		tx[TURRIS_MOX_MAX_MODULES];
+	char		module_topology[128];
+};
+
+struct moxtet_driver {
+	const enum turris_mox_module_id	*id_table;
+	struct device_driver		driver;
+};
+
+static inline struct moxtet_driver *
+to_moxtet_driver(struct device_driver *drv)
+{
+	if (!drv)
+		return NULL;
+	return container_of(drv, struct moxtet_driver, driver);
+}
+
+extern int __moxtet_register_driver(struct module *owner,
+				    struct moxtet_driver *mdrv);
+
+static inline void moxtet_unregister_driver(struct moxtet_driver *mdrv)
+{
+	if (mdrv)
+		driver_unregister(&mdrv->driver);
+}
+
+#define moxtet_register_driver(driver) \
+	__moxtet_register_driver(THIS_MODULE, driver)
+
+#define module_moxtet_driver(__moxtet_driver) \
+	module_driver(__moxtet_driver, moxtet_register_driver, \
+			moxtet_unregister_driver)
+
+struct moxtet_device {
+	struct device			dev;
+	struct moxtet			*moxtet;
+	enum turris_mox_module_id	id;
+	unsigned int			idx;
+};
+
+extern int moxtet_device_read(struct device *dev);
+extern int moxtet_device_write(struct device *dev, u8 val);
+extern int moxtet_device_written(struct device *dev);
+
+static inline struct moxtet_device *
+to_moxtet_device(struct device *dev)
+{
+	if (!dev)
+		return NULL;
+	return container_of(dev, struct moxtet_device, dev);
+}
+
+#endif /* __LINUX_MFD_MOXTET_H */
-- 
2.16.4

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

* [PATCH v1 3/7] drivers: gpio: Add support for Turris Mox SFP GPIOs
  2018-08-08 15:26 [PATCH v1 0/7] Add support for the Turris Mox router Marek Behún
  2018-08-08 15:27 ` [PATCH v1 1/7] From: Ken Ma <make@marvell.com> Marek Behún
  2018-08-08 15:27 ` [PATCH v1 2/7] drivers: mfd: Add support for Moxtet bus Marek Behún
@ 2018-08-08 15:27 ` Marek Behún
  2018-08-08 16:55   ` Andrew Lunn
  2018-08-08 15:27 ` [PATCH v1 4/7] watchdog: Add support for Armada 37xx CPU watchdog Marek Behún
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 25+ messages in thread
From: Marek Behún @ 2018-08-08 15:27 UTC (permalink / raw)
  To: linux-arm-kernel

The SFP cage GPIOs on the SFP cage module of Turris Mox can be
configured via the moxtet bus.

This driver supports those GPIOs so that they can be used by phylink.

Signed-off-by: Marek Behun <marek.behun@nic.cz>

 create mode 100644 Documentation/devicetree/bindings/gpio/gpio-moxtet-sfp.txt
 create mode 100644 drivers/gpio/gpio-moxtet-sfp.c

diff --git a/Documentation/devicetree/bindings/gpio/gpio-moxtet-sfp.txt b/Documentation/devicetree/bindings/gpio/gpio-moxtet-sfp.txt
new file mode 100644
index 000000000000..a8267aef7d2c
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-moxtet-sfp.txt
@@ -0,0 +1,16 @@
+GPIO configuration of the SFP cage found on Turris Mox (over Moxtet bus)
+
+Required properties:
+ - compatible		: Should be "cznic,moxtet-sfp".
+ - gpio-controller	: Marks the device node as a GPIO controller.
+ - #gpio-cells		: Should be two. For consumer use see gpio.txt.
+
+Example:
+
+	moxtet_sfp: moxtet-sfp at 0 {
+		compatible = "cznic,moxtet-sfp";
+		gpio-controller;
+		#gpio-cells;
+		reg = <0>;
+		moxtet,id = <1>;
+	}
diff --git a/MAINTAINERS b/MAINTAINERS
index 27ca12e8309a..cfac1b21596c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1383,6 +1383,7 @@ M:	Marek Behun <marek.behun@nic.cz>
 W:	http://mox.turris.cz
 S:	Maintained
 F:	include/mfd/moxtet.h
+F:	drivers/gpio/gpio-moxtet-sfp.c
 F:	drivers/mfd/moxtet.c
 
 ARM/EBSA110 MACHINE SUPPORT
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 71c0ab46f216..bd6e52de99c5 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1048,6 +1048,15 @@ config GPIO_MAX77620
 	  driver also provides interrupt support for each of the gpios.
 	  Say yes here to enable the max77620 to be used as gpio controller.
 
+config GPIO_MOXTET_SFP
+	tristate "Turris Mox SFP GPIO expander"
+	depends on MFD_MOXTET
+	help
+	  Say yes here if you are building for the Turris Mox router.
+	  This is the driver needed for configuring the GPIOs found on the
+	  module with SFP cage of the Turris Mox router.
+	  This driver uses the Moxtet bus.
+
 config GPIO_MSIC
 	bool "Intel MSIC mixed signal gpio support"
 	depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 1324c8f966a7..ba464186c468 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -84,7 +84,8 @@ obj-$(CONFIG_GPIO_MC33880)	+= gpio-mc33880.o
 obj-$(CONFIG_GPIO_MC9S08DZ60)	+= gpio-mc9s08dz60.o
 obj-$(CONFIG_GPIO_ML_IOH)	+= gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MM_LANTIQ)	+= gpio-mm-lantiq.o
-obj-$(CONFIG_GPIO_MOCKUP)      += gpio-mockup.o
+obj-$(CONFIG_GPIO_MOCKUP)	+= gpio-mockup.o
+obj-$(CONFIG_GPIO_MOXTET_SFP)	+= gpio-moxtet-sfp.o
 obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o
 obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSIC)		+= gpio-msic.o
@@ -100,7 +101,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16)	+= gpio-pci-idio-16.o
 obj-$(CONFIG_GPIO_PCIE_IDIO_24)	+= gpio-pcie-idio-24.o
 obj-$(CONFIG_GPIO_PISOSR)	+= gpio-pisosr.o
 obj-$(CONFIG_GPIO_PL061)	+= gpio-pl061.o
-obj-$(CONFIG_GPIO_PMIC_EIC_SPRD)	+= gpio-pmic-eic-sprd.o
+obj-$(CONFIG_GPIO_PMIC_EIC_SPRD)+= gpio-pmic-eic-sprd.o
 obj-$(CONFIG_GPIO_PXA)		+= gpio-pxa.o
 obj-$(CONFIG_GPIO_RC5T583)	+= gpio-rc5t583.o
 obj-$(CONFIG_GPIO_RDC321X)	+= gpio-rdc321x.o
diff --git a/drivers/gpio/gpio-moxtet-sfp.c b/drivers/gpio/gpio-moxtet-sfp.c
new file mode 100644
index 000000000000..87ba73bf55c5
--- /dev/null
+++ b/drivers/gpio/gpio-moxtet-sfp.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Turris Mox SFP - GPIOs on the SFP cage found on Turris Mox SFP module
+ *
+ *  Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/gpio.h>
+#include <linux/mfd/moxtet.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+
+#define MOXTET_SFP_IN_GPIOS	3
+
+struct moxtet_sfp_chip {
+	struct device		*dev;
+	struct gpio_chip	gpio_chip;
+	struct gpio_desc	*gpiod_oe;
+	u8			state;
+};
+
+static int moxtet_sfp_get_value(struct gpio_chip *gc, unsigned int offset)
+{
+	struct moxtet_sfp_chip *chip = gpiochip_get_data(gc);
+	int ret;
+
+	if (offset < MOXTET_SFP_IN_GPIOS) {
+		ret = moxtet_device_read(chip->dev);
+	} else {
+		offset -= MOXTET_SFP_IN_GPIOS;
+		ret = moxtet_device_written(chip->dev);
+	}
+
+	if (ret < 0)
+		return ret;
+
+	return (ret >> offset) & 1;
+}
+
+static void moxtet_sfp_set_value(struct gpio_chip *gc, unsigned int offset,
+				 int val)
+{
+	struct moxtet_sfp_chip *chip = gpiochip_get_data(gc);
+	int ret;
+
+	if (offset < MOXTET_SFP_IN_GPIOS)
+		return;
+
+	offset -= MOXTET_SFP_IN_GPIOS;
+
+	ret = moxtet_device_written(chip->dev);
+	if (ret < 0)
+		return;
+
+	if (val)
+		ret |= (1 << offset);
+	else
+		ret &= ~(1 << offset);
+
+	moxtet_device_write(chip->dev, ret);
+}
+
+static int moxtet_sfp_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+	return offset < MOXTET_SFP_IN_GPIOS;
+}
+
+static int moxtet_sfp_direction_input(struct gpio_chip *gc, unsigned int offset)
+{
+	if (offset >= MOXTET_SFP_IN_GPIOS)
+		return -EINVAL;
+	return 0;
+}
+
+static int moxtet_sfp_direction_output(struct gpio_chip *gc,
+				       unsigned int offset, int val)
+{
+	if (offset < MOXTET_SFP_IN_GPIOS)
+		return -EINVAL;
+
+	moxtet_sfp_set_value(gc, offset, val);
+	return 0;
+}
+
+static int moxtet_sfp_probe(struct device *dev)
+{
+	struct moxtet_sfp_chip *chip;
+
+	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	chip->dev = dev;
+	chip->gpio_chip.parent = dev;
+
+	dev_set_drvdata(dev, chip);
+
+	chip->gpiod_oe = devm_gpiod_get_optional(dev, "enable",
+						 GPIOD_OUT_LOW);
+	if (IS_ERR(chip->gpiod_oe))
+		return PTR_ERR(chip->gpiod_oe);
+
+	gpiod_set_value_cansleep(chip->gpiod_oe, 1);
+
+	chip->gpio_chip.label = dev_name(dev);
+	chip->gpio_chip.get_direction = moxtet_sfp_get_direction;
+	chip->gpio_chip.direction_input = moxtet_sfp_direction_input;
+	chip->gpio_chip.direction_output = moxtet_sfp_direction_output;
+	chip->gpio_chip.get = moxtet_sfp_get_value;
+	chip->gpio_chip.set = moxtet_sfp_set_value;
+	chip->gpio_chip.base = -1;
+
+	chip->gpio_chip.ngpio = 5;
+
+	chip->gpio_chip.can_sleep = true;
+	chip->gpio_chip.owner = THIS_MODULE;
+
+	return gpiochip_add_data(&chip->gpio_chip, chip);
+}
+
+static int moxtet_sfp_remove(struct device *dev)
+{
+	struct moxtet_sfp_chip *chip = dev_get_drvdata(dev);
+
+	gpiod_set_value_cansleep(chip->gpiod_oe, 0);
+	gpiochip_remove(&chip->gpio_chip);
+
+	return 0;
+}
+
+static const struct of_device_id moxtet_sfp_dt_ids[] = {
+	{ .compatible = "cznic,moxtet-sfp" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, moxtet_sfp_dt_ids);
+
+static const enum turris_mox_module_id moxtet_sfp_id_table[] = {
+	TURRIS_MOX_MODULE_SFP,
+	0
+};
+
+static struct moxtet_driver moxtet_sfp_driver = {
+	.driver = {
+		.name		= "moxtet-sfp",
+		.of_match_table	= moxtet_sfp_dt_ids,
+		.probe		= moxtet_sfp_probe,
+		.remove		= moxtet_sfp_remove,
+	},
+	.id_table	= moxtet_sfp_id_table,
+};
+module_moxtet_driver(moxtet_sfp_driver);
+
+MODULE_AUTHOR("Marek Behun <marek.behun@nic.cz>");
+MODULE_DESCRIPTION("GPIO configuration of the SFP cage found on Turris Mox");
+MODULE_LICENSE("GPL v2");
-- 
2.16.4

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

* [PATCH v1 4/7] watchdog: Add support for Armada 37xx CPU watchdog
  2018-08-08 15:26 [PATCH v1 0/7] Add support for the Turris Mox router Marek Behún
                   ` (2 preceding siblings ...)
  2018-08-08 15:27 ` [PATCH v1 3/7] drivers: gpio: Add support for Turris Mox SFP GPIOs Marek Behún
@ 2018-08-08 15:27 ` Marek Behún
  2018-08-08 15:27 ` [PATCH v1 5/7] arm64: dts: marvell: armada-37xx: add nodes to support watchdog Marek Behún
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 25+ messages in thread
From: Marek Behún @ 2018-08-08 15:27 UTC (permalink / raw)
  To: linux-arm-kernel

This adds support for the CPU watchdog found on Marvell Armada 37xx
SoCs.

There are 4 counters which can be set as CPU watchdog counters.
This driver uses the second counter (ID 1, counting from 0)
(Marvell's Linux also uses second counter by default).
In the future it could be adapted to use other counters, with
definition in the device tree.

Signed-off-by: Marek Behun <marek.behun@nic.cz>
Tested-by: Gregory CLEMENT <gregory.clement@bootlin.com>

 create mode 100644 Documentation/devicetree/bindings/watchdog/armada-37xx-wdt.txt
 create mode 100644 drivers/watchdog/armada_37xx_wdt.c

diff --git a/Documentation/devicetree/bindings/watchdog/armada-37xx-wdt.txt b/Documentation/devicetree/bindings/watchdog/armada-37xx-wdt.txt
new file mode 100644
index 000000000000..4ba9e40ad386
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/armada-37xx-wdt.txt
@@ -0,0 +1,23 @@
+* Armada 37xx CPU Watchdog Timer Controller
+
+Required properties:
+- compatible : must be "marvell,armada-3700-wdt"
+- reg : base physical address of the controller and length of memory mapped
+	region.
+- clocks : the clock feeding the watchdog timer. See clock-bindings.txt
+- marvell,system-controller : reference to syscon node for the CPU Miscellaneous
+	Registers
+
+Example:
+
+	cpu_misc: system-controller at d000 {
+		compatible = "syscon", "simple-mfd";
+		reg = <0xd000 0x1000>;
+	};
+
+	wdt: watchdog-timer at 8300 {
+		compatible = "marvell,armada-3700-wdt";
+		reg = <0x8300 0x40>;
+		marvell,system-controller = <&cpu_misc>;
+		clocks = <&xtalclk>;
+	};
diff --git a/MAINTAINERS b/MAINTAINERS
index cfac1b21596c..e2d2955a8331 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1385,6 +1385,7 @@ S:	Maintained
 F:	include/mfd/moxtet.h
 F:	drivers/gpio/gpio-moxtet-sfp.c
 F:	drivers/mfd/moxtet.c
+F:	drivers/watchdog/armada_37xx_wdt.c
 
 ARM/EBSA110 MACHINE SUPPORT
 M:	Russell King <linux@armlinux.org.uk>
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 9af07fd92763..c3d82e3fe1e1 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -263,6 +263,17 @@ config ARM_SBSA_WATCHDOG
 	  To compile this driver as module, choose M here: The module
 	  will be called sbsa_gwdt.
 
+config ARMADA_37XX_WATCHDOG
+	tristate "Armada 37xx watchdog"
+	depends on ARCH_MVEBU || COMPILE_TEST
+	select MFD_SYSCON
+	select WATCHDOG_CORE
+	help
+	  Say Y here to include support for the watchdog timer found on
+	  Marvell Armada 37xx SoCs.
+	  To compile this driver as a module, choose M here: the
+	  module will be called armada_37xx_wdt.
+
 config ASM9260_WATCHDOG
 	tristate "Alphascale ASM9260 watchdog"
 	depends on MACH_ASM9260 || COMPILE_TEST
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 1d3c6b094fe5..476d9069ed7c 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
 # ARM Architecture
 obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
 obj-$(CONFIG_ARM_SBSA_WATCHDOG) += sbsa_gwdt.o
+obj-$(CONFIG_ARMADA_37XX_WATCHDOG) += armada_37xx_wdt.o
 obj-$(CONFIG_ASM9260_WATCHDOG) += asm9260_wdt.o
 obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
 obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o
diff --git a/drivers/watchdog/armada_37xx_wdt.c b/drivers/watchdog/armada_37xx_wdt.c
new file mode 100644
index 000000000000..83ba4ce40d2f
--- /dev/null
+++ b/drivers/watchdog/armada_37xx_wdt.c
@@ -0,0 +1,353 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Watchdog driver for Marvell Armada 37xx SoCs
+ *
+ * Author: Marek Behun <marek.behun@nic.cz>
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+
+/*
+ * There are four counters that can be used for watchdog on Armada 37xx.
+ * The addresses for counter control registers are register base plus ID*0x10,
+ * where ID is 0, 1, 2 or 3.
+ * In this driver we use ID 1. Marvell's Linux also uses this ID by default,
+ * and the U-Boot driver written simultaneosly by the same author as this
+ * driver also uses ID 1.
+ * Maybe in the future we could change this driver to support other counters,
+ * depending on the device tree, but I don't think this is necessary.
+ *
+ * Note that CNTR_ID cannot be 3, because the third counter is an increment
+ * counter, and this driver is written to support decrementing counters only.
+ */
+
+/* relative to cpu_misc */
+#define WDT_TIMER_SELECT		0x64
+#define WDT_TIMER_SELECT_MASK		0xf
+#define WDT_TIMER_SELECT_VAL		BIT(CNTR_ID)
+
+/* relative to reg */
+#define CNTR_ID				1
+
+#define CNTR_CTRL			(CNTR_ID * 0x10)
+#define CNTR_CTRL_ENABLE		0x0001
+#define CNTR_CTRL_ACTIVE		0x0002
+#define CNTR_CTRL_MODE_MASK		0x000c
+#define CNTR_CTRL_MODE_ONESHOT		0x0000
+#define CNTR_CTRL_PRESCALE_MASK		0xff00
+#define CNTR_CTRL_PRESCALE_MIN		2
+#define CNTR_CTRL_PRESCALE_SHIFT	8
+
+#define CNTR_COUNT_LOW			(CNTR_CTRL + 0x4)
+#define CNTR_COUNT_HIGH			(CNTR_CTRL + 0x8)
+
+#define WATCHDOG_TIMEOUT		120
+
+static unsigned int timeout = WATCHDOG_TIMEOUT;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="
+			  __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+			   __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+struct armada_37xx_watchdog {
+	struct watchdog_device wdt;
+	struct regmap *cpu_misc;
+	void __iomem *reg;
+	u64 timeout; /* in clock ticks */
+	unsigned long clk_rate;
+	struct clk *clk;
+};
+
+static u64 get_counter_value(struct armada_37xx_watchdog *dev)
+{
+	u64 val;
+
+	val = readl(dev->reg + CNTR_COUNT_HIGH);
+	val = (val << 32) | readl(dev->reg + CNTR_COUNT_LOW);
+
+	return val;
+}
+
+static void set_counter_value(struct armada_37xx_watchdog *dev)
+{
+	writel(dev->timeout & 0xffffffff, dev->reg + CNTR_COUNT_LOW);
+	writel(dev->timeout >> 32, dev->reg + CNTR_COUNT_HIGH);
+}
+
+static void armada_37xx_wdt_counter_enable(struct armada_37xx_watchdog *dev)
+{
+	u32 reg;
+
+	reg = readl(dev->reg + CNTR_CTRL);
+	reg |= CNTR_CTRL_ENABLE;
+	writel(reg, dev->reg + CNTR_CTRL);
+}
+
+static void armada_37xx_wdt_counter_disable(struct armada_37xx_watchdog *dev)
+{
+	u32 reg;
+
+	reg = readl(dev->reg + CNTR_CTRL);
+	reg &= ~CNTR_CTRL_ENABLE;
+	writel(reg, dev->reg + CNTR_CTRL);
+}
+
+static int armada_37xx_wdt_ping(struct watchdog_device *wdt)
+{
+	struct armada_37xx_watchdog *dev = watchdog_get_drvdata(wdt);
+
+	armada_37xx_wdt_counter_disable(dev);
+	set_counter_value(dev);
+	armada_37xx_wdt_counter_enable(dev);
+
+	return 0;
+}
+
+static unsigned int armada_37xx_wdt_get_timeleft(struct watchdog_device *wdt)
+{
+	struct armada_37xx_watchdog *dev = watchdog_get_drvdata(wdt);
+	unsigned int res;
+
+	res = get_counter_value(dev) * CNTR_CTRL_PRESCALE_MIN / dev->clk_rate;
+
+	return res;
+}
+
+static int armada_37xx_wdt_set_timeout(struct watchdog_device *wdt,
+				       unsigned int timeout)
+{
+	struct armada_37xx_watchdog *dev = watchdog_get_drvdata(wdt);
+
+	wdt->timeout = timeout;
+
+	/*
+	 * Compute the timeout in clock rate. We use smallest possible
+	 * prescaler, which divides the clock rate by 2
+	 * (CNTR_CTRL_PRESCALE_MIN).
+	 */
+	dev->timeout = (u64)dev->clk_rate * timeout / CNTR_CTRL_PRESCALE_MIN;
+
+	return 0;
+}
+
+static bool armada_37xx_wdt_is_running(struct armada_37xx_watchdog *dev)
+{
+	u32 reg;
+
+	regmap_read(dev->cpu_misc, WDT_TIMER_SELECT, &reg);
+	if ((reg & WDT_TIMER_SELECT_MASK) != WDT_TIMER_SELECT_VAL)
+		return false;
+
+	reg = readl(dev->reg + CNTR_CTRL);
+	return !!(reg & CNTR_CTRL_ACTIVE);
+}
+
+static int armada_37xx_wdt_start(struct watchdog_device *wdt)
+{
+	struct armada_37xx_watchdog *dev = watchdog_get_drvdata(wdt);
+	u32 reg;
+
+	reg = readl(dev->reg + CNTR_CTRL);
+
+	if (reg & CNTR_CTRL_ACTIVE)
+		return -EBUSY;
+
+	/* set mode */
+	reg = (reg & ~CNTR_CTRL_MODE_MASK) | CNTR_CTRL_MODE_ONESHOT;
+
+	/* set prescaler to the min value of 2 */
+	reg &= ~CNTR_CTRL_PRESCALE_MASK;
+	reg |= CNTR_CTRL_PRESCALE_MIN << CNTR_CTRL_PRESCALE_SHIFT;
+
+	writel(reg, dev->reg + CNTR_CTRL);
+
+	set_counter_value(dev);
+
+	regmap_write(dev->cpu_misc, WDT_TIMER_SELECT, WDT_TIMER_SELECT_VAL);
+	armada_37xx_wdt_counter_enable(dev);
+
+	return 0;
+}
+
+static int armada_37xx_wdt_stop(struct watchdog_device *wdt)
+{
+	struct armada_37xx_watchdog *dev = watchdog_get_drvdata(wdt);
+
+	armada_37xx_wdt_counter_disable(dev);
+	regmap_write(dev->cpu_misc, WDT_TIMER_SELECT, 0);
+
+	return 0;
+}
+
+static const struct watchdog_info armada_37xx_wdt_info = {
+	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.identity = "Armada 37xx Watchdog",
+};
+
+static const struct watchdog_ops armada_37xx_wdt_ops = {
+	.owner = THIS_MODULE,
+	.start = armada_37xx_wdt_start,
+	.stop = armada_37xx_wdt_stop,
+	.ping = armada_37xx_wdt_ping,
+	.set_timeout = armada_37xx_wdt_set_timeout,
+	.get_timeleft = armada_37xx_wdt_get_timeleft,
+};
+
+static int armada_37xx_wdt_probe(struct platform_device *pdev)
+{
+	struct armada_37xx_watchdog *dev;
+	struct resource *res;
+	struct regmap *regmap;
+	int ret;
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(struct armada_37xx_watchdog),
+			   GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->wdt.info = &armada_37xx_wdt_info;
+	dev->wdt.ops = &armada_37xx_wdt_ops;
+	dev->wdt.min_timeout = 1;
+
+	regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+						 "marvell,system-controller");
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+	dev->cpu_misc = regmap;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+	dev->reg = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+
+	/* init clock */
+	dev->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk))
+		return PTR_ERR(dev->clk);
+
+	ret = clk_prepare_enable(dev->clk);
+	if (ret)
+		return ret;
+
+	dev->clk_rate = clk_get_rate(dev->clk);
+
+	/*
+	 * Since the timeout in seconds is given as 32 bit unsigned int, and
+	 * the counters hold 64 bit values, even after multiplication by clock
+	 * rate the counter can hold timeout of UINT_MAX seconds.
+	 */
+	dev->wdt.min_timeout = 0;
+	dev->wdt.max_timeout = UINT_MAX;
+	dev->wdt.parent = &pdev->dev;
+
+	/* default value, possibly override by module parameter or dtb */
+	dev->wdt.timeout = WATCHDOG_TIMEOUT;
+	watchdog_init_timeout(&dev->wdt, timeout, &pdev->dev);
+
+	platform_set_drvdata(pdev, &dev->wdt);
+	watchdog_set_drvdata(&dev->wdt, dev);
+
+	armada_37xx_wdt_set_timeout(&dev->wdt, dev->wdt.timeout);
+
+	if (armada_37xx_wdt_is_running(dev))
+		set_bit(WDOG_HW_RUNNING, &dev->wdt.status);
+	else
+		armada_37xx_wdt_stop(&dev->wdt);
+
+	watchdog_set_nowayout(&dev->wdt, nowayout);
+	ret = watchdog_register_device(&dev->wdt);
+	if (ret)
+		goto disable_clk;
+
+	dev_info(&pdev->dev, "Initial timeout %d sec%s\n",
+		 dev->wdt.timeout, nowayout ? ", nowayout" : "");
+
+	return 0;
+
+disable_clk:
+	clk_disable_unprepare(dev->clk);
+	return ret;
+}
+
+static int armada_37xx_wdt_remove(struct platform_device *pdev)
+{
+	struct watchdog_device *wdt = platform_get_drvdata(pdev);
+	struct armada_37xx_watchdog *dev = watchdog_get_drvdata(wdt);
+
+	watchdog_unregister_device(wdt);
+	clk_disable_unprepare(dev->clk);
+	return 0;
+}
+
+static void armada_37xx_wdt_shutdown(struct platform_device *pdev)
+{
+	struct watchdog_device *wdt = platform_get_drvdata(pdev);
+
+	armada_37xx_wdt_stop(wdt);
+}
+
+static int __maybe_unused armada_37xx_wdt_suspend(struct device *dev)
+{
+	struct watchdog_device *wdt = dev_get_drvdata(dev);
+
+	return armada_37xx_wdt_stop(wdt);
+}
+
+static int __maybe_unused armada_37xx_wdt_resume(struct device *dev)
+{
+	struct watchdog_device *wdt = dev_get_drvdata(dev);
+
+	if (watchdog_active(wdt))
+		return armada_37xx_wdt_start(wdt);
+
+	return 0;
+}
+
+static const struct dev_pm_ops armada_37xx_wdt_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(armada_37xx_wdt_suspend,
+				armada_37xx_wdt_resume)
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id armada_37xx_wdt_match[] = {
+	{ .compatible = "marvell,armada-3700-wdt", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, armada_37xx_wdt_match);
+#endif
+
+static struct platform_driver armada_37xx_wdt_driver = {
+	.probe		= armada_37xx_wdt_probe,
+	.remove		= armada_37xx_wdt_remove,
+	.shutdown	= armada_37xx_wdt_shutdown,
+	.driver		= {
+		.name	= "armada_37xx_wdt",
+		.of_match_table = of_match_ptr(armada_37xx_wdt_match),
+		.pm = &armada_37xx_wdt_dev_pm_ops,
+	},
+};
+
+module_platform_driver(armada_37xx_wdt_driver);
+
+MODULE_AUTHOR("Marek Behun <marek.behun@nic.cz>");
+MODULE_DESCRIPTION("Armada 37xx CPU Watchdog");
+
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:armada_37xx_wdt");
-- 
2.16.4

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

* [PATCH v1 5/7] arm64: dts: marvell: armada-37xx: add nodes to support watchdog
  2018-08-08 15:26 [PATCH v1 0/7] Add support for the Turris Mox router Marek Behún
                   ` (3 preceding siblings ...)
  2018-08-08 15:27 ` [PATCH v1 4/7] watchdog: Add support for Armada 37xx CPU watchdog Marek Behún
@ 2018-08-08 15:27 ` Marek Behún
  2018-08-08 15:27   ` Marek Behún
  2018-08-08 15:27 ` [PATCH v1 7/7] ARM64: dts: marvell: Add DTS files for Turris Mox Marek Behún
  6 siblings, 0 replies; 25+ messages in thread
From: Marek Behún @ 2018-08-08 15:27 UTC (permalink / raw)
  To: linux-arm-kernel

This adds the system controller node for CPU Miscellaneous Registers
(which is needed for the watchdog node) and the watchdog node.

Signed-off-by: Marek Behun <marek.behun@nic.cz>

diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index 3353252d78a0..b2f041a17d9d 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -65,6 +65,18 @@
 			/* 32M internal register @ 0xd000_0000 */
 			ranges = <0x0 0x0 0xd0000000 0x2000000>;
 
+			wdt: watchdog-timer at 8300 {
+				compatible = "marvell,armada-3700-wdt";
+				reg = <0x8300 0x40>;
+				marvell,system-controller = <&cpu_misc>;
+				clocks = <&xtalclk>;
+			};
+
+			cpu_misc: system-controller at d000 {
+				compatible = "syscon", "simple-mfd";
+				reg = <0xd000 0x1000>;
+			};
+
 			spi0: spi at 10600 {
 				compatible = "marvell,armada-3700-spi";
 				#address-cells = <1>;
-- 
2.16.4

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

* [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
  2018-08-08 15:26 [PATCH v1 0/7] Add support for the Turris Mox router Marek Behún
@ 2018-08-08 15:27   ` Marek Behún
  2018-08-08 15:27 ` [PATCH v1 2/7] drivers: mfd: Add support for Moxtet bus Marek Behún
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 25+ messages in thread
From: Marek Behún @ 2018-08-08 15:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Gregory CLEMENT, Tomas Hlavacek, Marek Behún,
	Russell King - ARM Linux, netdev

For some reason on Armada 3720 boards (EspressoBin and Turris Mox) the
networking driver behaves weirdly when using napi_gro_receive.

For example downloading a big file from a local network (low ping) is
fast, but when downloading from a remote server (higher ping), the
download speed is at first high but drops rapidly to almost nothing or
absolutely nothing.

This is fixed when using netif_receive_skb instead of napi_gro_receive.

Signed-off-by: Marek Behun <marek.behun@nic.cz>
Cc: Russell King - ARM Linux <linux@armlinux.org.uk>
Cc: netdev@vger.kernel.org

diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 0ad2f3f7da85..27f3017d94c5 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -1959,7 +1959,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
 
 			skb->protocol = eth_type_trans(skb, dev);
 			mvneta_rx_csum(pp, rx_status, skb);
-			napi_gro_receive(&port->napi, skb);
+			if (pp->neta_armada3700)
+				netif_receive_skb(skb);
+			else
+				napi_gro_receive(&port->napi, skb);
 
 			rcvd_pkts++;
 			rcvd_bytes += rx_bytes;
@@ -2001,7 +2004,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
 
 		mvneta_rx_csum(pp, rx_status, skb);
 
-		napi_gro_receive(&port->napi, skb);
+		if (pp->neta_armada3700)
+			netif_receive_skb(skb);
+		else
+			napi_gro_receive(&port->napi, skb);
 	}
 
 	if (rcvd_pkts) {
-- 
2.16.4

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

* [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
@ 2018-08-08 15:27   ` Marek Behún
  0 siblings, 0 replies; 25+ messages in thread
From: Marek Behún @ 2018-08-08 15:27 UTC (permalink / raw)
  To: linux-arm-kernel

For some reason on Armada 3720 boards (EspressoBin and Turris Mox) the
networking driver behaves weirdly when using napi_gro_receive.

For example downloading a big file from a local network (low ping) is
fast, but when downloading from a remote server (higher ping), the
download speed is at first high but drops rapidly to almost nothing or
absolutely nothing.

This is fixed when using netif_receive_skb instead of napi_gro_receive.

Signed-off-by: Marek Behun <marek.behun@nic.cz>
Cc: Russell King - ARM Linux <linux@armlinux.org.uk>
Cc: netdev at vger.kernel.org

diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 0ad2f3f7da85..27f3017d94c5 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -1959,7 +1959,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
 
 			skb->protocol = eth_type_trans(skb, dev);
 			mvneta_rx_csum(pp, rx_status, skb);
-			napi_gro_receive(&port->napi, skb);
+			if (pp->neta_armada3700)
+				netif_receive_skb(skb);
+			else
+				napi_gro_receive(&port->napi, skb);
 
 			rcvd_pkts++;
 			rcvd_bytes += rx_bytes;
@@ -2001,7 +2004,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
 
 		mvneta_rx_csum(pp, rx_status, skb);
 
-		napi_gro_receive(&port->napi, skb);
+		if (pp->neta_armada3700)
+			netif_receive_skb(skb);
+		else
+			napi_gro_receive(&port->napi, skb);
 	}
 
 	if (rcvd_pkts) {
-- 
2.16.4

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

* [PATCH v1 7/7] ARM64: dts: marvell: Add DTS files for Turris Mox
  2018-08-08 15:26 [PATCH v1 0/7] Add support for the Turris Mox router Marek Behún
                   ` (5 preceding siblings ...)
  2018-08-08 15:27   ` Marek Behún
@ 2018-08-08 15:27 ` Marek Behún
  6 siblings, 0 replies; 25+ messages in thread
From: Marek Behún @ 2018-08-08 15:27 UTC (permalink / raw)
  To: linux-arm-kernel

This adds basic support for the Turris Mox board from CZ.NIC.

Turris Mox is as modular router based on the Armada 3720 SOC (same as
EspressoBin).

The basic module can be extended by different modules.
When those modules are connected, U-Boot shall patch this basic
device-tree with nodes corresponding to those modules.

Signed-off-by: Marek Behun <marek.behun@nic.cz>

 create mode 100644 Documentation/devicetree/bindings/arm/marvell/armada-3720-turris-mox.txt
 create mode 100644 arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts

diff --git a/Documentation/devicetree/bindings/arm/marvell/armada-3720-turris-mox.txt b/Documentation/devicetree/bindings/arm/marvell/armada-3720-turris-mox.txt
new file mode 100644
index 000000000000..408fc07a9bbf
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/marvell/armada-3720-turris-mox.txt
@@ -0,0 +1,6 @@
+CZ.NIC's Turris Mox SOHO router Device Tree Bindings
+----------------------------------------------------
+
+Required root node property:
+
+compatible: must contain "cznic,turris-mox"
diff --git a/MAINTAINERS b/MAINTAINERS
index e2d2955a8331..40af94bf0b0a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1382,6 +1382,7 @@ ARM/CZ.NIC TURRIS MOX SUPPORT
 M:	Marek Behun <marek.behun@nic.cz>
 W:	http://mox.turris.cz
 S:	Maintained
+F:	arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
 F:	include/mfd/moxtet.h
 F:	drivers/gpio/gpio-moxtet-sfp.c
 F:	drivers/mfd/moxtet.c
diff --git a/arch/arm64/boot/dts/marvell/Makefile b/arch/arm64/boot/dts/marvell/Makefile
index ea9d49f2a911..1dd89d1bf8ad 100644
--- a/arch/arm64/boot/dts/marvell/Makefile
+++ b/arch/arm64/boot/dts/marvell/Makefile
@@ -2,6 +2,7 @@
 # Mvebu SoC Family
 dtb-$(CONFIG_ARCH_MVEBU) += armada-3720-db.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += armada-3720-espressobin.dtb
+dtb-$(CONFIG_ARCH_MVEBU) += armada-3720-turris-mox.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += armada-7040-db.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-db.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-mcbin.dtb
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
new file mode 100644
index 000000000000..dd9de3388c1e
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0+ or X11
+/*
+ * Device Tree file for CZ.NIC Turris Mox Board
+ * 2018 by Marek Behun <marek.behun@nic.cz>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "armada-372x.dtsi"
+
+/ {
+	model = "CZ.NIC Turris Mox Board";
+	compatible = "cznic,turris-mox", "marvell,armada3720",
+		     "marvell,armada3710";
+
+	aliases {
+		spi0 = &spi0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory at 0 {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		red {
+			gpios = <&gpiosb 21 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		button at 0 {
+			label = "reset";
+			linux,code = <BTN_MISC>;
+			gpios = <&gpiosb 20 GPIO_ACTIVE_LOW>;
+			debounce-interval = <60>;
+		};
+	};
+
+	exp_usb3_vbus: usb3-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb3-vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		enable-active-high;
+		regulator-always-on;
+		gpio = <&gpiosb 0 GPIO_ACTIVE_HIGH>;
+	};
+
+	usb3_phy: usb3-phy {
+		compatible = "usb-nop-xceiv";
+		vcc-supply = <&exp_usb3_vbus>;
+	};
+
+	vsdc_reg: regulator at 1 {
+		compatible = "regulator-gpio";
+		regulator-name = "vsdc";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+
+		gpios = <&gpiosb 23 GPIO_ACTIVE_HIGH>;
+		gpios-states = <0>;
+		states = <1800000 0x1
+			  3300000 0x0>;
+		enable-active-high;
+	};
+
+	vsdio_reg: regulator at 2 {
+		compatible = "regulator-gpio";
+		regulator-name = "vsdio";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+
+		gpios = <&gpiosb 22 GPIO_ACTIVE_HIGH>;
+		gpios-states = <0>;
+		states = <1800000 0x1
+			  3300000 0x0>;
+		enable-active-high;
+	};
+};
+
+&pinctrl_nb {
+	spi_cs1_pins: spi-cs1-pins {
+		groups = "spi_cs1";
+		function = "spi";
+	};
+
+	sdio0_pins: sdio0-pins {
+		groups = "sdio0";
+		function = "sdio";
+	};
+};
+
+&pinctrl_sb {
+	sdio_sb_pins: sdio-sb-pins {
+		groups = "sdio_sb";
+		function = "sdio";
+	};
+
+	smi_pins: smi-pins {
+		groups = "smi";
+		function = "smi";
+	};
+
+	pcie_pins: pcie1-pins {
+		groups = "pcie1";
+		function = "gpio";
+	};
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+
+	rtc at 6f {
+		compatible = "microchip,mcp7940x";
+		reg = <0x6f>;
+	};
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie_pins>;
+	status = "okay";
+	max-link-speed = <2>;
+
+	/* this shall be enabled by u-boot if the PCIe module is present */
+	status = "disabled";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&eth0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	phy-mode = "rgmii-id";
+	phy = <&phy1>;
+	status = "okay";
+};
+
+&mdio {
+	pinctrl-names = "default";
+	pinctrl-0 = <&smi_pins>;
+	status = "okay";
+
+	phy1: ethernet-phy at 1 {
+		reg = <1>;
+	};
+};
+
+&sdhci0 {
+	wp-inverted;
+	bus-width = <4>;
+	cd-gpios = <&gpionb 10 GPIO_ACTIVE_HIGH>;
+	vqmmc-supply = <&vsdc_reg>;
+	marvell,pad-type = "sd";
+	status = "okay";
+};
+
+&sdhci1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdio0_pins &sdio_sb_pins>;
+	non-removable;
+	bus-width = <4>;
+	marvell,pad-type = "sd";
+	vqmmc-supply = <&vsdio_reg>;
+	status = "okay";
+};
+
+&spi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi_quad_pins &spi_cs1_pins>;
+
+	spi-flash at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <2000000>;
+
+		partition at 0 {
+			label = "u-boot";
+			reg = <0x0 0x3f0000>;
+		};
+
+		partition at 3f0000 {
+			label = "u-boot-env";
+			reg = <0x180000 0x10000>;
+		};
+
+		partition at 400000 {
+			label = "Rescue system";
+			reg = <0x190000 0x670000>;
+		};
+	};
+
+	moxtet at 1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "cznic,moxtet";
+		reg = <1>;
+		spi-max-frequency = <1000000>;
+		spi-cpol;
+		spi-cpha;
+	};
+};
+
+&usb3 {
+	status = "okay";
+	usb-phy = <&usb3_phy>;
+};
-- 
2.16.4

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

* [PATCH v1 2/7] drivers: mfd: Add support for Moxtet bus
  2018-08-08 15:27 ` [PATCH v1 2/7] drivers: mfd: Add support for Moxtet bus Marek Behún
@ 2018-08-08 15:32   ` Marek Behún
  0 siblings, 0 replies; 25+ messages in thread
From: Marek Behún @ 2018-08-08 15:32 UTC (permalink / raw)
  To: linux-arm-kernel

I found out that there are two calls to dev_err with too many
arguments, will patch in next version.

On Wed,  8 Aug 2018 17:27:01 +0200
Marek Beh?n <marek.behun@nic.cz> wrote:

> +static void
> +moxtet_register_devices_from_topology(struct moxtet *moxtet)
> +{
> +	struct moxtet_device *dev;
> +	int i, ret;
> +
> +	for (i = 0; i < moxtet->count; ++i) {
> +		dev = moxtet_alloc_device(moxtet);
> +		if (!dev) {
> +			dev_err(moxtet->dev, "Moxtet device %u alloc
> error\n",
> +				i, moxtet->modules[i]);

here

> +			continue;
> +		}
> +
> +		dev->idx = i;
> +		dev->id = moxtet->modules[i];
> +
> +		ret = moxtet_add_device(dev);
> +		if (ret && ret != -EBUSY) {
> +			dev_err(moxtet->dev,
> +				"Moxtet device %u register error:
> %i\n", i,
> +				moxtet->modules[i], ret);

and here

> +		}
> +	}
> +}

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

* [PATCH v1 1/7] From: Ken Ma <make@marvell.com>
  2018-08-08 15:27 ` [PATCH v1 1/7] From: Ken Ma <make@marvell.com> Marek Behún
@ 2018-08-08 16:49   ` Andrew Lunn
  0 siblings, 0 replies; 25+ messages in thread
From: Andrew Lunn @ 2018-08-08 16:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 08, 2018 at 05:27:00PM +0200, Marek Beh?n wrote:
> pinctrl: armada-37xx: Correct mpp definitions

Hi Marek

The subject line is messed up.

> 
> This patch corrects below mpp definitions:
>  - The sdio_sb group is composed of 6 pins and not 5;
>  - The rgmii group contains pins mpp2[17:6] and not mpp2[19:6];
>  - Pin of group "pmic0" is mpp1[6] but not mpp1[16];
>  - Pin of group "pmic1" is mpp1[7] but not mpp1[17];
>  - A new group "smi" is added in A0 with 2 pins - mpp2[19:18], its
>    bitmask is bit4;
>  - Group "pcie1" has 3 pins in A0 - mpp2[5:3], its bit mask is
>    bit5 | bit9 | bit10 but not bit4;
>  - Group "ptp" has 3 pins in A0 as Z1, but its bitmask is changed to
>    bit11 | bit12 | bit13.
> 
> Signed-off-by: Marek Behun <marek.behun@nic.cz>

This probably should should have the original Marvell SOB as well.

     Andrew

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

* [PATCH v1 3/7] drivers: gpio: Add support for Turris Mox SFP GPIOs
  2018-08-08 15:27 ` [PATCH v1 3/7] drivers: gpio: Add support for Turris Mox SFP GPIOs Marek Behún
@ 2018-08-08 16:55   ` Andrew Lunn
  2018-08-08 20:40     ` Marek Behun
  0 siblings, 1 reply; 25+ messages in thread
From: Andrew Lunn @ 2018-08-08 16:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 08, 2018 at 05:27:02PM +0200, Marek Beh?n wrote:
> The SFP cage GPIOs on the SFP cage module of Turris Mox can be
> configured via the moxtet bus.
> 
> This driver supports those GPIOs so that they can be used by phylink.

I don't see anything in this driver which is specific to SFP. It is
just a GPIO driver for 3 lines. So i would drop all references to SFP.
You can then use it to blink LEDs on some other module, etc.

     Andrew

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

* Re: [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
  2018-08-08 15:27   ` Marek Behún
@ 2018-08-08 16:58     ` Andrew Lunn
  -1 siblings, 0 replies; 25+ messages in thread
From: Andrew Lunn @ 2018-08-08 16:58 UTC (permalink / raw)
  To: Marek Behún
  Cc: linux-arm-kernel, netdev, Gregory CLEMENT, Tomas Hlavacek,
	Russell King - ARM Linux

On Wed, Aug 08, 2018 at 05:27:05PM +0200, Marek Behún wrote:
> For some reason on Armada 3720 boards (EspressoBin and Turris Mox) the
> networking driver behaves weirdly when using napi_gro_receive.
> 
> For example downloading a big file from a local network (low ping) is
> fast, but when downloading from a remote server (higher ping), the
> download speed is at first high but drops rapidly to almost nothing or
> absolutely nothing.
> 
> This is fixed when using netif_receive_skb instead of napi_gro_receive.

Before doing this, we should really understand what is going on. It is
probably just a driver bug which needs fixing. And GRO should be good
for performance, so we do want to use it, if possible.

    Andrew

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

* [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
@ 2018-08-08 16:58     ` Andrew Lunn
  0 siblings, 0 replies; 25+ messages in thread
From: Andrew Lunn @ 2018-08-08 16:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 08, 2018 at 05:27:05PM +0200, Marek Beh?n wrote:
> For some reason on Armada 3720 boards (EspressoBin and Turris Mox) the
> networking driver behaves weirdly when using napi_gro_receive.
> 
> For example downloading a big file from a local network (low ping) is
> fast, but when downloading from a remote server (higher ping), the
> download speed is at first high but drops rapidly to almost nothing or
> absolutely nothing.
> 
> This is fixed when using netif_receive_skb instead of napi_gro_receive.

Before doing this, we should really understand what is going on. It is
probably just a driver bug which needs fixing. And GRO should be good
for performance, so we do want to use it, if possible.

    Andrew

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

* Re: [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
  2018-08-08 16:58     ` Andrew Lunn
@ 2018-08-08 17:57       ` Dave Taht
  -1 siblings, 0 replies; 25+ messages in thread
From: Dave Taht @ 2018-08-08 17:57 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: marek.behun, linux-arm-kernel, Linux Kernel Network Developers,
	gregory.clement, tomas.hlavacek, linux

On Wed, Aug 8, 2018 at 10:00 AM Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Wed, Aug 08, 2018 at 05:27:05PM +0200, Marek Behún wrote:
> > For some reason on Armada 3720 boards (EspressoBin and Turris Mox) the
> > networking driver behaves weirdly when using napi_gro_receive.
> >
> > For example downloading a big file from a local network (low ping) is
> > fast, but when downloading from a remote server (higher ping), the
> > download speed is at first high but drops rapidly to almost nothing or
> > absolutely nothing.
> >
> > This is fixed when using netif_receive_skb instead of napi_gro_receive.
>
> Before doing this, we should really understand what is going on. It is
> probably just a driver bug which needs fixing. And GRO should be good
> for performance, so we do want to use it, if possible.

I'd just disable it and worry about it later. The software gro in the
mvneta would batch up 64k and is one of the reasons why sch_cake does
gso splitting by default. (64k unsplit, downshifted to 1mbit = ~540ms
of latency). If this mvneta facility is in addition buggy, that
explains some puzzling things I've seen in various benchmarks. thx for
the steer as to what to look for!

IMHO: in general gro looks good on dumb single stream benchmarks, not
as useful on mixed routed traffic with more entropy, and batching
clutters up the mvneta receive path that otherwise could be draining
the rx ring and spitting packets into the rest of the system faster.
The mvneta is mostly (?) used on routing devices.



>
>     Andrew



-- 

Dave Täht
CEO, TekLibre, LLC
http://www.teklibre.com
Tel: 1-669-226-2619

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

* [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
@ 2018-08-08 17:57       ` Dave Taht
  0 siblings, 0 replies; 25+ messages in thread
From: Dave Taht @ 2018-08-08 17:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 8, 2018 at 10:00 AM Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Wed, Aug 08, 2018 at 05:27:05PM +0200, Marek Beh?n wrote:
> > For some reason on Armada 3720 boards (EspressoBin and Turris Mox) the
> > networking driver behaves weirdly when using napi_gro_receive.
> >
> > For example downloading a big file from a local network (low ping) is
> > fast, but when downloading from a remote server (higher ping), the
> > download speed is at first high but drops rapidly to almost nothing or
> > absolutely nothing.
> >
> > This is fixed when using netif_receive_skb instead of napi_gro_receive.
>
> Before doing this, we should really understand what is going on. It is
> probably just a driver bug which needs fixing. And GRO should be good
> for performance, so we do want to use it, if possible.

I'd just disable it and worry about it later. The software gro in the
mvneta would batch up 64k and is one of the reasons why sch_cake does
gso splitting by default. (64k unsplit, downshifted to 1mbit = ~540ms
of latency). If this mvneta facility is in addition buggy, that
explains some puzzling things I've seen in various benchmarks. thx for
the steer as to what to look for!

IMHO: in general gro looks good on dumb single stream benchmarks, not
as useful on mixed routed traffic with more entropy, and batching
clutters up the mvneta receive path that otherwise could be draining
the rx ring and spitting packets into the rest of the system faster.
The mvneta is mostly (?) used on routing devices.



>
>     Andrew



-- 

Dave T?ht
CEO, TekLibre, LLC
http://www.teklibre.com
Tel: 1-669-226-2619

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

* [PATCH v1 3/7] drivers: gpio: Add support for Turris Mox SFP GPIOs
  2018-08-08 16:55   ` Andrew Lunn
@ 2018-08-08 20:40     ` Marek Behun
  0 siblings, 0 replies; 25+ messages in thread
From: Marek Behun @ 2018-08-08 20:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 8 Aug 2018 18:55:32 +0200
Andrew Lunn <andrew@lunn.ch> wrote:

> On Wed, Aug 08, 2018 at 05:27:02PM +0200, Marek Beh?n wrote:
> > The SFP cage GPIOs on the SFP cage module of Turris Mox can be
> > configured via the moxtet bus.
> > 
> > This driver supports those GPIOs so that they can be used by
> > phylink.  
> 
> I don't see anything in this driver which is specific to SFP. It is
> just a GPIO driver for 3 lines. So i would drop all references to SFP.
> You can then use it to blink LEDs on some other module, etc.
> 
>      Andrew

You are right, I shall rewrite the code to be more general.
Marek

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

* Re: [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
  2018-08-08 15:27   ` Marek Behún
@ 2018-08-09  4:40     ` Jisheng Zhang
  -1 siblings, 0 replies; 25+ messages in thread
From: Jisheng Zhang @ 2018-08-09  4:40 UTC (permalink / raw)
  To: Marek Behún, Thomas Petazzoni, Andrew Lunn
  Cc: linux-arm-kernel, netdev, Gregory CLEMENT, Tomas Hlavacek,
	Russell King - ARM Linux, David S. Miller

+ more people

On Wed,  8 Aug 2018 17:27:05 +0200 Marek Behún wrote:

> For some reason on Armada 3720 boards (EspressoBin and Turris Mox) the
> networking driver behaves weirdly when using napi_gro_receive.
> 
> For example downloading a big file from a local network (low ping) is
> fast, but when downloading from a remote server (higher ping), the
> download speed is at first high but drops rapidly to almost nothing or
> absolutely nothing.

We also met this issue on some berlin platforms. I tried to fix the bug,
but no clue so far.

> 
> This is fixed when using netif_receive_skb instead of napi_gro_receive.

This is a workaround. The good news is this workaround also fixes the issue
we saw on berlin.

> 
> Signed-off-by: Marek Behun <marek.behun@nic.cz>
> Cc: Russell King - ARM Linux <linux@armlinux.org.uk>
> Cc: netdev@vger.kernel.org
> 
> diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
> index 0ad2f3f7da85..27f3017d94c5 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -1959,7 +1959,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
>  
>  			skb->protocol = eth_type_trans(skb, dev);
>  			mvneta_rx_csum(pp, rx_status, skb);
> -			napi_gro_receive(&port->napi, skb);
> +			if (pp->neta_armada3700)
> +				netif_receive_skb(skb);
> +			else
> +				napi_gro_receive(&port->napi, skb);
>  
>  			rcvd_pkts++;
>  			rcvd_bytes += rx_bytes;
> @@ -2001,7 +2004,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
>  
>  		mvneta_rx_csum(pp, rx_status, skb);
>  
> -		napi_gro_receive(&port->napi, skb);
> +		if (pp->neta_armada3700)
> +			netif_receive_skb(skb);
> +		else
> +			napi_gro_receive(&port->napi, skb);
>  	}
>  
>  	if (rcvd_pkts) {

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

* [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
@ 2018-08-09  4:40     ` Jisheng Zhang
  0 siblings, 0 replies; 25+ messages in thread
From: Jisheng Zhang @ 2018-08-09  4:40 UTC (permalink / raw)
  To: linux-arm-kernel

+ more people

On Wed,  8 Aug 2018 17:27:05 +0200 Marek Beh?n wrote:

> For some reason on Armada 3720 boards (EspressoBin and Turris Mox) the
> networking driver behaves weirdly when using napi_gro_receive.
> 
> For example downloading a big file from a local network (low ping) is
> fast, but when downloading from a remote server (higher ping), the
> download speed is at first high but drops rapidly to almost nothing or
> absolutely nothing.

We also met this issue on some berlin platforms. I tried to fix the bug,
but no clue so far.

> 
> This is fixed when using netif_receive_skb instead of napi_gro_receive.

This is a workaround. The good news is this workaround also fixes the issue
we saw on berlin.

> 
> Signed-off-by: Marek Behun <marek.behun@nic.cz>
> Cc: Russell King - ARM Linux <linux@armlinux.org.uk>
> Cc: netdev at vger.kernel.org
> 
> diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
> index 0ad2f3f7da85..27f3017d94c5 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -1959,7 +1959,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
>  
>  			skb->protocol = eth_type_trans(skb, dev);
>  			mvneta_rx_csum(pp, rx_status, skb);
> -			napi_gro_receive(&port->napi, skb);
> +			if (pp->neta_armada3700)
> +				netif_receive_skb(skb);
> +			else
> +				napi_gro_receive(&port->napi, skb);
>  
>  			rcvd_pkts++;
>  			rcvd_bytes += rx_bytes;
> @@ -2001,7 +2004,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
>  
>  		mvneta_rx_csum(pp, rx_status, skb);
>  
> -		napi_gro_receive(&port->napi, skb);
> +		if (pp->neta_armada3700)
> +			netif_receive_skb(skb);
> +		else
> +			napi_gro_receive(&port->napi, skb);
>  	}
>  
>  	if (rcvd_pkts) {

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

* Re: [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
  2018-08-09  4:40     ` Jisheng Zhang
@ 2018-08-09 11:27       ` Jisheng Zhang
  -1 siblings, 0 replies; 25+ messages in thread
From: Jisheng Zhang @ 2018-08-09 11:27 UTC (permalink / raw)
  To: Marek Behún, Thomas Petazzoni, Andrew Lunn
  Cc: linux-arm-kernel, netdev, Gregory CLEMENT, Tomas Hlavacek,
	Russell King - ARM Linux, David S. Miller

Hi,

On Thu, 9 Aug 2018 12:40:41 +0800 Jisheng Zhang wrote:

> + more people
> 
> On Wed,  8 Aug 2018 17:27:05 +0200 Marek Behún wrote:
> 
> > For some reason on Armada 3720 boards (EspressoBin and Turris Mox) the
> > networking driver behaves weirdly when using napi_gro_receive.
> > 
> > For example downloading a big file from a local network (low ping) is
> > fast, but when downloading from a remote server (higher ping), the
> > download speed is at first high but drops rapidly to almost nothing or
> > absolutely nothing.  
> 
> We also met this issue on some berlin platforms. I tried to fix the bug,
> but no clue so far.
> 
> > 
> > This is fixed when using netif_receive_skb instead of napi_gro_receive.  
> 
> This is a workaround. The good news is this workaround also fixes the issue
> we saw on berlin.
> 
> > 
> > Signed-off-by: Marek Behun <marek.behun@nic.cz>
> > Cc: Russell King - ARM Linux <linux@armlinux.org.uk>
> > Cc: netdev@vger.kernel.org
> > 
> > diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
> > index 0ad2f3f7da85..27f3017d94c5 100644
> > --- a/drivers/net/ethernet/marvell/mvneta.c
> > +++ b/drivers/net/ethernet/marvell/mvneta.c
> > @@ -1959,7 +1959,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
> >  
> >  			skb->protocol = eth_type_trans(skb, dev);
> >  			mvneta_rx_csum(pp, rx_status, skb);
> > -			napi_gro_receive(&port->napi, skb);
> > +			if (pp->neta_armada3700)
> > +				netif_receive_skb(skb);
> > +			else
> > +				napi_gro_receive(&port->napi, skb);

I think I found the root cause, if neta_armada3700 is true, the port got from
this_cpu_ptr(pp->ports) is invalid, this is bug... I'll cook a patch for this

Thanks

> >  
> >  			rcvd_pkts++;
> >  			rcvd_bytes += rx_bytes;
> > @@ -2001,7 +2004,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
> >  
> >  		mvneta_rx_csum(pp, rx_status, skb);
> >  
> > -		napi_gro_receive(&port->napi, skb);
> > +		if (pp->neta_armada3700)
> > +			netif_receive_skb(skb);
> > +		else
> > +			napi_gro_receive(&port->napi, skb);
> >  	}
> >  
> >  	if (rcvd_pkts) {  
> 

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

* [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
@ 2018-08-09 11:27       ` Jisheng Zhang
  0 siblings, 0 replies; 25+ messages in thread
From: Jisheng Zhang @ 2018-08-09 11:27 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Thu, 9 Aug 2018 12:40:41 +0800 Jisheng Zhang wrote:

> + more people
> 
> On Wed,  8 Aug 2018 17:27:05 +0200 Marek Beh?n wrote:
> 
> > For some reason on Armada 3720 boards (EspressoBin and Turris Mox) the
> > networking driver behaves weirdly when using napi_gro_receive.
> > 
> > For example downloading a big file from a local network (low ping) is
> > fast, but when downloading from a remote server (higher ping), the
> > download speed is at first high but drops rapidly to almost nothing or
> > absolutely nothing.  
> 
> We also met this issue on some berlin platforms. I tried to fix the bug,
> but no clue so far.
> 
> > 
> > This is fixed when using netif_receive_skb instead of napi_gro_receive.  
> 
> This is a workaround. The good news is this workaround also fixes the issue
> we saw on berlin.
> 
> > 
> > Signed-off-by: Marek Behun <marek.behun@nic.cz>
> > Cc: Russell King - ARM Linux <linux@armlinux.org.uk>
> > Cc: netdev at vger.kernel.org
> > 
> > diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
> > index 0ad2f3f7da85..27f3017d94c5 100644
> > --- a/drivers/net/ethernet/marvell/mvneta.c
> > +++ b/drivers/net/ethernet/marvell/mvneta.c
> > @@ -1959,7 +1959,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
> >  
> >  			skb->protocol = eth_type_trans(skb, dev);
> >  			mvneta_rx_csum(pp, rx_status, skb);
> > -			napi_gro_receive(&port->napi, skb);
> > +			if (pp->neta_armada3700)
> > +				netif_receive_skb(skb);
> > +			else
> > +				napi_gro_receive(&port->napi, skb);

I think I found the root cause, if neta_armada3700 is true, the port got from
this_cpu_ptr(pp->ports) is invalid, this is bug... I'll cook a patch for this

Thanks

> >  
> >  			rcvd_pkts++;
> >  			rcvd_bytes += rx_bytes;
> > @@ -2001,7 +2004,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
> >  
> >  		mvneta_rx_csum(pp, rx_status, skb);
> >  
> > -		napi_gro_receive(&port->napi, skb);
> > +		if (pp->neta_armada3700)
> > +			netif_receive_skb(skb);
> > +		else
> > +			napi_gro_receive(&port->napi, skb);
> >  	}
> >  
> >  	if (rcvd_pkts) {  
> 

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

* Re: [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
  2018-08-09 11:27       ` Jisheng Zhang
@ 2018-08-09 12:08         ` Jisheng Zhang
  -1 siblings, 0 replies; 25+ messages in thread
From: Jisheng Zhang @ 2018-08-09 12:08 UTC (permalink / raw)
  To: Marek Behún, Thomas Petazzoni, Andrew Lunn
  Cc: linux-arm-kernel, netdev, Gregory CLEMENT, Tomas Hlavacek,
	Russell King - ARM Linux, David S. Miller

On Thu, 9 Aug 2018 19:27:55 +0800 Jisheng Zhang wrote:

> Hi,
> 
> On Thu, 9 Aug 2018 12:40:41 +0800 Jisheng Zhang wrote:
> 
> > + more people
> > 
> > On Wed,  8 Aug 2018 17:27:05 +0200 Marek Behún wrote:
> >   
> > > For some reason on Armada 3720 boards (EspressoBin and Turris Mox) the
> > > networking driver behaves weirdly when using napi_gro_receive.
> > > 
> > > For example downloading a big file from a local network (low ping) is
> > > fast, but when downloading from a remote server (higher ping), the
> > > download speed is at first high but drops rapidly to almost nothing or
> > > absolutely nothing.    
> > 
> > We also met this issue on some berlin platforms. I tried to fix the bug,
> > but no clue so far.
> >   
> > > 
> > > This is fixed when using netif_receive_skb instead of napi_gro_receive.    
> > 
> > This is a workaround. The good news is this workaround also fixes the issue
> > we saw on berlin.
> >   
> > > 
> > > Signed-off-by: Marek Behun <marek.behun@nic.cz>
> > > Cc: Russell King - ARM Linux <linux@armlinux.org.uk>
> > > Cc: netdev@vger.kernel.org
> > > 
> > > diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
> > > index 0ad2f3f7da85..27f3017d94c5 100644
> > > --- a/drivers/net/ethernet/marvell/mvneta.c
> > > +++ b/drivers/net/ethernet/marvell/mvneta.c
> > > @@ -1959,7 +1959,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
> > >  
> > >  			skb->protocol = eth_type_trans(skb, dev);
> > >  			mvneta_rx_csum(pp, rx_status, skb);
> > > -			napi_gro_receive(&port->napi, skb);
> > > +			if (pp->neta_armada3700)
> > > +				netif_receive_skb(skb);
> > > +			else
> > > +				napi_gro_receive(&port->napi, skb);  
> 
> I think I found the root cause, if neta_armada3700 is true, the port got from
> this_cpu_ptr(pp->ports) is invalid, this is bug... I'll cook a patch for this

correct it as:

the port's(port is got from this_cpu_ptr(pp->ports) napi is invalid.

Patch is sent out. Could you please try?

Per my test, it solves the issue we saw on berlin.

> 
> Thanks
> 
> > >  
> > >  			rcvd_pkts++;
> > >  			rcvd_bytes += rx_bytes;
> > > @@ -2001,7 +2004,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
> > >  
> > >  		mvneta_rx_csum(pp, rx_status, skb);
> > >  
> > > -		napi_gro_receive(&port->napi, skb);
> > > +		if (pp->neta_armada3700)
> > > +			netif_receive_skb(skb);
> > > +		else
> > > +			napi_gro_receive(&port->napi, skb);
> > >  	}
> > >  
> > >  	if (rcvd_pkts) {    
> >   
> 

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

* [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
@ 2018-08-09 12:08         ` Jisheng Zhang
  0 siblings, 0 replies; 25+ messages in thread
From: Jisheng Zhang @ 2018-08-09 12:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 9 Aug 2018 19:27:55 +0800 Jisheng Zhang wrote:

> Hi,
> 
> On Thu, 9 Aug 2018 12:40:41 +0800 Jisheng Zhang wrote:
> 
> > + more people
> > 
> > On Wed,  8 Aug 2018 17:27:05 +0200 Marek Beh?n wrote:
> >   
> > > For some reason on Armada 3720 boards (EspressoBin and Turris Mox) the
> > > networking driver behaves weirdly when using napi_gro_receive.
> > > 
> > > For example downloading a big file from a local network (low ping) is
> > > fast, but when downloading from a remote server (higher ping), the
> > > download speed is at first high but drops rapidly to almost nothing or
> > > absolutely nothing.    
> > 
> > We also met this issue on some berlin platforms. I tried to fix the bug,
> > but no clue so far.
> >   
> > > 
> > > This is fixed when using netif_receive_skb instead of napi_gro_receive.    
> > 
> > This is a workaround. The good news is this workaround also fixes the issue
> > we saw on berlin.
> >   
> > > 
> > > Signed-off-by: Marek Behun <marek.behun@nic.cz>
> > > Cc: Russell King - ARM Linux <linux@armlinux.org.uk>
> > > Cc: netdev at vger.kernel.org
> > > 
> > > diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
> > > index 0ad2f3f7da85..27f3017d94c5 100644
> > > --- a/drivers/net/ethernet/marvell/mvneta.c
> > > +++ b/drivers/net/ethernet/marvell/mvneta.c
> > > @@ -1959,7 +1959,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
> > >  
> > >  			skb->protocol = eth_type_trans(skb, dev);
> > >  			mvneta_rx_csum(pp, rx_status, skb);
> > > -			napi_gro_receive(&port->napi, skb);
> > > +			if (pp->neta_armada3700)
> > > +				netif_receive_skb(skb);
> > > +			else
> > > +				napi_gro_receive(&port->napi, skb);  
> 
> I think I found the root cause, if neta_armada3700 is true, the port got from
> this_cpu_ptr(pp->ports) is invalid, this is bug... I'll cook a patch for this

correct it as:

the port's(port is got from this_cpu_ptr(pp->ports) napi is invalid.

Patch is sent out. Could you please try?

Per my test, it solves the issue we saw on berlin.

> 
> Thanks
> 
> > >  
> > >  			rcvd_pkts++;
> > >  			rcvd_bytes += rx_bytes;
> > > @@ -2001,7 +2004,10 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
> > >  
> > >  		mvneta_rx_csum(pp, rx_status, skb);
> > >  
> > > -		napi_gro_receive(&port->napi, skb);
> > > +		if (pp->neta_armada3700)
> > > +			netif_receive_skb(skb);
> > > +		else
> > > +			napi_gro_receive(&port->napi, skb);
> > >  	}
> > >  
> > >  	if (rcvd_pkts) {    
> >   
> 

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

* Re: [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
  2018-08-09 12:08         ` Jisheng Zhang
@ 2018-08-21 10:07           ` Marek Behún
  -1 siblings, 0 replies; 25+ messages in thread
From: Marek Behún @ 2018-08-21 10:07 UTC (permalink / raw)
  To: Jisheng Zhang
  Cc: Thomas Petazzoni, Andrew Lunn, linux-arm-kernel, netdev,
	Gregory CLEMENT, Tomas Hlavacek, Russell King - ARM Linux,
	David S. Miller

On Thu, 9 Aug 2018 20:08:32 +0800
Jisheng Zhang <Jisheng.Zhang@synaptics.com> wrote:

> On Thu, 9 Aug 2018 19:27:55 +0800 Jisheng Zhang wrote:
> 
> > Hi,
> > 
> > On Thu, 9 Aug 2018 12:40:41 +0800 Jisheng Zhang wrote:
> >   
> > > + more people
> > > 
> > > On Wed,  8 Aug 2018 17:27:05 +0200 Marek Behún wrote:
> > >     
> > > > For some reason on Armada 3720 boards (EspressoBin and Turris
> > > > Mox) the networking driver behaves weirdly when using
> > > > napi_gro_receive.
> > > > 
> > > > For example downloading a big file from a local network (low
> > > > ping) is fast, but when downloading from a remote server
> > > > (higher ping), the download speed is at first high but drops
> > > > rapidly to almost nothing or absolutely nothing.      
> > > 
> > > We also met this issue on some berlin platforms. I tried to fix
> > > the bug, but no clue so far.
> > >     
> > > > 
> > > > This is fixed when using netif_receive_skb instead of
> > > > napi_gro_receive.      
> > > 
> > > This is a workaround. The good news is this workaround also fixes
> > > the issue we saw on berlin.
> > >     
> > > > 
> > > > Signed-off-by: Marek Behun <marek.behun@nic.cz>
> > > > Cc: Russell King - ARM Linux <linux@armlinux.org.uk>
> > > > Cc: netdev@vger.kernel.org
> > > > 
> > > > diff --git a/drivers/net/ethernet/marvell/mvneta.c
> > > > b/drivers/net/ethernet/marvell/mvneta.c index
> > > > 0ad2f3f7da85..27f3017d94c5 100644 ---
> > > > a/drivers/net/ethernet/marvell/mvneta.c +++
> > > > b/drivers/net/ethernet/marvell/mvneta.c @@ -1959,7 +1959,10 @@
> > > > static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo, 
> > > >  			skb->protocol = eth_type_trans(skb,
> > > > dev); mvneta_rx_csum(pp, rx_status, skb);
> > > > -			napi_gro_receive(&port->napi, skb);
> > > > +			if (pp->neta_armada3700)
> > > > +				netif_receive_skb(skb);
> > > > +			else
> > > > +				napi_gro_receive(&port->napi,
> > > > skb);    
> > 
> > I think I found the root cause, if neta_armada3700 is true, the
> > port got from this_cpu_ptr(pp->ports) is invalid, this is bug...
> > I'll cook a patch for this  
> 
> correct it as:
> 
> the port's(port is got from this_cpu_ptr(pp->ports) napi is invalid.
> 
> Patch is sent out. Could you please try?
> 
> Per my test, it solves the issue we saw on berlin.
> 
> > 
> > Thanks
> >   
> > > >  
> > > >  			rcvd_pkts++;
> > > >  			rcvd_bytes += rx_bytes;
> > > > @@ -2001,7 +2004,10 @@ static int mvneta_rx_swbm(struct
> > > > mvneta_port *pp, int rx_todo, 
> > > >  		mvneta_rx_csum(pp, rx_status, skb);
> > > >  
> > > > -		napi_gro_receive(&port->napi, skb);
> > > > +		if (pp->neta_armada3700)
> > > > +			netif_receive_skb(skb);
> > > > +		else
> > > > +			napi_gro_receive(&port->napi, skb);
> > > >  	}
> > > >  
> > > >  	if (rcvd_pkts) {      
> > >     
> >   
> 

Jisheng, the issue is solved with your patch. Thanks :)

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

* [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720
@ 2018-08-21 10:07           ` Marek Behún
  0 siblings, 0 replies; 25+ messages in thread
From: Marek Behún @ 2018-08-21 10:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 9 Aug 2018 20:08:32 +0800
Jisheng Zhang <Jisheng.Zhang@synaptics.com> wrote:

> On Thu, 9 Aug 2018 19:27:55 +0800 Jisheng Zhang wrote:
> 
> > Hi,
> > 
> > On Thu, 9 Aug 2018 12:40:41 +0800 Jisheng Zhang wrote:
> >   
> > > + more people
> > > 
> > > On Wed,  8 Aug 2018 17:27:05 +0200 Marek Beh?n wrote:
> > >     
> > > > For some reason on Armada 3720 boards (EspressoBin and Turris
> > > > Mox) the networking driver behaves weirdly when using
> > > > napi_gro_receive.
> > > > 
> > > > For example downloading a big file from a local network (low
> > > > ping) is fast, but when downloading from a remote server
> > > > (higher ping), the download speed is at first high but drops
> > > > rapidly to almost nothing or absolutely nothing.      
> > > 
> > > We also met this issue on some berlin platforms. I tried to fix
> > > the bug, but no clue so far.
> > >     
> > > > 
> > > > This is fixed when using netif_receive_skb instead of
> > > > napi_gro_receive.      
> > > 
> > > This is a workaround. The good news is this workaround also fixes
> > > the issue we saw on berlin.
> > >     
> > > > 
> > > > Signed-off-by: Marek Behun <marek.behun@nic.cz>
> > > > Cc: Russell King - ARM Linux <linux@armlinux.org.uk>
> > > > Cc: netdev at vger.kernel.org
> > > > 
> > > > diff --git a/drivers/net/ethernet/marvell/mvneta.c
> > > > b/drivers/net/ethernet/marvell/mvneta.c index
> > > > 0ad2f3f7da85..27f3017d94c5 100644 ---
> > > > a/drivers/net/ethernet/marvell/mvneta.c +++
> > > > b/drivers/net/ethernet/marvell/mvneta.c @@ -1959,7 +1959,10 @@
> > > > static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo, 
> > > >  			skb->protocol = eth_type_trans(skb,
> > > > dev); mvneta_rx_csum(pp, rx_status, skb);
> > > > -			napi_gro_receive(&port->napi, skb);
> > > > +			if (pp->neta_armada3700)
> > > > +				netif_receive_skb(skb);
> > > > +			else
> > > > +				napi_gro_receive(&port->napi,
> > > > skb);    
> > 
> > I think I found the root cause, if neta_armada3700 is true, the
> > port got from this_cpu_ptr(pp->ports) is invalid, this is bug...
> > I'll cook a patch for this  
> 
> correct it as:
> 
> the port's(port is got from this_cpu_ptr(pp->ports) napi is invalid.
> 
> Patch is sent out. Could you please try?
> 
> Per my test, it solves the issue we saw on berlin.
> 
> > 
> > Thanks
> >   
> > > >  
> > > >  			rcvd_pkts++;
> > > >  			rcvd_bytes += rx_bytes;
> > > > @@ -2001,7 +2004,10 @@ static int mvneta_rx_swbm(struct
> > > > mvneta_port *pp, int rx_todo, 
> > > >  		mvneta_rx_csum(pp, rx_status, skb);
> > > >  
> > > > -		napi_gro_receive(&port->napi, skb);
> > > > +		if (pp->neta_armada3700)
> > > > +			netif_receive_skb(skb);
> > > > +		else
> > > > +			napi_gro_receive(&port->napi, skb);
> > > >  	}
> > > >  
> > > >  	if (rcvd_pkts) {      
> > >     
> >   
> 

Jisheng, the issue is solved with your patch. Thanks :)

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

end of thread, other threads:[~2018-08-21 13:29 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-08 15:26 [PATCH v1 0/7] Add support for the Turris Mox router Marek Behún
2018-08-08 15:27 ` [PATCH v1 1/7] From: Ken Ma <make@marvell.com> Marek Behún
2018-08-08 16:49   ` Andrew Lunn
2018-08-08 15:27 ` [PATCH v1 2/7] drivers: mfd: Add support for Moxtet bus Marek Behún
2018-08-08 15:32   ` Marek Behún
2018-08-08 15:27 ` [PATCH v1 3/7] drivers: gpio: Add support for Turris Mox SFP GPIOs Marek Behún
2018-08-08 16:55   ` Andrew Lunn
2018-08-08 20:40     ` Marek Behun
2018-08-08 15:27 ` [PATCH v1 4/7] watchdog: Add support for Armada 37xx CPU watchdog Marek Behún
2018-08-08 15:27 ` [PATCH v1 5/7] arm64: dts: marvell: armada-37xx: add nodes to support watchdog Marek Behún
2018-08-08 15:27 ` [PATCH v1 6/7] net: mvneta: Don't use GRO on Armada 3720 Marek Behún
2018-08-08 15:27   ` Marek Behún
2018-08-08 16:58   ` Andrew Lunn
2018-08-08 16:58     ` Andrew Lunn
2018-08-08 17:57     ` Dave Taht
2018-08-08 17:57       ` Dave Taht
2018-08-09  4:40   ` Jisheng Zhang
2018-08-09  4:40     ` Jisheng Zhang
2018-08-09 11:27     ` Jisheng Zhang
2018-08-09 11:27       ` Jisheng Zhang
2018-08-09 12:08       ` Jisheng Zhang
2018-08-09 12:08         ` Jisheng Zhang
2018-08-21 10:07         ` Marek Behún
2018-08-21 10:07           ` Marek Behún
2018-08-08 15:27 ` [PATCH v1 7/7] ARM64: dts: marvell: Add DTS files for Turris Mox Marek Behún

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.