Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4/5] RFC: bus: 96boards Low-Speed Connector
From: Linus Walleij @ 2018-06-18  7:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618074556.6944-1-linus.walleij@linaro.org>

This illustrates my idea for using a small connector driver to
plug in "mezzanine boards" on the 96boards low-speed connector.

These "mezzanine boards" are no different than "capes", "logic
modules", etc. This thing, a non-discoverable connector where
a user can plug in a few peripherals has been reinvented a few
times.

As a proof-of-concept we add the Secure96, a quite minimal
mezzanine board.

Users can register their boards in a simple way. Either just
add their compatible-string in the device tree:

board {
        compatible = "96boards,secure96";
};

And if they can't even change three lines in their device tree,
or if they at runtime decide to plug in some board and test it,
they can use sysfs, as exemplified by plugging in the secure96
security board at runtime:

> cd /sys/devices/platform/connector
> echo 1 > secure96
[   61.014629] lscon connector: called mezzanine_store on secure96
[   61.020530] lscon connector: populate secure96
[   61.027081] at24 1-0050: 2048 byte 24c128 EEPROM, writable, 128 bytes/write
[   61.053569] atmel-ecc 1-0060: configuration zone is unlocked
[   61.502535] tpm_tis_spi spi0.0: 2.0 TPM (device-id 0x1B, rev-id 16)
(...)

The plug-in board can be removed from sysfs and added back
again multiple times like this with the devices being runtime
added and removed by two writes to sysfs.

> echo 0 > secure96
> echo 1 > secure96
> echo 0 > secure96
(...)

I certainly see some scalability problems with this particular
code for example, but the fact is: it pretty much works. The
devices need hooks in I2C and SPI, and need to be able to accept
initialized GPIO descriptors passed in as platform data.

Any discussions related to the concept compared to doing
device tree overlays/fragments etc: please discuss in patch
0 (the cover letter).

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 .../96boards-ls-connector.c                   | 307 ++++++++++++++++++
 .../96boards-mezzanines/96boards-mezzanines.h |  46 +++
 .../96boards-mezzanines/96boards-secure96.c   | 249 ++++++++++++++
 drivers/bus/96boards-mezzanines/Kconfig       |  36 ++
 drivers/bus/96boards-mezzanines/Makefile      |   6 +
 drivers/bus/Kconfig                           |   2 +
 drivers/bus/Makefile                          |   4 +-
 7 files changed, 649 insertions(+), 1 deletion(-)
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-ls-connector.c
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-mezzanines.h
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-secure96.c
 create mode 100644 drivers/bus/96boards-mezzanines/Kconfig
 create mode 100644 drivers/bus/96boards-mezzanines/Makefile

