Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V5 04/13] boot_constraint: Add support for supply constraints
From: Viresh Kumar @ 2017-12-14 15:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1513264961.git.viresh.kumar@linaro.org>

This patch adds the first constraint type: power-supply.

The constraint is set by enabling the regulator and setting a voltage
range (if required) for the respective regulator device, which will be
honored by the regulator core even if more users turn up. Once the
device is probed, the regulator is released and the constraint is
removed.

Tested-by: Rajendra Nayak <rnayak@codeaurora.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/boot_constraint/Makefile |  2 +-
 drivers/boot_constraint/core.c   |  4 ++
 drivers/boot_constraint/core.h   |  5 +++
 drivers/boot_constraint/supply.c | 95 ++++++++++++++++++++++++++++++++++++++++
 include/linux/boot_constraint.h  | 17 ++++++-
 5 files changed, 121 insertions(+), 2 deletions(-)
 create mode 100644 drivers/boot_constraint/supply.c

diff --git a/drivers/boot_constraint/Makefile b/drivers/boot_constraint/Makefile
index 0f2680177974..a45616f0c3b0 100644
--- a/drivers/boot_constraint/Makefile
+++ b/drivers/boot_constraint/Makefile
@@ -1,3 +1,3 @@
 # Makefile for device boot constraints
 
