Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4/5] rpmsg: Driver for user space endpoint interface
From: loic pallardy @ 2016-10-11  7:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475900595-8375-4-git-send-email-bjorn.andersson@linaro.org>



On 10/08/2016 06:23 AM, Bjorn Andersson wrote:
> This driver allows rpmsg instances to expose access to rpmsg endpoints
> to user space processes. It provides a control interface, allowing
> userspace to export endpoints and an endpoint interface for each exposed
> endpoint.
>
> The implementation is based on prior art by Texas Instrument, Google,
> PetaLogix and was derived from a FreeRTOS performance statistics driver
> written by Michal Simek.
>
> The control interface provides a "create endpoint" ioctl, which is fed a
> name, source and destination address. The three values are used to
> create the endpoint, in a backend-specific way, and a rpmsg endpoint
> device is created - with the three parameters are available in sysfs for
> udev usage.
>
> E.g. to create an endpoint device for one of the Qualcomm SMD channel
> related to DIAG one would issue:
>
>   struct rpmsg_endpoint_info info = { "DIAG_CNTL", 0, 0 };
>   int fd = open("/dev/rpmsg_ctrl0", O_RDWR);
>   ioctl(fd, RPMSG_CREATE_EPT_IOCTL, &info);
>
> Each created endpoint device shows up as an individual character device
> in /dev, allowing permission to be controlled on a per-endpoint basis.
> The rpmsg endpoint will be created and destroyed following the opening
> and closing of the endpoint device, allowing rpmsg backends to open and
> close the physical channel, if supported by the wire protocol.
>
> Cc: Marek Novak <marek.novak@nxp.com>
> Cc: Matteo Sartori <matteo.sartori@t3lab.it>
> Cc: Michal Simek <monstr@monstr.eu>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>  Documentation/ioctl/ioctl-number.txt |   1 +
>  drivers/rpmsg/Makefile               |   2 +-
>  drivers/rpmsg/rpmsg_char.c           | 576 +++++++++++++++++++++++++++++++++++
>  drivers/rpmsg/rpmsg_internal.h       |   2 +
>  include/uapi/linux/rpmsg.h           |  35 +++
>  5 files changed, 615 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/rpmsg/rpmsg_char.c
>  create mode 100644 include/uapi/linux/rpmsg.h
>
> diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
> index 81c7f2bb7daf..08244bea5048 100644
> --- a/Documentation/ioctl/ioctl-number.txt
> +++ b/Documentation/ioctl/ioctl-number.txt
> @@ -321,6 +321,7 @@ Code  Seq#(hex)	Include File		Comments
>  0xB1	00-1F	PPPoX			<mailto:mostrows@styx.uwaterloo.ca>
>  0xB3	00	linux/mmc/ioctl.h
>  0xB4	00-0F	linux/gpio.h		<mailto:linux-gpio@vger.kernel.org>
> +0xB5	00-0F	uapi/linux/rpmsg.h	<mailto:linux-remoteproc@vger.kernel.org>
>  0xC0	00-0F	linux/usb/iowarrior.h
>  0xCA	00-0F	uapi/misc/cxl.h
>  0xCA	80-8F	uapi/scsi/cxlflash_ioctl.h
> diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
> index ae9c9132cf76..5daf1209b77d 100644
> --- a/drivers/rpmsg/Makefile
> +++ b/drivers/rpmsg/Makefile
> @@ -1,3 +1,3 @@
> -obj-$(CONFIG_RPMSG)		+= rpmsg_core.o
> +obj-$(CONFIG_RPMSG)		+= rpmsg_core.o rpmsg_char.o
Hi Bjorn,

Could you please create a dedicated Kconfig entry for this new interface?
This should be an option like i2C_dev.

Regards,
Loic