diff --git a/drivers/bus/96boards-mezzanines/96boards-ls-connector.c b/drivers/bus/96boards-mezzanines/96boards-ls-connector.c
new file mode 100644
index 000000000000..1a012b0cd457
--- /dev/null
+++ b/drivers/bus/96boards-mezzanines/96boards-ls-connector.c
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * 96boards Low-speed Connector driver
+ * (C) 2018 Linus Walleij <linus.walleij@linaro.org>
+ */
+
+#include <linux/init.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include "96boards-mezzanines.h"
+
+/**
+ * struct mezzanine - daughter boards (mezzanines) data
+ * Having dynamic data here means that we can only plug ONE board
+ * of each type. Stacking two different boards is fine. This
+ * should be fixed using a linked list of mezzanines if we
+ * go for this solution.
+ */
+struct mezzanine {
+	const char *compatible;
+	const char *sysfs_name;
+	struct dev_ext_attribute ext_attr;
+	void * (*populate) (struct lscon *ls);
+	void (*depopulate) (void *data);
+	void *data;
+};
+
+static struct mezzanine mezzanines[] = {
+#if IS_ENABLED(96BOARDS_SECURE96)
+	{
+		.compatible = "96boards,secure96",
+		.sysfs_name = "secure96",
+		.populate = secure96_populate,
+		.depopulate = secure96_depopulate,
+	},
+#endif
+	/* Add any other mezzanines here */
+};
+
+struct gpio_desc *mezzanine_ls_get_gpiod(struct lscon *ls,
+					 enum mezzanine_ls_gpio pin,
+					 const char *consumer_name,
+					 enum gpiod_flags flags)
+{
+	struct gpio_desc *retdesc;
+
+	/*
+	 * TODO: get all the LS GPIOs as an array on probe() then
+	 * the consumers can skip error handling of IS_ERR() descriptors
+	 * and this need only set the consumer name.
+	 */
+	retdesc = devm_gpiod_get_index(ls->dev, NULL, pin, flags);
+	if (!IS_ERR(retdesc) && consumer_name)
+		gpiod_set_consumer_name(retdesc, consumer_name);
+
+	return retdesc;
+}
+EXPORT_SYMBOL_GPL(mezzanine_ls_get_gpiod);
+
+/*
+ * Mezzanine boards will call this to orderly remove their claimed
+ * gpio descriptors, since we acquired them all with devm_gpiod_get()
+ * they will eventually be released once this connector device
+ * disappears if the board do not release them in order.
+ */
+void mezzanine_ls_put_gpiod(struct lscon *ls, struct gpio_desc *gpiod)
+{
+	devm_gpiod_put(ls->dev, gpiod);
+}
+EXPORT_SYMBOL_GPL(mezzanine_ls_put_gpiod);
+
+static ssize_t mezzanine_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct lscon *ls = dev_get_drvdata(dev);
+	struct dev_ext_attribute *d = container_of(attr,
+						   struct dev_ext_attribute,
+						   attr);
+	struct mezzanine *mez = d->var;
+
+	dev_info(ls->dev, "called %s on %s\n", __func__, mez->sysfs_name);
+	return 0;
+}
+
+static ssize_t mezzanine_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct lscon *ls = dev_get_drvdata(dev);
+	struct dev_ext_attribute *d = container_of(attr,
+						   struct dev_ext_attribute,
+						   attr);
+	struct mezzanine *mez = d->var;
+	unsigned long state;
+	int ret;
+
+	dev_info(ls->dev, "called %s on %s\n", __func__, mez->sysfs_name);
+
+	ret = kstrtoul(buf, 0, &state);
+	if (ret)
+		return ret;
+
+	if (state == 1) {
+		void *data;
+
+		/* Already populated */
+		if (mez->data)
+			return count;
+
+		data = mez->populate(ls);
+		if (IS_ERR(data))
+			return PTR_ERR(data);
+		mez->data = data;
+		return count;
+	}
+
+	if (state == 0) {
+		/* Not populated so nothing to do here */
+		if (!mez->data)
+			return count;
+		mez->depopulate(mez->data);
+		mez->data = NULL;
+		return count;
+	}
+
+	return -EINVAL;
+}
+
+/**
+ * This adds one sysfs file per mezzanine board that we support, so they
+ * can be probed and added from userspace.
+ */
+static int lscon_add_sysfs_mezzanines(struct lscon *ls)
+{
+	struct mezzanine *mez;
+	struct dev_ext_attribute *ext_attr;
+	int ret;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mezzanines); i++) {
+		mez = &mezzanines[i];
+		ext_attr = &mez->ext_attr;
+
+		ext_attr->var = mez;
+		ext_attr->attr.attr.name = mez->sysfs_name;
+		ext_attr->attr.attr.mode = VERIFY_OCTAL_PERMISSIONS(0644);
+		ext_attr->attr.show = mezzanine_show;
+		ext_attr->attr.store = mezzanine_store;
+		ret = device_create_file(ls->dev, &ext_attr->attr);
+		if (ret)
+			dev_err(ls->dev, "unable to create sysfs entries\n");
+
+	}
+
+	return 0;
+}
+
+static int lscon_probe_of_mezzanine(struct lscon *ls, struct device_node *np)
+{
+	struct mezzanine *mez;
+	void *data;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mezzanines); i++) {
+		mez = &mezzanines[i];
+		if (of_device_is_compatible(np, mez->compatible)) {
+			dev_info(ls->dev, "found %s\n", mez->compatible);
+			data = mez->populate(ls);
+			if (IS_ERR(data))
+				return PTR_ERR(data);
+			mez->data = data;
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static int lscon_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *child;
+	struct spi_controller *spi;
+	struct mezzanine *mez;
+	struct lscon *ls;
+	int ret;
+	int i;
+
+	ls = devm_kzalloc(dev, sizeof(*ls), GFP_KERNEL);
+	if (!ls)
+		return -ENOMEM;
+	ls->dev = dev;
+
+	/* Bridge I2C busses */
+	child = of_parse_phandle(np, "i2c0", 0);
+	if (!child) {
+		dev_err(dev, "no i2c0 phandle\n");
+		return -ENODEV;
+	}
+	ls->i2c0 = of_get_i2c_adapter_by_node(child);
+	if (!ls->i2c0) {
+		dev_err(dev, "no i2c0 adapter, deferring\n");
+		return -EPROBE_DEFER;
+	}
+
+	child = of_parse_phandle(np, "i2c1", 0);
+	if (!child) {
+		dev_err(dev, "no i2c1 phandle\n");
+		ret = -ENODEV;
+		goto out_put_i2c0;
+	}
+	ls->i2c1 = of_get_i2c_adapter_by_node(child);
+	if (!ls->i2c1) {
+		dev_err(dev, "no i2c0 adapter, deferring\n");
+		ret = -EPROBE_DEFER;
+		goto out_put_i2c0;
+	}
+
+	/* Bride SPI bus */
+	child = of_parse_phandle(np, "spi", 0);
+	if (!child) {
+		dev_err(dev, "no spi phandle\n");
+		ret = -ENODEV;
+		goto out_put_i2c1;
+	}
+	spi = of_find_spi_controller_by_node(child);
+	if (!spi) {
+		dev_err(dev, "no spi controller, deferring\n");
+		ret = -EPROBE_DEFER;
+		goto out_put_i2c1;
+	}
+	ls->spi = spi_controller_get(spi);
+	if (!ls->spi) {
+		dev_err(dev, "no spi reference\n");
+		ret = -ENODEV;
+		goto out_put_i2c1;
+	}
+
+	platform_set_drvdata(pdev, ls);
+
+	/* Get the mezzanine boards, stacking possible */
+	for_each_available_child_of_node(np, child)
+		lscon_probe_of_mezzanine(ls, child);
+
+	ret = lscon_add_sysfs_mezzanines(ls);
+	if (ret)
+		goto out_remove_mezzanines;
+
+	return 0;
+
+out_remove_mezzanines:
+	/* Depopulate any populated boards */
+	for (i = 0; i < ARRAY_SIZE(mezzanines); i++) {
+		mez = &mezzanines[i];
+		if (mez->data)
+			mez->depopulate(mez->data);
+		mez->data = NULL;
+	}
+out_put_i2c1:
+	i2c_put_adapter(ls->i2c1);
+out_put_i2c0:
+	i2c_put_adapter(ls->i2c0);
+	return ret;
+}
+
+static int lscon_remove(struct platform_device *pdev)
+{
+	struct lscon *ls = platform_get_drvdata(pdev);
+	struct mezzanine *mez;
+	int i;
+
+	/* Depopulate any populated boards */
+	for (i = 0; i < ARRAY_SIZE(mezzanines); i++) {
+		mez = &mezzanines[i];
+		if (mez->data)
+			mez->depopulate(mez->data);
+		mez->data = NULL;
+	}
+
+	spi_controller_put(ls->spi);
+	i2c_put_adapter(ls->i2c1);
+	i2c_put_adapter(ls->i2c0);
+
+	return 0;
+}
+
+static const struct of_device_id lscon_of_match[] = {
+	{
+		.compatible = "96boards,low-speed-connector",
+	},
+};
+
+static struct platform_driver lscon_driver = {
+	.driver = {
+		.name = "lscon",
+		.of_match_table = of_match_ptr(lscon_of_match),
+	},
+	.probe  = lscon_probe,
+	.remove = lscon_remove,
+};
+builtin_platform_driver(lscon_driver);
diff --git a/drivers/bus/96boards-mezzanines/96boards-mezzanines.h b/drivers/bus/96boards-mezzanines/96boards-mezzanines.h
new file mode 100644
index 000000000000..f6a460766ff3
--- /dev/null
+++ b/drivers/bus/96boards-mezzanines/96boards-mezzanines.h
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/of.h>
+#include <linux/i2c.h>
+#include <linux/gpio/consumer.h>
+
+/**
+ * enum mezzanine_ls_gpio - the GPIO lines on the low-speed connector
+ */
+enum mezzanine_ls_gpio {
+	MEZZANINE_LS_GPIO_A = 0,
+	MEZZANINE_LS_GPIO_B,
+	MEZZANINE_LS_GPIO_C,
+	MEZZANINE_LS_GPIO_D,
+	MEZZANINE_LS_GPIO_E,
+	MEZZANINE_LS_GPIO_F,
+	MEZZANINE_LS_GPIO_G,
+	MEZZANINE_LS_GPIO_H,
+	MEZZANINE_LS_GPIO_I,
+	MEZZANINE_LS_GPIO_J,
+	MEZZANINE_LS_GPIO_K,
+	MEZZANINE_LS_GPIO_L,
+};
+
+/**
+ * struct lscon - low speed connector state container
+ * @dev: containing device for this instance
+ */
+struct lscon {
+	struct device *dev;
+	struct i2c_adapter *i2c0;
+	struct i2c_adapter *i2c1;
+	struct spi_controller *spi;
+};
+
+struct gpio_desc *mezzanine_ls_get_gpiod(struct lscon *ls,
+					 enum mezzanine_ls_gpio pin,
+					 const char *consumer_name,
+					 enum gpiod_flags flags);
+void mezzanine_ls_put_gpiod(struct lscon *ls, struct gpio_desc *gpiod);
+
+#if IS_ENABLED(96BOARDS_SECURE96)
+void *secure96_populate(struct lscon *ls);
+void secure96_depopulate(void *data);
+#endif
+/* Add any other mezzanine population calls here */
diff --git a/drivers/bus/96boards-mezzanines/96boards-secure96.c b/drivers/bus/96boards-mezzanines/96boards-secure96.c
new file mode 100644
index 000000000000..6c44a699d2e0
--- /dev/null
+++ b/drivers/bus/96boards-mezzanines/96boards-secure96.c
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * 96boards Secure96 mezzanine board driver
+ * (C) 2018 Linus Walleij <linus.walleij@linaro.org>
+ */
+#include <linux/gpio/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/sizes.h>
+#include <linux/platform_data/at24.h>
+#include <linux/delay.h>
+
+#include "96boards-mezzanines.h"
+
+struct secure96 {
+	struct device *dev;
+	struct lscon *ls;
+	struct platform_device *leds_device;
+	struct gpio_led *secure96_leds;
+	struct i2c_client *eeprom;
+	struct i2c_client *crypto;
+	struct i2c_client *hash;
+	struct gpio_desc *tpm_reset;
+	struct gpio_desc *tpm_irq;
+	struct spi_device *tpm;
+};
+
+struct secure96_ledinfo {
+	enum mezzanine_ls_gpio pin;
+	const char *ledname;
+};
+
+/*
+ * GPIO-F, G, H and I are connected to LEDs, two red and two green
+ */
+static const struct secure96_ledinfo ledinfos[] = {
+	{
+		.pin = MEZZANINE_LS_GPIO_F,
+		.ledname = "secure96:red:0",
+	},
+	{
+		.pin = MEZZANINE_LS_GPIO_G,
+		.ledname = "secure96:red:1",
+	},
+	{
+		.pin = MEZZANINE_LS_GPIO_H,
+		.ledname = "secure96:green:0",
+	},
+	{
+		.pin = MEZZANINE_LS_GPIO_I,
+		.ledname = "secure96:green:1",
+	},
+};
+
+/*
+ * The On Semiconductor CAT21M01 is 131072bits i.e. 16KB. This should be
+ * mostly compatible to 24c128 so we register that with special pdata so
+ * that we can fill in the GPIO descriptor for write protect.
+ */
+static struct at24_platform_data secure96_eeprom_pdata = {
+	.byte_len = SZ_16K / 8,
+	.page_size = 256,
+	.flags = AT24_FLAG_ADDR16,
+};
+
+static const struct i2c_board_info secure96_eeprom = {
+	I2C_BOARD_INFO("24c128", 0x50),
+	.platform_data  = &secure96_eeprom_pdata,
+};
+
+/* Crypto chip */
+static const struct i2c_board_info secure96_crypto = {
+	I2C_BOARD_INFO("atecc508a", 0x60),
+};
+
+/* SHA hash chip */
+static const struct i2c_board_info secure96_hash = {
+	I2C_BOARD_INFO("atsha204a", 0x64),
+};
+
+/* Infineon SLB9670 TPM 2.0 chip */
+static struct spi_board_info secure96_tpm = {
+	.modalias = "tpm_tis_spi",
+	/* The manual says 22.5MHz for 1.8V supply */
+	.max_speed_hz = 22500000,
+	.chip_select = 0,
+};
+
+void *secure96_populate(struct lscon *ls)
+{
+	struct device *dev = ls->dev;
+	struct secure96 *sec;
+	struct gpio_desc *gpiod;
+	struct gpio_led_platform_data secure96_leds_pdata;
+	int ret;
+	int i;
+
+	/* TODO: create a struct device for secure96? */
+
+	sec = devm_kzalloc(dev, sizeof(*sec), GFP_KERNEL);
+	if (!sec)
+		return ERR_PTR(-ENOMEM);
+	sec->dev = dev;
+	sec->ls = ls;
+
+	sec->secure96_leds = devm_kzalloc(dev,
+			ARRAY_SIZE(ledinfos) * sizeof(*sec->secure96_leds),
+			GFP_KERNEL);
+	if (!sec->secure96_leds)
+		return ERR_PTR(-ENOMEM);
+
+	dev_info(ls->dev, "populate secure96\n");
+
+	/* Populate the four LEDs */
+	for (i = 0; i < ARRAY_SIZE(ledinfos); i++) {
+		const struct secure96_ledinfo *linfo;
+
+		linfo = &ledinfos[i];
+
+		gpiod = mezzanine_ls_get_gpiod(ls, linfo->pin, linfo->ledname,
+					       GPIOD_OUT_LOW);
+		if (IS_ERR(gpiod)) {
+			dev_err(dev, "failed to get GPIO line %d\n",
+				linfo->pin);
+			return ERR_PTR(-ENODEV);
+		}
+		sec->secure96_leds[i].gpiod = gpiod;
+		sec->secure96_leds[i].name = linfo->ledname;
+		/* Heartbeat on first LED */
+		if (i == 0)
+			sec->secure96_leds[i].default_trigger = "heartbeat";
+	}
+
+	secure96_leds_pdata.num_leds = ARRAY_SIZE(ledinfos);
+	secure96_leds_pdata.leds = sec->secure96_leds;
+
+	sec->leds_device = platform_device_register_data(dev,
+					"leds-gpio",
+					PLATFORM_DEVID_AUTO,
+					&secure96_leds_pdata,
+					sizeof(secure96_leds_pdata));
+	if (IS_ERR(sec->leds_device)) {
+		dev_err(dev, "failed to populate LEDs device\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	/* Populate the three I2C0 devices */
+	gpiod = mezzanine_ls_get_gpiod(ls, MEZZANINE_LS_GPIO_B, "cat21m01-wp",
+				       GPIOD_OUT_HIGH);
+	if (IS_ERR(gpiod))
+		dev_err(dev, "no CAT21M01 write-protect GPIO\n");
+	else
+		secure96_eeprom_pdata.wp_gpiod = gpiod;
+	sec->eeprom = i2c_new_device(ls->i2c0, &secure96_eeprom);
+	if (!sec->eeprom) {
+		dev_err(dev, "failed to populate EEPROM\n");
+		ret = -ENODEV;
+		goto out_unreg_leds;
+	}
+
+	sec->crypto = i2c_new_device(ls->i2c0, &secure96_crypto);
+	if (!sec->eeprom) {
+		dev_err(dev, "failed to populate crypto device\n");
+		ret = -ENODEV;
+		goto out_remove_eeprom;
+	}
+
+	sec->hash = i2c_new_device(ls->i2c0, &secure96_hash);
+	if (!sec->eeprom) {
+		dev_err(dev, "failed to populate hash device\n");
+		ret = -ENODEV;
+		goto out_remove_crypto;
+	}
+
+	/* Populate the SPI TPM device */
+	gpiod = mezzanine_ls_get_gpiod(ls, MEZZANINE_LS_GPIO_D,
+				       "tpm-slb9670-rst",
+				       GPIOD_OUT_LOW);
+	if (IS_ERR(gpiod)) {
+		dev_err(dev, "failed to get TPM RESET\n");
+		ret = -ENODEV;
+		goto out_remove_hash;
+	}
+	udelay(80);
+	/* Deassert RST */
+	gpiod_set_value(gpiod, 1);
+	sec->tpm_reset = gpiod;
+
+	gpiod = mezzanine_ls_get_gpiod(ls, MEZZANINE_LS_GPIO_C,
+				       "tpm-slb9670-irq",
+				       GPIOD_IN);
+	if (IS_ERR(gpiod)) {
+		dev_err(dev, "failed to get TPM IRQ GPIO\n");
+		ret = -ENODEV;
+		goto out_remove_tpm_reset;
+	}
+	sec->tpm_irq = gpiod;
+	secure96_tpm.irq = gpiod_to_irq(gpiod);
+	sec->tpm = spi_new_device(ls->spi, &secure96_tpm);
+	if (!sec->tpm) {
+		dev_err(dev, "failed to populate TPM device\n");
+		ret = -ENODEV;
+		goto out_remove_tpm_irq;
+	}
+
+	return sec;
+
+out_remove_tpm_irq:
+	mezzanine_ls_put_gpiod(ls, sec->tpm_irq);
+out_remove_tpm_reset:
+	mezzanine_ls_put_gpiod(ls, sec->tpm_reset);
+out_remove_hash:
+	i2c_unregister_device(sec->hash);
+out_remove_crypto:
+	i2c_unregister_device(sec->crypto);
+out_remove_eeprom:
+	i2c_unregister_device(sec->eeprom);
+	if (secure96_eeprom_pdata.wp_gpiod)
+		mezzanine_ls_put_gpiod(ls, secure96_eeprom_pdata.wp_gpiod);
+out_unreg_leds:
+	platform_device_unregister(sec->leds_device);
+	for (i = 0; i < ARRAY_SIZE(ledinfos); i++) {
+		mezzanine_ls_put_gpiod(ls, sec->secure96_leds[i].gpiod);
+	};
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(secure96_populate);
+
+void secure96_depopulate(void *data)
+{
+	struct secure96 *sec = data;
+	int i;
+
+	spi_unregister_device(sec->tpm);
+	mezzanine_ls_put_gpiod(sec->ls, sec->tpm_irq);
+	mezzanine_ls_put_gpiod(sec->ls, sec->tpm_reset);
+	i2c_unregister_device(sec->hash);
+	i2c_unregister_device(sec->crypto);
+	i2c_unregister_device(sec->eeprom);
+	if (secure96_eeprom_pdata.wp_gpiod)
+		mezzanine_ls_put_gpiod(sec->ls, secure96_eeprom_pdata.wp_gpiod);
+	platform_device_unregister(sec->leds_device);
+	for (i = 0; i < ARRAY_SIZE(ledinfos); i++) {
+		mezzanine_ls_put_gpiod(sec->ls, sec->secure96_leds[i].gpiod);
+	};
+}
+EXPORT_SYMBOL_GPL(secure96_depopulate);
diff --git a/drivers/bus/96boards-mezzanines/Kconfig b/drivers/bus/96boards-mezzanines/Kconfig
new file mode 100644
index 000000000000..18f94e9ec0f8
--- /dev/null
+++ b/drivers/bus/96boards-mezzanines/Kconfig
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# 96boards mezzanine connectors and drivers
+
+menuconfig 96BOARDS_MEZZANINES
+	bool "96boards mezzanine boards"
+
+if 96BOARDS_MEZZANINES
+
+config 96BOARDS_LS_CONNECTOR
+	bool "96boards low speed connector driver"
+	depends on OF
+	depends on I2C
+	depends on SPI_MASTER
+	depends on GPIOLIB
+	help
+	 Driver for the 96boards low speed connector
+
+config 96BOARDS_SECURE96
+	bool "96boards Secure96 board driver"
+	depends on 96BOARDS_LS_CONNECTOR
+	select NEW_LEDS
+	select LEDS_CLASS
+	select LEDS_GPIO
+	select EEPROM_AT24
+	select CRYPTO_HW
+	select CRYPTO_DEV_ATMEL_ECC
+	select HW_RANDOM
+	select TCG_TPM
+	select HW_RANDOM_TPM
+	select TCG_TIS
+	select TCG_TIS_SPI
+	help
+	 Driver for the 96boards Secure96 mezzanine
+
+endif
diff --git a/drivers/bus/96boards-mezzanines/Makefile b/drivers/bus/96boards-mezzanines/Makefile
new file mode 100644
index 000000000000..a6e1f3507672
--- /dev/null
+++ b/drivers/bus/96boards-mezzanines/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the 96boards mezzanines
+#
+obj-$(CONFIG_96BOARDS_LS_CONNECTOR)	+= 96boards-ls-connector.o
+obj-$(CONFIG_96BOARDS_SECURE96)		+= 96boards-secure96.o
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index d1c0b60e9326..46f7785f27e9 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -173,4 +173,6 @@ config DA8XX_MSTPRI
 
 source "drivers/bus/fsl-mc/Kconfig"
 
+source "drivers/bus/96boards-mezzanines/Kconfig"
+
 endmenu
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index b8f036cca7ff..f6d080a63bd7 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -29,5 +29,7 @@ obj-$(CONFIG_TI_SYSC)		+= ti-sysc.o
 obj-$(CONFIG_TS_NBUS)		+= ts-nbus.o
 obj-$(CONFIG_UNIPHIER_SYSTEM_BUS)	+= uniphier-system-bus.o
 obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o
-
 obj-$(CONFIG_DA8XX_MSTPRI)	+= da8xx-mstpri.o
+
+# 96boards mezzanines
+obj-$(CONFIG_96BOARDS_MEZZANINES)	+= 96boards-mezzanines/
-- 
2.17.0

^ permalink raw reply related

* [PATCH 5/5] RFC: ARM64: dts: Add Low-Speed Connector to ZCU100
From: Linus Walleij @ 2018-06-18  7:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618074556.6944-1-linus.walleij@linaro.org>

This adds the low-speed connector to the ZCU100 rev C device
tree (also known as the Ultra96 board).

This is a proof-of-concept only, showing how it is possible
to populate a Secure96 board using the other patches in the
series.

If you comment out or delete the board {} node, you can
populate/depopulate the board from sysfs instead.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 .../boot/dts/xilinx/zynqmp-zcu100-revC.dts    | 27 +++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts
index d62276e0e0a9..fc30497f248d 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts
@@ -110,6 +110,28 @@
 		compatible = "mmc-pwrseq-simple";
 		reset-gpios = <&gpio 7 GPIO_ACTIVE_LOW>; /* WIFI_EN */
 	};
+
+	lscon: connector {
+		compatible = "96boards,low-speed-connector";
+		i2c0 = <&i2csw_0>;
+		i2c1 = <&i2csw_1>;
+		spi = <&spi0>;
+		gpios = <&gpio 36 GPIO_ACTIVE_HIGH>, /* GPIO-A */
+		        <&gpio 37 GPIO_ACTIVE_HIGH>, /* GPIO-B */
+			<&gpio 39 GPIO_ACTIVE_HIGH>, /* GPIO-C */
+			<&gpio 40 GPIO_ACTIVE_HIGH>, /* GPIO-D */
+			<&gpio 44 GPIO_ACTIVE_HIGH>, /* GPIO-E */
+			<&gpio 45 GPIO_ACTIVE_HIGH>, /* GPIO-F */
+			<&gpio 78 GPIO_ACTIVE_HIGH>, /* GPIO-G */
+			<&gpio 79 GPIO_ACTIVE_HIGH>, /* GPIO-H */
+			<&gpio 80 GPIO_ACTIVE_HIGH>, /* GPIO-I */
+			<&gpio 81 GPIO_ACTIVE_HIGH>, /* GPIO-J */
+			<&gpio 82 GPIO_ACTIVE_HIGH>, /* GPIO-K */
+			<&gpio 83 GPIO_ACTIVE_HIGH>; /* GPIO-L */
+		board {
+			compatible = "96boards,secure96";
+		};
+	};
 };
 
 &dcc {
@@ -134,8 +156,9 @@
 			  "USB1_DIR", "USB1_DATA2", "USB1_NXT", "USB1_DATA0", "USB1_DATA1",
 			  "USB1_STP", "USB1_DATA3", "USB1_DATA4", "USB1_DATA5", "USB1_DATA6",
 			  "USB_DATA7", "WLAN_IRQ", "PMIC_IRQ", /* MIO end and EMIO start */
-			  "", "",
-			  "", "", "", "", "", "", "", "", "", "",
+			  "GPIO-G", "GPIO-H",
+			  "GPIO-I", "GPIO-J", "GPIO-K", "GPIO-L",
+			  "", "", "", "", "", "",
 			  "", "", "", "", "", "", "", "", "", "",
 			  "", "", "", "", "", "", "", "", "", "",
 			  "", "", "", "", "", "", "", "", "", "",
-- 
2.17.0

^ permalink raw reply related

* [PATCH v3 24/27] devicetree: fix a series of wrong file references
From: Alexandre Torgue @ 2018-06-18  7:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <bce1b59268ac2d659fd7cb37f89285ef2acc8316.1528990947.git.mchehab+samsung@kernel.org>



On 06/14/2018 06:09 PM, Mauro Carvalho Chehab wrote:
> As files got renamed, their references broke.
> 
> Manually fix a series of broken refs at the DT bindings.
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> ---

For stm32 part:

Acked-by: Alexandre TORGUE <alexandre.torgue@st.com>

Thanks
Alex


>   .../devicetree/bindings/input/rmi4/rmi_2d_sensor.txt |  2 +-
>   Documentation/devicetree/bindings/mfd/sun6i-prcm.txt |  2 +-
>   .../devicetree/bindings/pci/hisilicon-pcie.txt       |  2 +-
>   Documentation/devicetree/bindings/pci/kirin-pcie.txt |  2 +-
>   .../devicetree/bindings/pci/pci-keystone.txt         |  4 ++--
>   .../devicetree/bindings/sound/st,stm32-i2s.txt       |  2 +-
>   .../devicetree/bindings/sound/st,stm32-sai.txt       |  2 +-
>   MAINTAINERS                                          | 12 ++++++------
>   8 files changed, 14 insertions(+), 14 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/input/rmi4/rmi_2d_sensor.txt b/Documentation/devicetree/bindings/input/rmi4/rmi_2d_sensor.txt
> index f2c30c8b725d..9afffbdf6e28 100644
> --- a/Documentation/devicetree/bindings/input/rmi4/rmi_2d_sensor.txt
> +++ b/Documentation/devicetree/bindings/input/rmi4/rmi_2d_sensor.txt
> @@ -12,7 +12,7 @@ Additional documentation for F11 can be found at:
>   http://www.synaptics.com/sites/default/files/511-000136-01-Rev-E-RMI4-Interfacing-Guide.pdf
>   
>   Optional Touch Properties:
> -Description in Documentation/devicetree/bindings/input/touch
> +Description in Documentation/devicetree/bindings/input/touchscreen
>   - touchscreen-inverted-x
>   - touchscreen-inverted-y
>   - touchscreen-swapped-x-y
> diff --git a/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt b/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt
> index 4d21ffdb0fc1..daa091c2e67b 100644
> --- a/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt
> +++ b/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt
> @@ -8,7 +8,7 @@ Required properties:
>    - reg: The PRCM registers range
>   
>   The prcm node may contain several subdevices definitions:
> - - see Documentation/devicetree/clk/sunxi.txt for clock devices
> + - see Documentation/devicetree/bindings/clock/sunxi.txt for clock devices
>    - see Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt for reset
>      controller devices
>   
> diff --git a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
> index 7bf9df047a1e..0dcb87d6554f 100644
> --- a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
> @@ -3,7 +3,7 @@ HiSilicon Hip05 and Hip06 PCIe host bridge DT description
>   HiSilicon PCIe host controller is based on the Synopsys DesignWare PCI core.
>   It shares common functions with the PCIe DesignWare core driver and inherits
>   common properties defined in
> -Documentation/devicetree/bindings/pci/designware-pci.txt.
> +Documentation/devicetree/bindings/pci/designware-pcie.txt.
>   
>   Additional properties are described here:
>   
> diff --git a/Documentation/devicetree/bindings/pci/kirin-pcie.txt b/Documentation/devicetree/bindings/pci/kirin-pcie.txt
> index 6e217c63123d..6bbe43818ad5 100644
> --- a/Documentation/devicetree/bindings/pci/kirin-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/kirin-pcie.txt
> @@ -3,7 +3,7 @@ HiSilicon Kirin SoCs PCIe host DT description
>   Kirin PCIe host controller is based on the Synopsys DesignWare PCI core.
>   It shares common functions with the PCIe DesignWare core driver and
>   inherits common properties defined in
> -Documentation/devicetree/bindings/pci/designware-pci.txt.
> +Documentation/devicetree/bindings/pci/designware-pcie.txt.
>   
>   Additional properties are described here:
>   
> diff --git a/Documentation/devicetree/bindings/pci/pci-keystone.txt b/Documentation/devicetree/bindings/pci/pci-keystone.txt
> index 7e05487544ed..3d4a209b0fd0 100644
> --- a/Documentation/devicetree/bindings/pci/pci-keystone.txt
> +++ b/Documentation/devicetree/bindings/pci/pci-keystone.txt
> @@ -3,9 +3,9 @@ TI Keystone PCIe interface
>   Keystone PCI host Controller is based on the Synopsys DesignWare PCI
>   hardware version 3.65.  It shares common functions with the PCIe DesignWare
>   core driver and inherits common properties defined in
> -Documentation/devicetree/bindings/pci/designware-pci.txt
> +Documentation/devicetree/bindings/pci/designware-pcie.txt
>   
> -Please refer to Documentation/devicetree/bindings/pci/designware-pci.txt
> +Please refer to Documentation/devicetree/bindings/pci/designware-pcie.txt
>   for the details of DesignWare DT bindings.  Additional properties are
>   described here as well as properties that are not applicable.
>   
> diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
> index 4bda52042402..58c341300552 100644
> --- a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
> +++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
> @@ -18,7 +18,7 @@ Required properties:
>       See Documentation/devicetree/bindings/dma/stm32-dma.txt.
>     - dma-names: Identifier for each DMA request line. Must be "tx" and "rx".
>     - pinctrl-names: should contain only value "default"
> -  - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
> +  - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
>   
>   Optional properties:
>     - resets: Reference to a reset controller asserting the reset controller
> diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
> index f301cdf0b7e6..3a3fc506e43a 100644
> --- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
> +++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
> @@ -37,7 +37,7 @@ SAI subnodes required properties:
>   	"tx": if sai sub-block is configured as playback DAI
>   	"rx": if sai sub-block is configured as capture DAI
>     - pinctrl-names: should contain only value "default"
> -  - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
> +  - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
>   
>   SAI subnodes Optional properties:
>     - st,sync: specify synchronization mode.
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 67641f5bb373..69c9e9924902 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6965,7 +6965,7 @@ IIO MULTIPLEXER
>   M:	Peter Rosin <peda@axentia.se>
>   L:	linux-iio at vger.kernel.org
>   S:	Maintained
> -F:	Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
> +F:	Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
>   F:	drivers/iio/multiplexer/iio-mux.c
>   
>   IIO SUBSYSTEM AND DRIVERS
> @@ -9695,7 +9695,7 @@ MXSFB DRM DRIVER
>   M:	Marek Vasut <marex@denx.de>
>   S:	Supported
>   F:	drivers/gpu/drm/mxsfb/
> -F:	Documentation/devicetree/bindings/display/mxsfb-drm.txt
> +F:	Documentation/devicetree/bindings/display/mxsfb.txt
>   
>   MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
>   M:	Chris Lee <christopher.lee@cspi.com>
> @@ -10884,7 +10884,7 @@ M:	Will Deacon <will.deacon@arm.com>
>   L:	linux-pci at vger.kernel.org
>   L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
>   S:	Maintained
> -F:	Documentation/devicetree/bindings/pci/controller-generic-pci.txt
> +F:	Documentation/devicetree/bindings/pci/host-generic-pci.txt
>   F:	drivers/pci/controller/pci-host-common.c
>   F:	drivers/pci/controller/pci-host-generic.c
>   
> @@ -11065,7 +11065,7 @@ M:	Xiaowei Song <songxiaowei@hisilicon.com>
>   M:	Binghui Wang <wangbinghui@hisilicon.com>
>   L:	linux-pci at vger.kernel.org
>   S:	Maintained
> -F:	Documentation/devicetree/bindings/pci/pcie-kirin.txt
> +F:	Documentation/devicetree/bindings/pci/kirin-pcie.txt
>   F:	drivers/pci/controller/dwc/pcie-kirin.c
>   
>   PCIE DRIVER FOR HISILICON STB
> @@ -12456,7 +12456,7 @@ L:	linux-crypto at vger.kernel.org
>   L:	linux-samsung-soc at vger.kernel.org
>   S:	Maintained
>   F:	drivers/crypto/exynos-rng.c
> -F:	Documentation/devicetree/bindings/crypto/samsung,exynos-rng4.txt
> +F:	Documentation/devicetree/bindings/rng/samsung,exynos4-rng.txt
>   
>   SAMSUNG EXYNOS TRUE RANDOM NUMBER GENERATOR (TRNG) DRIVER
>   M:	?ukasz Stelmach <l.stelmach@samsung.com>
> @@ -13570,7 +13570,7 @@ F:	drivers/*/stm32-*timer*
>   F:	drivers/pwm/pwm-stm32*
>   F:	include/linux/*/stm32-*tim*
>   F:	Documentation/ABI/testing/*timer-stm32
> -F:	Documentation/devicetree/bindings/*/stm32-*timer
> +F:	Documentation/devicetree/bindings/*/stm32-*timer*
>   F:	Documentation/devicetree/bindings/pwm/pwm-stm32*
>   
>   STMMAC ETHERNET DRIVER
> 

^ permalink raw reply

* [PATCH v4 0/3] Add controls for VP8/VP9 profile
From: Keiichi Watanabe @ 2018-06-18  7:58 UTC (permalink / raw)
  To: linux-arm-kernel

Here is the 4th revision of the patch set that adds controls for VP8/VP9
profiles. Please see v3 cover letter for more details.
<https://lkml.org/lkml/2018/6/14/132>

In this version, I changed the contents that pointed out by Stanimir and Hans.

Changelog
----------

Version 4 changes:
- Remove unnecessary changes in venus drivers.
- Remove unnecessary blank lines in documentations.
- Fix typo and grammar mistakes.

Version 3 changes:
- Add V4L2_CID_MPEG_VIDEO_VP8_PROFILE in v4l2-controls.
- Make V4L2_CID_MPEG_VIDEO_VPX_PROFILE to be an alias of
  V4L2_CID_MPEG_VIDEO_VP8_PROFILE.
- Fix the use of V4L2_CID_MPEG_VIDEO_VPX_PROFILE in venus/s5p_mfc drivers.
- Small fix in mtk_vcodec_dec.

Version 2 changes:
- Support V4L2_CID_MPEG_VIDEO_VP9_PROFILE in MediaTek decoder's driver.

Version 1 changes:
- Add V4L2_CID_MPEG_VIDEO_VP9_PROFILE in v4l2-controls.

Keiichi Watanabe (3):
  media: v4l2-ctrl: Change control for VP8 profile to menu control
  media: v4l2-ctrl: Add control for VP9 profile
  media: mtk-vcodec: Support VP9 profile in decoder

 .../media/uapi/v4l/extended-controls.rst      | 48 +++++++++++++++++--
 .../platform/mtk-vcodec/mtk_vcodec_dec.c      |  5 ++
 .../media/platform/qcom/venus/vdec_ctrls.c    | 10 ++--
 drivers/media/platform/qcom/venus/venc.c      |  4 +-
 .../media/platform/qcom/venus/venc_ctrls.c    | 10 ++--
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c  | 15 +++---
 drivers/media/v4l2-core/v4l2-ctrls.c          | 23 ++++++++-
 include/uapi/linux/v4l2-controls.h            | 18 ++++++-
 8 files changed, 110 insertions(+), 23 deletions(-)

--
2.18.0.rc1.244.gcf134e6275-goog

^ permalink raw reply

* [PATCH v4 1/3] media: v4l2-ctrl: Change control for VP8 profile to menu control
From: Keiichi Watanabe @ 2018-06-18  7:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618075854.12881-1-keiichiw@chromium.org>

Add a menu control V4L2_CID_MPEG_VIDEO_VP8_PROFILE for VP8 profile and make
V4L2_CID_MPEG_VIDEO_VPX_PROFILE an alias of it. This new control is used to
select the desired profile for VP8 encoder and query for supported profiles by
VP8 encoder/decoder.

Though we have originally a control V4L2_CID_MPEG_VIDEO_VPX_PROFILE and its name
contains 'VPX', it works only for VP8 because supported profiles usually differ
between VP8 and VP9. In addition, this control cannot be used for querying since
it is not a menu control but an integer control, which cannot return an
arbitrary set of supported profiles.

The new control V4L2_CID_MPEG_VIDEO_VP8_PROFILE is a menu control as with
controls for other codec profiles. (e.g. H264)

In addition, this patch also fixes the use of V4L2_CID_MPEG_VIDEO_VPX_PROFILE in
drivers of Qualcomm's venus and Samsung's s5p-mfc.

Signed-off-by: Keiichi Watanabe <keiichiw@chromium.org>
---
 .../media/uapi/v4l/extended-controls.rst      | 25 ++++++++++++++++---
 .../media/platform/qcom/venus/vdec_ctrls.c    | 10 +++++---
 drivers/media/platform/qcom/venus/venc.c      |  4 +--
 .../media/platform/qcom/venus/venc_ctrls.c    | 10 +++++---
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c  | 15 ++++++-----
 drivers/media/v4l2-core/v4l2-ctrls.c          | 12 ++++++++-
 include/uapi/linux/v4l2-controls.h            | 11 +++++++-
 7 files changed, 64 insertions(+), 23 deletions(-)

diff --git a/Documentation/media/uapi/v4l/extended-controls.rst b/Documentation/media/uapi/v4l/extended-controls.rst
index 03931f9b1285..01ef31a934b4 100644
--- a/Documentation/media/uapi/v4l/extended-controls.rst
+++ b/Documentation/media/uapi/v4l/extended-controls.rst
@@ -1955,9 +1955,28 @@ enum v4l2_vp8_golden_frame_sel -
 ``V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP (integer)``
     Quantization parameter for a P frame for VP8.

-``V4L2_CID_MPEG_VIDEO_VPX_PROFILE (integer)``
-    Select the desired profile for VPx encoder. Acceptable values are 0,
-    1, 2 and 3 corresponding to encoder profiles 0, 1, 2 and 3.
+.. _v4l2-mpeg-video-vp8-profile:
+
+``V4L2_CID_MPEG_VIDEO_VP8_PROFILE``
+    (enum)
+
+enum v4l2_mpeg_video_vp8_profile -
+    This control allows selecting the profile for VP8 encoder.
+    This is also used to enumerate supported profiles by VP8 encoder or decoder.
+    Possible values are:
+
+.. flat-table::
+    :header-rows:  0
+    :stub-columns: 0
+
+    * - ``V4L2_MPEG_VIDEO_VP8_PROFILE_0``
+      - Profile 0
+    * - ``V4L2_MPEG_VIDEO_VP8_PROFILE_1``
+      - Profile 1
+    * - ``V4L2_MPEG_VIDEO_VP8_PROFILE_2``
+      - Profile 2
+    * - ``V4L2_MPEG_VIDEO_VP8_PROFILE_3``
+      - Profile 3


 High Efficiency Video Coding (HEVC/H.265) Control Reference
diff --git a/drivers/media/platform/qcom/venus/vdec_ctrls.c b/drivers/media/platform/qcom/venus/vdec_ctrls.c
index 032839bbc967..f4604b0cd57e 100644
--- a/drivers/media/platform/qcom/venus/vdec_ctrls.c
+++ b/drivers/media/platform/qcom/venus/vdec_ctrls.c
@@ -29,7 +29,7 @@ static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
 		break;
 	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
 	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
-	case V4L2_CID_MPEG_VIDEO_VPX_PROFILE:
+	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
 		ctr->profile = ctrl->val;
 		break;
 	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
@@ -54,7 +54,7 @@ static int vdec_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 	switch (ctrl->id) {
 	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
 	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
-	case V4L2_CID_MPEG_VIDEO_VPX_PROFILE:
+	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
 		ret = hfi_session_get_property(inst, ptype, &hprop);
 		if (!ret)
 			ctr->profile = hprop.profile_level.profile;
@@ -130,8 +130,10 @@ int vdec_ctrl_init(struct venus_inst *inst)
 	if (ctrl)
 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;

-	ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
-				 V4L2_CID_MPEG_VIDEO_VPX_PROFILE, 0, 3, 1, 0);
+	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
+				      V4L2_CID_MPEG_VIDEO_VP8_PROFILE,
+				      V4L2_MPEG_VIDEO_VP8_PROFILE_3,
+				      0, V4L2_MPEG_VIDEO_VP8_PROFILE_0);
 	if (ctrl)
 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;

diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
index 6b2ce479584e..cba6ef1e2d04 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -223,7 +223,7 @@ static int venc_v4l2_to_hfi(int id, int value)
 		case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC:
 			return HFI_H264_ENTROPY_CABAC;
 		}
-	case V4L2_CID_MPEG_VIDEO_VPX_PROFILE:
+	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
 		switch (value) {
 		case 0:
 		default:
@@ -756,7 +756,7 @@ static int venc_set_properties(struct venus_inst *inst)
 		level = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_H264_LEVEL,
 					 ctr->level.h264);
 	} else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_VP8) {
-		profile = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_VPX_PROFILE,
+		profile = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_VP8_PROFILE,
 					   ctr->profile.vpx);
 		level = 0;
 	} else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_MPEG4) {
diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c
index 21e938a28662..459101728d26 100644
--- a/drivers/media/platform/qcom/venus/venc_ctrls.c
+++ b/drivers/media/platform/qcom/venus/venc_ctrls.c
@@ -101,7 +101,7 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
 	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
 		ctr->profile.h264 = ctrl->val;
 		break;
-	case V4L2_CID_MPEG_VIDEO_VPX_PROFILE:
+	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
 		ctr->profile.vpx = ctrl->val;
 		break;
 	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
@@ -248,6 +248,11 @@ int venc_ctrl_init(struct venus_inst *inst)
 		V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES,
 		0, V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE);

+	v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_VP8_PROFILE,
+		V4L2_MPEG_VIDEO_VP8_PROFILE_3,
+		0, V4L2_MPEG_VIDEO_VP8_PROFILE_0);
+
 	v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
 		V4L2_CID_MPEG_VIDEO_BITRATE, BITRATE_MIN, BITRATE_MAX,
 		BITRATE_STEP, BITRATE_DEFAULT);
@@ -256,9 +261,6 @@ int venc_ctrl_init(struct venus_inst *inst)
 		V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, BITRATE_MIN, BITRATE_MAX,
 		BITRATE_STEP, BITRATE_DEFAULT_PEAK);

-	v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_VPX_PROFILE, 0, 3, 1, 0);
-
 	v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
 		V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 1, 51, 1, 26);

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index 570f391f2cfd..3ad4f5073002 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -692,12 +692,12 @@ static struct mfc_control controls[] = {
 		.default_value = 10,
 	},
 	{
-		.id = V4L2_CID_MPEG_VIDEO_VPX_PROFILE,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.minimum = 0,
-		.maximum = 3,
-		.step = 1,
-		.default_value = 0,
+		.id = V4L2_CID_MPEG_VIDEO_VP8_PROFILE,
+		.type = V4L2_CTRL_TYPE_MENU,
+		.minimum = V4L2_MPEG_VIDEO_VP8_PROFILE_0,
+		.maximum = V4L2_MPEG_VIDEO_VP8_PROFILE_3,
+		.default_value = V4L2_MPEG_VIDEO_VP8_PROFILE_0,
+		.menu_skip_mask = 0,
 	},
 	{
 		.id = V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
@@ -2057,7 +2057,7 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
 	case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP:
 		p->codec.vp8.rc_p_frame_qp = ctrl->val;
 		break;
-	case V4L2_CID_MPEG_VIDEO_VPX_PROFILE:
+	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
 		p->codec.vp8.profile = ctrl->val;
 		break;
 	case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
@@ -2711,4 +2711,3 @@ void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx)
 	f.fmt.pix_mp.pixelformat = DEF_DST_FMT_ENC;
 	ctx->dst_fmt = find_format(&f, MFC_FMT_ENC);
 }
-
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index d29e45516eb7..e7e6340b395e 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -431,6 +431,13 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		"Use Previous Specific Frame",
 		NULL,
 	};
+	static const char * const vp8_profile[] = {
+		"0",
+		"1",
+		"2",
+		"3",
+		NULL,
+	};

 	static const char * const flash_led_mode[] = {
 		"Off",
@@ -614,6 +621,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		return mpeg4_profile;
 	case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
 		return vpx_golden_frame_sel;
+	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
+		return vp8_profile;
 	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
 		return jpeg_chroma_subsampling;
 	case V4L2_CID_DV_TX_MODE:
@@ -839,7 +848,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_MPEG_VIDEO_VPX_MAX_QP:			return "VPX Maximum QP Value";
 	case V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP:		return "VPX I-Frame QP Value";
 	case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP:		return "VPX P-Frame QP Value";
-	case V4L2_CID_MPEG_VIDEO_VPX_PROFILE:			return "VPX Profile";
+	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:			return "VP8 Profile";

 	/* HEVC controls */
 	case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:		return "HEVC I-Frame QP Value";
@@ -1180,6 +1189,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_DEINTERLACING_MODE:
 	case V4L2_CID_TUNE_DEEMPHASIS:
 	case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
+	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
 	case V4L2_CID_DETECT_MD_MODE:
 	case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
 	case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 8d473c979b61..2001823c3072 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -587,7 +587,16 @@ enum v4l2_vp8_golden_frame_sel {
 #define V4L2_CID_MPEG_VIDEO_VPX_MAX_QP			(V4L2_CID_MPEG_BASE+508)
 #define V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP		(V4L2_CID_MPEG_BASE+509)
 #define V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP		(V4L2_CID_MPEG_BASE+510)
-#define V4L2_CID_MPEG_VIDEO_VPX_PROFILE			(V4L2_CID_MPEG_BASE+511)
+
+#define V4L2_CID_MPEG_VIDEO_VP8_PROFILE			(V4L2_CID_MPEG_BASE+511)
+enum v4l2_mpeg_video_vp8_profile {
+	V4L2_MPEG_VIDEO_VP8_PROFILE_0				= 0,
+	V4L2_MPEG_VIDEO_VP8_PROFILE_1				= 1,
+	V4L2_MPEG_VIDEO_VP8_PROFILE_2				= 2,
+	V4L2_MPEG_VIDEO_VP8_PROFILE_3				= 3,
+};
+/* Deprecated alias for compatibility reasons. */
+#define V4L2_CID_MPEG_VIDEO_VPX_PROFILE	V4L2_CID_MPEG_VIDEO_VP8_PROFILE

 /* CIDs for HEVC encoding. */

--
2.18.0.rc1.244.gcf134e6275-goog

^ permalink raw reply related

* [PATCH v4 2/3] media: v4l2-ctrl: Add control for VP9 profile
From: Keiichi Watanabe @ 2018-06-18  7:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618075854.12881-1-keiichiw@chromium.org>

Add a new control V4L2_CID_MPEG_VIDEO_VP9_PROFILE for VP9 profiles. This control
allows selecting the desired profile for VP9 encoder and querying for supported
profiles by VP9 encoder/decoder.

Though this control is similar to V4L2_CID_MPEG_VIDEO_VP8_PROFILE, we need to
separate this control from it because supported profiles usually differ between
VP8 and VP9.

Signed-off-by: Keiichi Watanabe <keiichiw@chromium.org>
---
 .../media/uapi/v4l/extended-controls.rst      | 23 +++++++++++++++++++
 drivers/media/v4l2-core/v4l2-ctrls.c          | 11 +++++++++
 include/uapi/linux/v4l2-controls.h            |  7 ++++++
 3 files changed, 41 insertions(+)

diff --git a/Documentation/media/uapi/v4l/extended-controls.rst b/Documentation/media/uapi/v4l/extended-controls.rst
index 01ef31a934b4..9f7312bf3365 100644
--- a/Documentation/media/uapi/v4l/extended-controls.rst
+++ b/Documentation/media/uapi/v4l/extended-controls.rst
@@ -1978,6 +1978,29 @@ enum v4l2_mpeg_video_vp8_profile -
     * - ``V4L2_MPEG_VIDEO_VP8_PROFILE_3``
       - Profile 3

+.. _v4l2-mpeg-video-vp9-profile:
+
+``V4L2_CID_MPEG_VIDEO_VP9_PROFILE``
+    (enum)
+
+enum v4l2_mpeg_video_vp9_profile -
+    This control allows selecting the profile for VP9 encoder.
+    This is also used to enumerate supported profiles by VP9 encoder or decoder.
+    Possible values are:
+
+.. flat-table::
+    :header-rows:  0
+    :stub-columns: 0
+
+    * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_0``
+      - Profile 0
+    * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_1``
+      - Profile 1
+    * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_2``
+      - Profile 2
+    * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_3``
+      - Profile 3
+

 High Efficiency Video Coding (HEVC/H.265) Control Reference
 -----------------------------------------------------------
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index e7e6340b395e..eacfab7574dc 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -438,6 +438,13 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		"3",
 		NULL,
 	};
+	static const char * const vp9_profile[] = {
+		"0",
+		"1",
+		"2",
+		"3",
+		NULL,
+	};

 	static const char * const flash_led_mode[] = {
 		"Off",
@@ -623,6 +630,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		return vpx_golden_frame_sel;
 	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
 		return vp8_profile;
+	case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
+		return vp9_profile;
 	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
 		return jpeg_chroma_subsampling;
 	case V4L2_CID_DV_TX_MODE:
@@ -849,6 +858,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP:		return "VPX I-Frame QP Value";
 	case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP:		return "VPX P-Frame QP Value";
 	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:			return "VP8 Profile";
+	case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:			return "VP9 Profile";

 	/* HEVC controls */
 	case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:		return "HEVC I-Frame QP Value";
@@ -1190,6 +1200,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_TUNE_DEEMPHASIS:
 	case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
 	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
+	case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
 	case V4L2_CID_DETECT_MD_MODE:
 	case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
 	case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 2001823c3072..f03d3214eec2 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -597,6 +597,13 @@ enum v4l2_mpeg_video_vp8_profile {
 };
 /* Deprecated alias for compatibility reasons. */
 #define V4L2_CID_MPEG_VIDEO_VPX_PROFILE	V4L2_CID_MPEG_VIDEO_VP8_PROFILE
+#define V4L2_CID_MPEG_VIDEO_VP9_PROFILE			(V4L2_CID_MPEG_BASE+512)
+enum v4l2_mpeg_video_vp9_profile {
+	V4L2_MPEG_VIDEO_VP9_PROFILE_0				= 0,
+	V4L2_MPEG_VIDEO_VP9_PROFILE_1				= 1,
+	V4L2_MPEG_VIDEO_VP9_PROFILE_2				= 2,
+	V4L2_MPEG_VIDEO_VP9_PROFILE_3				= 3,
+};

 /* CIDs for HEVC encoding. */

--
2.18.0.rc1.244.gcf134e6275-goog

^ permalink raw reply related

* [PATCH v4 3/3] media: mtk-vcodec: Support VP9 profile in decoder
From: Keiichi Watanabe @ 2018-06-18  7:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618075854.12881-1-keiichiw@chromium.org>

Add V4L2_CID_MPEG_VIDEO_VP9_PROFILE control in MediaTek decoder's
driver. MediaTek decoder only supports profile 0 for now.

Signed-off-by: Keiichi Watanabe <keiichiw@chromium.org>
---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
index 86f0a7134365..ba986232b953 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
@@ -1400,6 +1400,11 @@ int mtk_vcodec_dec_ctrls_setup(struct mtk_vcodec_ctx *ctx)
 				V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
 				0, 32, 1, 1);
 	ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+	v4l2_ctrl_new_std_menu(&ctx->ctrl_hdl,
+				&mtk_vcodec_dec_ctrl_ops,
+				V4L2_CID_MPEG_VIDEO_VP9_PROFILE,
+				V4L2_MPEG_VIDEO_VP9_PROFILE_0,
+				0, V4L2_MPEG_VIDEO_VP9_PROFILE_0);

 	if (ctx->ctrl_hdl.error) {
 		mtk_v4l2_err("Adding control failed %d",
--
2.18.0.rc1.244.gcf134e6275-goog

^ permalink raw reply related

* [PATCH 4.16 178/279] spi: bcm2835aux: ensure interrupts are enabled for shared handler
From: Greg Kroah-Hartman @ 2018-06-18  8:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618080608.851973560@linuxfoundation.org>

4.16-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Rob Herring <robh@kernel.org>

[ Upstream commit bc519d9574618e47a0c788000fb78da95e18d953 ]

The BCM2835 AUX SPI has a shared interrupt line (with AUX UART).
Downstream fixes this with an AUX irqchip to demux the IRQ sources and a
DT change which breaks compatibility with older kernels. The AUX irqchip
was already rejected for upstream[1] and the DT change would break
working systems if the DTB is updated to a newer one. The latter issue
was brought to my attention by Alex Graf.

The root cause however is a bug in the shared handler. Shared handlers
must check that interrupts are actually enabled before servicing the
interrupt. Add a check that the TXEMPTY or IDLE interrupts are enabled.

[1] https://patchwork.kernel.org/patch/9781221/

Cc: Alexander Graf <agraf@suse.de>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Eric Anholt <eric@anholt.net>
Cc: Stefan Wahren <stefan.wahren@i2se.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Ray Jui <rjui@broadcom.com>
Cc: Scott Branden <sbranden@broadcom.com>
Cc: bcm-kernel-feedback-list at broadcom.com
Cc: linux-spi at vger.kernel.org
Cc: linux-rpi-kernel at lists.infradead.org
Cc: linux-arm-kernel at lists.infradead.org
Signed-off-by: Rob Herring <robh@kernel.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/spi/spi-bcm2835aux.c |    5 +++++
 1 file changed, 5 insertions(+)

--- a/drivers/spi/spi-bcm2835aux.c
+++ b/drivers/spi/spi-bcm2835aux.c
@@ -184,6 +184,11 @@ static irqreturn_t bcm2835aux_spi_interr
 	struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
 	irqreturn_t ret = IRQ_NONE;
 
+	/* IRQ may be shared, so return if our interrupts are disabled */
+	if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) &
+	      (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE)))
+		return ret;
+
 	/* check if we have data to read */
 	while (bs->rx_len &&
 	       (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &

^ permalink raw reply

* [PATCH 1/3] drm: mxsfb: Change driver.name to mxsfb-drm
From: Stefan Agner @ 2018-06-18  8:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618074320.GS3438@phenom.ffwll.local>

On 18.06.2018 09:43, Daniel Vetter wrote:
> On Sat, Jun 16, 2018 at 01:32:44AM +0200, Marek Vasut wrote:
>> On 06/16/2018 12:42 AM, Leonard Crestez wrote:
>> > On Fri, 2018-06-15 at 23:36 +0200, Marek Vasut wrote:
>> >> On 06/15/2018 10:58 PM, Leonard Crestez wrote:
>> >>> On Fri, 2018-06-15 at 16:47 -0300, Fabio Estevam wrote:
>> >>>> On Fri, Jun 15, 2018 at 4:43 PM, Leonard Crestez
>> >>>> <leonard.crestez@nxp.com> wrote:
>> >
>> >>>>> The FBDEV driver uses the same name and both can't be registered at the
>> >>>>> same time. Fix this by renaming the drm driver to mxsfb-drm
>> >>>>
>> >>>> Stefan sent the same patch a few days ago:
>> >>>
>> >>> In that thread there is a proposal for removing the old fbdev/mxsfb
>> >>> driver entirely.
>> >>>
>> >>> That would break old DTBs, isn't this generally considered bad? Also,
>> >>> are we sure the removal of fbdev/mxsfb wouldn't lose any features?
>> >>>
>> >>> What my series does is make both drivers work with the same kernel
>> >>> image and turns the choice into a board-level dtb decision. Supporting
>> >>> everything at once seems desirable to me and it allows for a very
>> >>> smooth upgrade path.
>> >>
>> >> Having two drivers in the kernel with different set of bugs is always bad.
>> >>
>> >>> The old driver could be removed later, after all users are converted.
>> >>
>> >> Both drivers were in for long enough already. And let's be realistic,
>> >> how many MX23/MX28 users of old DTs with new kernels are there who
>> >> cannot update the DT as well ?
>> >
>> > Grepping for "display =" in arch/arm/boot/dts/imx* I see that old
>> > bindings are also used by 3rd-party boards for imx6/7:
>> >  * imx6sx-nitrogen6sx
>> >  * imx6ul-geam
>> >  * imx6ul-isiot
>> >  * imx6ul-opos6uldev
>> >  * imx6ul-pico-hobbit
>> >  * imx6ul-tx6ul
>> >  * imx7d-nitrogen7
>>
>> Er, yes, a handful of boards which could be updated :)
>>
>> > Converting everything might be quite a bit of work, and explicitly
>> > supporting old bindings is also work.
>>
>> Does adding support for old bindings justify the effort invested ? I
>> doubt so, it only adds more code to maintain.
>>
>> > It is very confusing that there is a whole set of displays for imx6/7
>> > which are supported by upstream but only with a non-default config.
>> > While it is extremely common in the embedded field to have custom
>> > configs the default one in the kernel should try to "just work".
>> >
>> > Couldn't this patch series be considered a bugfix? It was also
>> > surprisingly small.
>>
>> I think it's just a workaround which allows you to postpone the real
>> fix, and I don't like that.
> 
> Yeah agreed, imo the proper fix here would be to either update the dts for
> the affected boards and/or make mxsfb accept the old dt bindings for
> backwards compat. Artificially extending the life of the fbdev drivers
> seems silly.

We shouldn't have merged a DRM driver with a driver name which conflicts
with an existing driver... If anything, this is artificially shortening
the lifetime of the fbdev driver :-)

Again, I am ok with removing the driver. I just think it is silly to do
it just because of the conflicting driver name.

Maybe Sascha, original author of the mxs fbdev driver has an opinion on
this?

--
Stefan

^ permalink raw reply

* [PATCH 4.16 222/279] perf cs-etm: Support unknown_thread in cs_etm_auxtrace
From: Greg Kroah-Hartman @ 2018-06-18  8:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618080608.851973560@linuxfoundation.org>

4.16-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Leo Yan <leo.yan@linaro.org>

[ Upstream commit 46d53620044f7b574c0f3216f8b4f2ce3559ce31 ]

CoreSight doesn't allocate thread structure for unknown_thread in ETM
auxtrace, so unknown_thread is NULL pointer.  If the perf data doesn't
contain valid tid and then cs_etm__mem_access() uses unknown_thread
instead as thread handler, this results in a segmentation fault when
thread__find_addr_map() accesses the thread handler.

This commit creates a new thread data which is used by unknown_thread, so
CoreSight tracing can roll back to use unknown_thread if perf data
doesn't include valid thread info.  This commit also releases thread
data for initialization failure case and for normal auxtrace free flow.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
Acked-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: linux-arm-kernel at lists.infradead.org
Link: http://lkml.kernel.org/r/1525924920-4381-1-git-send-email-leo.yan at linaro.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 tools/perf/util/cs-etm.c |   24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -212,6 +212,7 @@ static void cs_etm__free(struct perf_ses
 	for (i = 0; i < aux->num_cpu; i++)
 		zfree(&aux->metadata[i]);
 
+	thread__zput(aux->unknown_thread);
 	zfree(&aux->metadata);
 	zfree(&aux);
 }
@@ -980,6 +981,23 @@ int cs_etm__process_auxtrace_info(union
 	etm->auxtrace.free = cs_etm__free;
 	session->auxtrace = &etm->auxtrace;
 
+	etm->unknown_thread = thread__new(999999999, 999999999);
+	if (!etm->unknown_thread)
+		goto err_free_queues;
+
+	/*
+	 * Initialize list node so that at thread__zput() we can avoid
+	 * segmentation fault at list_del_init().
+	 */
+	INIT_LIST_HEAD(&etm->unknown_thread->node);
+
+	err = thread__set_comm(etm->unknown_thread, "unknown", 0);
+	if (err)
+		goto err_delete_thread;
+
+	if (thread__init_map_groups(etm->unknown_thread, etm->machine))
+		goto err_delete_thread;
+
 	if (dump_trace) {
 		cs_etm__print_auxtrace_info(auxtrace_info->priv, num_cpu);
 		return 0;
@@ -994,16 +1012,18 @@ int cs_etm__process_auxtrace_info(union
 
 	err = cs_etm__synth_events(etm, session);
 	if (err)
-		goto err_free_queues;
+		goto err_delete_thread;
 
 	err = auxtrace_queues__process_index(&etm->queues, session);
 	if (err)
-		goto err_free_queues;
+		goto err_delete_thread;
 
 	etm->data_queued = etm->queues.populated;
 
 	return 0;
 
+err_delete_thread:
+	thread__zput(etm->unknown_thread);
 err_free_queues:
 	auxtrace_queues__free(&etm->queues);
 	session->auxtrace = NULL;

^ permalink raw reply

* [PATCH 4.14 116/189] spi: bcm2835aux: ensure interrupts are enabled for shared handler
From: Greg Kroah-Hartman @ 2018-06-18  8:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618081209.254234434@linuxfoundation.org>

4.14-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Rob Herring <robh@kernel.org>

[ Upstream commit bc519d9574618e47a0c788000fb78da95e18d953 ]

The BCM2835 AUX SPI has a shared interrupt line (with AUX UART).
Downstream fixes this with an AUX irqchip to demux the IRQ sources and a
DT change which breaks compatibility with older kernels. The AUX irqchip
was already rejected for upstream[1] and the DT change would break
working systems if the DTB is updated to a newer one. The latter issue
was brought to my attention by Alex Graf.

The root cause however is a bug in the shared handler. Shared handlers
must check that interrupts are actually enabled before servicing the
interrupt. Add a check that the TXEMPTY or IDLE interrupts are enabled.

[1] https://patchwork.kernel.org/patch/9781221/

Cc: Alexander Graf <agraf@suse.de>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Eric Anholt <eric@anholt.net>
Cc: Stefan Wahren <stefan.wahren@i2se.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Ray Jui <rjui@broadcom.com>
Cc: Scott Branden <sbranden@broadcom.com>
Cc: bcm-kernel-feedback-list at broadcom.com
Cc: linux-spi at vger.kernel.org
Cc: linux-rpi-kernel at lists.infradead.org
Cc: linux-arm-kernel at lists.infradead.org
Signed-off-by: Rob Herring <robh@kernel.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/spi/spi-bcm2835aux.c |    5 +++++
 1 file changed, 5 insertions(+)

--- a/drivers/spi/spi-bcm2835aux.c
+++ b/drivers/spi/spi-bcm2835aux.c
@@ -184,6 +184,11 @@ static irqreturn_t bcm2835aux_spi_interr
 	struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
 	irqreturn_t ret = IRQ_NONE;
 
+	/* IRQ may be shared, so return if our interrupts are disabled */
+	if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) &
+	      (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE)))
+		return ret;
+
 	/* check if we have data to read */
 	while (bs->rx_len &&
 	       (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &

^ permalink raw reply

* [PATCH v2 1/2] ARM: dts: imx6qdl-sabreauto: Add sensors
From: Leonard Crestez @ 2018-06-18  8:15 UTC (permalink / raw)
  To: linux-arm-kernel

The following sensors are on I2C3 on the baseboard:
* isil,isl29023 light sensor
* fsl,mag3110 magnetometer
* fsl,mma8451 accelerometer

Added under i2cmux/i2c at 1 because they're not otherwise accessible.

These are all supported by iio with following configs:
* CONFIG_SENSORS_ISL29018
* CONFIG_MAG3110
* CONFIG_MMA8452

Tested with raw reads from iio sysfs.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 arch/arm/boot/dts/imx6qdl-sabreauto.dtsi | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

Changes since v1:
 * adjusted node names (Fabio)

Link: https://lkml.org/lkml/2018/6/7/970

diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 0e28e36ddbb2..a59a0fd1eb02 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -153,10 +153,31 @@
 				compatible = "maxim,max7310";
 				reg = <0x34>;
 				gpio-controller;
 				#gpio-cells = <2>;
 			};
+
+			light-sensor at 44 {
+				compatible = "isil,isl29023";
+				reg = <0x44>;
+				interrupt-parent = <&gpio5>;
+				interrupts = <17 IRQ_TYPE_EDGE_FALLING>;
+			};
+
+			magnetometer at e {
+				compatible = "fsl,mag3110";
+				reg = <0x0e>;
+				interrupt-parent = <&gpio2>;
+				interrupts = <29 IRQ_TYPE_EDGE_RISING>;
+			};
+
+			accelerometer at 1c {
+				compatible = "fsl,mma8451";
+				reg = <0x1c>;
+				interrupt-parent = <&gpio6>;
+				interrupts = <31 IRQ_TYPE_LEVEL_LOW>;
+			};
 		};
 	};
 };
 
 &ipu1_csi0_from_ipu1_csi0_mux {
-- 
2.17.1

^ permalink raw reply related

* [PATCH v2 2/2] ARM: imx_v6_v7_defconfig: Enable imx6qdl-sabreauto sensors
From: Leonard Crestez @ 2018-06-18  8:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1be8dc197f842d3be31a15315594a25c8ad8f298.1529309235.git.leonard.crestez@nxp.com>

CONFIG_SENSORS_ISL29018 supports isil,il29023 light sensor
CONFIG_MMA8452 supports fsl,mma8451 accelerometer

CONFIG_MAG3110 for fsl,mag3110 is already enabled

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
---
 arch/arm/configs/imx_v6_v7_defconfig | 2 ++
 1 file changed, 2 insertions(+)

Changes since v1:
 * Added "ARM:" prefix in title (Fabio)

diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index f70507ab91ee..a647cbb0e59f 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -372,12 +372,14 @@ CONFIG_MXS_DMA=y
 CONFIG_STAGING=y
 CONFIG_STAGING_MEDIA=y
 CONFIG_VIDEO_IMX_MEDIA=y
 CONFIG_COMMON_CLK_PWM=y
 CONFIG_IIO=y
+CONFIG_MMA8452=y
 CONFIG_IMX7D_ADC=y
 CONFIG_VF610_ADC=y
+CONFIG_SENSORS_ISL29018=y
 CONFIG_MAG3110=y
 CONFIG_MPL3115=y
 CONFIG_PWM=y
 CONFIG_PWM_FSL_FTM=y
 CONFIG_PWM_IMX=y
-- 
2.17.1

^ permalink raw reply related

* [PATCH] Revert "drm/sun4i: Handle DRM_BUS_FLAG_PIXDATA_*EDGE"
From: Maxime Ripard @ 2018-06-18  8:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180613081647.31183-1-paul.kocialkowski@bootlin.com>

On Wed, Jun 13, 2018 at 10:16:47AM +0200, Paul Kocialkowski wrote:
> This reverts commit 2c17a4368aad2b88b68e4390c819e226cf320f70.
> 
> The offending commit triggers a run-time fault when accessing the panel
> element of the sun4i_tcon structure when no such panel is attached.
> 
> It was apparently assumed in said commit that a panel is always used with
> the TCON. Although it is often the case, this is not always true.
> For instance a bridge might be used instead of a panel.
> 
> This issue was discovered using an A13-OLinuXino, that uses the TCON
> in RGB mode for a simple DAC-based VGA bridge.
> 
> Cc: stable at vger.kernel.org
> Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>

Applied, thanks

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180618/9bd97802/attachment.sig>

^ permalink raw reply

* Charge counter on droid 4
From: Tony Lindgren @ 2018-06-18  8:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618074023.GA16955@amd>

* Pavel Machek <pavel@ucw.cz> [180618 07:43]:
> 
> So... there are mA, mAh values. Those come from hardware, and I
> believe we should keep them.
> 
> But there are also mW, mWh values, which are synthetic. Userland can
> compute them from mV, mA values... and it is confusing that kernel
> provides them. (My tendency was to start computing these synthetic
> values in userland, to compare them with "real hardware" values from
> kernel. But then I looked at kernel implementation, and realized they
> are synthetic, tooo...)

Hmm mWh value is based on the hardware sampled shunt
values and number of samples gathered between the
two readings. I'd rather call the calculated values
based on userland reading mV and mA values "synthetic" :)