-obj-y := core.o
+obj-y := core.o supply.o
diff --git a/drivers/boot_constraint/core.c b/drivers/boot_constraint/core.c
index 45a0fbed1b11..63a4b1a2fa2c 100644
--- a/drivers/boot_constraint/core.c
+++ b/drivers/boot_constraint/core.c
@@ -91,6 +91,10 @@ static struct constraint *constraint_allocate(struct constraint_dev *cdev,
 	void (*remove)(struct constraint *constraint);
 
 	switch (type) {
+	case DEV_BOOT_CONSTRAINT_SUPPLY:
+		add = constraint_supply_add;
+		remove = constraint_supply_remove;
+		break;
 	default:
 		return ERR_PTR(-EINVAL);
 	}
diff --git a/drivers/boot_constraint/core.h b/drivers/boot_constraint/core.h
index 1e87125de531..d0d3e7bf7d57 100644
--- a/drivers/boot_constraint/core.h
+++ b/drivers/boot_constraint/core.h
@@ -27,4 +27,9 @@ struct constraint {
 	void (*remove)(struct constraint *constraint);
 	void *private;
 };
+
+/* Forward declarations of constraint specific callbacks */
+int constraint_supply_add(struct constraint *constraint, void *data);
+void constraint_supply_remove(struct constraint *constraint);
+
 #endif /* _CORE_H */
diff --git a/drivers/boot_constraint/supply.c b/drivers/boot_constraint/supply.c
new file mode 100644
index 000000000000..916e5d6848d5
--- /dev/null
+++ b/drivers/boot_constraint/supply.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Linaro.
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ */
+
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include "core.h"
+
+struct constraint_supply {
+	struct dev_boot_constraint_supply_info supply;
+	struct regulator *reg;
+};
+
+int constraint_supply_add(struct constraint *constraint, void *data)
+{
+	struct dev_boot_constraint_supply_info *supply = data;
+	struct constraint_supply *csupply;
+	struct device *dev = constraint->cdev->dev;
+	int ret;
+
+	csupply = kzalloc(sizeof(*csupply), GFP_KERNEL);
+	if (!csupply)
+		return -ENOMEM;
+
+	csupply->reg = regulator_get(dev, supply->name);
+	if (IS_ERR(csupply->reg)) {
+		ret = PTR_ERR(csupply->reg);
+		if (ret != -EPROBE_DEFER) {
+			dev_err(dev, "regulator_get() failed for %s (%d)\n",
+				supply->name, ret);
+		}
+		goto free;
+	}
+
+	if (supply->u_volt_min != 0 && supply->u_volt_max != 0) {
+		ret = regulator_set_voltage(csupply->reg, supply->u_volt_min,
+					    supply->u_volt_max);
+		if (ret) {
+			dev_err(dev, "regulator_set_voltage %s failed (%d)\n",
+				supply->name, ret);
+			goto free_regulator;
+		}
+	}
+
+	ret = regulator_enable(csupply->reg);
+	if (ret) {
+		dev_err(dev, "regulator_enable %s failed (%d)\n",
+			supply->name, ret);
+		goto remove_voltage;
+	}
+
+	memcpy(&csupply->supply, supply, sizeof(*supply));
+	csupply->supply.name = kstrdup_const(supply->name, GFP_KERNEL);
+	constraint->private = csupply;
+
+	return 0;
+
+remove_voltage:
+	if (supply->u_volt_min != 0 && supply->u_volt_max != 0)
+		regulator_set_voltage(csupply->reg, 0, INT_MAX);
+free_regulator:
+	regulator_put(csupply->reg);
+free:
+	kfree(csupply);
+
+	return ret;
+}
+
+void constraint_supply_remove(struct constraint *constraint)
+{
+	struct constraint_supply *csupply = constraint->private;
+	struct dev_boot_constraint_supply_info *supply = &csupply->supply;
+	struct device *dev = constraint->cdev->dev;
+	int ret;
+
+	kfree_const(supply->name);
+
+	ret = regulator_disable(csupply->reg);
+	if (ret)
+		dev_err(dev, "regulator_disable failed (%d)\n", ret);
+
+	if (supply->u_volt_min != 0 && supply->u_volt_max != 0) {
+		ret = regulator_set_voltage(csupply->reg, 0, INT_MAX);
+		if (ret)
+			dev_err(dev, "regulator_set_voltage failed (%d)\n",
+				ret);
+	}
+
+	regulator_put(csupply->reg);
+	kfree(csupply);
+}
diff --git a/include/linux/boot_constraint.h b/include/linux/boot_constraint.h
index 2ce62b7b3cc6..1db24d53b622 100644
--- a/include/linux/boot_constraint.h
+++ b/include/linux/boot_constraint.h
@@ -16,9 +16,24 @@ struct device;
 /**
  * enum dev_boot_constraint_type - This defines different boot constraint types.
  *
+ * @DEV_BOOT_CONSTRAINT_SUPPLY: This represents a power supply boot constraint.
  */
 enum dev_boot_constraint_type {
-	DEV_BOOT_CONSTRAINT_NONE,
+	DEV_BOOT_CONSTRAINT_SUPPLY,
+};
+
+/**
+ * struct dev_boot_constraint_supply_info - Power supply boot constraint
+ * information.
+ *
+ * @name: This must match the power supply name for the device.
+ * @u_volt_min: This is the minimum microvolts value supported by the device.
+ * @u_volt_max: This is the maximum microvolts value supported by the device.
+ */
+struct dev_boot_constraint_supply_info {
+	const char *name;
+	unsigned int u_volt_min;
+	unsigned int u_volt_max;
 };
 
 /**
-- 
2.15.0.194.g9af6a3dea062

^ permalink raw reply related

* [PATCH V5 03/13] drivers: Add boot constraints core
From: Viresh Kumar @ 2017-12-14 15:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1513264961.git.viresh.kumar@linaro.org>

Some devices are powered ON by the bootloader before the bootloader
handovers control to Linux. It maybe important for those devices to keep
working until the time a Linux device driver probes the device and
reconfigure its resources.

A typical example of that can be the LCD controller, which is used by
the bootloaders to show image(s) while the platform is booting into
Linux. The LCD controller can be using some resources, like clk,
regulators, PM domain, etc, that are shared between several devices.
These shared resources should be configured to satisfy need of all the
users. If another device's (X) driver gets probed before the LCD
controller driver in this case, then it may end up reconfiguring these
resources to ranges satisfying the current users (only device X) and
that can make the LCD screen unstable.

This patch introduces the concept of boot-constraints, which will be set
by the bootloaders and the kernel will satisfy them until the time
driver for such a device is probed (successfully or unsuccessfully).

The list of boot constraint types is empty for now, and will be
incrementally updated by later patches.

Only two routines are exposed by the boot constraints core for now:

- dev_boot_constraint_add(): This shall be called by parts of the kernel
  (before the device is probed) to set the constraints.

- dev_boot_constraints_remove(): This is called only by the driver core
  after a device is probed successfully or unsuccessfully. Special
  handling is done here for deferred probing.

Tested-by: Rajendra Nayak <rnayak@codeaurora.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/Kconfig                  |   2 +
 drivers/Makefile                 |   1 +
 drivers/base/dd.c                |  20 ++--
 drivers/boot_constraint/Kconfig  |   9 ++
 drivers/boot_constraint/Makefile |   3 +
 drivers/boot_constraint/core.c   | 219 +++++++++++++++++++++++++++++++++++++++
 drivers/boot_constraint/core.h   |  30 ++++++
 include/linux/boot_constraint.h  |  66 ++++++++++++
 8 files changed, 343 insertions(+), 7 deletions(-)
 create mode 100644 drivers/boot_constraint/Kconfig
 create mode 100644 drivers/boot_constraint/Makefile
 create mode 100644 drivers/boot_constraint/core.c
 create mode 100644 drivers/boot_constraint/core.h
 create mode 100644 include/linux/boot_constraint.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index ef5fb8395d76..87ec868c74c5 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -5,6 +5,8 @@ source "drivers/amba/Kconfig"
 
 source "drivers/base/Kconfig"
 
+source "drivers/boot_constraint/Kconfig"
+
 source "drivers/bus/Kconfig"
 
 source "drivers/connector/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 7a2330077e47..7fd71b658aa7 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_FB_INTEL)          += video/fbdev/intelfb/
 obj-$(CONFIG_PARPORT)		+= parport/
 obj-$(CONFIG_NVM)		+= lightnvm/
 obj-y				+= base/ block/ misc/ mfd/ nfc/
+obj-$(CONFIG_DEV_BOOT_CONSTRAINT) += boot_constraint/
 obj-$(CONFIG_LIBNVDIMM)		+= nvdimm/
 obj-$(CONFIG_DAX)		+= dax/
 obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 533c82f55cea..dc89f98a2487 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -16,6 +16,7 @@
  * Copyright (c) 2007-2009 Novell Inc.
  */
 
+#include <linux/boot_constraint.h>
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
@@ -419,15 +420,20 @@ static int really_probe(struct device *dev, struct device_driver *drv)
 	 */
 	devices_kset_move_last(dev);
 
-	if (dev->bus->probe) {
+	if (dev->bus->probe)
 		ret = dev->bus->probe(dev);
-		if (ret)
-			goto probe_failed;
-	} else if (drv->probe) {
+	else if (drv->probe)
 		ret = drv->probe(dev);
-		if (ret)
-			goto probe_failed;
-	}
+
+	/*
+	 * Remove boot constraints for both successful and unsuccessful probe(),
+	 * except for the case where EPROBE_DEFER is returned by probe().
+	 */
+	if (ret != -EPROBE_DEFER)
+		dev_boot_constraints_remove(dev);
+
+	if (ret)
+		goto probe_failed;
 
 	if (test_remove) {
 		test_remove = false;
diff --git a/drivers/boot_constraint/Kconfig b/drivers/boot_constraint/Kconfig
new file mode 100644
index 000000000000..9195f9a39fe2
--- /dev/null
+++ b/drivers/boot_constraint/Kconfig
@@ -0,0 +1,9 @@
+config DEV_BOOT_CONSTRAINT
+	bool "Boot constraints for devices"
+	help
+	  This enables boot constraints detection for devices. These constraints
+	  are (normally) set by the Bootloader and must be satisfied by the
+	  kernel until the relevant device driver is probed. Once the driver is
+	  probed, the constraint is dropped.
+
+	  If unsure, say N.
diff --git a/drivers/boot_constraint/Makefile b/drivers/boot_constraint/Makefile
new file mode 100644
index 000000000000..0f2680177974
--- /dev/null
+++ b/drivers/boot_constraint/Makefile
@@ -0,0 +1,3 @@
+# Makefile for device boot constraints
+
+obj-y := core.o
diff --git a/drivers/boot_constraint/core.c b/drivers/boot_constraint/core.c
new file mode 100644
index 000000000000..45a0fbed1b11
--- /dev/null
+++ b/drivers/boot_constraint/core.c
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This takes care of boot time device constraints, normally set by the
+ * Bootloader.
+ *
+ * Copyright (C) 2017 Linaro.
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ */
+
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include "core.h"
+
+#define for_each_constraint(_constraint, _temp, _cdev)		\
+	list_for_each_entry_safe(_constraint, _temp, &_cdev->constraints, node)
+
+/* Global list of all constraint devices currently registered */
+static LIST_HEAD(constraint_devices);
+static DEFINE_MUTEX(constraint_devices_mutex);
+
+/* Boot constraints core */
+
+static struct constraint_dev *constraint_device_find(struct device *dev)
+{
+	struct constraint_dev *cdev;
+
+	list_for_each_entry(cdev, &constraint_devices, node) {
+		if (cdev->dev == dev)
+			return cdev;
+	}
+
+	return NULL;
+}
+
+static struct constraint_dev *constraint_device_allocate(struct device *dev)
+{
+	struct constraint_dev *cdev;
+
+	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+	if (!cdev)
+		return ERR_PTR(-ENOMEM);
+
+	cdev->dev = dev;
+	INIT_LIST_HEAD(&cdev->node);
+	INIT_LIST_HEAD(&cdev->constraints);
+
+	list_add(&cdev->node, &constraint_devices);
+
+	return cdev;
+}
+
+static void constraint_device_free(struct constraint_dev *cdev)
+{
+	list_del(&cdev->node);
+	kfree(cdev);
+}
+
+static struct constraint_dev *constraint_device_get(struct device *dev)
+{
+	struct constraint_dev *cdev;
+
+	cdev = constraint_device_find(dev);
+	if (cdev)
+		return cdev;
+
+	cdev = constraint_device_allocate(dev);
+	if (IS_ERR(cdev)) {
+		dev_err(dev, "Failed to add constraint dev (%ld)\n",
+			PTR_ERR(cdev));
+	}
+
+	return cdev;
+}
+
+static void constraint_device_put(struct constraint_dev *cdev)
+{
+	if (!list_empty(&cdev->constraints))
+		return;
+
+	constraint_device_free(cdev);
+}
+
+static struct constraint *constraint_allocate(struct constraint_dev *cdev,
+					enum dev_boot_constraint_type type)
+{
+	struct constraint *constraint;
+	int (*add)(struct constraint *constraint, void *data);
+	void (*remove)(struct constraint *constraint);
+
+	switch (type) {
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+
+	constraint = kzalloc(sizeof(*constraint), GFP_KERNEL);
+	if (!constraint)
+		return ERR_PTR(-ENOMEM);
+
+	constraint->cdev = cdev;
+	constraint->type = type;
+	constraint->add = add;
+	constraint->remove = remove;
+	INIT_LIST_HEAD(&constraint->node);
+
+	list_add(&constraint->node, &cdev->constraints);
+
+	return constraint;
+}
+
+static void constraint_free(struct constraint *constraint)
+{
+	list_del(&constraint->node);
+	kfree(constraint);
+}
+
+/**
+ * dev_boot_constraint_add: Adds a boot constraint.
+ *
+ * @dev: Device for which the boot constraint is getting added.
+ * @info: Structure representing the boot constraint.
+ *
+ * This routine adds a single boot constraint for the device. This must be
+ * called before the device is probed by its driver, otherwise the boot
+ * constraint will never get removed and may result in unwanted behavior of the
+ * hardware. The boot constraint is removed by the driver core automatically
+ * after the device is probed (successfully or unsuccessfully).
+ *
+ * Return: 0 on success, and a negative error otherwise.
+ */
+int dev_boot_constraint_add(struct device *dev,
+			    struct dev_boot_constraint_info *info)
+{
+	struct constraint_dev *cdev;
+	struct constraint *constraint;
+	int ret;
+
+	mutex_lock(&constraint_devices_mutex);
+
+	/* Find or add the cdev type first */
+	cdev = constraint_device_get(dev);
+	if (IS_ERR(cdev)) {
+		ret = PTR_ERR(cdev);
+		goto unlock;
+	}
+
+	constraint = constraint_allocate(cdev, info->constraint.type);
+	if (IS_ERR(constraint)) {
+		dev_err(dev, "Failed to add constraint type: %d (%ld)\n",
+			info->constraint.type, PTR_ERR(constraint));
+		ret = PTR_ERR(constraint);
+		goto put_cdev;
+	}
+
+	constraint->free_resources = info->free_resources;
+	constraint->free_resources_data = info->free_resources_data;
+
+	/* Set constraint */
+	ret = constraint->add(constraint, info->constraint.data);
+	if (ret)
+		goto free_constraint;
+
+	dev_dbg(dev, "Added boot constraint-type (%d)\n",
+		info->constraint.type);
+
+	mutex_unlock(&constraint_devices_mutex);
+
+	return 0;
+
+free_constraint:
+	constraint_free(constraint);
+put_cdev:
+	constraint_device_put(cdev);
+unlock:
+	mutex_unlock(&constraint_devices_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_boot_constraint_add);
+
+static void constraint_remove(struct constraint *constraint)
+{
+	constraint->remove(constraint);
+
+	if (constraint->free_resources)
+		constraint->free_resources(constraint->free_resources_data);
+
+	constraint_free(constraint);
+}
+
+/**
+ * dev_boot_constraints_remove: Removes all boot constraints of a device.
+ *
+ * @dev: Device for which the boot constraints are getting removed.
+ *
+ * This routine removes all the boot constraints that were previously added for
+ * the device. This is called directly by the driver core and should not be
+ * called by platform specific code.
+ */
+void dev_boot_constraints_remove(struct device *dev)
+{
+	struct constraint_dev *cdev;
+	struct constraint *constraint, *temp;
+
+	mutex_lock(&constraint_devices_mutex);
+
+	cdev = constraint_device_find(dev);
+	if (!cdev)
+		goto unlock;
+
+	for_each_constraint(constraint, temp, cdev)
+		constraint_remove(constraint);
+
+	constraint_device_put(cdev);
+unlock:
+	mutex_unlock(&constraint_devices_mutex);
+}
diff --git a/drivers/boot_constraint/core.h b/drivers/boot_constraint/core.h
new file mode 100644
index 000000000000..1e87125de531
--- /dev/null
+++ b/drivers/boot_constraint/core.h
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Linaro.
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ */
+#ifndef _CORE_H
+#define _CORE_H
+
+#include <linux/boot_constraint.h>
+#include <linux/device.h>
+#include <linux/list.h>
+
+struct constraint_dev {
+	struct device *dev;
+	struct list_head node;
+	struct list_head constraints;
+};
+
+struct constraint {
+	struct constraint_dev *cdev;
+	struct list_head node;
+	enum dev_boot_constraint_type type;
+	void (*free_resources)(void *data);
+	void *free_resources_data;
+
+	int (*add)(struct constraint *constraint, void *data);
+	void (*remove)(struct constraint *constraint);
+	void *private;
+};
+#endif /* _CORE_H */
diff --git a/include/linux/boot_constraint.h b/include/linux/boot_constraint.h
new file mode 100644
index 000000000000..2ce62b7b3cc6
--- /dev/null
+++ b/include/linux/boot_constraint.h
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Boot constraints header.
+ *
+ * Copyright (C) 2017 Linaro.
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ */
+#ifndef _LINUX_BOOT_CONSTRAINT_H
+#define _LINUX_BOOT_CONSTRAINT_H
+
+#include <linux/err.h>
+#include <linux/types.h>
+
+struct device;
+
+/**
+ * enum dev_boot_constraint_type - This defines different boot constraint types.
+ *
+ */
+enum dev_boot_constraint_type {
+	DEV_BOOT_CONSTRAINT_NONE,
+};
+
+/**
+ * struct dev_boot_constraint - This represents a single boot constraint.
+ *
+ * @type: This is boot constraint type (like: clk, supply, etc.).
+ * @data: This points to constraint type specific data (like:
+ * dev_boot_constraint_clk_info).
+ */
+struct dev_boot_constraint {
+	enum dev_boot_constraint_type type;
+	void *data;
+};
+
+/**
+ * struct dev_boot_constraint_info - This is used to add a single boot
+ * constraint.
+ *
+ * @constraint: This represents a single boot constraint.
+ * @free_resources: This callback is called by the boot constraint core after
+ * the constraint is removed. This is an optional field.
+ * @free_resources_data: This is data to be passed to free_resources() callback.
+ * This is an optional field.
+ */
+struct dev_boot_constraint_info {
+	struct dev_boot_constraint constraint;
+
+	/* This will be called just before the constraint is removed */
+	void (*free_resources)(void *data);
+	void *free_resources_data;
+};
+
+#ifdef CONFIG_DEV_BOOT_CONSTRAINT
+int dev_boot_constraint_add(struct device *dev,
+			    struct dev_boot_constraint_info *info);
+void dev_boot_constraints_remove(struct device *dev);
+#else
+static inline
+int dev_boot_constraint_add(struct device *dev,
+			    struct dev_boot_constraint_info *info)
+{ return 0; }
+static inline void dev_boot_constraints_remove(struct device *dev) {}
+#endif /* CONFIG_DEV_BOOT_CONSTRAINT */
+
+#endif /* _LINUX_BOOT_CONSTRAINT_H */
-- 
2.15.0.194.g9af6a3dea062

^ permalink raw reply related

* [PATCH V5 02/13] of: platform: Make of_platform_bus_create() global
From: Viresh Kumar @ 2017-12-14 15:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1513264961.git.viresh.kumar@linaro.org>

The boot constraints core needs to create platform or AMBA devices
corresponding to a compatible string and not for rest of the nodes in
DT. of_platform_bus_create() fits in the best to achieve that.

Allow it to be used outside of platform.c.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/of/platform.c       |  8 ++++----
 include/linux/of_platform.h | 11 +++++++++++
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 61a4a81bea9f..6f707bfb348f 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -397,10 +397,10 @@ static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *l
  * Creates a platform_device for the provided device_node, and optionally
  * recursively create devices for all the child nodes.
  */
-static int of_platform_bus_create(struct device_node *bus,
-				  const struct of_device_id *matches,
-				  const struct of_dev_auxdata *lookup,
-				  struct device *parent, bool strict)
+int of_platform_bus_create(struct device_node *bus,
+			   const struct of_device_id *matches,
+			   const struct of_dev_auxdata *lookup,
+			   struct device *parent, bool strict)
 {
 	const struct of_dev_auxdata *auxdata;
 	struct device_node *child;
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index 4909d1aa47ec..511a59fb8e15 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -77,6 +77,10 @@ extern struct platform_device *of_platform_device_create(struct device_node *np,
 						   struct device *parent);
 
 extern int of_platform_device_destroy(struct device *dev, void *data);
+extern int of_platform_bus_create(struct device_node *bus,
+				  const struct of_device_id *matches,
+				  const struct of_dev_auxdata *lookup,
+				  struct device *parent, bool strict);
 extern int of_platform_bus_probe(struct device_node *root,
 				 const struct of_device_id *matches,
 				 struct device *parent);
@@ -94,6 +98,13 @@ extern int devm_of_platform_populate(struct device *dev);
 
 extern void devm_of_platform_depopulate(struct device *dev);
 #else
+static inline int of_platform_bus_create(struct device_node *bus,
+					 const struct of_device_id *matches,
+					 const struct of_dev_auxdata *lookup,
+					 struct device *parent, bool strict)
+{
+	return -ENODEV;
+}
 static inline int of_platform_populate(struct device_node *root,
 					const struct of_device_id *matches,
 					const struct of_dev_auxdata *lookup,
-- 
2.15.0.194.g9af6a3dea062

^ permalink raw reply related

* [PATCH V5 01/13] of: platform: Add of_find_any_device_by_node()
From: Viresh Kumar @ 2017-12-14 15:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1513264961.git.viresh.kumar@linaro.org>

This creates a new helper that returns the struct device corresponding
to a struct device_node. This currently works only for amba and platform
devices, but can be easily extended to include other bus types.

This also creates an internal of_find_amba_device_by_node() helper,
which isn't exported as of now.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/of/platform.c       | 55 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_platform.h |  5 +++++
 2 files changed, 60 insertions(+)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index b7cf84b29737..61a4a81bea9f 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -60,6 +60,61 @@ struct platform_device *of_find_device_by_node(struct device_node *np)
 }
 EXPORT_SYMBOL(of_find_device_by_node);
 
+#ifdef CONFIG_ARM_AMBA
+/**
+ * of_find_amba_device_by_node - Find the amba_device associated with a node
+ * @np: Pointer to device tree node
+ *
+ * Takes a reference to the embedded struct device which needs to be dropped
+ * after use.
+ *
+ * Returns amba_device pointer, or NULL if not found
+ */
+static struct amba_device *of_find_amba_device_by_node(struct device_node *np)
+{
+	struct device *dev;
+
+	dev = bus_find_device(&amba_bustype, NULL, np, of_dev_node_match);
+	return dev ? to_amba_device(dev) : NULL;
+}
+#else
+static inline struct amba_device *of_find_amba_device_by_node(struct device_node *np)
+{
+	return NULL;
+}
+#endif
+
+/**
+ * of_find_any_device_by_node - Find the struct device associated with a node
+ * @np: Pointer to device tree node
+ *
+ * Takes a reference to the embedded struct device which needs to be dropped
+ * after use.
+ *
+ * This currently supports only AMBA and platform devices.
+ *
+ * Returns struct device pointer, or NULL if not found
+ */
+struct device *of_find_any_device_by_node(struct device_node *np)
+{
+	struct device *dev = NULL;
+
+	if (of_device_is_compatible(np, "arm,primecell")) {
+		struct amba_device *adev = of_find_amba_device_by_node(np);
+
+		if (adev)
+			dev = &adev->dev;
+	} else {
+		struct platform_device *pdev = of_find_device_by_node(np);
+
+		if (pdev)
+			dev = &pdev->dev;
+	}
+
+	return dev;
+}
+EXPORT_SYMBOL(of_find_any_device_by_node);
+
 #ifdef CONFIG_OF_ADDRESS
 /*
  * The following routines scan a subtree and registers a device for
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index fb908e598348..4909d1aa47ec 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -59,11 +59,16 @@ extern struct platform_device *of_device_alloc(struct device_node *np,
 					 struct device *parent);
 #ifdef CONFIG_OF
 extern struct platform_device *of_find_device_by_node(struct device_node *np);
+extern struct device *of_find_any_device_by_node(struct device_node *np);
 #else
 static inline struct platform_device *of_find_device_by_node(struct device_node *np)
 {
 	return NULL;
 }
+static inline struct device *of_find_any_device_by_node(struct device_node *np)
+{
+	return NULL;
+}
 #endif
 
 /* Platform devices and busses creation */
-- 
2.15.0.194.g9af6a3dea062

^ permalink raw reply related

* [PATCH V5 00/13] drivers: Boot Constraint core
From: Viresh Kumar @ 2017-12-14 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Greg,

Here is V5 of the boot constraints core based on your feedback from V4.
Hope this looks better now :)

I have tested the Hisilicon patches (again) on hikey 9660 board, IMX
stuff was earlier tested by Sascha (Pengutronix) on i.MX6 and Qualcomm
stuff was earlier tested by Rajendra (Qualcomm) on Dragonboard 410C
(This required some more patches related to display driver which
Rajendra should be sending separately later on).


Problem statement:

Some devices are powered ON by the bootloader before the bootloader
handovers control to Linux. It maybe important for those devices to keep
working until the time a Linux device driver probes the device and
reconfigure its resources.

A typical example of that can be the LCD controller, which is used by
the bootloaders to show image(s) while the platform is booting into
Linux.  The LCD controller can be using some resources, like clk,
regulators, etc, that are shared between several devices. These shared
resources should be configured to satisfy need of all the users.  If
another device's (X) driver gets probed before the LCD controller driver
in this case, then it may end up disabling or reconfiguring these
resources to ranges satisfying the current users (only device X) and
that can make the LCD screen unstable.

Another case can be a debug serial port enabled from the bootloader.

Of course we can have more complex cases where the same resource is
getting used by two devices while the kernel boots and the order in
which devices get probed wouldn't matter as the other device will surely
break then.

There are also cases where the resources may not be shared, but the
kernel will disable them forcefully as no users may have appeared until
a certain point in kernel boot. This makes sure that the resources stay
enabled. A wide variety of constraints can be satisfied using the new
framework.

Proposed solution:

This series introduces the concept of "boot-constraint", which are set
by platform specific drivers (for now at least) at early init (like
subsys_initcall) and the kernel will keep satisfying them until the time
driver for such a device is probed (successfully or unsuccessfully).
Once the driver is probed, the driver core removes the constraints set
for the device. This series implements clk, regulator and PM domain
constraints currently.

Targeted for: v4.16

Pushed here:
git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/linux.git boot-constraints

V4->V5:
- SPDX Licence format used.
- arm,primecell stuff removed from boot constraint core and added a
  helper in OF core (which already handles amba and platform devices).
- Removed a bunch of BUG_ON(), pr_fmt(), comments.
- Changed directory and other names from
  boot_constraints/boot_constraint.
- Removed serial.o file and moved the code to hikey and imx files.
- Don't return error from dummy helper.
- Added documentation and corresponding kernel doc comments in the code.
- Updated MAINTAINERS.

V3->V4:
- Added support for imx, hikey and Qcom usecases.
- Enhanced boot constraints core to make drivers code easy and handle
  complex cases.
- Two new patches for OF included to provide APIs to boot constraint
  core.
- Removed the kernel parameter patch for now.
- Don't check return values of debugfs routines.
- Moved the boot constraints core from drivers/base/ to drivers/.

V2->V3:
- Removed DT support as we aren't sure about how to define the bindings
  yet.
- Added CLK and PM domain constraint types.
- A new directory is added for boot constraints, which will also contain
  platform specific drivers in future.
- Deferred devices are still supported, just that it wouldn't be called
  from generic code anymore but platform specific code.
- Tested on Qcom 410c dragonboard with display flash screen (Rajendra).
- Usual renaming/commit-log-updates/etc changes done.

V1->V2:
- Add support for setting constraints for devices created from DT.
- Allow handling deferred devices earlier then late_init.
- Remove 'default y' line from kconfig.
- Drop '=" after boot_constraints_disable kernel param.
- Dropped the dummy testing patch now.

--
viresh

Rajendra Nayak (1):
  boot_constraint: Add Qualcomm display controller constraints

Viresh Kumar (12):
  of: platform: Add of_find_any_device_by_node()
  of: platform: Make of_platform_bus_create() global
  drivers: Add boot constraints core
  boot_constraint: Add support for supply constraints
  boot_constraint: Add support for clk constraints
  boot_constraint: Add support for PM constraints
  boot_constraint: Add debugfs support
  boot_constraint: Manage deferrable constraints
  boot_constraint: Add support for Hisilicon platforms
  boot_constraint: Add support for IMX platform
  boot_constraint: Update MAINTAINERS
  boot_constraint: Add documentation

 .../driver-api/boot-constraint/constraints.rst     |  98 +++++++
 Documentation/driver-api/boot-constraint/index.rst |   4 +
 Documentation/driver-api/index.rst                 |   1 +
 MAINTAINERS                                        |   9 +
 arch/arm/mach-imx/Kconfig                          |   1 +
 arch/arm64/Kconfig.platforms                       |   2 +
 drivers/Kconfig                                    |   2 +
 drivers/Makefile                                   |   1 +
 drivers/base/dd.c                                  |  32 ++-
 drivers/boot_constraint/Kconfig                    |   9 +
 drivers/boot_constraint/Makefile                   |   7 +
 drivers/boot_constraint/clk.c                      |  70 +++++
 drivers/boot_constraint/core.c                     | 290 +++++++++++++++++++++
 drivers/boot_constraint/core.h                     |  47 ++++
 drivers/boot_constraint/deferrable_dev.c           | 241 +++++++++++++++++
 drivers/boot_constraint/hikey.c                    | 158 +++++++++++
 drivers/boot_constraint/imx.c                      | 126 +++++++++
 drivers/boot_constraint/pm.c                       |  28 ++
 drivers/boot_constraint/qcom.c                     | 122 +++++++++
 drivers/boot_constraint/supply.c                   | 104 ++++++++
 drivers/clk/imx/clk-imx25.c                        |  12 -
 drivers/clk/imx/clk-imx27.c                        |  13 -
 drivers/clk/imx/clk-imx31.c                        |  12 -
 drivers/clk/imx/clk-imx35.c                        |  10 -
 drivers/clk/imx/clk-imx51-imx53.c                  |  16 --
 drivers/clk/imx/clk-imx6q.c                        |   8 -
 drivers/clk/imx/clk-imx6sl.c                       |   8 -
 drivers/clk/imx/clk-imx6sx.c                       |   8 -
 drivers/clk/imx/clk-imx7d.c                        |  14 -
 drivers/clk/imx/clk.c                              |  38 ---
 drivers/clk/imx/clk.h                              |   1 -
 drivers/of/platform.c                              |  63 ++++-
 include/linux/boot_constraint.h                    | 121 +++++++++
 include/linux/of_platform.h                        |  16 ++
 34 files changed, 1541 insertions(+), 151 deletions(-)
 create mode 100644 Documentation/driver-api/boot-constraint/constraints.rst
 create mode 100644 Documentation/driver-api/boot-constraint/index.rst
 create mode 100644 drivers/boot_constraint/Kconfig
 create mode 100644 drivers/boot_constraint/Makefile
 create mode 100644 drivers/boot_constraint/clk.c
 create mode 100644 drivers/boot_constraint/core.c
 create mode 100644 drivers/boot_constraint/core.h
 create mode 100644 drivers/boot_constraint/deferrable_dev.c
 create mode 100644 drivers/boot_constraint/hikey.c
 create mode 100644 drivers/boot_constraint/imx.c
 create mode 100644 drivers/boot_constraint/pm.c
 create mode 100644 drivers/boot_constraint/qcom.c
 create mode 100644 drivers/boot_constraint/supply.c
 create mode 100644 include/linux/boot_constraint.h

-- 
2.15.0.194.g9af6a3dea062

^ permalink raw reply

* [PATCH] KVM: arm/arm64: don't set vtimer->cnt_ctl in kvm_arch_timer_handler
From: Jia He @ 2017-12-14 15:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171214130954.GV910@cbox>

Hi Christoffer


On 12/14/2017 9:09 PM, Christoffer Dall Wrote:
> On Thu, Dec 14, 2017 at 12:57:54PM +0800, Jia He wrote:
> Hi Jia,
>
>> I have tried your newer level-mapped-v7 branch, but bug is still there.
>>
>> There is no special load in both host and guest. The guest (kernel
>> 4.14) is often hanging when booting
>>
>> the guest kernel log
>>
>> [ OK ] Reached target Remote File Systems.
>> Starting File System Check on /dev/mapper/fedora-root...
>> [ OK ] Started File System Check on /dev/mapper/fedora-root.
>> Mounting /sysroot...
>> [ 2.670764] SGI XFS with ACLs, security attributes, no debug enabled
>> [ 2.678180] XFS (dm-0): Mounting V5 Filesystem
>> [ 2.740364] XFS (dm-0): Ending clean mount
>> [ OK ] Mounted /sysroot.
>> [ OK ] Reached target Initrd Root File System.
>> Starting Reload Configuration from the Real Root...
>> [ 61.288215] INFO: rcu_sched detected stalls on CPUs/tasks:
>> [ 61.290791] 1-...!: (0 ticks this GP) idle=574/0/0 softirq=5/5 fqs=1
>> [ 61.293664] (detected by 0, t=6002 jiffies, g=-263, c=-264, q=39760)
>> [ 61.296480] Task dump for CPU 1:
>> [ 61.297938] swapper/1 R running task 0 0 1 0x00000020
>> [ 61.300643] Call trace:
>> [ 61.301260] __switch_to+0x6c/0x78
>> [ 61.302095] cpu_number+0x0/0x8
>> [ 61.302867] rcu_sched kthread starved for 6000 jiffies!
>> g18446744073709551353 c18446744073709551352 f0x0 RCU_GP_WAIT_FQS(3)
>> ->state=0x402 ->cpu=1
>> [ 61.305941] rcu_sched I 0 8 2 0x00000020
>> [ 61.307250] Call trace:
>> [ 61.307854] __switch_to+0x6c/0x78
>> [ 61.308693] __schedule+0x268/0x8f0
>> [ 61.309545] schedule+0x2c/0x88
>> [ 61.310325] schedule_timeout+0x84/0x3b8
>> [ 61.311278] rcu_gp_kthread+0x4d4/0x7d8
>> [ 61.312213] kthread+0x134/0x138
>> [ 61.313001] ret_from_fork+0x10/0x1c
>>
>> Maybe my previous patch is not perfect enough, thanks for your comments.
>>
>> I digged it futher more, do you think below code logic is possibly
>> problematic?
>>
>>
>> vtimer_save_state?????????? (vtimer->loaded = false, cntv_ctl is 0)
>>
>> kvm_arch_timer_handler????????(read cntv_ctl and set vtimer->cnt_ctl = 0)
>>
>> vtimer_restore_state ? ? ? ? ?? (write vtimer->cnt_ctl to cntv_ctl,
>> then cntv_ctl will
>>
>>  ??? ??? ??? ??? ?? ? ? be 0 forever)
>>
>>
>> If above analysis is reasonable
> Yes, I think there's something there if the hardware doesn't retire the
> signal fast enough...
>
>> how about below patch? already
>> tested in my arm64 server.
>>
>> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
>> index f9555b1..ee6dd3f 100644
>> --- a/virt/kvm/arm/arch_timer.c
>> +++ b/virt/kvm/arm/arch_timer.c
>> @@ -99,7 +99,7 @@ static irqreturn_t kvm_arch_timer_handler(int irq,
>> void *dev_id)
>>  ??????? }
>>  ??????? vtimer = vcpu_vtimer(vcpu);
>>
>> -?????? if (!vtimer->irq.level) {
>> +?????? if (vtimer->loaded && !vtimer->irq.level) {
>>  ??????????????? vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl);
>>  ??????????????? if (kvm_timer_irq_can_fire(vtimer))
>>  ??????????????????????? kvm_timer_update_irq(vcpu, true, vtimer);
>>
> There's nothing really wrong with that patch, I just didn't think it
> would be necessary, as we really shouldn't see interrupts if the timer
> is not loaded.  Can you confirm that a WARN_ON(!vtimer->loaded) in
> kvm_arch_timer_handler() gives you a splat?
Please see the WARN_ON result (without my patch)
[?? 72.171706] WARNING: CPU: 24 PID: 1768 at 
arch/arm64/kvm/../../../virt/kvm/arm/arch_timer.c:101 
kvm_arch_timer_handler+0xc0/0xc8
[?? 72.182305] Modules linked in: vhost_net tap xt_CHECKSUM 
iptable_mangle ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat 
nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack 
nf_conntrack ipt_REJECT nf_reject_ipv4 xt_tcpudp bridge stp llc 
ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter 
ip_tables x_tables vhost_scsi vhost tcm_qla2xxx qla2xxx nvme_fc 
nvme_fabrics tcm_fc libfc scsi_transport_fc ib_srpt ib_cm ib_core 
iscsi_target_mod tcm_loop target_core_file target_core_iblock 
target_core_pscsi target_core_mod binfmt_misc nls_iso8859_1 shpchp 
crc32_ce crct10dif_ce i2c_qup dm_multipath autofs4 btrfs zstd_decompress 
zstd_compress xxhash raid10 raid456 async_raid6_recov async_memcpy 
async_pq async_xor async_tx xor raid6_pq libcrc32c raid1 raid0 multipath 
linear at803x ixgbe
[?? 72.252877]? xhci_plat_hcd xhci_hcd usbcore qcom_emac mdio 
ahci_platform libahci_platform libahci
[?? 72.261733] CPU: 24 PID: 1768 Comm: qemu-system-aar Tainted: G??????? 
W??????? 4.15.0-rc3+ #128
[?? 72.270412] Hardware name: WIWYNN QDF2400 Reference Evaluation 
Platform CV90-LA115-P151/QDF2400 Customer Reference Board, BIOS 0ACJA425 
09/07/2017
[?? 72.283520] pstate: 80400085 (Nzcv daIf +PAN -UAO)
[?? 72.288295] pc : kvm_arch_timer_handler+0xc0/0xc8
[?? 72.292984] lr : handle_percpu_devid_irq+0x8c/0x230
[?? 72.297842] sp : ffff00000830ff00
[?? 72.301141] x29: ffff00000830ff00 x28: ffffc17b9feaff00
[?? 72.306436] x27: ffff2e7462531000 x26: ffff000008310000
[?? 72.311731] x25: ffff000008300000 x24: ffffc17b80069100
[?? 72.317026] x23: 0000000000000003 x22: ffff2e74632248e8
[?? 72.322321] x21: ffffc17b80054c00 x20: 0000000000000000
[?? 72.327616] x19: ffffc17b8ac37dc0 x18: 0000000000000010
[?? 72.332911] x17: 000000000000000a x16: 0000000000007fff
[?? 72.338207] x15: ffffffffffffffff x14: 6d202c6666666666
[?? 72.343502] x13: 6666667830203a73 x12: 656c6379635f7861
[?? 72.348797] x11: ffff000009395448 x10: ffff00000862b5b8
[?? 72.354092] x9 : 0000000000000040 x8 : ffffc17b60007238
[?? 72.359387] x7 : 0000000000000000 x6 : ffffc17b80054c00
[?? 72.364682] x5 : ffffc17b60007250 x4 : 0000930756ce0000
[?? 72.369977] x3 : ffff2e74619cfff0 x2 : 0000930756ce0000
[?? 72.375273] x1 : 0000000000000000 x0 : ffffc17b8ac399c0
[?? 72.380568] Call trace:
[?? 72.383000]? kvm_arch_timer_handler+0xc0/0xc8
[?? 72.387340]? handle_percpu_devid_irq+0x8c/0x230
[?? 72.391853]? generic_handle_irq+0x34/0x50
[?? 72.395846]? __handle_domain_irq+0x68/0xc0
[?? 72.399926]? gic_handle_irq+0xcc/0x188
[?? 72.403658]? el1_irq+0xd8/0x180
[?? 72.406785]? hrtimer_try_to_cancel+0x0/0x160
[?? 72.411037]? kvm_timer_vcpu_put+0x3c/0x50
[?? 72.415030]? kvm_arch_vcpu_put+0x20/0x50
[?? 72.418937]? vcpu_put+0x20/0x40
[?? 72.422061]? kvm_vcpu_ioctl+0x244/0x7b8
[?? 72.425882]? do_vfs_ioctl+0xc4/0x988
[?? 72.429440]? SyS_ioctl+0x94/0xa8
[?? 72.432652]? el0_svc_naked+0x20/0x24
[?? 72.436210] ---[ end trace 11d0c8bba284e766 ]---

> Also, could you give the following a try (without your patch):
>
> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
> index 73d262c4712b..4751255345d1 100644
> --- a/virt/kvm/arm/arch_timer.c
> +++ b/virt/kvm/arm/arch_timer.c
> @@ -367,6 +367,7 @@ static void vtimer_save_state(struct kvm_vcpu *vcpu)
>   
>   	/* Disable the virtual timer */
>   	write_sysreg_el0(0, cntv_ctl);
> +	isb();
No luck? the bug is still there

Cheers,
Jia

^ permalink raw reply

* arm64: unhandled level 0 translation fault
From: Dave P Martin @ 2017-12-14 15:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMuHMdWH=3kRmwjDHsTzUVmB7=s5cnY16Ujfroe_B6dawGSDfw@mail.gmail.com>

On Thu, Dec 14, 2017 at 02:34:50PM +0000, Geert Uytterhoeven wrote:
> Hi Catalin, Will, Dave,
>
> On Tue, Dec 12, 2017 at 11:20 AM, Geert Uytterhoeven
> <geert@linux-m68k.org> wrote:
> > During userspace (Debian jessie NFS root) boot on arm64:
> >
> > rpcbind[1083]: unhandled level 0 translation fault (11) at 0x00000008,
> > esr 0x92000004, in dash[aaaaadf77000+1a000]
> > CPU: 0 PID: 1083 Comm: rpcbind Not tainted
> > 4.15.0-rc3-arm64-renesas-02176-g14f9a1826e48e355 #51
> > Hardware name: Renesas Salvator-X 2nd version board based on r8a7795 ES2.0+ (DT)
>
> This is a quad Cortex A57.
>
> > pstate: 80000000 (Nzcv daif -PAN -UAO)
> > pc : 0xaaaaadf8a51c
> > lr : 0xaaaaadf8ac08
> > sp : 0000ffffcffeac00
> > x29: 0000ffffcffeac00 x28: 0000aaaaadfa1000
> > x27: 0000ffffcffebf7c x26: 0000ffffcffead20
> > x25: 0000aaaacea1c5f0 x24: 0000000000000000
> > x23: 0000aaaaadfa1000 x22: 0000aaaaadfa1000
> > x21: 0000000000000000 x20: 0000000000000008
> > x19: 0000000000000000 x18: 0000ffffcffeb500
> > x17: 0000ffffa22babfc x16: 0000aaaaadfa1ae8
> > x15: 0000ffffa2363588 x14: ffffffffffffffff
> > x13: 0000000000000020 x12: 0000000000000010
> > x11: 0101010101010101 x10: 0000aaaaadfa1000
> > x9 : 00000000ffffff81 x8 : 0000aaaaadfa2000
> > x7 : 0000000000000000 x6 : 0000000000000000
> > x5 : 0000aaaaadfa2338 x4 : 0000aaaaadfa2000
> > x3 : 0000aaaaadfa2338 x2 : 0000000000000000
> > x1 : 0000aaaaadfa28b0 x0 : 0000aaaaadfa4c30
> >
> > Sometimes it happens with other processes, but the main address, esr, and
> > pstate values are always the same.
> >
> > I regularly run arm64/for-next/core (through bi-weekly renesas-drivers
> > releases, so the last time was two weeks ago), but never saw the issue
> > before until today, so probably v4.15-rc1 is OK.
> > Unfortunately it doesn't happen during every boot, which makes it
> > cumbersome to bisect.
> >
> > My first guess was UNMAP_KERNEL_AT_EL0, but even after disabling that,
> > and even without today's arm64/for-next/core merged in, I still managed to
> > reproduce the issue, so I believe it was introduced in v4.15-rc2 or
> > v4.15-rc3.
> >
> > Once, when the kernel message above wasn't shown, I got an error from
> > userspace, which may be related:
> > *** Error in `/bin/sh': free(): invalid pointer: 0x0000aaaadd970988 ***
>
> With more boots (10 instead of 6) to declare a kernel good, I bisected this
> to commit 9de52a755cfb6da5 ("arm64: fpsimd: Fix failure to restore FPSIMD
> state after signals").
>
> Reverting that commit on top of v4.15-rc3 fixed the issue for me.

Good work on the bisect -- I'll need to have a think about this...

That patch fixes a genuine problem so we can't just revert it.


What if you revert _just this function_ back to what it was in v4.14?

Cheers
---Dave
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

^ permalink raw reply

* [PATCH v3] arm64: cpu_errata: Add Kryo to Falkor 1003 errata
From: Will Deacon @ 2017-12-14 15:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171213221937.28065-1-sboyd@codeaurora.org>

On Wed, Dec 13, 2017 at 02:19:37PM -0800, Stephen Boyd wrote:
> The Kryo CPUs are also affected by the Falkor 1003 errata, so
> we need to do the same workaround on Kryo CPUs. The MIDR is
> slightly more complicated here, where the PART number is not
> always the same when looking at all the bits from 15 to 4. Drop
> the lower 8 bits and just look at the top 4 to see if it's '2'
> and then consider those as Kryo CPUs. This covers all the
> combinations without having to list them all out.
> 
> Fixes: 38fd94b0275c ("arm64: Work around Falkor erratum 1003")
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---

Acked-by: Will Deacon <will.deacon@arm.com>

Thanks for respinning this. Catalin -- can you take this for 4.16, please?

Will

^ permalink raw reply

* arm64: unhandled level 0 translation fault
From: Will Deacon @ 2017-12-14 15:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMuHMdWH=3kRmwjDHsTzUVmB7=s5cnY16Ujfroe_B6dawGSDfw@mail.gmail.com>

Hi Geert,

On Thu, Dec 14, 2017 at 03:34:50PM +0100, Geert Uytterhoeven wrote:
> On Tue, Dec 12, 2017 at 11:20 AM, Geert Uytterhoeven
> <geert@linux-m68k.org> wrote:
> > During userspace (Debian jessie NFS root) boot on arm64:
> >
> > rpcbind[1083]: unhandled level 0 translation fault (11) at 0x00000008,
> > esr 0x92000004, in dash[aaaaadf77000+1a000]
> > CPU: 0 PID: 1083 Comm: rpcbind Not tainted
> > 4.15.0-rc3-arm64-renesas-02176-g14f9a1826e48e355 #51
> > Hardware name: Renesas Salvator-X 2nd version board based on r8a7795 ES2.0+ (DT)
> 
> This is a quad Cortex A57.

It's so bizarre that nobody else is running into this!

> > pstate: 80000000 (Nzcv daif -PAN -UAO)
> > pc : 0xaaaaadf8a51c
> > lr : 0xaaaaadf8ac08
> > sp : 0000ffffcffeac00
> > x29: 0000ffffcffeac00 x28: 0000aaaaadfa1000
> > x27: 0000ffffcffebf7c x26: 0000ffffcffead20
> > x25: 0000aaaacea1c5f0 x24: 0000000000000000
> > x23: 0000aaaaadfa1000 x22: 0000aaaaadfa1000
> > x21: 0000000000000000 x20: 0000000000000008
> > x19: 0000000000000000 x18: 0000ffffcffeb500
> > x17: 0000ffffa22babfc x16: 0000aaaaadfa1ae8
> > x15: 0000ffffa2363588 x14: ffffffffffffffff
> > x13: 0000000000000020 x12: 0000000000000010
> > x11: 0101010101010101 x10: 0000aaaaadfa1000
> > x9 : 00000000ffffff81 x8 : 0000aaaaadfa2000
> > x7 : 0000000000000000 x6 : 0000000000000000
> > x5 : 0000aaaaadfa2338 x4 : 0000aaaaadfa2000
> > x3 : 0000aaaaadfa2338 x2 : 0000000000000000
> > x1 : 0000aaaaadfa28b0 x0 : 0000aaaaadfa4c30
> >
> > Sometimes it happens with other processes, but the main address, esr, and
> > pstate values are always the same.
> >
> > I regularly run arm64/for-next/core (through bi-weekly renesas-drivers
> > releases, so the last time was two weeks ago), but never saw the issue
> > before until today, so probably v4.15-rc1 is OK.
> > Unfortunately it doesn't happen during every boot, which makes it
> > cumbersome to bisect.
> >
> > My first guess was UNMAP_KERNEL_AT_EL0, but even after disabling that,
> > and even without today's arm64/for-next/core merged in, I still managed to
> > reproduce the issue, so I believe it was introduced in v4.15-rc2 or
> > v4.15-rc3.
> >
> > Once, when the kernel message above wasn't shown, I got an error from
> > userspace, which may be related:
> > *** Error in `/bin/sh': free(): invalid pointer: 0x0000aaaadd970988 ***
> 
> With more boots (10 instead of 6) to declare a kernel good, I bisected this
> to commit 9de52a755cfb6da5 ("arm64: fpsimd: Fix failure to restore FPSIMD
> state after signals").
> 
> Reverting that commit on top of v4.15-rc3 fixed the issue for me.

Thanks for persevering with the bisect. We'll get this fixed ASAP, but we'll
be relying on you to test the patch we come up with.

Cheers,

Will

^ permalink raw reply

* [PATCH 04/14] ARM: dts: dra76x: Create a common file with MMC/SD IOdelay data
From: Tony Lindgren @ 2017-12-14 15:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171214134054.7749-5-kishon@ti.com>

* Kishon Vijay Abraham I <kishon@ti.com> [171214 13:44]:
> +&dra7_pmx_core {
> +	mmc1_pins_default: mmc1_pins_default {
> +		pinctrl-single,pins = <
> +			DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */
> +			DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */
> +			DRA7XX_CORE_IOPAD(0x375c, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */
> +			DRA7XX_CORE_IOPAD(0x3760, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */
> +			DRA7XX_CORE_IOPAD(0x3764, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */
> +			DRA7XX_CORE_IOPAD(0x3768, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */
> +		>;
> +	};
> +
> +	mmc1_pins_sdr12: mmc1_pins_sdr12 {
> +		pinctrl-single,pins = <
> +			DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc1_clk.clk */
> +			DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc1_cmd.cmd */
> +			DRA7XX_CORE_IOPAD(0x375c, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc1_dat0.dat0 */
> +			DRA7XX_CORE_IOPAD(0x3760, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc1_dat1.dat1 */
> +			DRA7XX_CORE_IOPAD(0x3764, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc1_dat2.dat2 */
> +			DRA7XX_CORE_IOPAD(0x3768, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc1_dat3.dat3 */
> +		>;
> +	};

Can't you just do:

pinctrl-0 = <&mmc1_pins_default>;
pinctrl-1 = <&mmc1_pins_default>;
pinctrl-2 = <&mmc1_pins_hs>;
pinctrl-names = "default", "sdr12", "sdr25";

And avoid defining duplicate pinctrl groups that way?

Regards,

Tony

^ permalink raw reply

* [PATCH] of: build dbts with symbols when CONFIG_OF_OVERLAY is set
From: Andre Heider @ 2017-12-14 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

The overlay feature requires the base dtb to be built with symbols, so
lets build the dtbs with symbols when overlay support was explicitly
enabled.

With CONFIG_OF_ALL_DTBS on ARCH=arm the 989 dtb files grow about ~38% on
average.

Totals in bytes with the 3 biggest ones:

Before:
	90471	arch/arm/boot/dts/am57xx-beagle-x15-revc.dtb
	90521	arch/arm/boot/dts/am57xx-beagle-x15-revb1.dtb
	92639	arch/arm/boot/dts/dra7-evm.dtb
	25731296	total

After:
	133203	arch/arm/boot/dts/am57xx-beagle-x15-revc.dtb
	133237	arch/arm/boot/dts/am57xx-beagle-x15-revb1.dtb
	134545	arch/arm/boot/dts/dra7-evm.dtb
	35464440	total

Signed-off-by: Andre Heider <a.heider@gmail.com>
---

Hi,

while playing around with overlays I noticed that I needed to rebuilt
my distro's device trees because they didn't come with symbols.

Is that for a reason, maybe the not so minor increase in size?

Thanks,
Andre

 drivers/of/unittest-data/Makefile | 7 -------
 scripts/Makefile.lib              | 5 +++++
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/of/unittest-data/Makefile b/drivers/of/unittest-data/Makefile
index 32389acfa616..b65061013512 100644
--- a/drivers/of/unittest-data/Makefile
+++ b/drivers/of/unittest-data/Makefile
@@ -15,13 +15,6 @@ targets += overlay.dtb overlay.dtb.S
 targets += overlay_bad_phandle.dtb overlay_bad_phandle.dtb.S
 targets += overlay_bad_symbol.dtb overlay_bad_symbol.dtb.S
 targets += overlay_base.dtb overlay_base.dtb.S
-
-# enable creation of __symbols__ node
-DTC_FLAGS_overlay := -@
-DTC_FLAGS_overlay_bad_phandle := -@
-DTC_FLAGS_overlay_bad_symbol := -@
-DTC_FLAGS_overlay_base := -@
-
 endif
 
 .PRECIOUS: \
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 1ca4dcd2d500..c7ba4aa8a07a 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -278,6 +278,11 @@ DTC_FLAGS += -Wnode_name_chars_strict \
 	-Wproperty_name_chars_strict
 endif
 
+ifeq ($(CONFIG_OF_OVERLAY),y)
+# enable creation of __symbols__ node
+DTC_FLAGS += -@
+endif
+
 DTC_FLAGS += $(DTC_FLAGS_$(basetarget))
 
 # Generate an assembly file to wrap the output of the device tree compiler
-- 
2.15.1

^ permalink raw reply related

* [PATCH] arm64/sve: Report SVE to userspace via CPUID only if supported
From: Suzuki K Poulose @ 2017-12-14 15:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513260094-9893-1-git-send-email-Dave.Martin@arm.com>

On 14/12/17 14:01, Dave Martin wrote:
> Currently, the SVE field in ID_AA64PFR0_EL1 is visible
> unconditionally to userspace via the CPU ID register emulation,
> irrespective of the kernel config.  This means that if a kernel
> configured with CONFIG_ARM64_SVE=n is run on SVE-capable hardware,
> userspace will see SVE reported as present in the ID regs even
> though the kernel forbids execution of SVE instructions.
> 
> This patch makes the exposure of the SVE field in ID_AA64PFR0_EL1
> conditional on CONFIG_ARM64_SVE=y.
> 
> Since future architecture features are likely to encounter a
> similar requirement, this patch adds a suitable helper macros for
> use when declaring config-conditional ID register fields.
> 
> Fixes: 43994d824e84 ("arm64/sve: Detect SVE and activate runtime support")
> Reported-by: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> Cc: Suzuki Poulose <suzuki.poulose@arm.com>
> ---
> 
> This patch is proposed as a fix for v4.15, since we don't want to create
> unintentional ABI by exposing the wrong thing to userspace in a full
> kernel release.
> 
>   arch/arm64/include/asm/cpufeature.h | 3 +++
>   arch/arm64/kernel/cpufeature.c      | 3 ++-
>   2 files changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index ac67cfc..060e3a4 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -60,6 +60,9 @@ enum ftr_type {
>   #define FTR_VISIBLE	true	/* Feature visible to the user space */
>   #define FTR_HIDDEN	false	/* Feature is hidden from the user */
>   
> +#define FTR_VISIBLE_IF_IS_ENABLED(config)		\
> +	(IS_ENABLED(config) ? FTR_VISIBLE : FTR_HIDDEN)
> +
>   struct arm64_ftr_bits {
>   	bool		sign;	/* Value is signed ? */
>   	bool		visible;
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index c5ba009..a73a592 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -145,7 +145,8 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
>   };
>   
>   static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
> -	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_SVE_SHIFT, 4, 0),
> +	ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE),
> +				   FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_SVE_SHIFT, 4, 0),
>   	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_GIC_SHIFT, 4, 0),
>   	S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI),
>   	S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI),
> 

Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Suzuki

^ permalink raw reply

* [PATCH 1/1] dt-bindings: arm: document supported STM32 SoC family
From: Rob Herring @ 2017-12-14 15:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <16700917-a53a-c319-d27d-f447c6ed3dce@st.com>

On Wed, Dec 13, 2017 at 2:40 AM, Ludovic BARRE <ludovic.barre@st.com> wrote:
> hi Rob
>
> Today there was no bindings documentation for STM32 SoC
> already upstreamed. This patch adds initial list of STM32
> existing in kernel.
> The next serie adds just new soc and one compatible on STM32 list.

Yes, and that series will go thru arm-soc tree so this patch needs to too.

> So, I think you could apply this patch.

If your series is not going into 4.16, then I can take this one.

Rob

^ permalink raw reply

* [PATCH 06/12] mmc: sdhci_omap: Add support to set IODELAY values
From: Tony Lindgren @ 2017-12-14 15:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171214130941.26666-7-kishon@ti.com>

Hi,

* Kishon Vijay Abraham I <kishon@ti.com> [171214 13:13]:
> The data manual of J6/J6 Eco recommends to set different IODELAY values
> depending on the mode in which the MMC/SD is enumerated in order to
> ensure IO timings are met.
> 
> Add support to set the IODELAY values depending on the various MMC
> modes using the pinctrl APIs.
...

> --- a/drivers/mmc/host/sdhci-omap.c
> +++ b/drivers/mmc/host/sdhci-omap.c
> @@ -105,6 +109,20 @@ struct sdhci_omap_host {
>  	struct sdhci_host	*host;
>  	u8			bus_mode;
>  	u8			power_mode;
> +	u8			timing;
> +	u8			flags;
> +
> +	struct pinctrl		*pinctrl;
> +	struct pinctrl_state	*pinctrl_state;
> +	struct pinctrl_state	*default_pinctrl_state;
> +	struct pinctrl_state	*sdr104_pinctrl_state;
> +	struct pinctrl_state	*hs200_1_8v_pinctrl_state;
> +	struct pinctrl_state	*ddr50_pinctrl_state;
> +	struct pinctrl_state	*sdr50_pinctrl_state;
> +	struct pinctrl_state	*sdr25_pinctrl_state;
> +	struct pinctrl_state	*sdr12_pinctrl_state;
> +	struct pinctrl_state	*hs_pinctrl_state;
> +	struct pinctrl_state	*ddr_1_8v_pinctrl_state;
>  };


You can make the pinctrl code more generic by allocating an array
of states and have just:

	struct pinctrl_state **pinctrl_state;

Then access it with omap_host->pinctrl_state[MMC_TIMING_MMC_HS200]
and so on.

This way the code gets simplified and you can do a generic function
to initialize things and call it from a for loop etc.

Just remember that pinctrl use can be optional as the pins can be
set up in the bootloader alone. Then you can just continue with the
default iodelay state like we are currently doing.

Regards,

Tony

^ permalink raw reply

* [PATCH v4 4/4] arm64: dts: marvell: armada-37xx: add nodes allowing cpufreq support
From: Gregory CLEMENT @ 2017-12-14 15:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171214150006.25438-1-gregory.clement@free-electrons.com>

In order to be able to use cpu freq, we need to associate a clock to each
CPU and to expose the power management registers.

Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
 arch/arm64/boot/dts/marvell/armada-372x.dtsi | 1 +
 arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 7 +++++++
 2 files changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/marvell/armada-372x.dtsi b/arch/arm64/boot/dts/marvell/armada-372x.dtsi
index 59d7557d3b1b..2554e0baea6b 100644
--- a/arch/arm64/boot/dts/marvell/armada-372x.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-372x.dtsi
@@ -56,6 +56,7 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a53","arm,armv8";
 			reg = <0x1>;
+			clocks = <&nb_periph_clk 16>;
 			enable-method = "psci";
 		};
 	};
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index 90c26d616a54..3056d7168e0b 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -65,6 +65,7 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a53", "arm,armv8";
 			reg = <0>;
+			clocks = <&nb_periph_clk 16>;
 			enable-method = "psci";
 		};
 	};
@@ -234,6 +235,12 @@
 				};
 			};
 
+			nb_pm: syscon at 14000 {
+				compatible = "marvell,armada-3700-nb-pm",
+					     "syscon";
+				reg = <0x14000 0x60>;
+			};
+
 			pinctrl_sb: pinctrl at 18800 {
 				compatible = "marvell,armada3710-sb-pinctrl",
 					     "syscon", "simple-mfd";
-- 
2.15.1

^ permalink raw reply related

* [PATCH v4 3/4] cpufreq: Add DVFS support for Armada 37xx
From: Gregory CLEMENT @ 2017-12-14 15:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171214150006.25438-1-gregory.clement@free-electrons.com>

This patch adds DVFS support for the Armada 37xx SoCs

There are up to four CPU frequency loads for Armada 37xx controlled by
the hardware.

This driver associates the CPU load level to a frequency, then the
hardware will switch while selecting a load level.

The hardware also can associate a voltage for each level (AVS support)
but it is not yet supported

Tested-by: Andre Heider <a.heider@gmail.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
 drivers/cpufreq/Kconfig.arm           |   7 +
 drivers/cpufreq/Makefile              |   1 +
 drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++
 3 files changed, 249 insertions(+)
 create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index beb8826afbb1..3a88e33b0cfe 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -18,6 +18,13 @@ config ACPI_CPPC_CPUFREQ
 
 	  If in doubt, say N.
 
+config ARM_ARMADA_37XX_CPUFREQ
+	tristate "Armada 37xx CPUFreq support"
+	depends on ARCH_MVEBU
+	help
+	  This adds the CPUFreq driver support for Marvell Armada 37xx SoCs.
+	  The Armada 37xx PMU supports 4 frequency and VDD levels.
+
 # big LITTLE core layer and glue drivers
 config ARM_BIG_LITTLE_CPUFREQ
 	tristate "Generic ARM big LITTLE CPUfreq driver"
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index d762e76887e7..e07715ce8844 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ)	+= arm_big_little.o
 # LITTLE drivers, so that it is probed last.
 obj-$(CONFIG_ARM_DT_BL_CPUFREQ)		+= arm_big_little_dt.o
 
+obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ)	+= armada-37xx-cpufreq.o
 obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ)	+= brcmstb-avs-cpufreq.o
 obj-$(CONFIG_ACPI_CPPC_CPUFREQ)		+= cppc_cpufreq.o
 obj-$(CONFIG_ARCH_DAVINCI)		+= davinci-cpufreq.o
diff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c
new file mode 100644
index 000000000000..c6ebc88a7d8d
--- /dev/null
+++ b/drivers/cpufreq/armada-37xx-cpufreq.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * CPU frequency scaling support for Armada 37xx platform.
+ *
+ * Copyright (C) 2017 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+/* Power management in North Bridge register set */
+#define ARMADA_37XX_NB_L0L1	0x18
+#define ARMADA_37XX_NB_L2L3	0x1C
+#define  ARMADA_37XX_NB_TBG_DIV_OFF	13
+#define  ARMADA_37XX_NB_TBG_DIV_MASK	0x7
+#define  ARMADA_37XX_NB_CLK_SEL_OFF	11
+#define  ARMADA_37XX_NB_CLK_SEL_MASK	0x1
+#define  ARMADA_37XX_NB_CLK_SEL_TBG	0x1
+#define  ARMADA_37XX_NB_TBG_SEL_OFF	9
+#define  ARMADA_37XX_NB_TBG_SEL_MASK	0x3
+#define  ARMADA_37XX_NB_VDD_SEL_OFF	6
+#define  ARMADA_37XX_NB_VDD_SEL_MASK	0x3
+#define  ARMADA_37XX_NB_CONFIG_SHIFT	16
+#define ARMADA_37XX_NB_DYN_MOD	0x24
+#define  ARMADA_37XX_NB_CLK_SEL_EN	BIT(26)
+#define  ARMADA_37XX_NB_TBG_EN		BIT(28)
+#define  ARMADA_37XX_NB_DIV_EN		BIT(29)
+#define  ARMADA_37XX_NB_VDD_EN		BIT(30)
+#define  ARMADA_37XX_NB_DFS_EN		BIT(31)
+#define ARMADA_37XX_NB_CPU_LOAD 0x30
+#define  ARMADA_37XX_NB_CPU_LOAD_MASK	0x3
+#define  ARMADA_37XX_DVFS_LOAD_0	0
+#define  ARMADA_37XX_DVFS_LOAD_1	1
+#define  ARMADA_37XX_DVFS_LOAD_2	2
+#define  ARMADA_37XX_DVFS_LOAD_3	3
+
+/*
+ * On Armada 37xx the Power management manages 4 level of CPU load,
+ * each level can be associated with a CPU clock source, a CPU
+ * divider, a VDD level, etc...
+ */
+#define LOAD_LEVEL_NR	4
+
+struct armada_37xx_dvfs {
+	u32 cpu_freq_max;
+	u8 divider[LOAD_LEVEL_NR];
+};
+
+static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
+	{.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
+	{.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
+	{.cpu_freq_max = 800*1000*1000,  .divider = {1, 2, 3, 4} },
+	{.cpu_freq_max = 600*1000*1000,  .divider = {2, 4, 5, 6} },
+};
+
+static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) {
+		if (freq == armada_37xx_dvfs[i].cpu_freq_max)
+			return &armada_37xx_dvfs[i];
+	}
+
+	pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000);
+	return NULL;
+}
+
+/*
+ * Setup the four level managed by the hardware. Once the four level
+ * will be configured then the DVFS will be enabled.
+ */
+static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
+						 struct clk *clk, u8 *divider)
+{
+	int load_lvl;
+	struct clk *parent;
+
+	for (load_lvl = 0; load_lvl < LOAD_LEVEL_NR; load_lvl++) {
+		unsigned int reg, mask, val, offset = 0;
+
+		if (load_lvl <= ARMADA_37XX_DVFS_LOAD_1)
+			reg = ARMADA_37XX_NB_L0L1;
+		else
+			reg = ARMADA_37XX_NB_L2L3;
+
+		if (load_lvl == ARMADA_37XX_DVFS_LOAD_0 ||
+		    load_lvl == ARMADA_37XX_DVFS_LOAD_2)
+			offset += ARMADA_37XX_NB_CONFIG_SHIFT;
+
+		/* Set cpu clock source, for all the level we use TBG */
+		val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF;
+		mask = (ARMADA_37XX_NB_CLK_SEL_MASK
+			<< ARMADA_37XX_NB_CLK_SEL_OFF);
+
+		/*
+		 * Set cpu divider based on the pre-computed array in
+		 * order to have balanced step.
+		 */
+		val |= divider[load_lvl] << ARMADA_37XX_NB_TBG_DIV_OFF;
+		mask |= (ARMADA_37XX_NB_TBG_DIV_MASK
+			<< ARMADA_37XX_NB_TBG_DIV_OFF);
+
+		/* Set VDD divider which is actually the load level. */
+		val |= load_lvl << ARMADA_37XX_NB_VDD_SEL_OFF;
+		mask |= (ARMADA_37XX_NB_VDD_SEL_MASK
+			<< ARMADA_37XX_NB_VDD_SEL_OFF);
+
+		val <<= offset;
+		mask <<= offset;
+
+		regmap_update_bits(base, reg, mask, val);
+	}
+
+	/*
+	 * Set cpu clock source, for all the level we keep the same
+	 * clock source that the one already configured. For this one
+	 * we need to use the clock framework
+	 */
+	parent = clk_get_parent(clk);
+	clk_set_parent(clk, parent);
+}
+
+static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base)
+{
+	unsigned int reg = ARMADA_37XX_NB_DYN_MOD,
+		mask = ARMADA_37XX_NB_DFS_EN;
+
+	regmap_update_bits(base, reg, mask, 0);
+}
+
+static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base)
+{
+	unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD,
+		mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
+
+	/* Start with the highest load (0) */
+	val = ARMADA_37XX_DVFS_LOAD_0;
+	regmap_update_bits(base, reg, mask, val);
+
+	/* Now enable DVFS for the CPUs */
+	reg = ARMADA_37XX_NB_DYN_MOD;
+	mask =	ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN |
+		ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN |
+		ARMADA_37XX_NB_DFS_EN;
+
+	regmap_update_bits(base, reg, mask, mask);
+}
+
+static int __init armada37xx_cpufreq_driver_init(void)
+{
+	struct armada_37xx_dvfs *dvfs;
+	struct platform_device *pdev;
+	unsigned int cur_frequency;
+	struct regmap *nb_pm_base;
+	struct device *cpu_dev;
+	int load_lvl, ret;
+	struct clk *clk;
+
+	nb_pm_base =
+		syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
+
+	if (IS_ERR(nb_pm_base))
+		return -ENODEV;
+
+	/* Before doing any configuration on the DVFS first, disable it */
+	armada37xx_cpufreq_disable_dvfs(nb_pm_base);
+
+	/*
+	 * On CPU 0 register the operating points supported (which are
+	 * the nominal CPU frequency and full integer divisions of
+	 * it).
+	 */
+	cpu_dev = get_cpu_device(0);
+	if (!cpu_dev) {
+		dev_err(cpu_dev, "Cannot get CPU\n");
+		return -ENODEV;
+	}
+
+	clk = clk_get(cpu_dev, 0);
+	if (IS_ERR(clk)) {
+		dev_err(cpu_dev, "Cannot get clock for CPU0\n");
+		return PTR_ERR(clk);
+	}
+
+	/* Get nominal (current) CPU frequency */
+	cur_frequency = clk_get_rate(clk);
+	if (!cur_frequency) {
+		dev_err(cpu_dev, "Failed to get clock rate for CPU\n");
+		return -EINVAL;
+	}
+
+	dvfs = armada_37xx_cpu_freq_info_get(cur_frequency);
+	if (!dvfs)
+		return -EINVAL;
+
+	armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
+
+	for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR;
+	     load_lvl++) {
+		unsigned long freq = cur_frequency / dvfs->divider[load_lvl];
+
+		ret = dev_pm_opp_add(cpu_dev, freq, 0);
+		if (ret) {
+			/* clean-up the already added opp before leaving */
+			while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) {
+				freq = cur_frequency / dvfs->divider[load_lvl];
+				dev_pm_opp_remove(cpu_dev, freq);
+			}
+			return ret;
+		}
+	}
+
+	/* Now that everything is setup, enable the DVFS at hardware level */
+	armada37xx_cpufreq_enable_dvfs(nb_pm_base);
+
+	pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
+
+	return PTR_ERR_OR_ZERO(pdev);
+}
+/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
+late_initcall(armada37xx_cpufreq_driver_init);
+
+MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
+MODULE_DESCRIPTION("Armada 37xx cpufreq driver");
+MODULE_LICENSE("GPL");
-- 
2.15.1