>  obj-$(CONFIG_RPMSG_QCOM_SMD)	+= qcom_smd.o
>  obj-$(CONFIG_RPMSG_VIRTIO)	+= virtio_rpmsg_bus.o
> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> new file mode 100644
> index 000000000000..a398a63e8d44
> --- /dev/null
> +++ b/drivers/rpmsg/rpmsg_char.c
> @@ -0,0 +1,576 @@
> +/*
> + * Copyright (c) 2016, Linaro Ltd.
> + * Copyright (c) 2012, Michal Simek <monstr@monstr.eu>
> + * Copyright (c) 2012, PetaLogix
> + * Copyright (c) 2011, Texas Instruments, Inc.
> + * Copyright (c) 2011, Google, Inc.
> + *
> + * Based on rpmsg performance statistics driver by Michal Simek, which in turn
> + * was based on TI & Google OMX rpmsg driver.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +#include <linux/cdev.h>
> +#include <linux/device.h>
> +#include <linux/fs.h>
> +#include <linux/idr.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/rpmsg.h>
> +#include <linux/skbuff.h>
> +#include <linux/slab.h>
> +#include <linux/uaccess.h>
> +#include <uapi/linux/rpmsg.h>
> +
> +#include "rpmsg_internal.h"
> +
> +#define RPMSG_DEV_MAX	256
> +
> +static dev_t rpmsg_major;
> +static struct class *rpmsg_class;
> +
> +static DEFINE_IDA(rpmsg_ctrl_ida);
> +static DEFINE_IDA(rpmsg_ept_ida);
> +static DEFINE_IDA(rpmsg_minor_ida);
> +
> +#define dev_to_eptdev(dev) container_of(dev, struct rpmsg_eptdev, dev)
> +#define cdev_to_eptdev(i_cdev) container_of(i_cdev, struct rpmsg_eptdev, cdev)
> +
> +#define dev_to_ctrldev(dev) container_of(dev, struct rpmsg_ctrldev, dev)
> +#define cdev_to_ctrldev(i_cdev) container_of(i_cdev, struct rpmsg_ctrldev, cdev)
> +
> +struct rpmsg_ctrldev {
> +	struct rpmsg_device *rpdev;
> +	struct cdev cdev;
> +	struct device dev;
> +};
> +
> +struct rpmsg_eptdev {
> +	struct device dev;
> +	struct cdev cdev;
> +
> +	struct rpmsg_device *rpdev;
> +	struct rpmsg_channel_info chinfo;
> +
> +	struct mutex ept_lock;
> +	struct rpmsg_endpoint *ept;
> +
> +	spinlock_t queue_lock;
> +	struct sk_buff_head queue;
> +	wait_queue_head_t readq;
> +};
> +
> +static int rpmsg_eptdev_destroy(struct rpmsg_eptdev *eptdev);
> +
> +
> +static int rpmsg_cdev_register(struct device *dev,
> +			       struct cdev *cdev,
> +			       const struct file_operations *fops,
> +			       dev_t *assigned_devt)
> +{
> +	dev_t devt;
> +	int ret;
> +
> +	ret = ida_simple_get(&rpmsg_minor_ida, 0, 0, GFP_KERNEL);
> +	if (ret < 0)
> +		return ret;
> +
> +	devt = MKDEV(MAJOR(rpmsg_major), ret);
> +
> +	cdev_init(cdev, fops);
> +	cdev->owner = THIS_MODULE;
> +	ret = cdev_add(cdev, devt, 1);
> +	if (ret < 0) {
> +		dev_err(dev, "cdev_add failed: %d\n", ret);
> +		ida_simple_remove(&rpmsg_minor_ida, MINOR(devt));
> +		return ret;
> +	}
> +
> +	*assigned_devt = devt;
> +	return 0;
> +}
> +
> +static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void *buf, int len,
> +			void *priv, u32 addr)
> +{
> +	struct rpmsg_eptdev *eptdev = priv;
> +	struct sk_buff *skb;
> +
> +	skb = alloc_skb(len, GFP_ATOMIC);
> +	if (!skb)
> +		return -ENOMEM;
> +
> +	memcpy(skb_put(skb, len), buf, len);
> +
> +	spin_lock(&eptdev->queue_lock);
> +	skb_queue_tail(&eptdev->queue, skb);
> +	spin_unlock(&eptdev->queue_lock);
> +
> +	/* wake up any blocking processes, waiting for new data */
> +	wake_up_interruptible(&eptdev->readq);
> +
> +	return 0;
> +}
> +
> +static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
> +{
> +	struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
> +	struct rpmsg_endpoint *ept;
> +	struct rpmsg_device *rpdev = eptdev->rpdev;
> +	struct device *dev = &eptdev->dev;
> +
> +	get_device(dev);
> +
> +	ept = rpmsg_create_ept(rpdev, rpmsg_ept_cb, eptdev, eptdev->chinfo);
> +	if (!ept) {
> +		dev_err(dev, "failed to open %s\n", eptdev->chinfo.name);
> +		put_device(dev);
> +		return -EINVAL;
> +	}
> +
> +	eptdev->ept = ept;
> +	filp->private_data = eptdev;
> +
> +	return 0;
> +}
> +
> +static int rpmsg_eptdev_release(struct inode *inode, struct file *filp)
> +{
> +	struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
> +	struct device *dev = &eptdev->dev;
> +	struct sk_buff *skb;
> +
> +	/* Close the endpoint, if it's not already destroyed by the parent */
> +	if (eptdev->ept)
> +		rpmsg_destroy_ept(eptdev->ept);
> +
> +	/* Discard all SKBs */
> +	while (!skb_queue_empty(&eptdev->queue)) {
> +		skb = skb_dequeue(&eptdev->queue);
> +		kfree_skb(skb);
> +	}
> +
> +	put_device(dev);
> +
> +	return 0;
> +}
> +
> +static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
> +			       unsigned long arg)
> +{
> +	struct rpmsg_eptdev *eptdev = fp->private_data;
> +
> +	if (cmd != RPMSG_DESTROY_EPT_IOCTL)
> +		return -EINVAL;
> +
> +	return rpmsg_eptdev_destroy(eptdev);
> +}
> +
> +static ssize_t rpmsg_eptdev_read(struct file *filp, char __user *buf,
> +				 size_t count, loff_t *f_pos)
> +{
> +	struct rpmsg_eptdev *eptdev = filp->private_data;
> +	unsigned long flags;
> +	struct sk_buff *skb;
> +	int use;
> +
> +	spin_lock_irqsave(&eptdev->queue_lock, flags);
> +
> +	/* Wait for data in the queue */
> +	if (skb_queue_empty(&eptdev->queue)) {
> +		spin_unlock_irqrestore(&eptdev->queue_lock, flags);
> +
> +		if (filp->f_flags & O_NONBLOCK)
> +			return -EAGAIN;
> +
> +		/* Wait until we get data or the endpoint goes away */
> +		if (wait_event_interruptible(eptdev->readq,
> +					     !skb_queue_empty(&eptdev->queue) ||
> +					     !eptdev->ept))
> +			return -ERESTARTSYS;
> +
> +		/* We lost the endpoint while waiting */
> +		if (!eptdev->ept)
> +			return -EPIPE;
> +
> +		spin_lock_irqsave(&eptdev->queue_lock, flags);
> +	}
> +
> +	skb = skb_dequeue(&eptdev->queue);
> +	if (!skb)
> +		return -EFAULT;
> +
> +	spin_unlock_irqrestore(&eptdev->queue_lock, flags);
> +
> +	use = min_t(size_t, count, skb->len);
> +	if (copy_to_user(buf, skb->data, use))
> +		use = -EFAULT;
> +
> +	kfree_skb(skb);
> +
> +	return use;
> +}
> +
> +static ssize_t rpmsg_eptdev_write(struct file *filp, const char __user *buf,
> +				  size_t count, loff_t *f_pos)
> +{
> +	struct rpmsg_eptdev *eptdev = filp->private_data;
> +	void *kbuf;
> +	int ret;
> +
> +	kbuf = kzalloc(count, GFP_KERNEL);
> +	if (!kbuf)
> +		return -ENOMEM;
> +
> +	if (copy_from_user(kbuf, buf, count)) {
> +		ret = -EFAULT;
> +		goto free_kbuf;
> +	}
> +
> +	if (mutex_lock_interruptible(&eptdev->ept_lock)) {
> +		ret = -ERESTARTSYS;
> +		goto free_kbuf;
> +	}
> +
> +	if (!eptdev->ept) {
> +		ret = -EPIPE;
> +		goto unlock_eptdev;
> +	}
> +
> +	if (filp->f_flags & O_NONBLOCK)
> +		ret = rpmsg_trysend(eptdev->ept, kbuf, count);
> +	else
> +		ret = rpmsg_send(eptdev->ept, kbuf, count);
> +
> +unlock_eptdev:
> +	mutex_unlock(&eptdev->ept_lock);
> +
> +free_kbuf:
> +	kfree(kbuf);
> +	return ret;
> +}
> +
> +static const struct file_operations rpmsg_eptdev_fops = {
> +	.owner = THIS_MODULE,
> +	.open = rpmsg_eptdev_open,
> +	.release = rpmsg_eptdev_release,
> +	.read = rpmsg_eptdev_read,
> +	.write = rpmsg_eptdev_write,
> +	.unlocked_ioctl = rpmsg_eptdev_ioctl,
> +};
> +
> +static ssize_t name_show(struct device *dev, struct device_attribute *attr,
> +			 char *buf)
> +{
> +	struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
> +
> +	return sprintf(buf, "%s\n", eptdev->chinfo.name);
> +}
> +static DEVICE_ATTR_RO(name);
> +
> +static ssize_t src_show(struct device *dev, struct device_attribute *attr,
> +			 char *buf)
> +{
> +	struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
> +
> +	return sprintf(buf, "%d\n", eptdev->chinfo.src);
> +}
> +static DEVICE_ATTR_RO(src);
> +
> +static ssize_t dst_show(struct device *dev, struct device_attribute *attr,
> +			 char *buf)
> +{
> +	struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
> +
> +	return sprintf(buf, "%d\n", eptdev->chinfo.dst);
> +}
> +static DEVICE_ATTR_RO(dst);
> +
> +static struct attribute *rpmsg_eptdev_attrs[] = {
> +	&dev_attr_name.attr,
> +	&dev_attr_src.attr,
> +	&dev_attr_dst.attr,
> +	NULL
> +};
> +ATTRIBUTE_GROUPS(rpmsg_eptdev);
> +
> +static void rpmsg_eptdev_release_device(struct device *dev)
> +{
> +	struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev);
> +
> +	ida_simple_remove(&rpmsg_minor_ida, MINOR(eptdev->dev.devt));
> +	kfree(eptdev);
> +}
> +
> +static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
> +			       struct rpmsg_channel_info chinfo)
> +{
> +	struct rpmsg_device *rpdev = ctrldev->rpdev;
> +	struct rpmsg_eptdev *eptdev;
> +	struct device *dev;
> +	int ret;
> +	int id;
> +
> +	eptdev = kzalloc(sizeof(*eptdev), GFP_KERNEL);
> +	if (!eptdev)
> +		return -ENOMEM;
> +
> +	eptdev->rpdev = rpdev;
> +	eptdev->chinfo = chinfo;
> +
> +	mutex_init(&eptdev->ept_lock);
> +	spin_lock_init(&eptdev->queue_lock);
> +	skb_queue_head_init(&eptdev->queue);
> +	init_waitqueue_head(&eptdev->readq);
> +
> +	id = ida_simple_get(&rpmsg_ept_ida, 0, 0, GFP_KERNEL);
> +	if (id < 0) {
> +		kfree(eptdev);
> +		return id;
> +	}
> +
> +	dev = &eptdev->dev;
> +	device_initialize(dev);
> +	dev->class = rpmsg_class;
> +	dev->id = id;
> +	dev->parent = &ctrldev->dev;
> +	dev->release = rpmsg_eptdev_release_device;
> +	dev->groups = rpmsg_eptdev_groups;
> +	dev_set_name(dev, "rpmsg%d", id);
> +	dev_set_drvdata(dev, eptdev);
> +
> +	ret = rpmsg_cdev_register(dev, &eptdev->cdev,
> +				  &rpmsg_eptdev_fops, &dev->devt);
> +	if (ret) {
> +		dev_err(dev, "cdev_add failed: %d\n", ret);
> +		goto out;
> +	}
> +
> +	ret = device_add(dev);
> +	if (ret) {
> +		dev_err(dev, "device_register failed: %d\n", ret);
> +		goto out;
> +	}
> +
> +out:
> +	if (ret < 0)
> +		put_device(dev);
> +
> +	return ret;
> +}
> +
> +static int rpmsg_eptdev_destroy(struct rpmsg_eptdev *eptdev)
> +{
> +	struct rpmsg_endpoint *ept = eptdev->ept;
> +
> +	mutex_lock(&eptdev->ept_lock);
> +	eptdev->ept = NULL;
> +	mutex_unlock(&eptdev->ept_lock);
> +
> +	rpmsg_destroy_ept(ept);
> +
> +	/* wake up any blocking processes */
> +	wake_up_interruptible(&eptdev->readq);
> +
> +	cdev_del(&eptdev->cdev);
> +	device_del(&eptdev->dev);
> +	put_device(&eptdev->dev);
> +
> +	return 0;
> +}
> +
> +static int rpmsg_ctrldev_open(struct inode *inode, struct file *filp)
> +{
> +	struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
> +
> +	get_device(&ctrldev->rpdev->dev);
> +	filp->private_data = ctrldev;
> +
> +	return 0;
> +}
> +
> +static int rpmsg_ctrldev_release(struct inode *inode, struct file *filp)
> +{
> +	struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
> +
> +	put_device(&ctrldev->rpdev->dev);
> +
> +	return 0;
> +}
> +
> +static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd,
> +				unsigned long arg)
> +{
> +	struct rpmsg_ctrldev *ctrldev = fp->private_data;
> +	void __user *argp = (void __user *)arg;
> +	struct rpmsg_endpoint_info eptinfo;
> +	struct rpmsg_channel_info chinfo;
> +
> +	if (cmd != RPMSG_CREATE_EPT_IOCTL)
> +		return -EINVAL;
> +
> +	if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
> +		return -EFAULT;
> +
> +	memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
> +	chinfo.name[RPMSG_NAME_SIZE-1] = '\0';
> +	chinfo.src = eptinfo.src;
> +	chinfo.dst = eptinfo.dst;
> +
> +	return rpmsg_eptdev_create(ctrldev, chinfo);
> +};
> +
> +static const struct file_operations rpmsg_ctrldev_fops = {
> +	.owner = THIS_MODULE,
> +	.open = rpmsg_ctrldev_open,
> +	.release = rpmsg_ctrldev_release,
> +	.unlocked_ioctl = rpmsg_ctrldev_ioctl,
> +};
> +
> +static void rpmsg_chrdev_release_device(struct device *dev)
> +{
> +	struct rpmsg_ctrldev *ctrldev = dev_to_ctrldev(dev);
> +
> +	ida_simple_remove(&rpmsg_ctrl_ida, MINOR(dev->devt));
> +	cdev_del(&ctrldev->cdev);
> +	kfree(ctrldev);
> +}
> +
> +static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
> +{
> +	struct rpmsg_ctrldev *ctrldev;
> +	struct device *dev;
> +	int ret;
> +	int id;
> +
> +	ctrldev = kzalloc(sizeof(*ctrldev), GFP_KERNEL);
> +	if (!ctrldev)
> +		return -ENOMEM;
> +
> +	dev = &ctrldev->dev;
> +
> +	ctrldev->rpdev = rpdev;
> +
> +	id = ida_simple_get(&rpmsg_ctrl_ida, 0, 0, GFP_KERNEL);
> +	if (id < 0) {
> +		kfree(ctrldev);
> +		return id;
> +	}
> +
> +	device_initialize(dev);
> +	dev->parent = &rpdev->dev;
> +	dev->class = rpmsg_class;
> +	dev->release = rpmsg_chrdev_release_device;
> +	dev_set_name(&ctrldev->dev, "rpmsg_ctrl%d", id);
> +
> +	ret = rpmsg_cdev_register(dev, &ctrldev->cdev,
> +				  &rpmsg_ctrldev_fops, &dev->devt);
> +	if (ret < 0) {
> +		put_device(dev);
> +		return ret;
> +	}
> +
> +	ret = device_add(dev);
> +	if (ret) {
> +		dev_err(&rpdev->dev, "device_register failed: %d\n", ret);
> +		put_device(dev);
> +	}
> +
> +	dev_set_drvdata(&rpdev->dev, ctrldev);
> +
> +	return ret;
> +}
> +
> +static int _rpmsg_eptdev_destroy(struct device *dev, void *data)
> +{
> +	struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev);
> +
> +	return rpmsg_eptdev_destroy(eptdev);
> +}
> +
> +static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
> +{
> +	struct rpmsg_ctrldev *ctrldev = dev_get_drvdata(&rpdev->dev);
> +	int ret;
> +
> +	/* Destroy all endpoints */
> +	ret = device_for_each_child(&ctrldev->dev, NULL, _rpmsg_eptdev_destroy);
> +	if (ret)
> +		dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret);
> +
> +	device_del(&ctrldev->dev);
> +	put_device(&ctrldev->dev);
> +}
> +
> +static struct rpmsg_driver rpmsg_chrdev_driver = {
> +	.probe = rpmsg_chrdev_probe,
> +	.remove = rpmsg_chrdev_remove,
> +	.drv = {
> +		.name = "rpmsg_chrdev",
> +	},
> +};
> +
> +/**
> + * rpmsg_chrdev_register_device() - register chrdev device based on rpdev
> + * @rpdev:	prepared rpdev to be used for creating endpoints
> + *
> + * This function wraps rpmsg_register_device() preparing the rpdev for use as
> + * basis for the rpmsg chrdev.
> + */
> +int rpmsg_chrdev_register_device(struct rpmsg_device *rpdev)
> +{
> +	strcpy(rpdev->id.name, "rpmsg_chrdev");
> +	rpdev->driver_override = "rpmsg_chrdev";
> +
> +	return rpmsg_register_device(rpdev);
> +}
> +EXPORT_SYMBOL(rpmsg_chrdev_register_device);
> +
> +static int rpmsg_char_init(void)
> +{
> +	int ret;
> +
> +	ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg");
> +	if (ret < 0) {
> +		pr_err("rpmsg: failed to allocate char dev region\n");
> +		return ret;
> +	}
> +
> +	rpmsg_class = class_create(THIS_MODULE, "rpmsg");
> +	if (IS_ERR(rpmsg_class)) {
> +		pr_err("failed to create rpmsg class\n");
> +		ret = PTR_ERR(rpmsg_class);
> +		goto unregister_chrdev;
> +	}
> +
> +	ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
> +	if (ret < 0) {
> +		pr_err("rpmsgchr: failed to register rpmsg driver\n");
> +		goto destroy_class;
> +	}
> +
> +	return 0;
> +
> +destroy_class:
> +	class_destroy(rpmsg_class);
> +
> +unregister_chrdev:
> +	unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> +
> +	return ret;
> +}
> +postcore_initcall(rpmsg_char_init);
> +
> +static void rpmsg_chrdev_exit(void)
> +{
> +	unregister_rpmsg_driver(&rpmsg_chrdev_driver);
> +	unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> +}
> +module_exit(rpmsg_chrdev_exit);
> diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
> index 8075a20f919b..53d300eacc1c 100644
> --- a/drivers/rpmsg/rpmsg_internal.h
> +++ b/drivers/rpmsg/rpmsg_internal.h
> @@ -79,4 +79,6 @@ int rpmsg_unregister_device(struct device *parent,
>  struct device *rpmsg_find_device(struct device *parent,
>  				 struct rpmsg_channel_info *chinfo);
>
> +int rpmsg_chrdev_register_device(struct rpmsg_device *rpdev);
> +
>  #endif
> diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h
> new file mode 100644
> index 000000000000..dedc226e0d3f
> --- /dev/null
> +++ b/include/uapi/linux/rpmsg.h
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright (c) 2016, Linaro Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _UAPI_RPMSG_H_
> +#define _UAPI_RPMSG_H_
> +
> +#include <linux/ioctl.h>
> +#include <linux/types.h>
> +
> +/**
> + * struct rpmsg_endpoint_info - endpoint info representation
> + * @name: name of service
> + * @src: local address
> + * @dst: destination address
> + */
> +struct rpmsg_endpoint_info {
> +	char name[32];
> +	__u32 src;
> +	__u32 dst;
> +};
> +
> +#define RPMSG_CREATE_EPT_IOCTL	_IOW(0xb5, 0x1, struct rpmsg_endpoint_info)
> +#define RPMSG_DESTROY_EPT_IOCTL	_IO(0xb5, 0x2)
> +
> +#endif
>

^ permalink raw reply

* [PATCH] arm64: mmu: set the contiguous for kernel mappings when appropriate
From: Mark Rutland @ 2016-10-11  7:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476123164-10532-1-git-send-email-ard.biesheuvel@linaro.org>

Hi Ard,

On Mon, Oct 10, 2016 at 07:12:44PM +0100, Ard Biesheuvel wrote:
> Now that we no longer allow live kernel PMDs to be split, it is safe to
> start using the contiguous bit for kernel mappings. So set the contiguous
> bit in the kernel page mappings for regions whose size and alignment are
> suitable for this.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Given the splitting is now gone, using the contiguous bit makes sense to me.

With 16K pages, we can have contiguous PMD entries. Should we handle those,
too? e.g. have separate {PMD,PTE}_CONT{,_SIZE}?

Otherwise, I have some comments below.

> ---
>  arch/arm64/mm/mmu.c | 23 ++++++++++++++++++++---
>  1 file changed, 20 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 05615a3fdc6f..c491025c6a70 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -98,8 +98,11 @@ static phys_addr_t __init early_pgtable_alloc(void)
>  static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
>  				  unsigned long end, unsigned long pfn,
>  				  pgprot_t prot,
> -				  phys_addr_t (*pgtable_alloc)(void))
> +				  phys_addr_t (*pgtable_alloc)(void),
> +				  bool allow_block_mappings)