Regards,

Tony

^ permalink raw reply

* [PATCH] mtd: nand: raw: atmel: add module param to avoid using dma
From: Boris Brezillon @ 2018-06-18  8:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180329131054.22506-1-peda@axentia.se>

On Thu, 29 Mar 2018 15:10:54 +0200
Peter Rosin <peda@axentia.se> wrote:

> On a sama5d31 with a Full-HD dual LVDS panel (132MHz pixel clock) NAND
> flash accesses have a tendency to cause display disturbances. Add a
> module param to disable DMA from the NAND controller, since that fixes
> the display problem for me.
> 
> Signed-off-by: Peter Rosin <peda@axentia.se>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

Miquel, can you queue this one to nand/next.

> ---
>  drivers/mtd/nand/raw/atmel/nand-controller.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
> index b2f00b398490..2ff7a77c7b8e 100644
> --- a/drivers/mtd/nand/raw/atmel/nand-controller.c
> +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
> @@ -129,6 +129,11 @@
>  #define DEFAULT_TIMEOUT_MS			1000
>  #define MIN_DMA_LEN				128
>  
> +static bool atmel_nand_avoid_dma __read_mostly;
> +
> +MODULE_PARM_DESC(avoiddma, "Avoid using DMA");
> +module_param_named(avoiddma, atmel_nand_avoid_dma, bool, 0400);
> +
>  enum atmel_nand_rb_type {
>  	ATMEL_NAND_NO_RB,
>  	ATMEL_NAND_NATIVE_RB,
> @@ -1977,7 +1982,7 @@ static int atmel_nand_controller_init(struct atmel_nand_controller *nc,
>  		return ret;
>  	}
>  
> -	if (nc->caps->has_dma) {
> +	if (nc->caps->has_dma && !atmel_nand_avoid_dma) {
>  		dma_cap_mask_t mask;
>  
>  		dma_cap_zero(mask);

^ permalink raw reply

* [PATCH v3 00/14] ARM: pxa: switch to DMA slave maps
From: Boris Brezillon @ 2018-06-18  8:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180617170217.24177-1-robert.jarzmik@free.fr>

Hi Robert,

On Sun, 17 Jun 2018 19:02:03 +0200
Robert Jarzmik <robert.jarzmik@free.fr> wrote:

> As I gathered almost all the required acks, this is an information only post
> before queuing to the PXA tree.

We'll need an immutable branch/tag containing those changes, just in
case other conflicting changes get submitted to the NAND driver.

Thanks,

Boris

^ permalink raw reply

* [PATCH v2 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
From: Leonard Crestez @ 2018-06-18  8:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180615095107.24610-3-o.rempel@pengutronix.de>

On Fri, 2018-06-15 at 11:51 +0200, Oleksij Rempel wrote:
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt

A recent patch was posted which adds a similar but different binding
for the MU on 8qm/8qxp SOCs:

https://patchwork.kernel.org/patch/10468885/

Looking at manuals side-by-side the hardware seems to be the same so
there should be a single binding. Right?

That series I pointed to uses the MU to implement a communication with
a special "SCU" core which runs NXP firmware for handling details like
power management. However imx8 socs also have other MUs and M4 cores
for customers to use pretty exactly like they would on 7d.

The hardware exposes a very generic interface and my impression is that
 drivers for the MU are actually highly specific to what is on the
other side of the MU. For example your driver code seems to be mapping
the 4 MU registers to separate "channels" but for SCU messages are
written in all registers in a round-robin way.

Shouldn't your MU-using driver be a separate node which references the
MU by phandle? Like in this patch:

https://patchwork.kernel.org/patch/10468887/

> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> new file mode 100644
> index 000000000000..1577b86f1206
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> @@ -0,0 +1,35 @@
> +i.MX Messaging Unit
> +===================
> +
> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most
> +cases they are accessible from all Processor Units. On one hand, at least for
> +mailbox functionality, it makes no difference which application or processor is
> +using which set of the MU. On other hand, the register sets for each of the MU
> +parts are not identical.
> +
> +Required properties:
> +- compatible :	Shell be one of:
> +                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
> +- reg :		physical base address of the mailbox and length of
> +		memory mapped region.
> +- #mbox-cells:	Common mailbox binding property to identify the number
> +		of cells required for the mailbox specifier. Should be 1.
> +- interrupts :	The interrupt number
> +- clocks     :  phandle to the input clock.
> +
> +Example:
> +	mu0a: mailbox at 30aa0000 {
> +		compatible = "fsl,imx7s-mu-a";
> +		reg = <0x30aa0000 0x28>;
> +		interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +		#mbox-cells = <1>;
> +	};
> +
> +	mu0b: mailbox at 30ab0000 {
> +		compatible = "fsl,imx7s-mu-b";
> +		reg = <0x30ab0000 0x28>;
> +		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +		#mbox-cells = <1>;
> +	};

^ permalink raw reply

* [PATCH V2 4/4] soc: imx: add SC firmware IPC and APIs
From: Leonard Crestez @ 2018-06-18  8:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1529239789-26849-5-git-send-email-aisheng.dong@nxp.com>

On Sun, 2018-06-17 at 20:49 +0800, Dong Aisheng wrote:
> The System Controller Firmware (SCFW) is a low-level system function
> which runs on a dedicated Cortex-M core to provide power, clock, and
> resource management. It exists on some i.MX8 processors. e.g. i.MX8QM
> (QM, QP), and i.MX8QX (QXP, DX).
> 
> This patch adds the SC firmware service APIs used by the system.
> It mainly consists of two parts:
> 1) Implementation of the IPC functions using MUs (client side).
> 2) SCU firmware services APIs implemented based on RPC calls

Most of the code in this patch is auto-generated but some of it (like
ipc.c) is not. Maybe that part should go to a separate patch?

It's otherwise difficult to tell which parts of this +5000 line patch
should be looked at by a human.

^ permalink raw reply

* [PATCH v2] mmc: sdhci-of-arasan: Add quirk for unstable clocks
From: Ulf Hansson @ 2018-06-18  8:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180615081830.zrgx6arwn6ga27gu@laureti-dev>

On 15 June 2018 at 10:18, Helmut Grohne <h.grohne@intenta.de> wrote:
> Some controllers immediately report SDHCI_CLOCK_INT_STABLE after
> enabling the clock even when the clock is not stable. When used in
> conjunction with older/slower cards, this can result in:
>
>     mmc0: error -84 whilst initialising SD card
>
> When the stable reporting is broken, we simply wait for the maximum
> stabilization period.
>
> Signed-off-by: Helmut Grohne <h.grohne@intenta.de>
> ---
>  Documentation/devicetree/bindings/mmc/arasan,sdhci.txt |  2 ++

Please split this. DT doc should be a separate patch.

Otherwise this looks good to me.

Kind regards
Uffe

>  drivers/mmc/host/sdhci-of-arasan.c                     | 16 ++++++++++++++++
>  2 files changed, 18 insertions(+)
>
> Changes since v1 (RFC):
>  * Use an arasan-specific quirk in the ->set_clock() callback as requested by
>    Adrian Hunter.
>
> diff --git a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
> index 60481bfc3d31..c0e0f04a8504 100644
> --- a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
> +++ b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
> @@ -39,6 +39,8 @@ Optional Properties:
>    - xlnx,fails-without-test-cd: when present, the controller doesn't work when
>      the CD line is not connected properly, and the line is not connected
>      properly. Test mode can be used to force the controller to function.
> +  - xlnx,int-clock-stable-broken: when present, the controller always reports
> +    that the internal clock is stable even when it is not.
>
>  Example:
>         sdhci at e0100000 {
> diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
> index c33a5f7393bd..f7fe26c75150 100644
> --- a/drivers/mmc/host/sdhci-of-arasan.c
> +++ b/drivers/mmc/host/sdhci-of-arasan.c
> @@ -102,6 +102,9 @@ struct sdhci_arasan_data {
>
>  /* Controller does not have CD wired and will not function normally without */
>  #define SDHCI_ARASAN_QUIRK_FORCE_CDTEST        BIT(0)
> +/* Controller immediately reports SDHCI_CLOCK_INT_STABLE after enabling the
> + * internal clock even when the clock isn't stable */
> +#define SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE BIT(1)
>  };
>
>  static const struct sdhci_arasan_soc_ctl_map rk3399_soc_ctl_map = {
> @@ -207,6 +210,16 @@ static void sdhci_arasan_set_clock(struct sdhci_host *host, unsigned int clock)
>
>         sdhci_set_clock(host, clock);
>
> +       if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE)
> +               /*
> +                * Some controllers immediately report SDHCI_CLOCK_INT_STABLE
> +                * after enabling the clock even though the clock is not
> +                * stable. Trying to use a clock without waiting here results
> +                * in EILSEQ while detecting some older/slower cards. The
> +                * chosen delay is the maximum delay from sdhci_set_clock.
> +                */
> +               msleep(20);
> +
>         if (ctrl_phy) {
>                 phy_power_on(sdhci_arasan->phy);
>                 sdhci_arasan->is_phy_on = true;
> @@ -759,6 +772,9 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
>         if (of_property_read_bool(np, "xlnx,fails-without-test-cd"))
>                 sdhci_arasan->quirks |= SDHCI_ARASAN_QUIRK_FORCE_CDTEST;
>
> +       if (of_property_read_bool(np, "xlnx,int-clock-stable-broken"))
> +               sdhci_arasan->quirks |= SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE;
> +
>         pltfm_host->clk = clk_xin;
>
>         if (of_device_is_compatible(pdev->dev.of_node,
> --
> 2.11.0
>

^ permalink raw reply

* [PATCH] soc: imx: gpc: fix PDN delay & improve readability
From: Sven Schmitt @ 2018-06-18  9:01 UTC (permalink / raw)
  To: linux-arm-kernel

- imx6_pm_domain_power_off(): reads iso and iso2sw
  from GPC_PGC_PUPSCR_OFFS which stores the power up delays
  => use GPC_PGC_PDNSCR_OFFS for the correct delays

- remove unused #defines

- struct imx_pm_domain: introduce cntr_pup_bit
  to replace usage of cntr_pdn_bit+1 in imx6_pm_domain_power_on()

- GPC_PGC_DOMAIN_*: made consistent use of index defines

Signed-off-by: Sven Schmitt <sven.schmitt@mixed-mode.de>
---
 drivers/soc/imx/gpc.c | 41 ++++++++++++++++++++---------------------
 1 file changed, 20 insertions(+), 21 deletions(-)

diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
index c4d35f32af8d..b92377c75ddf 100644
--- a/drivers/soc/imx/gpc.c
+++ b/drivers/soc/imx/gpc.c
@@ -24,15 +24,6 @@
 #define GPC_PGC_CTRL_OFFS	0x0
 #define GPC_PGC_PUPSCR_OFFS	0x4
 #define GPC_PGC_PDNSCR_OFFS	0x8
-#define GPC_PGC_SW2ISO_SHIFT	0x8
-#define GPC_PGC_SW_SHIFT	0x0
-
-#define GPC_PGC_GPU_PDN		0x260
-#define GPC_PGC_GPU_PUPSCR	0x264
-#define GPC_PGC_GPU_PDNSCR	0x268
-
-#define GPU_VPU_PUP_REQ		BIT(1)
-#define GPU_VPU_PDN_REQ		BIT(0)
 
 #define GPC_CLK_MAX		6
 
@@ -46,6 +37,7 @@ struct imx_pm_domain {
 	int num_clks;
 	unsigned int reg_offs;
 	signed char cntr_pdn_bit;
+	signed char cntr_pup_bit;
 	unsigned int ipg_rate_mhz;
 	unsigned int flags;
 };
@@ -66,7 +58,7 @@ static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
 		return -EBUSY;
 
 	/* Read ISO and ISO2SW power down delays */
-	regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
+	regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PDNSCR_OFFS, &val);
 	iso = val & 0x3f;
 	iso2sw = (val >> 8) & 0x3f;
 
@@ -116,7 +108,7 @@ static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)
 	sw2iso = (val >> 8) & 0x3f;
 
 	/* Request GPC to power up domain */
-	val = BIT(pd->cntr_pdn_bit + 1);
+	val = BIT(pd->cntr_pup_bit);
 	regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
 
 	/* Wait ISO + ISO2SW IPG clock cycles */
@@ -241,22 +233,24 @@ static struct platform_driver imx_pgc_power_domain_driver = {
 };
 builtin_platform_driver(imx_pgc_power_domain_driver)
 
-#define GPC_PGC_DOMAIN_ARM	0
-#define GPC_PGC_DOMAIN_PU	1
-#define GPC_PGC_DOMAIN_DISPLAY	2
-
 static struct genpd_power_state imx6_pm_domain_pu_state = {
 	.power_off_latency_ns = 25000,
 	.power_on_latency_ns = 2000000,
 };
 
+#define GPC_PGC_DOMAIN_ARM 0
+#define GPC_PGC_DOMAIN_PU 1
+#define GPC_PGC_DOMAIN_DISPLAY 2
+#define GPC_PGC_DOMAIN_PCI 3
+
 static struct imx_pm_domain imx_gpc_domains[] = {
-	{
+	[GPC_PGC_DOMAIN_ARM] {
 		.base = {
 			.name = "ARM",
 			.flags = GENPD_FLAG_ALWAYS_ON,
 		},
-	}, {
+	},
+	[GPC_PGC_DOMAIN_PU] {
 		.base = {
 			.name = "PU",
 			.power_off = imx6_pm_domain_power_off,
@@ -266,7 +260,9 @@ static struct imx_pm_domain imx_gpc_domains[] = {
 		},
 		.reg_offs = 0x260,
 		.cntr_pdn_bit = 0,
-	}, {
+		.cntr_pup_bit = 1,
+	},
+	[GPC_PGC_DOMAIN_DISPLAY] {
 		.base = {
 			.name = "DISPLAY",
 			.power_off = imx6_pm_domain_power_off,
@@ -274,7 +270,9 @@ static struct imx_pm_domain imx_gpc_domains[] = {
 		},
 		.reg_offs = 0x240,
 		.cntr_pdn_bit = 4,
-	}, {
+		.cntr_pup_bit = 5,
+	},
+	[GPC_PGC_DOMAIN_PCI] {
 		.base = {
 			.name = "PCI",
 			.power_off = imx6_pm_domain_power_off,
@@ -282,6 +280,7 @@ static struct imx_pm_domain imx_gpc_domains[] = {
 		},
 		.reg_offs = 0x200,
 		.cntr_pdn_bit = 6,
+		.cntr_pup_bit = 7,
 	},
 };
 
@@ -326,8 +325,8 @@ static const struct regmap_config imx_gpc_regmap_config = {
 };
 
 static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
-	&imx_gpc_domains[0].base,
-	&imx_gpc_domains[1].base,
+	&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base,
+	&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base,
 };
 
 static struct genpd_onecell_data imx_gpc_onecell_data = {
-- 
2.17.1

^ permalink raw reply related

* [PATCH] ARM: dts: rockchip: convert rk3288 to operating-points-v2
From: Viresh Kumar @ 2018-06-18  9:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180617131808.30283-1-heiko@sntech.de>

On 17-06-18, 15:18, Heiko Stuebner wrote:
> +	cpu_opp_table: cpu-opp-table {
> +		compatible = "operating-points-v2";
> +		opp-shared;
> +
> +		opp00 {

Most of the platforms write it as "opp-126000000". Maybe follow the same
nomenclature ?
-- 
viresh

^ permalink raw reply

* [PATCH] soc: imx: gpc: fix PDN delay & improve readability
From: Lucas Stach @ 2018-06-18  9:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1529312474617.59395@mixed-mode.de>

Am Montag, den 18.06.2018, 09:01 +0000 schrieb Sven Schmitt:
> - imx6_pm_domain_power_off(): reads iso and iso2sw
> ? from GPC_PGC_PUPSCR_OFFS which stores the power up delays
> ? => use GPC_PGC_PDNSCR_OFFS for the correct delays
> 
> - remove unused #defines
> 
> - struct imx_pm_domain: introduce cntr_pup_bit
> ? to replace usage of cntr_pdn_bit+1 in imx6_pm_domain_power_on()

I'm not sure I see the value in that one.
Otherwise this change looks fine.

Regards,
Lucas

> 
> - GPC_PGC_DOMAIN_*: made consistent use of index defines
> 
> Signed-off-by: Sven Schmitt <sven.schmitt@mixed-mode.de>
> ---
> ?drivers/soc/imx/gpc.c | 41 ++++++++++++++++++++---------------------
> ?1 file changed, 20 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
> index c4d35f32af8d..b92377c75ddf 100644
> --- a/drivers/soc/imx/gpc.c
> +++ b/drivers/soc/imx/gpc.c
> @@ -24,15 +24,6 @@
> ?#define GPC_PGC_CTRL_OFFS	0x0
> ?#define GPC_PGC_PUPSCR_OFFS	0x4
> ?#define GPC_PGC_PDNSCR_OFFS	0x8
> -#define GPC_PGC_SW2ISO_SHIFT	0x8
> -#define GPC_PGC_SW_SHIFT	0x0
> -
> -#define GPC_PGC_GPU_PDN		0x260
> -#define GPC_PGC_GPU_PUPSCR	0x264
> -#define GPC_PGC_GPU_PDNSCR	0x268
> -
> -#define GPU_VPU_PUP_REQ		BIT(1)
> -#define GPU_VPU_PDN_REQ		BIT(0)
> ?
> ?#define GPC_CLK_MAX		6
> ?
> @@ -46,6 +37,7 @@ struct imx_pm_domain {
> ?	int num_clks;
> ?	unsigned int reg_offs;
> ?	signed char cntr_pdn_bit;
> +	signed char cntr_pup_bit;
> ?	unsigned int ipg_rate_mhz;
> ?	unsigned int flags;
> ?};
> @@ -66,7 +58,7 @@ static int imx6_pm_domain_power_off(struct
> generic_pm_domain *genpd)
> ?		return -EBUSY;
> ?
> ?	/* Read ISO and ISO2SW power down delays */
> -	regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS,
> &val);
> +	regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PDNSCR_OFFS,
> &val);
> ?	iso = val & 0x3f;
> ?	iso2sw = (val >> 8) & 0x3f;
> ?
> @@ -116,7 +108,7 @@ static int imx6_pm_domain_power_on(struct
> generic_pm_domain *genpd)
> ?	sw2iso = (val >> 8) & 0x3f;
> ?
> ?	/* Request GPC to power up domain */
> -	val = BIT(pd->cntr_pdn_bit + 1);
> +	val = BIT(pd->cntr_pup_bit);
> ?	regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
> ?
> ?	/* Wait ISO + ISO2SW IPG clock cycles */
> @@ -241,22 +233,24 @@ static struct platform_driver
> imx_pgc_power_domain_driver = {
> ?};
> ?builtin_platform_driver(imx_pgc_power_domain_driver)
> ?
> -#define GPC_PGC_DOMAIN_ARM	0
> -#define GPC_PGC_DOMAIN_PU	1
> -#define GPC_PGC_DOMAIN_DISPLAY	2
> -
> ?static struct genpd_power_state imx6_pm_domain_pu_state = {
> ?	.power_off_latency_ns = 25000,
> ?	.power_on_latency_ns = 2000000,
> ?};
> ?
> +#define GPC_PGC_DOMAIN_ARM 0
> +#define GPC_PGC_DOMAIN_PU 1
> +#define GPC_PGC_DOMAIN_DISPLAY 2
> +#define GPC_PGC_DOMAIN_PCI 3
> +
> ?static struct imx_pm_domain imx_gpc_domains[] = {
> -	{
> +	[GPC_PGC_DOMAIN_ARM] {
> ?		.base = {
> ?			.name = "ARM",
> ?			.flags = GENPD_FLAG_ALWAYS_ON,
> ?		},
> -	}, {
> +	},
> +	[GPC_PGC_DOMAIN_PU] {
> ?		.base = {
> ?			.name = "PU",
> ?			.power_off = imx6_pm_domain_power_off,
> @@ -266,7 +260,9 @@ static struct imx_pm_domain imx_gpc_domains[] = {
> ?		},
> ?		.reg_offs = 0x260,
> ?		.cntr_pdn_bit = 0,
> -	}, {
> +		.cntr_pup_bit = 1,
> +	},
> +	[GPC_PGC_DOMAIN_DISPLAY] {
> ?		.base = {
> ?			.name = "DISPLAY",
> ?			.power_off = imx6_pm_domain_power_off,
> @@ -274,7 +270,9 @@ static struct imx_pm_domain imx_gpc_domains[] = {
> ?		},
> ?		.reg_offs = 0x240,
> ?		.cntr_pdn_bit = 4,
> -	}, {
> +		.cntr_pup_bit = 5,
> +	},
> +	[GPC_PGC_DOMAIN_PCI] {
> ?		.base = {
> ?			.name = "PCI",
> ?			.power_off = imx6_pm_domain_power_off,
> @@ -282,6 +280,7 @@ static struct imx_pm_domain imx_gpc_domains[] = {
> ?		},
> ?		.reg_offs = 0x200,
> ?		.cntr_pdn_bit = 6,
> +		.cntr_pup_bit = 7,
> ?	},
> ?};
> ?
> @@ -326,8 +325,8 @@ static const struct regmap_config
> imx_gpc_regmap_config = {
> ?};
> ?
> ?static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
> -	&imx_gpc_domains[0].base,
> -	&imx_gpc_domains[1].base,
> +	&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base,
> +	&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base,
> ?};
> ?
> ?static struct genpd_onecell_data imx_gpc_onecell_data = {

^ permalink raw reply

* [PATCH 1/2] media: stm32-dcmi: drop unnecessary while(1) loop
From: Hugues FRUCHET @ 2018-06-18  9:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1528824138-19089-1-git-send-email-hofrat@osadl.org>

Hi Nicholas,
thanks for patch !

On 06/12/2018 07:22 PM, Nicholas Mc Guire wrote:
> The while(1) is effectively useless as all possible paths within it
> return thus there is no way to loop.
> 
> Signed-off-by: Nicholas Mc Guire <hofrat@osadl.org>
Acked-by: Hugues Fruchet <hugues.fruchet@st.com>

> ---
> 
> This is not actually fixing any bug - the while(1){ } will not hurt here
> it is though simply unnecessary. Found during code review.
> 
> The diff output is not very readable - essentially only the outer
> while(1){ } was removed.
> 
> Patch was compile tested with: x86_64_defconfig, MEDIA_SUPPORT=y
> MEDIA_CAMERA_SUPPORT=y, V4L_PLATFORM_DRIVERS=y, OF=y, COMPILE_TEST=y
> CONFIG_VIDEO_STM32_DCMI=y
> (There are a number of sparse warnings - not related to the changes though)
> 
> Patch is against 4.17.0 (localversion-next is next-20180608)
> 
>   drivers/media/platform/stm32/stm32-dcmi.c | 28 +++++++++++++---------------
>   1 file changed, 13 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
> index 2e1933d..70b81d2 100644
> --- a/drivers/media/platform/stm32/stm32-dcmi.c
> +++ b/drivers/media/platform/stm32/stm32-dcmi.c
> @@ -1605,23 +1605,21 @@ static int dcmi_graph_parse(struct stm32_dcmi *dcmi, struct device_node *node)
>   	struct device_node *ep = NULL;
>   	struct device_node *remote;
>   
> -	while (1) {
> -		ep = of_graph_get_next_endpoint(node, ep);
> -		if (!ep)
> -			return -EINVAL;
> -
> -		remote = of_graph_get_remote_port_parent(ep);
> -		if (!remote) {
> -			of_node_put(ep);
> -			return -EINVAL;
> -		}
> +	ep = of_graph_get_next_endpoint(node, ep);
> +	if (!ep)
> +		return -EINVAL;
>   
> -		/* Remote node to connect */
> -		dcmi->entity.node = remote;
> -		dcmi->entity.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> -		dcmi->entity.asd.match.fwnode = of_fwnode_handle(remote);
> -		return 0;
> +	remote = of_graph_get_remote_port_parent(ep);
> +	if (!remote) {
> +		of_node_put(ep);
> +		return -EINVAL;
>   	}
> +
> +	/* Remote node to connect */
> +	dcmi->entity.node = remote;
> +	dcmi->entity.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> +	dcmi->entity.asd.match.fwnode = of_fwnode_handle(remote);
> +	return 0;
>   }
>   
>   static int dcmi_graph_init(struct stm32_dcmi *dcmi)
> 

BR,
Hugues.

^ permalink raw reply

* Charge counter on droid 4
From: Pavel Machek @ 2018-06-18  9:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618082858.GO112168@atomide.com>

On Mon 2018-06-18 01:28:58, Tony Lindgren wrote:
> * Pavel Machek <pavel@ucw.cz> [180618 07:43]:
> > 
> > So... there are mA, mAh values. Those come from hardware, and I
> > believe we should keep them.
> > 
> > But there are also mW, mWh values, which are synthetic. Userland can
> > compute them from mV, mA values... and it is confusing that kernel
> > provides them. (My tendency was to start computing these synthetic
> > values in userland, to compare them with "real hardware" values from
> > kernel. But then I looked at kernel implementation, and realized they
> > are synthetic, tooo...)
> 
> Hmm mWh value is based on the hardware sampled shunt
> values and number of samples gathered between the
> two readings. I'd rather call the calculated values
> based on userland reading mV and mA values "synthetic" :)

As far as I know, shunt resistors provide you with current (mA) not
power (mW) measurement... and cpcap-battery computes power_now as
voltage * current. I'd rather have kernel tell me "hardware can't
measure power" and do "voltage*current" computation in userspace.

So I'm proposing to apply patch below.

Best regards,
								Pavel


+++ b/drivers/power/supply/cpcap-battery.c
@@ -490,24 +490,6 @@ static int cpcap_battery_get_property(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
 		val->intval = latest->counter_uah;
 		break;
-	case POWER_SUPPLY_PROP_POWER_NOW:
-		tmp = (latest->voltage / 10000) * latest->current_ua;
-		val->intval = div64_s64(tmp, 100);
-		break;
-	case POWER_SUPPLY_PROP_POWER_AVG:
-		if (cached) {
-			tmp = cpcap_battery_cc_get_avg_current(ddata);
-			tmp *= (latest->voltage / 10000);
-			val->intval = div64_s64(tmp, 100);
-			break;
-		}
-		sample = latest->cc.sample - previous->cc.sample;
-		accumulator = latest->cc.accumulator - previous->cc.accumulator;
-		tmp = cpcap_battery_cc_to_ua(ddata, sample, accumulator,
-					     latest->cc.offset);
-		tmp *= ((latest->voltage + previous->voltage) / 20000);
-		val->intval = div64_s64(tmp, 100);
-		break;
 	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
 		if (cpcap_battery_full(ddata))
 			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180618/be105e1c/attachment.sig>

^ permalink raw reply


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