^ permalink raw reply related

* [PATCH v4 2/4] MAINTAINERS: add new entries for Armada 37xx cpufreq driver
From: Gregory CLEMENT @ 2017-12-14 15:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171214150006.25438-1-gregory.clement@free-electrons.com>

This new driver belongs to the mvebu family, update the MAINTAINER file
to document it.

Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index aa71ab52fd76..98dcee849481 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1582,6 +1582,7 @@ F:	arch/arm/boot/dts/kirkwood*
 F:	arch/arm/configs/mvebu_*_defconfig
 F:	arch/arm/mach-mvebu/
 F:	arch/arm64/boot/dts/marvell/armada*
+F:	drivers/cpufreq/armada-37xx-cpufreq.c
 F:	drivers/cpufreq/mvebu-cpufreq.c
 F:	drivers/irqchip/irq-armada-370-xp.c
 F:	drivers/irqchip/irq-mvebu-*
-- 
2.15.1

^ permalink raw reply related

* [PATCH v4 1/4] dt-bindings: marvell: Add documentation for the North Bridge PM on Armada 37xx
From: Gregory CLEMENT @ 2017-12-14 15:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171214150006.25438-1-gregory.clement@free-electrons.com>

Extend the documentation of the Armada 37xx SoC with the the North
Bridge Power Management component.

Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
 .../devicetree/bindings/arm/marvell/armada-37xx.txt   | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