Not a big deal, but the 'block' part here and elsewhere is now arguably
misleading (given 'block' is an architectural term).

I haven't come up with a better term, so again, not a big deal. ;)

>  {
> +	pgprot_t prot_cont = __pgprot(pgprot_val(prot) | PTE_CONT);
> +	bool cont = false;
>  	pte_t *pte;
>  
>  	BUG_ON(pmd_sect(*pmd));
> @@ -115,7 +118,20 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
>  
>  	pte = pte_set_fixmap_offset(pmd, addr);
>  	do {
> -		set_pte(pte, pfn_pte(pfn, prot));
> +		/*
> +		 * Set the contiguous bit for the subsequent group of PTEs if
> +		 * its size and alignment are suitable.
> +		 */
> +		if (((addr | PFN_PHYS(pfn)) & ~CONT_MASK) == 0)
> +			cont = allow_block_mappings && end - addr >= CONT_SIZE;

Given we increment addr by PAGE_SIZE in the loop, isn't this only true for the
first CONT_SIZE aligned entry, and not its (intended-to-be-contiguous)
siblings?

It be better to loop over CONT_SIZE increments, and then within that, pass the
prot (with the contiguous bit set as required) to a loop with a PAGE_SIZE
increment.

Or have I misunderstood something?

> +
> +		/*
> +		 * Ensure that we do not change the contiguous bit once this
> +		 * PTE has been assigned.
> +		 */
> +		BUG_ON(!pte_none(*pte) && (cont ^ !!(pte_val(*pte) & PTE_CONT)));

IIRC, we only ever intended to mess with the AP bits when remapping an existing region.

So we could mask those out and ensure everything else is identical, rather than
checking the cont bit specifically. Likewise at the {PMD,PUD,PGD} level.

> +
> +		set_pte(pte, pfn_pte(pfn, cont ? prot_cont : prot));

It would be clearer if we just assigned to a local pte_prot variable when
checking allow_block_mappings and so on above (or split the loop as above).

Thanks,
Mark.

^ permalink raw reply

* [PATCH 15/19] reset: sti: Remove STiH415/6 reset support
From: Patrice Chotard @ 2016-10-11  7:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474963347.2494.8.camel@pengutronix.de>

Hi Philipp

On 09/27/2016 10:02 AM, Philipp Zabel wrote:
> Hi Peter,
> 
> Am Mittwoch, den 14.09.2016, 14:27 +0100 schrieb Peter Griffin:
>> Support for STiH415/6 SoCs is being removed from the
>> kernel because the platforms are obsolete. This patch removes
>> the reset drivers for these SoC's.
>>
>> Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
>> Cc: <p.zabel@pengutronix.de>
>> ---

[...]

>> -	.driver = {
>> -		.name = "reset-stih416",
>> -		.of_match_table = stih416_reset_match,
>> -	},
>> -};
>> -
>> -static int __init stih416_reset_init(void)
>> -{
>> -	return platform_driver_register(&stih416_reset_driver);
>> -}
>> -arch_initcall(stih416_reset_init);
> 
> Can I pick up patches 15 and 19, or are there dependencies in the
> series?

Yes, you can pick up patches 15 and 19

> In the latter case,
> Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> to merge both together with the other patches. Currently there is no
> conflict with changes queued from the reset tree.
> 
> regards
> Philipp
> 

Thanks

Patrice

^ permalink raw reply

* [PATCH] mm/vmalloc: reduce the number of lazy_max_pages to reduce latency
From: Joel Fernandes @ 2016-10-11  5:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAD=GYpZQOQYE7x0kGTmLSeybh4Tn-CCEDouzkFVkdevq02j3SA@mail.gmail.com>

On Mon, Oct 10, 2016 at 10:06 PM, Joel Fernandes <agnel.joel@gmail.com> wrote:
> On Sun, Oct 9, 2016 at 12:26 PM, Chris Wilson <chris@chris-wilson.co.uk> wrote:
>> On Sun, Oct 09, 2016 at 12:00:31PM -0700, Joel Fernandes wrote:
>>> Ok. So I'll submit a patch with mutex for purge_lock and use
>>> cond_resched_lock for the vmap_area_lock as you suggested. I'll also
>>> drop the lazy_max_pages to 8MB as Andi suggested to reduce the lock
>>> hold time. Let me know if you have any objections.
>>
>> The downside of using a mutex here though, is that we may be called
>> from contexts that cannot sleep (alloc_vmap_area), or reschedule for
>> that matter! If we change the notion of purged, we can forgo the mutex
>> in favour of spinning on the direct reclaim path. That just leaves the
>> complication of whether to use cond_resched_lock() or a lock around
>> the individual __free_vmap_area().
>
> Good point. I agree with you. I think we still need to know if purging
> is in progress to preserve previous trylock behavior. How about
> something like the following diff? (diff is untested).
>
> This drops the purge lock and uses a ref count to indicate if purging
> is in progress, so that callers who don't want to purge if purging is
> already in progress can be kept happy. Also I am reducing vmap_lazy_nr
> as we go, and, not all at once, so that we don't reduce the counter
> too soon as we're not holding purge lock anymore. Lastly, I added the
> cond_resched as you suggested.
>
> diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> index f2481cb..5616ca4 100644
> --- a/mm/vmalloc.c
> +++ b/mm/vmalloc.c
> @@ -626,7 +626,7 @@ void set_iounmap_nonlazy(void)
>  static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
>                                         int sync, int force_flush)
>  {
> -       static DEFINE_SPINLOCK(purge_lock);
> +       static atomic_t purging;
>         struct llist_node *valist;
>         struct vmap_area *va;
>         struct vmap_area *n_va;
> @@ -638,10 +638,10 @@ static void __purge_vmap_area_lazy(unsigned long
> *start, unsigned long *end,
>          * the case that isn't actually used at the moment anyway.
>          */
>         if (!sync && !force_flush) {
> -               if (!spin_trylock(&purge_lock))
> +               if (atomic_cmpxchg(&purging, 0, 1))
>                         return;
>         } else
> -               spin_lock(&purge_lock);
> +               atomic_inc(&purging);
>
>         if (sync)
>                 purge_fragmented_blocks_allcpus();
> @@ -655,9 +655,6 @@ static void __purge_vmap_area_lazy(unsigned long
> *start, unsigned long *end,
>                 nr += (va->va_end - va->va_start) >> PAGE_SHIFT;
>         }
>
> -       if (nr)
> -               atomic_sub(nr, &vmap_lazy_nr);
> -
>         if (nr || force_flush)
>                 flush_tlb_kernel_range(*start, *end);
>
> @@ -665,9 +662,11 @@ static void __purge_vmap_area_lazy(unsigned long
> *start, unsigned long *end,
>                 spin_lock(&vmap_area_lock);
>                 llist_for_each_entry_safe(va, n_va, valist, purge_list)
>                         __free_vmap_area(va);
> +               atomic_sub(1, &vmap_lazy_nr);
> +               cond_resched_lock(&vmap_area_lock);
>                 spin_unlock(&vmap_area_lock);

For this particular hunk, I forgot the braces. sorry, I meant to say:

 @@ -665,9 +662,11 @@ static void __purge_vmap_area_lazy(unsigned long
 *start, unsigned long *end,
                 spin_lock(&vmap_area_lock);
-                llist_for_each_entry_safe(va, n_va, valist, purge_list)
+                llist_for_each_entry_safe(va, n_va, valist,
purge_list) {
                   __free_vmap_area(va);
+                  atomic_sub(1, &vmap_lazy_nr);
+                  cond_resched_lock(&vmap_area_lock);
+                }
                 spin_unlock(&vmap_area_lock);


Regards,
Joel

^ permalink raw reply

* [PATCH] mm/vmalloc: reduce the number of lazy_max_pages to reduce latency
From: Joel Fernandes @ 2016-10-11  5:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161009192610.GB2718@nuc-i3427.alporthouse.com>

On Sun, Oct 9, 2016 at 12:26 PM, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> On Sun, Oct 09, 2016 at 12:00:31PM -0700, Joel Fernandes wrote:
>> Ok. So I'll submit a patch with mutex for purge_lock and use
>> cond_resched_lock for the vmap_area_lock as you suggested. I'll also
>> drop the lazy_max_pages to 8MB as Andi suggested to reduce the lock
>> hold time. Let me know if you have any objections.
>
> The downside of using a mutex here though, is that we may be called
> from contexts that cannot sleep (alloc_vmap_area), or reschedule for
> that matter! If we change the notion of purged, we can forgo the mutex
> in favour of spinning on the direct reclaim path. That just leaves the
> complication of whether to use cond_resched_lock() or a lock around
> the individual __free_vmap_area().

Good point. I agree with you. I think we still need to know if purging
is in progress to preserve previous trylock behavior. How about
something like the following diff? (diff is untested).

This drops the purge lock and uses a ref count to indicate if purging
is in progress, so that callers who don't want to purge if purging is
already in progress can be kept happy. Also I am reducing vmap_lazy_nr
as we go, and, not all at once, so that we don't reduce the counter
too soon as we're not holding purge lock anymore. Lastly, I added the
cond_resched as you suggested.

diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index f2481cb..5616ca4 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -626,7 +626,7 @@ void set_iounmap_nonlazy(void)
 static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
                                        int sync, int force_flush)
 {
-       static DEFINE_SPINLOCK(purge_lock);
+       static atomic_t purging;
        struct llist_node *valist;
        struct vmap_area *va;
        struct vmap_area *n_va;
@@ -638,10 +638,10 @@ static void __purge_vmap_area_lazy(unsigned long
*start, unsigned long *end,
         * the case that isn't actually used at the moment anyway.
         */
        if (!sync && !force_flush) {
-               if (!spin_trylock(&purge_lock))
+               if (atomic_cmpxchg(&purging, 0, 1))
                        return;
        } else
-               spin_lock(&purge_lock);
+               atomic_inc(&purging);

        if (sync)
                purge_fragmented_blocks_allcpus();
@@ -655,9 +655,6 @@ static void __purge_vmap_area_lazy(unsigned long
*start, unsigned long *end,
                nr += (va->va_end - va->va_start) >> PAGE_SHIFT;
        }

-       if (nr)
-               atomic_sub(nr, &vmap_lazy_nr);
-
        if (nr || force_flush)
                flush_tlb_kernel_range(*start, *end);

@@ -665,9 +662,11 @@ static void __purge_vmap_area_lazy(unsigned long
*start, unsigned long *end,
                spin_lock(&vmap_area_lock);
                llist_for_each_entry_safe(va, n_va, valist, purge_list)
                        __free_vmap_area(va);
+               atomic_sub(1, &vmap_lazy_nr);
+               cond_resched_lock(&vmap_area_lock);
                spin_unlock(&vmap_area_lock);
        }
-       spin_unlock(&purge_lock);
+       atomic_dec(&purging);
 }

^ permalink raw reply related

* [PATCH v14 2/4] CMDQ: Mediatek CMDQ driver
From: Jassi Brar @ 2016-10-11  4:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476153632.477.2.camel@mtksdaap41>

On 11 October 2016 at 08:10, Horng-Shyang Liao <hs.liao@mediatek.com> wrote:
> On Thu, 2016-10-06 at 18:40 +0530, Jassi Brar wrote:
>> On 6 October 2016 at 18:31, Horng-Shyang Liao <hs.liao@mediatek.com> wrote:
>>
>> > Back to our original statement, we need to flush all tasks to queue
>> > in GCE HW; i.e. we need to use mbox_client_txdone after
>> > mbox_send_message, or send tx_done once mailbox controller receive
>> > message (task). However, we still need a way to notice done tasks to
>> > clients. Currently, we don't have a good way to call callback in mailbox
>> > framework. Therefore, CMDQ driver has its owner callback functions.
>> >
>> mbox_client_txdone() is called by the client driver when only it knows
>> the messages has been transmitted (i.e your submitted tasks are done).
>> Obviously the client driver should do any callbacks to its users
>> upstream.
>
> Hi Jassi,
>
> In current CMDQ driver, mbox_client_txdone() is called to prevent the
> blocking of chan->active_req. It is not the real point of CMDQ task
> done, so the client driver cannot do any callbacks to its user upstream.
>
> (1) If we don't use mbox_client_txdone(), could you tell us an
>     alternative way to prevent the blocking of chan->active_req?
>     And then we can use tx_done when CMDQ task is relly done.
>
mbox_client_txdone() should be used only when the mailbox controller
driver can't figure when the TX is done. Client driver (by like some
reply packet) realises the TX is done (for the reply to have arrived).

 If your hardware does flag/irq when tx is done, you should prefer
that over mbox_client_txdone().


> (2) If we use mbox_client_txdone() to prevent the blocking of
>     chan->active_req, could CMDQ driver just uses self-defined callback
>     function to notice client driver CMDQ task done?
>
Anything above the mailbox api, is none of its business. Your platform
specific 'server' driver can implement its own callbacks to notify its
users.

^ permalink raw reply

* [PATCH 1/5] dt-bindings: add vendor prefix for ILI Technology Corp
From: Icenowy Zheng @ 2016-10-11  3:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKdAkRT0WJ8EL62bumM1yz58LEAEqvmeX_hYzOZzAA0RvxJa3A@mail.gmail.com>



11.10.2016, 11:13, "Dmitry Torokhov" <dmitry.torokhov@gmail.com>:
> On Mon, Oct 10, 2016 at 5:33 PM, Icenowy Zheng <icenowy@aosc.xyz> wrote:
>> ?ILI Technology Corp (a.k.a Ilitek, http://www.ilitek.com/index-e.asp ) is a
>> ?company that produces LCD driver ICs and touch screen controller ICs.
>
> Was there patch 3/5? I do not see it in my mailbox.

Maybe it's spammed.

It can be retrieved at https://groups.google.com/d/msg/linux-sunxi/FY88KGfeCvk/tkEt6C4uBwAJ or http://lists.infradead.org/pipermail/linux-arm-kernel/2016-October/460908.html .

>
>> ?Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
>> ?---
>> ??Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>> ??1 file changed, 1 insertion(+)
>>
>> ?diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
>> ?index 24c6f65..4d37fdc 100644
>> ?--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
>> ?+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
>> ?@@ -130,6 +130,7 @@ i2se I2SE GmbH
>> ??ibm International Business Machines (IBM)
>> ??idt Integrated Device Technologies, Inc.
>> ??ifi Ingenieurburo Fur Ic-Technologie (I/F/I)
>> ?+ilitek ILI Technologies Corp.
>> ??img Imagination Technologies Ltd.
>> ??infineon Infineon Technologies
>> ??inforce Inforce Computing
>> ?--
>> ?2.10.1
>
> --
> Dmitry

^ permalink raw reply

* [RESEND PATCH v6, 4/5] usb: Add MediaTek USB3 DRD Driver
From: Chunfeng Yun @ 2016-10-11  3:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <49293f1b-42b5-f06b-8fdc-f46fe996e237@gmail.com>

On Mon, 2016-10-10 at 13:00 +0200, Matthias Brugger wrote:
> 
> On 09/21/2016 07:54 AM, Chunfeng Yun wrote:
> > This patch adds support for the MediaTek USB3 controller
> > integrated into MT8173. It can be configured as Dual-Role
> > Device (DRD), Peripheral Only and Host Only (xHCI) modes.
> >
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> >  drivers/usb/Kconfig                |    2 +
> >  drivers/usb/Makefile               |    1 +
> >  drivers/usb/mtu3/Kconfig           |   54 +++
> >  drivers/usb/mtu3/Makefile          |   19 +
> >  drivers/usb/mtu3/mtu3.h            |  422 +++++++++++++++++
> >  drivers/usb/mtu3/mtu3_core.c       |  871 +++++++++++++++++++++++++++++++++++
> >  drivers/usb/mtu3/mtu3_dr.c         |  379 ++++++++++++++++
> >  drivers/usb/mtu3/mtu3_dr.h         |  108 +++++
> >  drivers/usb/mtu3/mtu3_gadget.c     |  731 +++++++++++++++++++++++++++++
> >  drivers/usb/mtu3/mtu3_gadget_ep0.c |  883 ++++++++++++++++++++++++++++++++++++
> >  drivers/usb/mtu3/mtu3_host.c       |  294 ++++++++++++
> >  drivers/usb/mtu3/mtu3_hw_regs.h    |  473 +++++++++++++++++++
> >  drivers/usb/mtu3/mtu3_plat.c       |  490 ++++++++++++++++++++
> >  drivers/usb/mtu3/mtu3_qmu.c        |  599 ++++++++++++++++++++++++
> >  drivers/usb/mtu3/mtu3_qmu.h        |   43 ++
> >  15 files changed, 5369 insertions(+)
> >  create mode 100644 drivers/usb/mtu3/Kconfig
> >  create mode 100644 drivers/usb/mtu3/Makefile
> >  create mode 100644 drivers/usb/mtu3/mtu3.h
> >  create mode 100644 drivers/usb/mtu3/mtu3_core.c
> >  create mode 100644 drivers/usb/mtu3/mtu3_dr.c
> >  create mode 100644 drivers/usb/mtu3/mtu3_dr.h
> >  create mode 100644 drivers/usb/mtu3/mtu3_gadget.c
> >  create mode 100644 drivers/usb/mtu3/mtu3_gadget_ep0.c
> >  create mode 100644 drivers/usb/mtu3/mtu3_host.c
> >  create mode 100644 drivers/usb/mtu3/mtu3_hw_regs.h
> >  create mode 100644 drivers/usb/mtu3/mtu3_plat.c
> >  create mode 100644 drivers/usb/mtu3/mtu3_qmu.c
> >  create mode 100644 drivers/usb/mtu3/mtu3_qmu.h
> >
> 
> As Oliver already said, this patch is quiet big which makes it difficult 
> to review.
> I propose to provide a first implementation with minimal functionality 
> and incremental patches on top of this when the first got merged.
> 
> You could split the patch in three series/parts:
> 1. Host only
> 2. Peripheral only
> 3. Dual mode
> 
> What do you think?

Ok, I'll split the patch into some small ones as many as possible.

Thanks a lot
> 
> Regards,
> Matthias
> 

^ permalink raw reply

* [PATCH 1/5] dt-bindings: add vendor prefix for ILI Technology Corp
From: Dmitry Torokhov @ 2016-10-11  3:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161011003359.26079-1-icenowy@aosc.xyz>

On Mon, Oct 10, 2016 at 5:33 PM, Icenowy Zheng <icenowy@aosc.xyz> wrote:
> ILI Technology Corp (a.k.a Ilitek, http://www.ilitek.com/index-e.asp ) is a
> company that produces LCD driver ICs and touch screen controller ICs.

Was there patch 3/5? I do not see it in my mailbox.

>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> index 24c6f65..4d37fdc 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -130,6 +130,7 @@ i2se        I2SE GmbH
>  ibm    International Business Machines (IBM)
>  idt    Integrated Device Technologies, Inc.
>  ifi    Ingenieurburo Fur Ic-Technologie (I/F/I)
> +ilitek ILI Technologies Corp.
>  img    Imagination Technologies Ltd.
>  infineon Infineon Technologies
>  inforce        Inforce Computing
> --
> 2.10.1
>



-- 
Dmitry

^ permalink raw reply

* [RESEND PATCH v6, 3/5] usb: xhci-mtk: make IPPC register optional
From: Chunfeng Yun @ 2016-10-11  2:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <62b78471-d93f-a5c2-20ef-dfeeea1720db@gmail.com>

On Mon, 2016-10-10 at 12:55 +0200, Matthias Brugger wrote:
> 
> On 09/21/2016 07:54 AM, Chunfeng Yun wrote:
> > Make IPPC register optional to support host side of dual-role mode,
> > due to it is moved into common glue layer for simplification.
> >
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> >  drivers/usb/host/xhci-mtk.c |   36 +++++++++++++++++++++++++++++-------
> >  1 file changed, 29 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
> > index 79959f1..4bf99b9 100644
> > --- a/drivers/usb/host/xhci-mtk.c
> > +++ b/drivers/usb/host/xhci-mtk.c
> > @@ -94,6 +94,9 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk)
> >  	int ret;
> >  	int i;
> >
> > +	if (ippc == NULL)
> > +		return 0;
> > +
> >  	/* power on host ip */
> >  	value = readl(&ippc->ip_pw_ctr1);
> >  	value &= ~CTRL1_IP_HOST_PDN;
> > @@ -139,6 +142,9 @@ static int xhci_mtk_host_disable(struct xhci_hcd_mtk *mtk)
> >  	int ret;
> >  	int i;
> >
> > +	if (ippc == NULL)
> > +		return 0;
> > +
> >  	/* power down all u3 ports */
> >  	for (i = 0; i < mtk->num_u3_ports; i++) {
> >  		value = readl(&ippc->u3_ctrl_p[i]);
> > @@ -173,6 +179,9 @@ static int xhci_mtk_ssusb_config(struct xhci_hcd_mtk *mtk)
> >  	struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs;
> >  	u32 value;
> >
> > +	if (ippc == NULL)
> > +		return 0;
> > +
> 
> I would prefer to add a flag/bool in xhci_hcd_mtk to signal the absence 
> of the ippc. Or at least use a macro which checks the presence before 
> calling any of this three functions.

Ok. I will modify it later.

thanks.
> 
> Regards,
> Matthias

^ permalink raw reply

* [PATCH v14 2/4] CMDQ: Mediatek CMDQ driver
From: Horng-Shyang Liao @ 2016-10-11  2:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAJe_ZheptRQSmQp2gagqUyXqkOpi1qaTo8QPDTFpQ-+62B6kUw@mail.gmail.com>

On Thu, 2016-10-06 at 18:40 +0530, Jassi Brar wrote:
> On 6 October 2016 at 18:31, Horng-Shyang Liao <hs.liao@mediatek.com> wrote:
> 
> > Back to our original statement, we need to flush all tasks to queue
> > in GCE HW; i.e. we need to use mbox_client_txdone after
> > mbox_send_message, or send tx_done once mailbox controller receive
> > message (task). However, we still need a way to notice done tasks to
> > clients. Currently, we don't have a good way to call callback in mailbox
> > framework. Therefore, CMDQ driver has its owner callback functions.
> >
> mbox_client_txdone() is called by the client driver when only it knows
> the messages has been transmitted (i.e your submitted tasks are done).
> Obviously the client driver should do any callbacks to its users
> upstream.

Hi Jassi,

In current CMDQ driver, mbox_client_txdone() is called to prevent the
blocking of chan->active_req. It is not the real point of CMDQ task
done, so the client driver cannot do any callbacks to its user upstream.

(1) If we don't use mbox_client_txdone(), could you tell us an
    alternative way to prevent the blocking of chan->active_req?
    And then we can use tx_done when CMDQ task is relly done.
(2) If we use mbox_client_txdone() to prevent the blocking of
    chan->active_req, could CMDQ driver just uses self-defined callback
    function to notice client driver CMDQ task done?

Thanks,
HS

^ permalink raw reply

* [PATCH 0/6] crypto: arm64 - big endian fixes
From: Herbert Xu @ 2016-10-11  2:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKv+Gu9Nj5ccpRpgqg9Ohif4=k5+dAVuP8tKtNEj9_z7BQ_jjQ@mail.gmail.com>

On Mon, Oct 10, 2016 at 12:26:00PM +0100, Ard Biesheuvel wrote:
> 
> /* This piece of crap needs to disappear into per-type test hooks. */
> if (!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) &
>      CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV) &&
>    ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
>     CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize :
> alg->cra_ablkcipher.ivsize))
> type |= CRYPTO_ALG_TESTED;
> 
> This causes cbc(aes), ctr(aes) and xts(aes) to remain untested, unless
> I add CRYPTO_ALG_GENIV to their cra_flags. Is this expected behavior?
> What would be your recommended way to ensure these algos are covered
> by the boottime tests?

This is a leftover from the old blkcipher/ablkcipher interface.
I've got a patch pending which will remove this if clause.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH] clk: hi6220: use CLK_OF_DECLARE_DRIVER for sysctrl and mediactrl clock init
From: Shawn Guo @ 2016-10-11  2:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CALAqxLV5oOsP8ZcKrwzwK6OsZZwTjsvyk18+aWEFpZh17VttnA@mail.gmail.com>

Hi John,

On Mon, Oct 10, 2016 at 10:39:12AM -0700, John Stultz wrote:
> On Sat, Oct 8, 2016 at 6:38 AM, Shawn Guo <shawn.guo@linaro.org> wrote:
> > The hi6220-sysctrl and hi6220-mediactrl are not only clock provider but
> > also reset controller.  It worked fine that single sysctrl/mediactrl
> > device node in DT can be used to initialize clock driver and populate
> > platform device for reset controller.  But it stops working after
> > commit 989eafd0b609 ("clk: core: Avoid double initialization of clocks")
> > gets merged.  The commit sets flag OF_POPULATED during clock
> > initialization to skip the platform device populating for the same
> > device node.  On hi6220, it effectively makes hi6220-sysctrl reset
> > driver not probe any more.
> >
> > The patch changes hi6220 sysctrl and mediactrl clock init macro from
> > CLK_OF_DECLARE to CLK_OF_DECLARE_DRIVER, so that the reset driver using
> > the same hardware block can continue working.
> >
> > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> 
> Tested-by: John Stultz <john.stultz@linaro.org>
> 
> I hit this as well last week when 989eafd0b609 ("clk: core: Avoid
> double initialization of clocks") landed, which killed graphics on my
> HiKey.
> 
> My workaround was a bit hackish, as I don't really know when one
> should use OF_DECLARE vs OF_DECLARE_DRIVER, but I also converted the
> hi6220_clk_ao and hi6220_clk_power to the _DRIVER side. Your patch
> seems to work just as well for me, but I wanted to double check with
> you that the ao/power clks didn't need the conversion as well.

For now, clock driver is the only one matching compatible
"hisilicon,hi6220-aoctrl" and "hisilicon,hi6220-pmctrl".  Whoever
adding a platform driver probing the same compatible later will have
to change it CLK_OF_DECLARE_DRIVER.  Otherwise, the platform driver
simply doesn't probe.

Shawn

^ permalink raw reply

* [PATCH v8 10/16] mm/memblock: add a new function memblock_alloc_near_nid
From: Leizhen (ThunderTown) @ 2016-10-11  1:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1472712907-12700-11-git-send-email-thunder.leizhen@huawei.com>



On 2016/9/1 14:55, Zhen Lei wrote:
> If HAVE_MEMORYLESS_NODES is selected, and some memoryless numa nodes are
> actually exist. The percpu variable areas and numa control blocks of that
> memoryless numa nodes must be allocated from the nearest available node
> to improve performance.
> 
> Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
> ---
>  include/linux/memblock.h |  1 +
>  mm/memblock.c            | 28 ++++++++++++++++++++++++++++
>  2 files changed, 29 insertions(+)

Hi Will,
  It seems no one take care about this, how about I move below function into arch/arm64/mm/numa.c
again? So that, merge it and patch 11 into one.

> 
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index 2925da2..8e866e0 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -290,6 +290,7 @@ static inline int memblock_get_region_node(const struct memblock_region *r)
> 
>  phys_addr_t memblock_alloc_nid(phys_addr_t size, phys_addr_t align, int nid);
>  phys_addr_t memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid);
> +phys_addr_t memblock_alloc_near_nid(phys_addr_t size, phys_addr_t align, int nid);
> 
>  phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align);
> 
> diff --git a/mm/memblock.c b/mm/memblock.c
> index 483197e..6578fff 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -1189,6 +1189,34 @@ again:
>  	return ret;
>  }
> 
> +phys_addr_t __init memblock_alloc_near_nid(phys_addr_t size, phys_addr_t align, int nid)
> +{
> +	int i, best_nid, distance;
> +	u64 pa;
> +	DECLARE_BITMAP(nodes_map, MAX_NUMNODES);
> +
> +	bitmap_zero(nodes_map, MAX_NUMNODES);
> +
> +find_nearest_node:
> +	best_nid = NUMA_NO_NODE;
> +	distance = INT_MAX;
> +
> +	for_each_clear_bit(i, nodes_map, MAX_NUMNODES)
> +		if (node_distance(nid, i) < distance) {
> +			best_nid = i;
> +			distance = node_distance(nid, i);
> +		}
> +
> +	pa = memblock_alloc_nid(size, align, best_nid);
> +	if (!pa) {
> +		BUG_ON(best_nid == NUMA_NO_NODE);
> +		bitmap_set(nodes_map, best_nid, 1);
> +		goto find_nearest_node;
> +	}
> +
> +	return pa;
> +}
> +
>  phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
>  {
>  	return memblock_alloc_base_nid(size, align, max_addr, NUMA_NO_NODE,
> --
> 2.5.0
> 
> 
> 
> .
> 

^ permalink raw reply

* [PATCH 3/3] mtd: s3c2410: parse the device configuration from OF node
From: Sergio Prado @ 2016-10-11  1:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161007162810.GB4222@kozik-lap>

On Fri, Oct 07, 2016 at 07:28:10PM +0300, Krzysztof Kozlowski wrote:

> > +struct s3c24XX_nand_devtype_data {
> > +	enum s3c_cpu_type type;
> > +};
> > +
> > +struct s3c24XX_nand_devtype_data s3c2410_nand_devtype_data = {
> > +	.type = TYPE_S3C2410,
> > +};
> > +
> > +struct s3c24XX_nand_devtype_data s3c2412_nand_devtype_data = {
> > +	.type = TYPE_S3C2412,
> > +};
> > +
> > +struct s3c24XX_nand_devtype_data s3c2440_nand_devtype_data = {
> > +	.type = TYPE_S3C2440,
> > +};
> > +
> > +struct s3c24XX_nand_devtype_data s3c6400_nand_devtype_data = {
> > +	.type = TYPE_S3C2412,
> 
> All of these look like candidate for static const.
> 
> Additionally you are not actually differentiating between s3c2412 and
> s3c64xx so I think there is not need of samsung,s3c6400-nand compatible.
> Just use existing one.
> 
> Best regards,
> Krzysztof

You are right. I'll review and send V2.

Best regards,

Sergio Prado

^ permalink raw reply

* [GIT PULL 1/3] ARM: soc: exynos: Drivers for v4.9
From: Kukjin Kim @ 2016-10-11  0:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50A42280-0A39-44E3-8E35-C24031EB4DF0@gmail.com>

Kukjin Kim wrote:

- Krzysztof's samsung email because he is not using now

> 
> 2016. 10. 3. 21:19 Kukjin Kim <kgene.kim@gmail.com> wrote:
> 
> + my samsung email
> 
> > 2016. 10. 3. 15:48 Krzysztof Kozlowski <krzk@kernel.org> wrote:
> >
> >>>> On Sun, Oct 02, 2016 at 05:25:07PM -0700, Olof Johansson wrote:
> >>>>> On Mon, Sep 19, 2016 at 8:53 AM, Krzysztof Kozlowski <krzk@kernel.org> wrote:
> >>>>>> On Mon, Sep 19, 2016 at 05:02:40PM +0200, Arnd Bergmann wrote:
> >>>>>> On Sunday, September 18, 2016 6:39:46 PM CEST Krzysztof Kozlowski wrote:
> >>>>>> Samsung drivers/soc update for v4.9:
> >>>>>> 1. Allow compile testing of exynos-mct clocksource driver on ARM64.
> >>>>>> 2. Document Exynos5433 PMU compatible (already used by clkout
> >>>>>> driver and more  will be coming soon).
> >>>>>
> >>>>> Pulled into next/drivers, thanks
> >>>>>
> >>>>> Just for my understanding: why do we need the exynos-mct driver on
> >>>>> ARM64 but not the delay-timer portion of it?
> >>>>
> >>>> I think we want all of it but Doug's optimization 3252a646aa2c
> >>>> ("clocksource: exynos_mct: Only use 32-bits where possible") is not
> >>>> ARM64 friendly. One way of dealing with it would be to prepare two
> >>>> versions of exynos4_read_current_timer(). One reading only lower
> >>>> 32-bit value for ARMv7 and second (slow) reading lower and upper for ARMv8.
> >>>>
> >>>>>
> >>>>> Is there an advantage in using MCT over the architected timer on
> >>>>> these chips? If so, should we also have a way to use it as the delay timer?
> >>>>
> >>>> No, there is no real advantage... except that the SoC has some
> >>>> interesting "characteristics"... The timers are tightly coupled.
> >>>> Very tightly. I spent a lot of time and failed to boot my ARMv8
> >>>> board without some MCT magic.
> >>>
> >>> What kind of magic is that?
> >>
> >> Most notably: the arch timer starts when MCT forward running counter
> >> starts. Without kicking MCT, the arch timer seems to be frozen.
> >>
> >>> I can understand that needing the MCT for some system-level timer
> >>> functionality might be true (wakeups, etc),

Yes correct, the MCT is designed for the power consumption related
functionalities such as cluster power down

> >>> but for system
> >>> timesource avoiding the MMIO timer and using the arch ones is a
> >>> substantial performance improvement for gettimeofday() and friends.
> >>>

At this moment, we can use the ARM arch timers as clocksource so I think
no performance degradation (some latency?) with using the CP15 access for
the gettimeofday() and friends

> >>> There was extensive discussion last year over using arch timers on
> >>> 5420/5422, and it fizzled out with vague comments about something
> >>> not working right between A15/A7 on b.L. hardware.

Current Exynos SoCs including ARMv8 architecture based have no hardware
something which means 'not working right'

> >>> I'm presuming
> >>> whatever implementation details of that SoC has since been fixed on
> >>> later chips (including v8). Any chance you can confirm? It'd be very
> >>> nice to leave MCT behind on v8 as a system time source.

It is depending on system level design architecture. If we don't need to
support some power mode such as cluster power down, we can use arch timers
without the MCT but actual product needed to support it for power consumption.

Let me add some comments.
According to the ARM architecture design, the ARM arch timers require toggle
from outside of the core as timer source and we're using the MCT for it. And
we can use the ARM arch timers as clocksource not the MCT on current Exynos.

> >> Unfortunately, I cannot confirm this, at least on Exynos5433 (ARMv8).
> >> I played with arch and MCT timers on it and failed to get the
> >> arch-timer-only setup working. I did not have access to newer Exynos
> >> designs (Exynos 7) so I do not know how it works there.
> >
> > Hi guys,
> >
> > I know what Olof want to know and actually several days ago someone asked me about that. As you guys
> talked, a couple of years ago there were some discussions...BTW I need to contact to hardware designer
> before let you guys know because something needs to be confirmed by them even I know roughly.
> >
> > Note I'm in vacation with my family. Will be back on this in several days with exact information.
> >
> > BRs,
> > Kukjin

k-gene

^ permalink raw reply

* [GIT PULL 1/3] ARM: soc: exynos: Drivers for v4.9
From: Kukjin Kim @ 2016-10-11  0:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <53745281-AF17-4A3A-8BB5-63EED3563298@gmail.com>

2016. 10. 3. 21:19 Kukjin Kim <kgene.kim@gmail.com> wrote:

+ my samsung email

> 2016. 10. 3. 15:48 Krzysztof Kozlowski <krzk@kernel.org> wrote:
> 
>>>> On Sun, Oct 02, 2016 at 05:25:07PM -0700, Olof Johansson wrote:
>>>>> On Mon, Sep 19, 2016 at 8:53 AM, Krzysztof Kozlowski <krzk@kernel.org> wrote:
>>>>>> On Mon, Sep 19, 2016 at 05:02:40PM +0200, Arnd Bergmann wrote:
>>>>>> On Sunday, September 18, 2016 6:39:46 PM CEST Krzysztof Kozlowski wrote:
>>>>>> Samsung drivers/soc update for v4.9:
>>>>>> 1. Allow compile testing of exynos-mct clocksource driver on ARM64.
>>>>>> 2. Document Exynos5433 PMU compatible (already used by clkout driver and more
>>>>>>  will be coming soon).
>>>>> 
>>>>> Pulled into next/drivers, thanks
>>>>> 
>>>>> Just for my understanding: why do we need the exynos-mct driver on ARM64
>>>>> but not the delay-timer portion of it?
>>>> 
>>>> I think we want all of it but Doug's optimization 3252a646aa2c
>>>> ("clocksource: exynos_mct: Only use 32-bits where possible") is not
>>>> ARM64 friendly. One way of dealing with it would be to prepare two
>>>> versions of exynos4_read_current_timer(). One reading only lower 32-bit
>>>> value for ARMv7 and second (slow) reading lower and upper for ARMv8.
>>>> 
>>>>> 
>>>>> Is there an advantage in using MCT over the architected timer on these
>>>>> chips? If so, should we also have a way to use it as the delay timer?
>>>> 
>>>> No, there is no real advantage... except that the SoC has some
>>>> interesting "characteristics"... The timers are tightly coupled. Very
>>>> tightly. I spent a lot of time and failed to boot my ARMv8 board without
>>>> some MCT magic.
>>> 
>>> What kind of magic is that?
>> 
>> Most notably: the arch timer starts when MCT forward running counter
>> starts. Without kicking MCT, the arch timer seems to be frozen.
>> 
>>> I can understand that needing the MCT for
>>> some system-level timer functionality might be true (wakeups, etc),
>>> but for system timesource avoiding the MMIO timer and using the arch
>>> ones is a substantial performance improvement for gettimeofday() and
>>> friends.
>>> 
>>> There was extensive discussion last year over using arch timers on
>>> 5420/5422, and it fizzled out with vague comments about something not
>>> working right between A15/A7 on b.L. hardware. I'm presuming whatever
>>> implementation details of that SoC has since been fixed on later chips
>>> (including v8). Any chance you can confirm? It'd be very nice to leave
>>> MCT behind on v8 as a system time source.
>> 
>> Unfortunately, I cannot confirm this, at least on Exynos5433 (ARMv8). I
>> played with arch and MCT timers on it and failed to get the
>> arch-timer-only setup working. I did not have access to newer Exynos
>> designs (Exynos 7) so I do not know how it works there.
> 
> Hi guys,
> 
> I know what Olof want to know and actually several days ago someone asked me about that. As you guys talked, a couple of years ago there were some discussions...BTW I need to contact to hardware designer before let you guys know because something needs to be confirmed by them even I know roughly.
> 
> Note I'm in vacation with my family. Will be back on this in several days with exact information.
> 
> BRs,
> Kukjin

^ permalink raw reply

* [PATCH 5/5] ARM: dts: sun6i: enable ili2139 on Colorfly E708 Q1
From: Icenowy Zheng @ 2016-10-11  0:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161011003359.26079-1-icenowy@aosc.xyz>

Many users report that their Colorfly E708 Q1's come with ili2139 touch
IC. This patch adds the device node of this IC.

It seems that two devices are attached to I2C bus 1: a ili2139 touch
controller at 0x41, and a stil unknown device at 0x38. So make PA2
controlled by a dummy regulator node, rather than a power sequence GPIO
for ili2139.

There's also some users who report that their tablets come with touch
screen with Goodix GT911 touch IC. In the device, the touch IC is
connected on the screen rather soldered on the PCB, so the two touch
screens may be both acceptable FRUs of the tablet. They have different
addresses, and may be runtime detectable. (The Allwinner BSP kernel have
such a detection method, however, mainline kernel have no such method
now except enable both touch ICs' driver and wait for one driver's
failure)

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts | 48 +++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts b/arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts
index 882a4d8..73ac574 100644
--- a/arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts
+++ b/arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts
@@ -47,6 +47,38 @@
 / {
 	model = "Colorfly E708 Q1 tablet";
 	compatible = "colorfly,e708-q1", "allwinner,sun6i-a31s";
+
+	/* This is actually a common reset line for both the
+	 * touchscreen and the accelerometer.
+	 */
+	i2c1_on: i2c1_on {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_on_e708_q1>;
+
+		regulator-name = "i2c1_on";
+		regulator-min-microvolt = "3000000";
+		regulator-max-microvolt = "3000000";
+		regulator-always-on;
+		gpio = <&pio 0 2 GPIO_ACTIVE_HIGH>; /* PA2 */
+		enable-active-high;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins_a>;
+
+	ctp at 41 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&ili2139_int_e708_q1>;
+
+		compatible = "ilitek,ili2139", "ili2139";
+		reg = <0x41>;
+		interrupt-parent = <&pio>;
+		interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>; /* PA3 */
+	};
 };
 
 &lradc {
@@ -61,6 +93,22 @@
 	};
 };
 
+&pio {
+	i2c1_on_e708_q1: i2c1_on at 0 {
+		allwinner,pins = "PA2";
+	        allwinner,function = "gpio_out";
+	        allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+	        allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	ili2139_int_e708_q1: ili2139_int at 0 {
+		allwinner,pins = "PA3";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
 &reg_dldo2 {
 	regulator-min-microvolt = <1800000>;
 	regulator-max-microvolt = <1800000>;
-- 
2.10.1

^ permalink raw reply related

* [PATCH 4/5] MAINTAINERS: Add myself as maintainer of ili2139 touchscreen driver
From: Icenowy Zheng @ 2016-10-11  0:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161011003359.26079-1-icenowy@aosc.xyz>

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index a009e00..8f8341b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6112,6 +6112,12 @@ M:	Stanislaw Gruszka <stf_xl@wp.pl>
 S:	Maintained
 F:	drivers/usb/atm/ueagle-atm.c
 
+ILI2139 TOUCHSCREEN DRIVER
+M:	Icenowy Zheng <icenowy@aosc.xyz>
+S:	Maintained
+F:	Documentation/devicetree/bindings/input/touchscreen/ilitek_ili2139.txt
+F:	drivers/input/touchscreen/ili2139.c
+
 INA209 HARDWARE MONITOR DRIVER
 M:	Guenter Roeck <linux@roeck-us.net>
 L:	linux-hwmon at vger.kernel.org
-- 
2.10.1

^ permalink raw reply related

* [PATCH 3/5] Input: add driver for Ilitek ili2139 touch IC
From: Icenowy Zheng @ 2016-10-11  0:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161011003359.26079-1-icenowy@aosc.xyz>

This driver adds support for Ilitek ili2139 touch IC, which is used in
several Colorfly tablets (for example, Colorfly E708 Q1, which is an
Allwinner A31s tablet with mainline kernel support).

Theortically it may support more Ilitek touch ICs, however, only ili2139
is used in any mainlined device.

It supports device tree enumeration, with screen resolution and axis
quirks configurable.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 drivers/input/touchscreen/Kconfig   |  14 ++
 drivers/input/touchscreen/Makefile  |   1 +
 drivers/input/touchscreen/ili2139.c | 320 ++++++++++++++++++++++++++++++++++++
 3 files changed, 335 insertions(+)
 create mode 100644 drivers/input/touchscreen/ili2139.c

diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 5079813..bb4d9d2 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -348,6 +348,20 @@ config TOUCHSCREEN_ILI210X
 	  To compile this driver as a module, choose M here: the
 	  module will be called ili210x.
 
+config TOUCHSCREEN_ILI2139
+	tristate "Ilitek ILI2139 based touchscreen"
+	depends on I2C
+	depends on OF
+	help
+	  Say Y here if you have a ILI2139 based touchscreen
+	  controller. Such kind of chipsets can be found in several
+	  Colorfly tablets.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here; the
+	  module will be called ili2139.
+
 config TOUCHSCREEN_IPROC
 	tristate "IPROC touch panel driver support"
 	depends on ARCH_BCM_IPROC || COMPILE_TEST
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 81b8645..930b5e2 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL)	+= egalax_ts_serial.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_GOODIX)	+= goodix.o
 obj-$(CONFIG_TOUCHSCREEN_ILI210X)	+= ili210x.o
+obj-$(CONFIG_TOUCHSCREEN_ILI2139)	+= ili2139.o
 obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC)	+= imx6ul_tsc.o
 obj-$(CONFIG_TOUCHSCREEN_INEXIO)	+= inexio.o
 obj-$(CONFIG_TOUCHSCREEN_INTEL_MID)	+= intel-mid-touch.o
diff --git a/drivers/input/touchscreen/ili2139.c b/drivers/input/touchscreen/ili2139.c
new file mode 100644
index 0000000..65c2dea
--- /dev/null
+++ b/drivers/input/touchscreen/ili2139.c
@@ -0,0 +1,320 @@
+/* -------------------------------------------------------------------------
+ * Copyright (C) 2016, Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * Derived from:
+ *  ili210x.c
+ *  Copyright (C) Olivier Sobrie <olivier@sobrie.be>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ * -------------------------------------------------------------------------
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+
+#define DEFAULT_POLL_PERIOD	20
+
+#define MAX_TOUCHES		10
+#define COMPATIBLE_TOUCHES	2
+
+/* Touchscreen commands */
+#define REG_TOUCHDATA		0x10
+#define REG_TOUCHSUBDATA	0x11
+#define REG_PANEL_INFO		0x20
+#define REG_FIRMWARE_VERSION	0x40
+#define REG_PROTO_VERSION	0x42
+
+#define SUBDATA_STATUS_TOUCH_POINT	0x80
+#define SUBDATA_STATUS_RELEASE_POINT	0x00
+
+struct finger {
+	u8 x_low;
+	u8 x_high;
+	u8 y_low;
+	u8 y_high;
+} __packed;
+
+struct touchdata {
+	u8 length;
+	struct finger finger[COMPATIBLE_TOUCHES];
+} __packed;
+
+struct touch_subdata {
+	u8 status;
+	struct finger finger;
+} __packed;
+
+struct panel_info {
+	struct finger finger_max;
+	u8 xchannel_num;
+	u8 ychannel_num;
+} __packed;
+
+struct firmware_version {
+	u8 id;
+	u8 major;
+	u8 minor;
+} __packed;
+
+struct ili2139 {
+	struct i2c_client *client;
+	struct input_dev *input;
+	unsigned int poll_period;
+	struct delayed_work dwork;
+	struct touchscreen_properties prop;
+	int slots[MAX_TOUCHES];
+	int ids[MAX_TOUCHES];
+	struct input_mt_pos pos[MAX_TOUCHES];
+};
+
+static int ili2139_read_reg(struct i2c_client *client, u8 reg, void *buf,
+			    size_t len)
+{
+	struct i2c_msg msg[2] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= &reg,
+		},
+		{
+			.addr	= client->addr,
+			.flags	= I2C_M_RD,
+			.len	= len,
+			.buf	= buf,
+		}
+	};
+
+	if (i2c_transfer(client->adapter, msg, 2) != 2) {
+		dev_err(&client->dev, "i2c transfer failed\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void ili2139_work(struct work_struct *work)
+{
+	int id;
+	struct ili2139 *priv = container_of(work, struct ili2139,
+					    dwork.work);
+	struct i2c_client *client = priv->client;
+	struct touchdata touchdata;
+	struct touch_subdata subdata;
+	int error;
+
+	error = ili2139_read_reg(client, REG_TOUCHDATA,
+				 &touchdata, sizeof(touchdata));
+	if (error) {
+		dev_err(&client->dev,
+			"Unable to get touchdata, err = %d\n", error);
+		return;
+	}
+
+	for (id = 0; id < touchdata.length; id++) {
+		error = ili2139_read_reg(client, REG_TOUCHSUBDATA, &subdata,
+					 sizeof(subdata));
+		if (error) {
+			dev_err(&client->dev,
+				"Unable to get touch subdata, err = %d\n",
+				error);
+			return;
+		}
+
+		priv->ids[id] = subdata.status & 0x3F;
+
+		/* The sequence changed in the v2 subdata protocol. */
+		touchscreen_set_mt_pos(&priv->pos[id], &priv->prop,
+			(subdata.finger.x_high | (subdata.finger.x_low << 8)),
+			(subdata.finger.y_high | (subdata.finger.y_low << 8)));
+	}
+
+	input_mt_assign_slots(priv->input, priv->slots, priv->pos,
+			      touchdata.length, 0);
+
+	for (id = 0; id < touchdata.length; id++) {
+		input_mt_slot(priv->input, priv->slots[id]);
+		input_mt_report_slot_state(priv->input, MT_TOOL_FINGER,
+					   subdata.status &
+					   SUBDATA_STATUS_TOUCH_POINT);
+		input_report_abs(priv->input, ABS_MT_POSITION_X,
+				 priv->pos[id].x);
+		input_report_abs(priv->input, ABS_MT_POSITION_Y,
+				 priv->pos[id].y);
+	}
+
+	input_mt_sync_frame(priv->input);
+	input_sync(priv->input);
+
+	schedule_delayed_work(&priv->dwork,
+			      msecs_to_jiffies(priv->poll_period));
+}
+
+static irqreturn_t ili2139_irq(int irq, void *irq_data)
+{
+	struct ili2139 *priv = irq_data;
+
+	schedule_delayed_work(&priv->dwork, 0);
+
+	return IRQ_HANDLED;
+}
+
+static int ili2139_i2c_probe(struct i2c_client *client,
+				       const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct ili2139 *priv;
+	struct input_dev *input;
+	struct panel_info panel;
+	struct firmware_version firmware;
+	int xmax, ymax;
+	int error;
+
+	dev_dbg(dev, "Probing for ILI2139 I2C Touschreen driver");
+
+	if (client->irq <= 0) {
+		dev_err(dev, "No IRQ!\n");
+		return -ENODEV;
+	}
+
+	/* Get firmware version */
+	error = ili2139_read_reg(client, REG_FIRMWARE_VERSION,
+				 &firmware, sizeof(firmware));
+	if (error) {
+		dev_err(dev, "Failed to get firmware version, err: %d\n",
+			error);
+		return error;
+	}
+
+	/* get panel info */
+	error = ili2139_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel));
+	if (error) {
+		dev_err(dev, "Failed to get panel information, err: %d\n",
+			error);
+		return error;
+	}
+
+	xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8);
+	ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8);
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	input = devm_input_allocate_device(dev);
+	if (!priv || !input)
+		return -ENOMEM;
+
+	priv->client = client;
+	priv->input = input;
+	priv->poll_period = DEFAULT_POLL_PERIOD;
+	INIT_DELAYED_WORK(&priv->dwork, ili2139_work);
+
+	/* Setup input device */
+	input->name = "ILI2139 Touchscreen";
+	input->id.bustype = BUS_I2C;
+	input->dev.parent = dev;
+
+	__set_bit(EV_SYN, input->evbit);
+	__set_bit(EV_KEY, input->evbit);
+	__set_bit(EV_ABS, input->evbit);
+
+	/* Multi touch */
+	input_mt_init_slots(input, MAX_TOUCHES, INPUT_MT_DIRECT |
+			    INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK);
+	input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);
+	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);
+
+	touchscreen_parse_properties(input, true, &priv->prop);
+
+	input_set_drvdata(input, priv);
+	i2c_set_clientdata(client, priv);
+
+	error = devm_request_irq(dev, client->irq, ili2139_irq,
+				 IRQF_TRIGGER_FALLING, client->name, priv);
+	if (error) {
+		dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
+			error);
+		return error;
+	}
+
+	error = input_register_device(priv->input);
+	if (error) {
+		dev_err(dev, "Cannot register input device, err: %d\n", error);
+		return error;
+	}
+
+	device_init_wakeup(&client->dev, 1);
+
+	dev_dbg(dev,
+		"ILI2139 initialized (IRQ: %d), firmware version %d.%d.%d",
+		client->irq, firmware.id, firmware.major, firmware.minor);
+
+	return 0;
+}
+
+static int ili2139_i2c_remove(struct i2c_client *client)
+{
+	struct ili2139 *priv = i2c_get_clientdata(client);
+
+	cancel_delayed_work_sync(&priv->dwork);
+
+	return 0;
+}
+
+static int __maybe_unused ili2139_i2c_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	if (device_may_wakeup(&client->dev))
+		enable_irq_wake(client->irq);
+
+	return 0;
+}
+
+static int __maybe_unused ili2139_i2c_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	if (device_may_wakeup(&client->dev))
+		disable_irq_wake(client->irq);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(ili2139_i2c_pm,
+			 ili2139_i2c_suspend, ili2139_i2c_resume);
+
+static const struct i2c_device_id ili2139_i2c_id[] = {
+	{ "ili2139", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ili2139_i2c_id);
+
+static struct i2c_driver ili2139_ts_driver = {
+	.driver = {
+		.name = "ili2139_i2c",
+		.pm = &ili2139_i2c_pm,
+	},
+	.id_table = ili2139_i2c_id,
+	.probe = ili2139_i2c_probe,
+	.remove = ili2139_i2c_remove,
+};
+
+module_i2c_driver(ili2139_ts_driver);
+
+MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>");
+MODULE_DESCRIPTION("ILI2139 I2C Touchscreen Driver");
+MODULE_LICENSE("GPL");
-- 
2.10.1

^ permalink raw reply related

* [PATCH 2/5] dt-bindings: add binding for Ilitek ili2139 touchscreen IC
From: Icenowy Zheng @ 2016-10-11  0:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161011003359.26079-1-icenowy@aosc.xyz>

Ilitek ili2139 is a touchscreen IC used in several tablet products, for
example, Colorfly E708 Q1.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 .../bindings/input/touchscreen/ilitek_ili2139.txt     | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/touchscreen/ilitek_ili2139.txt

diff --git a/Documentation/devicetree/bindings/input/touchscreen/ilitek_ili2139.txt b/Documentation/devicetree/bindings/input/touchscreen/ilitek_ili2139.txt
new file mode 100644
index 0000000..72d2352
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/ilitek_ili2139.txt
@@ -0,0 +1,19 @@
+* Ilitek ili2139 touchscreen controller
+
+Required properties:
+- compatible		  : "ilitek,ili2139"
+- reg			  : I2C slave address of the chip (0x41)
+- interrupt-parent	  : a phandle pointing to the interrupt controller
+			    serving the interrupt for this chip
+- interrupts		  : interrupt specification for the ili2139 interrupt
+
+Example:
+
+i2c at 00000000 {
+	ili2139: touchscreen at 41 {
+		compatible = "ilitek,ili2139"
+		reg = <0x41>;
+		interrupt-parent = <&pio>;
+		interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
-- 
2.10.1

^ permalink raw reply related

* [PATCH 1/5] dt-bindings: add vendor prefix for ILI Technology Corp
From: Icenowy Zheng @ 2016-10-11  0:33 UTC (permalink / raw)
  To: linux-arm-kernel

ILI Technology Corp (a.k.a Ilitek, http://www.ilitek.com/index-e.asp ) is a
company that produces LCD driver ICs and touch screen controller ICs.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 24c6f65..4d37fdc 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -130,6 +130,7 @@ i2se	I2SE GmbH
 ibm	International Business Machines (IBM)
 idt	Integrated Device Technologies, Inc.
 ifi	Ingenieurburo Fur Ic-Technologie (I/F/I)
+ilitek	ILI Technologies Corp.
 img	Imagination Technologies Ltd.
 infineon Infineon Technologies
 inforce	Inforce Computing
-- 
2.10.1

^ permalink raw reply related

* [PATCH/RFT 09/12] usb: host: ohci-da8xx: Add devicetree bindings documentation
From: David Lechner @ 2016-10-10 23:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475858577-10366-10-git-send-email-ahaslam@baylibre.com>

On 10/07/2016 11:42 AM, ahaslam at baylibre.com wrote:
> From: Axel Haslam <ahaslam@baylibre.com>
>
> This patch documents the device tree bindings required for
> the ohci controller found in TI da8xx family of SoC's
>
> Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
> ---
>  .../devicetree/bindings/usb/ohci-da8xx.txt         | 32 ++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/usb/ohci-da8xx.txt
>
> diff --git a/Documentation/devicetree/bindings/usb/ohci-da8xx.txt b/Documentation/devicetree/bindings/usb/ohci-da8xx.txt
> new file mode 100644
> index 0000000..e954ce5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/ohci-da8xx.txt
> @@ -0,0 +1,32 @@
> +DA8XX USB OHCI controller
> +
> +Required properties:
> +
> + - compatible: Should be "ti,da830-ohci"
> + - reg:        Should contain one register range i.e. start and length
> + - interrupts: Description of the interrupt line
> + - phys:       Phandle for the PHY device
> + - phy-names:  Should be "usb-phy"
> +

If these are required, shouldn't they say "Must" instead of "Should"?

> +Optional properties:
> + - vbus-gpio:  If present, specifies a gpio that needs to be
> +               activated for the bus to be powered.
> + - oci-gpio:   If present, specifies a gpio that needs to be
> +               activated for the overcurrent detection.
> + - power_on_delay: Power On to Power Good time - in ms.
> +
> +Example for omap138-lck:
> +
> +usb_phy: usb-phy {
> +        compatible = "ti,da830-usb-phy";
> +        #phy-cells = <1>;
> +        status = "disabled";
> +};
> +usb11: usb11 at 0225000 {
> +        compatible = "ti,da830-ohci";
> +        reg = <0x225000 0x1000>;
> +        interrupts = <59>;
> +        phys = <&usb_phy 1>;
> +        phy-names = "usb-phy";
> +        status = "disabled";
> +};
>

^ permalink raw reply

* [PATCH/RFT 08/12] ARM: davinci: register the usb20_phy clock on the SoC file
From: David Lechner @ 2016-10-10 23:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475858577-10366-9-git-send-email-ahaslam@baylibre.com>

On 10/07/2016 11:42 AM, ahaslam at baylibre.com wrote:
> From: Axel Haslam <ahaslam@baylibre.com>
>
> The usb20_phy clock needs to be registered for the driver to be able
> to get and enable a clock. Currently the usb phy clocks are registered
> form board files, which will not be called during a device tree based
> boot.
>
> To be able to probe correctly usb form a device tree boot, register
> the usb phy clocks form the SoC specific init.
>
> Unfourtunatly, davinci does not have proper clock support on device tree
> yet, so by registering the clock form de SoC specific file we are
> forced to hardcode the parent clock, and cannot select refclkin as
> parent for any of the phy clocks of the da850 family.

FYI, I have started working on the clocks as well if you want to take it 
and run with it.

https://github.com/dlech/ev3dev-kernel/compare/9d6b50cde34b51309c74d97c26b1430c7ff6aa0f...d02084598785c369fdb23884171cbbec4fef77b0

(Ignore the ev3dev commit stuck in the middle there.)

>
> As none of the current da850 based boards currently in mainline use
> refclkin as source. I guess we can live with this limitation until clocks
> are correctly represented through CCF/device tree.
>

^ permalink raw reply

* [PATCH 0/8] pinctrl: aspeed: Fixes for core and g5, implement remaining pins
From: Andrew Jeffery @ 2016-10-10 23:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdZWbx1_SYJMOn40teQaEw1JAq80kDAp7N+OYaMRRO6NBg@mail.gmail.com>

On Mon, 2016-10-10 at 09:59 +0200, Linus Walleij wrote:
> On Tue, Sep 27, 2016 at 4:50 PM, Andrew Jeffery <andrew@aj.id.au> wrote:
> 
> > 
> > The initial Aspeed pinctrl patches implemented a subset of pins for each of the
> > g4 and g5 SoCs. This series provides a number of fixes to the initial patches,
> > mostly for issues identified in the g5 driver. The fixes account for the first
> > half of the series (up to and including "pinctrl: aspeed-g5: Fix pin
> > association of SPI1 function") and should be applied for 4.9.
> Those are applied for fixes.

Thanks!

> 
> > 
> > The second half, from "pinctrl: aspeed: Enable capture of off-SCU pinmux
> > state", implements some additional functionality in the core engine for the
> > Aspeed SoCs and follows up with patches implementing mux configuration tables
> > for all remaining pins. Given the significant additions in the last few
> > patches, their lateness in the cycle and the light testing they have received
> > they are best left for 4.10, but I'm keen to get them out for review.
> I'm holding these back until v4.9-rc1 is out.

No worries; they need some discussion when you have the time.

Cheers,

Andrew
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161011/339a02a0/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