index 51336e5fc761..35c3c3460d17 100644
--- a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
+++ b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
@@ -14,3 +14,22 @@ following property before the previous one:
 Example:
 
 compatible = "marvell,armada-3720-db", "marvell,armada3720", "marvell,armada3710";
+
+
+Power management
+----------------
+
+For power management (particularly DVFS and AVS), the North Bridge
+Power Management component is needed:
+
+Required properties:
+- compatible     : should contain "marvell,armada-3700-nb-pm", "syscon";
+- reg            : the register start and length for the North Bridge
+		    Power Management
+
+Example:
+
+nb_pm: syscon at 14000 {
+	compatible = "marvell,armada-3700-nb-pm", "syscon";
+	reg = <0x14000 0x60>;
+}
-- 
2.15.1

^ permalink raw reply related

* [PATCH v4 0/4] Add CPU Frequency scaling support on Armada 37xx
From: Gregory CLEMENT @ 2017-12-14 15:00 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

This is the forth version of a series adding the CPU Frequency support
on Armada 37xx using DVFS. It is based on the initial work of Evan
Wang and Victor Gu.

This time the only change is fixing the last white space issues found
by Viresh. This was not mandatory but it is good to start with a clean
new file.

The last patch is for arm-soc the arm-soc subsystem through mvebu and
update the device tree to support the CPU frequency scaling.

An update on the CPU clock driver is needed in order to take into
account the DVFS setting. It's the purpose of an other series already
sent, but is no dependencies between the series (for building or at
runtime).

Thanks,

Gregory

Changelog:

v1 -> v2:

 - using syscon instead of nb_pm for the binding of the North bridge
   power management unit: reported by Rob Herring

 - fix sorting inside the big LITTLE section for the Kconfig: reported
   by Viresh Kumar

 - fix the bogus freq calculation in armada37xx_cpufreq_driver_init,
   bug reported by Andre Heider

 - use dev_pm_opp_remove() on the previous opp if dev_pm_opp_add()
   failed, reported by Viresh Kumar

 - add the Tested-by flag from Andre Heider on "cpufreq: Add DVFS
   support for Armada 37xx" patch

v2 -> v3:

 - move patches "cpufreq: ARM: sort the Kconfig menu", " cpufreq:
   sort the drivers in ARM part", "cpufreq: mvebu: Use
   dev_pm_opp_remove()" in separate series

- add reviewed-by and acked-by flags on the commits

- use space instead of tab in the #define in the armada-37xx-cpufreq.c file.

v3 -> v4

 - fix white space in the armada-37xx-cpufreq.c file.

Gregory CLEMENT (4):
  dt-bindings: marvell: Add documentation for the North Bridge PM on
    Armada 37xx
  MAINTAINERS: add new entries for Armada 37xx cpufreq driver
  cpufreq: Add DVFS support for Armada 37xx
  arm64: dts: marvell: armada-37xx: add nodes allowing cpufreq support

 .../bindings/arm/marvell/armada-37xx.txt           |  19 ++
 MAINTAINERS                                        |   1 +
 arch/arm64/boot/dts/marvell/armada-372x.dtsi       |   1 +
 arch/arm64/boot/dts/marvell/armada-37xx.dtsi       |   7 +
 drivers/cpufreq/Kconfig.arm                        |   7 +
 drivers/cpufreq/Makefile                           |   1 +
 drivers/cpufreq/armada-37xx-cpufreq.c              | 241 +++++++++++++++++++++
 7 files changed, 277 insertions(+)
 create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c

-- 
2.15.1

^ permalink raw reply

* [PATCH v2] ARM64: dts: meson-axg: add ethernet mac controller
From: Jerome Brunet @ 2017-12-14 14:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171214030242.113152-1-yixun.lan@amlogic.com>

On Thu, 2017-12-14 at 11:02 +0800, Yixun Lan wrote:
> Add DT info for the stmmac ethernet MAC which found in
> the Amlogic's Meson-AXG SoC, also describe the ethernet
> pinctrl & clock information here.
> 
> This is tested in the S400 dev board which use a RTL8211F PHY,
> and the pins connect to the 'eth_rgmii_y_pins' group.
> 
> Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
> Signed-off-by: Yixun Lan <yixun.lan@amlogic.com>

I think it would have been better to split this into 2 patches.
One adding the controller for axg, the other using it in the s400, but maybe
Kevin is OK with it...

> 
> ---
> Changes in v2 since [1]:
>  - rebase to kevin's v4.16/dt64 branch
>  - add Neil's Reviewed-by
>  - move clock info to board.dts instead of in soc.dtsi
>  - drop "meson-axg-dwmac" compatible string, since we didn't use this
>    we could re-add it later when we really need.
>  - note: to make ethernet work properly,it depend on clock & pinctrl[2],
>    to compile the DTS, the patch [3] is required.
>    the code part will be taken via clock & pinctrl subsystem tree.
> 
> [1]
> http://lists.infradead.org/pipermail/linux-amlogic/2017-November/005301.html
> 
> [2]
> http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005735.html
> http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005694.html
> 
> [3]
> http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005738.html
> ---
>  arch/arm64/boot/dts/amlogic/meson-axg-s400.dts | 11 ++++++
>  arch/arm64/boot/dts/amlogic/meson-axg.dtsi     | 50 ++++++++++++++++++++++++++
>  2 files changed, 61 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
> index 70eca1f8736a..138de3bc7cc8 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
> +++ b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
> @@ -20,3 +20,14 @@
>  &uart_AO {
>  	status = "okay";
>  };
> +
> +&ethmac {

We try to keep nodes alphabetically ordered.
Please put ethmac before uart_A0

thx

> 
> 

With all the dependencies sorted out, it works

Tested-by: Jerome Brunet <jbrunet@baylibre.com> 

^ permalink raw reply

* [2/2] ARM: davinci: remove watchdog reset
From: Guenter Roeck @ 2017-12-14 14:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513012869-7647-3-git-send-email-david@lechnology.com>

On Mon, Dec 11, 2017 at 11:21:09AM -0600, David Lechner wrote:
> This removes the watchdog reset code. The reset has been moved to
> drivers/watchdog/davinci_wdt.c. The watchdog driver registers the reset
> with the kernel so defining a reset for each machine is no longer needed.
> 
> Signed-off-by: David Lechner <david@lechnology.com>

Acked-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  arch/arm/mach-davinci/board-da830-evm.c     |  1 -
>  arch/arm/mach-davinci/board-da850-evm.c     |  1 -
>  arch/arm/mach-davinci/board-dm355-evm.c     |  1 -
>  arch/arm/mach-davinci/board-dm355-leopard.c |  1 -
>  arch/arm/mach-davinci/board-dm365-evm.c     |  1 -
>  arch/arm/mach-davinci/board-dm644x-evm.c    |  1 -
>  arch/arm/mach-davinci/board-dm646x-evm.c    |  2 -
>  arch/arm/mach-davinci/board-mityomapl138.c  |  1 -
>  arch/arm/mach-davinci/board-neuros-osd2.c   |  1 -
>  arch/arm/mach-davinci/board-omapl138-hawk.c |  1 -
>  arch/arm/mach-davinci/board-sffsdr.c        |  1 -
>  arch/arm/mach-davinci/clock.h               |  3 --
>  arch/arm/mach-davinci/da8xx-dt.c            |  1 -
>  arch/arm/mach-davinci/devices-da8xx.c       | 13 -------
>  arch/arm/mach-davinci/devices.c             |  7 +---
>  arch/arm/mach-davinci/include/mach/common.h |  1 -
>  arch/arm/mach-davinci/include/mach/da8xx.h  |  1 -
>  arch/arm/mach-davinci/time.c                | 57 -----------------------------
>  18 files changed, 1 insertion(+), 94 deletions(-)
> 
> diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
> index 2cc5426..7adf009 100644
> --- a/arch/arm/mach-davinci/board-da830-evm.c
> +++ b/arch/arm/mach-davinci/board-da830-evm.c
> @@ -642,5 +642,4 @@ MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM")
>  	.init_machine	= da830_evm_init,
>  	.init_late	= davinci_init_late,
>  	.dma_zone_size	= SZ_128M,
> -	.restart	= da8xx_restart,
>  MACHINE_END
> diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
> index 458f26d..8602d0d 100644
> --- a/arch/arm/mach-davinci/board-da850-evm.c
> +++ b/arch/arm/mach-davinci/board-da850-evm.c
> @@ -1485,6 +1485,5 @@ MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
>  	.init_machine	= da850_evm_init,
>  	.init_late	= davinci_init_late,
>  	.dma_zone_size	= SZ_128M,
> -	.restart	= da8xx_restart,
>  	.reserve	= da8xx_rproc_reserve_cma,
>  MACHINE_END
> diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
> index 2b4d553..3c15cb7 100644
> --- a/arch/arm/mach-davinci/board-dm355-evm.c
> +++ b/arch/arm/mach-davinci/board-dm355-evm.c
> @@ -420,5 +420,4 @@ MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
>  	.init_machine = dm355_evm_init,
>  	.init_late	= davinci_init_late,
>  	.dma_zone_size	= SZ_128M,
> -	.restart	= davinci_restart,
>  MACHINE_END
> diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
> index 69399d7..3ebc89d 100644
> --- a/arch/arm/mach-davinci/board-dm355-leopard.c
> +++ b/arch/arm/mach-davinci/board-dm355-leopard.c
> @@ -275,5 +275,4 @@ MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
>  	.init_machine = dm355_leopard_init,
>  	.init_late	= davinci_init_late,
>  	.dma_zone_size	= SZ_128M,
> -	.restart	= davinci_restart,
>  MACHINE_END
> diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
> index e414cb9..3daeac7 100644
> --- a/arch/arm/mach-davinci/board-dm365-evm.c
> +++ b/arch/arm/mach-davinci/board-dm365-evm.c
> @@ -778,6 +778,5 @@ MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
>  	.init_machine	= dm365_evm_init,
>  	.init_late	= davinci_init_late,
>  	.dma_zone_size	= SZ_128M,
> -	.restart	= davinci_restart,
>  MACHINE_END
>  
> diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
> index 6b26786..8d8c4ab 100644
> --- a/arch/arm/mach-davinci/board-dm644x-evm.c
> +++ b/arch/arm/mach-davinci/board-dm644x-evm.c
> @@ -821,5 +821,4 @@ MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
>  	.init_machine = davinci_evm_init,
>  	.init_late	= davinci_init_late,
>  	.dma_zone_size	= SZ_128M,
> -	.restart	= davinci_restart,
>  MACHINE_END
> diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
> index b3b81a8..dafc852 100644
> --- a/arch/arm/mach-davinci/board-dm646x-evm.c
> +++ b/arch/arm/mach-davinci/board-dm646x-evm.c
> @@ -804,7 +804,6 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
>  	.init_machine = evm_init,
>  	.init_late	= davinci_init_late,
>  	.dma_zone_size	= SZ_128M,
> -	.restart	= davinci_restart,
>  MACHINE_END
>  
>  MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
> @@ -815,6 +814,5 @@ MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
>  	.init_machine = evm_init,
>  	.init_late	= davinci_init_late,
>  	.dma_zone_size	= SZ_128M,
> -	.restart	= davinci_restart,
>  MACHINE_END
>  
> diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
> index c930c31..f9a725a 100644
> --- a/arch/arm/mach-davinci/board-mityomapl138.c
> +++ b/arch/arm/mach-davinci/board-mityomapl138.c
> @@ -574,5 +574,4 @@ MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808")
>  	.init_machine	= mityomapl138_init,
>  	.init_late	= davinci_init_late,
>  	.dma_zone_size	= SZ_128M,
> -	.restart	= da8xx_restart,
>  MACHINE_END
> diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
> index 925ada1..ff871a0 100644
> --- a/arch/arm/mach-davinci/board-neuros-osd2.c
> +++ b/arch/arm/mach-davinci/board-neuros-osd2.c
> @@ -231,5 +231,4 @@ MACHINE_START(NEUROS_OSD2, "Neuros OSD2")
>  	.init_machine = davinci_ntosd2_init,
>  	.init_late	= davinci_init_late,
>  	.dma_zone_size	= SZ_128M,
> -	.restart	= davinci_restart,
>  MACHINE_END
> diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
> index c1277b3..bc8a747 100644
> --- a/arch/arm/mach-davinci/board-omapl138-hawk.c
> +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
> @@ -338,6 +338,5 @@ MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
>  	.init_machine	= omapl138_hawk_init,
>  	.init_late	= davinci_init_late,
>  	.dma_zone_size	= SZ_128M,
> -	.restart	= da8xx_restart,
>  	.reserve	= da8xx_rproc_reserve_cma,
>  MACHINE_END
> diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
> index 4038de8..2922da9 100644
> --- a/arch/arm/mach-davinci/board-sffsdr.c
> +++ b/arch/arm/mach-davinci/board-sffsdr.c
> @@ -154,5 +154,4 @@ MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
>  	.init_machine = davinci_sffsdr_init,
>  	.init_late	= davinci_init_late,
>  	.dma_zone_size	= SZ_128M,
> -	.restart	= davinci_restart,
>  MACHINE_END
> diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
> index aea4f14..a0b559e 100644
> --- a/arch/arm/mach-davinci/clock.h
> +++ b/arch/arm/mach-davinci/clock.h
> @@ -131,9 +131,6 @@ void davinci_clk_enable(struct davinci_clk *clk);
>  void davinci_clk_disable(struct davinci_clk *clk);
>  int davinci_clk_register(struct davinci_clk *clk);
>  
> -extern struct platform_device davinci_wdt_device;
> -extern void davinci_watchdog_reset(struct platform_device *);
> -
>  static inline struct davinci_clk *to_davinci_clk(struct clk_hw *hw)
>  {
>  	if (IS_ERR_OR_NULL(hw))
> diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c
> index 3630f0a..ab199f4 100644
> --- a/arch/arm/mach-davinci/da8xx-dt.c
> +++ b/arch/arm/mach-davinci/da8xx-dt.c
> @@ -100,7 +100,6 @@ DT_MACHINE_START(DA850_DT, "Generic DA850/OMAP-L138/AM18x")
>  	.init_machine	= da850_init_machine,
>  	.dt_compat	= da850_boards_compat,
>  	.init_late	= davinci_init_late,
> -	.restart	= da8xx_restart,
>  MACHINE_END
>  
>  #endif
> diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
> index 6724a8d..272e12e 100644
> --- a/arch/arm/mach-davinci/devices-da8xx.c
> +++ b/arch/arm/mach-davinci/devices-da8xx.c
> @@ -371,19 +371,6 @@ static struct platform_device da8xx_wdt_device = {
>  	.resource	= da8xx_watchdog_resources,
>  };
>  
> -void da8xx_restart(enum reboot_mode mode, const char *cmd)
> -{
> -	struct device *dev;
> -
> -	dev = bus_find_device_by_name(&platform_bus_type, NULL, "davinci-wdt");
> -	if (!dev) {
> -		pr_err("%s: failed to find watchdog device\n", __func__);
> -		return;
> -	}
> -
> -	davinci_watchdog_reset(to_platform_device(dev));
> -}
> -
>  int __init da8xx_register_watchdog(void)
>  {
>  	return platform_device_register(&da8xx_wdt_device);
> diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c
> index 3ae70f2..0edda40 100644
> --- a/arch/arm/mach-davinci/devices.c
> +++ b/arch/arm/mach-davinci/devices.c
> @@ -282,18 +282,13 @@ static struct resource wdt_resources[] = {
>  	},
>  };
>  
> -struct platform_device davinci_wdt_device = {
> +static struct platform_device davinci_wdt_device = {
>  	.name		= "davinci-wdt",
>  	.id		= -1,
>  	.num_resources	= ARRAY_SIZE(wdt_resources),
>  	.resource	= wdt_resources,
>  };
>  
> -void davinci_restart(enum reboot_mode mode, const char *cmd)
> -{
> -	davinci_watchdog_reset(&davinci_wdt_device);
> -}
> -
>  int davinci_init_wdt(void)
>  {
>  	return platform_device_register(&davinci_wdt_device);
> diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h
> index 69a0ad9..f0d5e858 100644
> --- a/arch/arm/mach-davinci/include/mach/common.h
> +++ b/arch/arm/mach-davinci/include/mach/common.h
> @@ -80,7 +80,6 @@ extern struct davinci_soc_info davinci_soc_info;
>  
>  extern void davinci_common_init(const struct davinci_soc_info *soc_info);
>  extern void davinci_init_ide(void);
> -void davinci_restart(enum reboot_mode mode, const char *cmd);
>  void davinci_init_late(void);
>  
>  #ifdef CONFIG_DAVINCI_RESET_CLOCKS
> diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
> index dd12e39..3481a0d 100644
> --- a/arch/arm/mach-davinci/include/mach/da8xx.h
> +++ b/arch/arm/mach-davinci/include/mach/da8xx.h
> @@ -121,7 +121,6 @@ int da850_register_vpif_display
>  			(struct vpif_display_config *display_config);
>  int da850_register_vpif_capture
>  			(struct vpif_capture_config *capture_config);
> -void da8xx_restart(enum reboot_mode mode, const char *cmd);
>  void da8xx_rproc_reserve_cma(void);
>  int da8xx_register_rproc(void);
>  int da850_register_gpio(void);
> diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
> index 034f865..1bb991a 100644
> --- a/arch/arm/mach-davinci/time.c
> +++ b/arch/arm/mach-davinci/time.c
> @@ -80,13 +80,6 @@ enum {
>  #define TGCR_UNRESET                 0x1
>  #define TGCR_RESET_MASK              0x3
>  
> -#define WDTCR_WDEN_SHIFT             14
> -#define WDTCR_WDEN_DISABLE           0x0
> -#define WDTCR_WDEN_ENABLE            0x1
> -#define WDTCR_WDKEY_SHIFT            16
> -#define WDTCR_WDKEY_SEQ0             0xa5c6
> -#define WDTCR_WDKEY_SEQ1             0xda7e
> -
>  struct timer_s {
>  	char *name;
>  	unsigned int id;
> @@ -409,53 +402,3 @@ void __init davinci_timer_init(void)
>  	for (i=0; i< ARRAY_SIZE(timers); i++)
>  		timer32_config(&timers[i]);
>  }
> -
> -/* reset board using watchdog timer */
> -void davinci_watchdog_reset(struct platform_device *pdev)
> -{
> -	u32 tgcr, wdtcr;
> -	void __iomem *base;
> -	struct clk *wd_clk;
> -
> -	base = ioremap(pdev->resource[0].start, SZ_4K);
> -	if (WARN_ON(!base))
> -		return;
> -
> -	wd_clk = clk_get(&pdev->dev, NULL);
> -	if (WARN_ON(IS_ERR(wd_clk)))
> -		return;
> -	clk_prepare_enable(wd_clk);
> -
> -	/* disable, internal clock source */
> -	__raw_writel(0, base + TCR);
> -
> -	/* reset timer, set mode to 64-bit watchdog, and unreset */
> -	tgcr = 0;
> -	__raw_writel(tgcr, base + TGCR);
> -	tgcr = TGCR_TIMMODE_64BIT_WDOG << TGCR_TIMMODE_SHIFT;
> -	tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
> -		(TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
> -	__raw_writel(tgcr, base + TGCR);
> -
> -	/* clear counter and period regs */
> -	__raw_writel(0, base + TIM12);
> -	__raw_writel(0, base + TIM34);
> -	__raw_writel(0, base + PRD12);
> -	__raw_writel(0, base + PRD34);
> -
> -	/* put watchdog in pre-active state */
> -	wdtcr = __raw_readl(base + WDTCR);
> -	wdtcr = (WDTCR_WDKEY_SEQ0 << WDTCR_WDKEY_SHIFT) |
> -		(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
> -	__raw_writel(wdtcr, base + WDTCR);
> -
> -	/* put watchdog in active state */
> -	wdtcr = (WDTCR_WDKEY_SEQ1 << WDTCR_WDKEY_SHIFT) |
> -		(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
> -	__raw_writel(wdtcr, base + WDTCR);
> -
> -	/* write an invalid value to the WDKEY field to trigger
> -	 * a watchdog reset */
> -	wdtcr = 0x00004000;
> -	__raw_writel(wdtcr, base + WDTCR);
> -}

^ permalink raw reply

* arm64: unhandled level 0 translation fault
From: Geert Uytterhoeven @ 2017-12-14 14:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMuHMdXh_6FaV-SFGWxcBb1-NNGYngDrYnnWA=9Y6xmRAkcxqg@mail.gmail.com>

Hi Catalin, Will, Dave,

On Tue, Dec 12, 2017 at 11:20 AM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> During userspace (Debian jessie NFS root) boot on arm64:
>
> rpcbind[1083]: unhandled level 0 translation fault (11) at 0x00000008,
> esr 0x92000004, in dash[aaaaadf77000+1a000]
> CPU: 0 PID: 1083 Comm: rpcbind Not tainted
> 4.15.0-rc3-arm64-renesas-02176-g14f9a1826e48e355 #51
> Hardware name: Renesas Salvator-X 2nd version board based on r8a7795 ES2.0+ (DT)

This is a quad Cortex A57.

> pstate: 80000000 (Nzcv daif -PAN -UAO)
> pc : 0xaaaaadf8a51c
> lr : 0xaaaaadf8ac08
> sp : 0000ffffcffeac00
> x29: 0000ffffcffeac00 x28: 0000aaaaadfa1000
> x27: 0000ffffcffebf7c x26: 0000ffffcffead20
> x25: 0000aaaacea1c5f0 x24: 0000000000000000
> x23: 0000aaaaadfa1000 x22: 0000aaaaadfa1000
> x21: 0000000000000000 x20: 0000000000000008
> x19: 0000000000000000 x18: 0000ffffcffeb500
> x17: 0000ffffa22babfc x16: 0000aaaaadfa1ae8
> x15: 0000ffffa2363588 x14: ffffffffffffffff
> x13: 0000000000000020 x12: 0000000000000010
> x11: 0101010101010101 x10: 0000aaaaadfa1000
> x9 : 00000000ffffff81 x8 : 0000aaaaadfa2000
> x7 : 0000000000000000 x6 : 0000000000000000
> x5 : 0000aaaaadfa2338 x4 : 0000aaaaadfa2000
> x3 : 0000aaaaadfa2338 x2 : 0000000000000000
> x1 : 0000aaaaadfa28b0 x0 : 0000aaaaadfa4c30
>
> Sometimes it happens with other processes, but the main address, esr, and
> pstate values are always the same.
>
> I regularly run arm64/for-next/core (through bi-weekly renesas-drivers
> releases, so the last time was two weeks ago), but never saw the issue
> before until today, so probably v4.15-rc1 is OK.
> Unfortunately it doesn't happen during every boot, which makes it
> cumbersome to bisect.
>
> My first guess was UNMAP_KERNEL_AT_EL0, but even after disabling that,
> and even without today's arm64/for-next/core merged in, I still managed to
> reproduce the issue, so I believe it was introduced in v4.15-rc2 or
> v4.15-rc3.
>
> Once, when the kernel message above wasn't shown, I got an error from
> userspace, which may be related:
> *** Error in `/bin/sh': free(): invalid pointer: 0x0000aaaadd970988 ***

With more boots (10 instead of 6) to declare a kernel good, I bisected this
to commit 9de52a755cfb6da5 ("arm64: fpsimd: Fix failure to restore FPSIMD
state after signals").

Reverting that commit on top of v4.15-rc3 fixed the issue for me.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [RFC PATCH 7/7] ARM: dts: at91-sama5d2_xplained: remove gpios from pinmux
From: Ludovic Desroches @ 2017-12-14 14:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171214142138.23008-1-ludovic.desroches@microchip.com>

As we can setup the pin configuration of a GPIO through the gpiolib,
enable the pinmuxing strict mode and remove GPIOs from the pinmuxing.

Signed-off-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
 arch/arm/boot/dts/at91-sama5d2_xplained.dts | 45 +++++------------------------
 1 file changed, 7 insertions(+), 38 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index 56de21de2779..9e0bf162e6bd 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -68,20 +68,16 @@
 
 	ahb {
 		usb0: gadget at 300000 {
-			atmel,vbus-gpio = <&pioA PIN_PA31 GPIO_ACTIVE_HIGH>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_usba_vbus>;
+			atmel,vbus-gpio = <&pioA PIN_PA31 (GPIO_ACTIVE_LOW | GPIO_BIAS_PULL_UP)>;
 			status = "okay";
 		};
 
 		usb1: ohci at 400000 {
 			num-ports = <3>;
 			atmel,vbus-gpio = <0 /* &pioA PIN_PB9 GPIO_ACTIVE_HIGH */
-					   &pioA PIN_PB10 GPIO_ACTIVE_HIGH
+					   &pioA PIN_PB10 (GPIO_ACTIVE_LOW | GPIO_BIAS_PULL_UP)
 					   0
 					  >;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_usb_default>;
 			status = "okay";
 		};
 
@@ -325,6 +321,7 @@
 			};
 
 			pinctrl at fc038000 {
+				atmel,use-strict-mode;
 				/*
 				 * There is no real pinmux for ADC, if the pin
 				 * is not requested by another peripheral then
@@ -412,18 +409,6 @@
 					bias-disable;
 				};
 
-				pinctrl_key_gpio_default: key_gpio_default {
-					pinmux = <PIN_PB9__GPIO>;
-					bias-pull-up;
-				};
-
-				pinctrl_led_gpio_default: led_gpio_default {
-					pinmux = <PIN_PB0__GPIO>,
-						 <PIN_PB5__GPIO>,
-						 <PIN_PB6__GPIO>;
-					bias-pull-up;
-				};
-
 				pinctrl_macb0_default: macb0_default {
 					pinmux = <PIN_PB14__GTXCK>,
 						 <PIN_PB15__GTXEN>,
@@ -509,16 +494,6 @@
 					bias-disable;
 				};
 
-				pinctrl_usb_default: usb_default {
-					pinmux = <PIN_PB10__GPIO>;
-					bias-disable;
-				};
-
-				pinctrl_usba_vbus: usba_vbus {
-					pinmux = <PIN_PA31__GPIO>;
-					bias-disable;
-				};
-
 				pinctrl_pwm0_pwm2_default: pwm0_pwm2_default {
 					pinmux = <PIN_PB5__PWMH2>,
 						 <PIN_PB6__PWML2>;
@@ -544,13 +519,9 @@
 
 	gpio_keys {
 		compatible = "gpio-keys";
-
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_key_gpio_default>;
-
 		bp1 {
 			label = "PB_USER";
-			gpios = <&pioA PIN_PB9 GPIO_ACTIVE_LOW>;
+			gpios = <&pioA PIN_PB9 (GPIO_ACTIVE_LOW | GPIO_BIAS_PULL_UP)>;
 			linux,code = <0x104>;
 			wakeup-source;
 		};
@@ -558,24 +529,22 @@
 
 	leds {
 		compatible = "gpio-leds";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_led_gpio_default>;
 		status = "okay"; /* conflict with pwm0 */
 
 		red {
 			label = "red";
-			gpios = <&pioA PIN_PB6 GPIO_ACTIVE_LOW>;
+			gpios = <&pioA PIN_PB6 (GPIO_ACTIVE_LOW | GPIO_BIAS_PULL_UP)>;
 		};
 
 
 		green {
 			label = "green";
-			gpios = <&pioA PIN_PB5 GPIO_ACTIVE_LOW>;
+			gpios = <&pioA PIN_PB5 (GPIO_ACTIVE_LOW | GPIO_BIAS_PULL_UP)>;
 		};
 
 		blue {
 			label = "blue";
-			gpios = <&pioA PIN_PB0 GPIO_ACTIVE_LOW>;
+			gpios = <&pioA PIN_PB0 (GPIO_ACTIVE_LOW | GPIO_BIAS_PULL_UP)>;
 			linux,default-trigger = "heartbeat";
 		};
 	};
-- 
2.12.2

^ permalink raw reply related

* [RFC PATCH 6/7] pinctrl: at91-pio4: use strict mode if explicitly requested
From: Ludovic Desroches @ 2017-12-14 14:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171214142138.23008-1-ludovic.desroches@microchip.com>

Add a property to use pinmux strict mode. It corresponds to the
legacy behavior of the controller. It was not used because there
were no solution to configure (open drain, bias, etc) a pin
requested as a GPIO.

If the strict mode is used by default, it will break several boards.
The owner of a GPIO requested by a device is not the device itself
but the pinctrl. So there is an ownership mismatch since the owner
of the pinmuxing is the device which requested it. It will lead to
an error when requesting the GPIO.

By adding a DT property, we can enable it only for DTs which are
written correctly.

The gpio_request_enable operation is needed to mux the pin as a
GPIO but it has to be used only if strict mode is enabled. If not,
a pin muxed to a device may be muxed to a GPIO silently.

Signed-off-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
 .../bindings/pinctrl/atmel,at91-pio4-pinctrl.txt   |  4 ++++
 drivers/pinctrl/pinctrl-at91-pio4.c                | 24 +++++++++++++++++++++-
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
index 61ac75706cc9..440cb5687b4e 100644
--- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
@@ -11,6 +11,10 @@ Required properties:
 - #interrupt-cells: should be two.
 - gpio-controller: mark the device node as a gpio controller.
 - #gpio-cells: should be two.
+Optional properties:
+- atmel,use-strict-mode: enable the pinmux strict mode which prevents
+simultaneous use of the same pin for GPIO and another function. It implies to
+not put a pin requested as a GPIO in the pinmux property.
 
 Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
 a general description of GPIO and interrupt bindings.
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index 4b8dda770af8..6acbbcc9b4a6 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -358,6 +358,8 @@ static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 }
 
 static struct gpio_chip atmel_gpio_chip = {
+	.request		= gpiochip_generic_request,
+	.free			= gpiochip_generic_free,
 	.direction_input        = atmel_gpio_direction_input,
 	.get                    = atmel_gpio_get,
 	.direction_output       = atmel_gpio_direction_output,
@@ -644,7 +646,22 @@ static int atmel_pmx_set_mux(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
-static const struct pinmux_ops atmel_pmxops = {
+static int atmel_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
+					 struct pinctrl_gpio_range *range,
+					 unsigned offset)
+{
+	u32 conf;
+
+	conf = atmel_pin_config_read(pctldev, offset);
+	conf &= (~ATMEL_PIO_CFGR_FUNC_MASK);
+	atmel_pin_config_write(pctldev, offset, conf);
+
+	dev_dbg(pctldev->dev, "enable pin %u as GPIO\n", offset);
+
+	return 0;
+}
+
+static struct pinmux_ops atmel_pmxops = {
 	.get_functions_count	= atmel_pmx_get_functions_count,
 	.get_function_name	= atmel_pmx_get_function_name,
 	.get_function_groups	= atmel_pmx_get_function_groups,
@@ -930,6 +947,11 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
 	atmel_pioctrl->nbanks = atmel_pioctrl_data->nbanks;
 	atmel_pioctrl->npins = atmel_pioctrl->nbanks * ATMEL_PIO_NPINS_PER_BANK;
 
+	if (of_property_read_bool(dev->of_node, "atmel,use-strict-mode")) {
+		atmel_pmxops.strict = true;
+		atmel_pmxops.gpio_request_enable = atmel_pmx_gpio_request_enable;
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(dev, "unable to get atmel pinctrl resource\n");
-- 
2.12.2

^ permalink raw reply related

* [RFC PATCH 5/7] pinctrl: at91-pio4: allow the gpiolib to set pin configuration
From: Ludovic Desroches @ 2017-12-14 14:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171214142138.23008-1-ludovic.desroches@microchip.com>

Use gpiochip_generic_config to allow the gpiolib to set pin
configuration. Since it relies on .pin_config_set(), add it too.
For this controller, one pin is on group so we can use
atmel_conf_pin_config_group_set() function.

Signed-off-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
 drivers/pinctrl/pinctrl-at91-pio4.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index b1ca838dd80a..4b8dda770af8 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -364,6 +364,7 @@ static struct gpio_chip atmel_gpio_chip = {
 	.set                    = atmel_gpio_set,
 	.to_irq                 = atmel_gpio_to_irq,
 	.base                   = 0,
+	.set_config		= gpiochip_generic_config,
 };
 
 /* --- PINCTRL --- */
@@ -817,6 +818,7 @@ static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev,
 }
 
 static const struct pinconf_ops atmel_confops = {
+	.pin_config_set		= atmel_conf_pin_config_group_set, /* In our case, a pin = a group */
 	.pin_config_group_get	= atmel_conf_pin_config_group_get,
 	.pin_config_group_set	= atmel_conf_pin_config_group_set,
 	.pin_config_dbg_show	= atmel_conf_pin_config_dbg_show,
-- 
2.12.2

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox