Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv4 03/15] dt-bindings: clock: add omap4 hwmod clock IDs
From: Tony Lindgren @ 2016-10-20 12:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476805568-19264-4-git-send-email-t-kristo@ti.com>

* Tero Kristo <t-kristo@ti.com> [161018 08:47]:
> Add IDs for omap4 hwmod clocks. These are basically register offsets
> from the beginning of the clockdomain address space.

Looks like you have a wrong subject for this patch?

Tony

^ permalink raw reply

* [PATCH] drivers: psci: Allow PSCI node to be disabled
From: Mark Rutland @ 2016-10-20 12:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161017104653.18783-1-thierry.reding@gmail.com>

On Mon, Oct 17, 2016 at 12:46:53PM +0200, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Allow disabling PSCI support (mostly for testing purposes) by setting
> the status property to "disabled". This makes the node behave in much
> the same way as proper device nodes.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>

This looks sensible to me; FWIW:

Acked-by: Mark Rutland <mark.rutland@arm.com>

Lorenzo, do we need to batch this up with other PSCI patches, or should
this go direct to arm-soc?

Thanks,
Mark.

> ---
>  drivers/firmware/psci.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index 8263429e21b8..6c60a5087caf 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -630,7 +630,7 @@ int __init psci_dt_init(void)
>  
>  	np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
>  
> -	if (!np)
> +	if (!np || !of_device_is_available(np))
>  		return -ENODEV;
>  
>  	init_fn = (psci_initcall_t)matched_np->data;
> -- 
> 2.10.0
> 

^ permalink raw reply

* [PATCH v3 2/3] drm: zte: add initial vou drm driver
From: Gustavo Padovan @ 2016-10-20 12:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476948625-8521-3-git-send-email-shawn.guo@linaro.org>

2016-10-20 Shawn Guo <shawn.guo@linaro.org>:

> It adds the initial ZTE VOU display controller DRM driver.  There are
> still some features to be added, like overlay plane, scaling, and more
> output devices support.  But it's already useful with dual CRTCs and
> HDMI monitor working.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> ---
>  drivers/gpu/drm/Kconfig          |   2 +
>  drivers/gpu/drm/Makefile         |   1 +
>  drivers/gpu/drm/zte/Kconfig      |   8 +
>  drivers/gpu/drm/zte/Makefile     |   7 +
>  drivers/gpu/drm/zte/zx_drm_drv.c | 267 +++++++++++++
>  drivers/gpu/drm/zte/zx_drm_drv.h |  36 ++
>  drivers/gpu/drm/zte/zx_hdmi.c    | 678 +++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/zte/zx_plane.c   | 375 ++++++++++++++++++
>  drivers/gpu/drm/zte/zx_plane.h   |  26 ++
>  drivers/gpu/drm/zte/zx_vou.c     | 799 +++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/zte/zx_vou.h     |  46 +++
>  11 files changed, 2245 insertions(+)
>  create mode 100644 drivers/gpu/drm/zte/Kconfig
>  create mode 100644 drivers/gpu/drm/zte/Makefile
>  create mode 100644 drivers/gpu/drm/zte/zx_drm_drv.c
>  create mode 100644 drivers/gpu/drm/zte/zx_drm_drv.h
>  create mode 100644 drivers/gpu/drm/zte/zx_hdmi.c
>  create mode 100644 drivers/gpu/drm/zte/zx_plane.c
>  create mode 100644 drivers/gpu/drm/zte/zx_plane.h
>  create mode 100644 drivers/gpu/drm/zte/zx_vou.c
>  create mode 100644 drivers/gpu/drm/zte/zx_vou.h
> 
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index 483059a22b1b..a91f8cecbe0f 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -223,6 +223,8 @@ source "drivers/gpu/drm/hisilicon/Kconfig"
>  
>  source "drivers/gpu/drm/mediatek/Kconfig"
>  
> +source "drivers/gpu/drm/zte/Kconfig"
> +
>  # Keep legacy drivers last
>  
>  menuconfig DRM_LEGACY
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 25c720454017..f3251750c92b 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -86,3 +86,4 @@ obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
>  obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
>  obj-$(CONFIG_DRM_ARCPGU)+= arc/
>  obj-y			+= hisilicon/
> +obj-$(CONFIG_DRM_ZTE)	+= zte/
> diff --git a/drivers/gpu/drm/zte/Kconfig b/drivers/gpu/drm/zte/Kconfig
> new file mode 100644
> index 000000000000..4065b2840f1c
> --- /dev/null
> +++ b/drivers/gpu/drm/zte/Kconfig
> @@ -0,0 +1,8 @@
> +config DRM_ZTE
> +	tristate "DRM Support for ZTE SoCs"
> +	depends on DRM && ARCH_ZX
> +	select DRM_KMS_CMA_HELPER
> +	select DRM_KMS_FB_HELPER
> +	select DRM_KMS_HELPER
> +	help
> +	  Choose this option to enable DRM on ZTE ZX SoCs.
> diff --git a/drivers/gpu/drm/zte/Makefile b/drivers/gpu/drm/zte/Makefile
> new file mode 100644
> index 000000000000..699180bfd57c
> --- /dev/null
> +++ b/drivers/gpu/drm/zte/Makefile
> @@ -0,0 +1,7 @@
> +zxdrm-y := \
> +	zx_drm_drv.o \
> +	zx_hdmi.o \
> +	zx_plane.o \
> +	zx_vou.o
> +
> +obj-$(CONFIG_DRM_ZTE) += zxdrm.o
> diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c
> new file mode 100644
> index 000000000000..2476a9b92cea
> --- /dev/null
> +++ b/drivers/gpu/drm/zte/zx_drm_drv.c
> @@ -0,0 +1,267 @@
> +/*
> + * Copyright 2016 Linaro Ltd.
> + * Copyright 2016 ZTE Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/of_graph.h>
> +#include <linux/of_platform.h>
> +#include <linux/spinlock.h>
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_of.h>
> +#include <drm/drmP.h>
> +
> +#include "zx_drm_drv.h"
> +#include "zx_vou.h"
> +
> +struct zx_drm_private {
> +	struct drm_fbdev_cma *fbdev;
> +};
> +
> +static void zx_drm_fb_output_poll_changed(struct drm_device *drm)
> +{
> +	struct zx_drm_private *priv = drm->dev_private;
> +
> +	drm_fbdev_cma_hotplug_event(priv->fbdev);
> +}
> +
> +static const struct drm_mode_config_funcs zx_drm_mode_config_funcs = {
> +	.fb_create = drm_fb_cma_create,
> +	.output_poll_changed = zx_drm_fb_output_poll_changed,
> +	.atomic_check = drm_atomic_helper_check,
> +	.atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +static void zx_drm_lastclose(struct drm_device *drm)
> +{
> +	struct zx_drm_private *priv = drm->dev_private;
> +
> +	drm_fbdev_cma_restore_mode(priv->fbdev);
> +}
> +
> +static const struct file_operations zx_drm_fops = {
> +	.owner = THIS_MODULE,
> +	.open = drm_open,
> +	.release = drm_release,
> +	.unlocked_ioctl = drm_ioctl,
> +#ifdef CONFIG_COMPAT
> +	.compat_ioctl = drm_compat_ioctl,
> +#endif
> +	.poll = drm_poll,
> +	.read = drm_read,
> +	.llseek = noop_llseek,
> +	.mmap = drm_gem_cma_mmap,
> +};
> +
> +static struct drm_driver zx_drm_driver = {
> +	.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
> +			   DRIVER_ATOMIC,
> +	.lastclose = zx_drm_lastclose,
> +	.get_vblank_counter = drm_vblank_no_hw_counter,
> +	.enable_vblank = zx_vou_enable_vblank,
> +	.disable_vblank = zx_vou_disable_vblank,
> +	.gem_free_object = drm_gem_cma_free_object,
> +	.gem_vm_ops = &drm_gem_cma_vm_ops,
> +	.dumb_create = drm_gem_cma_dumb_create,
> +	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
> +	.dumb_destroy = drm_gem_dumb_destroy,
> +	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> +	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> +	.gem_prime_export = drm_gem_prime_export,
> +	.gem_prime_import = drm_gem_prime_import,
> +	.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
> +	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
> +	.gem_prime_vmap = drm_gem_cma_prime_vmap,
> +	.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
> +	.gem_prime_mmap = drm_gem_cma_prime_mmap,
> +	.fops = &zx_drm_fops,
> +	.name = "zx-vou",
> +	.desc = "ZTE VOU Controller DRM",
> +	.date = "20160811",
> +	.major = 1,
> +	.minor = 0,
> +};
> +
> +static int zx_drm_bind(struct device *dev)
> +{
> +	struct drm_device *drm;
> +	struct zx_drm_private *priv;
> +	int ret;
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	drm = drm_dev_alloc(&zx_drm_driver, dev);
> +	if (!drm)
> +		return -ENOMEM;
> +
> +	drm->dev_private = priv;
> +	dev_set_drvdata(dev, drm);
> +
> +	drm_mode_config_init(drm);
> +	drm->mode_config.min_width = 16;
> +	drm->mode_config.min_height = 16;
> +	drm->mode_config.max_width = 4096;
> +	drm->mode_config.max_height = 4096;
> +	drm->mode_config.funcs = &zx_drm_mode_config_funcs;
> +
> +	ret = component_bind_all(dev, drm);
> +	if (ret) {
> +		dev_err(dev, "failed to bind all components: %d\n", ret);
> +		goto out_unregister;
> +	}
> +
> +	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
> +	if (ret < 0) {
> +		dev_err(dev, "failed to init vblank: %d\n", ret);
> +		goto out_unbind;
> +	}
> +
> +	/*
> +	 * We will manage irq handler on our own.  In this case, irq_enabled
> +	 * need to be true for using vblank core support.
> +	 */
> +	drm->irq_enabled = true;
> +
> +	drm_mode_config_reset(drm);
> +	drm_kms_helper_poll_init(drm);
> +
> +	priv->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc,
> +					 drm->mode_config.num_connector);
> +	if (IS_ERR(priv->fbdev)) {
> +		ret = PTR_ERR(priv->fbdev);
> +		dev_err(dev, "failed to init cma fbdev: %d\n", ret);
> +		priv->fbdev = NULL;
> +		goto out_poll_fini;
> +	}
> +
> +	ret = drm_dev_register(drm, 0);
> +	if (ret)
> +		goto out_fbdev_fini;
> +
> +	return 0;
> +
> +out_fbdev_fini:
> +	if (priv->fbdev) {
> +		drm_fbdev_cma_fini(priv->fbdev);
> +		priv->fbdev = NULL;
> +	}
> +out_poll_fini:
> +	drm_kms_helper_poll_fini(drm);
> +	drm_mode_config_cleanup(drm);
> +	drm_vblank_cleanup(drm);
> +out_unbind:
> +	component_unbind_all(dev, drm);
> +out_unregister:
> +	dev_set_drvdata(dev, NULL);
> +	drm->dev_private = NULL;
> +	drm_dev_unref(drm);
> +	return ret;
> +}
> +
> +static void zx_drm_unbind(struct device *dev)
> +{
> +	struct drm_device *drm = dev_get_drvdata(dev);
> +	struct zx_drm_private *priv = drm->dev_private;
> +
> +	drm_dev_unregister(drm);
> +	if (priv->fbdev) {
> +		drm_fbdev_cma_fini(priv->fbdev);
> +		priv->fbdev = NULL;
> +	}
> +	drm_kms_helper_poll_fini(drm);
> +	drm_mode_config_cleanup(drm);
> +	drm_vblank_cleanup(drm);
> +	component_unbind_all(dev, drm);
> +	dev_set_drvdata(dev, NULL);
> +	drm->dev_private = NULL;
> +	drm_dev_unref(drm);
> +}
> +
> +static const struct component_master_ops zx_drm_master_ops = {
> +	.bind = zx_drm_bind,
> +	.unbind = zx_drm_unbind,
> +};
> +
> +static int compare_of(struct device *dev, void *data)
> +{
> +	return dev->of_node == data;
> +}
> +
> +static int zx_drm_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *parent = dev->of_node;
> +	struct device_node *child;
> +	struct component_match *match = NULL;
> +	int ret;
> +
> +	ret = of_platform_populate(parent, NULL, NULL, dev);
> +	if (ret)
> +		return ret;
> +
> +	for_each_available_child_of_node(parent, child) {
> +		component_match_add(dev, &match, compare_of, child);
> +		of_node_put(child);
> +	}
> +
> +	return component_master_add_with_match(dev, &zx_drm_master_ops, match);
> +}
> +
> +static int zx_drm_remove(struct platform_device *pdev)
> +{
> +	component_master_del(&pdev->dev, &zx_drm_master_ops);
> +	return 0;
> +}
> +
> +static const struct of_device_id zx_drm_of_match[] = {
> +	{ .compatible = "zte,zx296718-vou", },
> +	{ /* end */ },
> +};
> +MODULE_DEVICE_TABLE(of, zx_drm_of_match);
> +
> +static struct platform_driver zx_drm_platform_driver = {
> +	.probe = zx_drm_probe,
> +	.remove = zx_drm_remove,
> +	.driver	= {
> +		.name = "zx-drm",
> +		.of_match_table	= zx_drm_of_match,
> +	},
> +};
> +
> +static struct platform_driver *drivers[] = {
> +	&zx_crtc_driver,
> +	&zx_hdmi_driver,
> +	&zx_drm_platform_driver,
> +};
> +
> +static int zx_drm_init(void)
> +{
> +	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
> +}
> +module_init(zx_drm_init);
> +
> +static void zx_drm_exit(void)
> +{
> +	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
> +}
> +module_exit(zx_drm_exit);
> +
> +MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
> +MODULE_DESCRIPTION("ZTE ZX VOU DRM driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/gpu/drm/zte/zx_drm_drv.h b/drivers/gpu/drm/zte/zx_drm_drv.h
> new file mode 100644
> index 000000000000..e65cd18a6cba
> --- /dev/null
> +++ b/drivers/gpu/drm/zte/zx_drm_drv.h
> @@ -0,0 +1,36 @@
> +/*
> + * Copyright 2016 Linaro Ltd.
> + * Copyright 2016 ZTE Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#ifndef __ZX_DRM_DRV_H__
> +#define __ZX_DRM_DRV_H__
> +
> +extern struct platform_driver zx_crtc_driver;
> +extern struct platform_driver zx_hdmi_driver;
> +
> +static inline u32 zx_readl(void __iomem *reg)
> +{
> +	return readl_relaxed(reg);
> +}
> +
> +static inline void zx_writel(void __iomem *reg, u32 val)
> +{
> +	writel_relaxed(val, reg);
> +}
> +
> +static inline void zx_writel_mask(void __iomem *reg, u32 mask, u32 val)
> +{
> +	u32 tmp;
> +
> +	tmp = zx_readl(reg);
> +	tmp = (tmp & ~mask) | (val & mask);
> +	zx_writel(reg, tmp);
> +}
> +
> +#endif /* __ZX_DRM_DRV_H__ */
> diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c
> new file mode 100644
> index 000000000000..81e1c3716ed8
> --- /dev/null
> +++ b/drivers/gpu/drm/zte/zx_hdmi.c
> @@ -0,0 +1,678 @@
> +/*
> + * Copyright 2016 Linaro Ltd.
> + * Copyright 2016 ZTE Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/hdmi.h>
> +#include <linux/irq.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of_device.h>
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_edid.h>
> +#include <drm/drm_of.h>
> +#include <drm/drmP.h>
> +
> +#include "zx_vou.h"
> +
> +#define FUNC_SEL			0x000b
> +#define FUNC_HDMI_EN			BIT(0)
> +#define CLKPWD				0x000d
> +#define CLKPWD_PDIDCK			BIT(2)
> +#define PWD_SRST			0x0010
> +#define P2T_CTRL			0x0066
> +#define P2T_DC_PKT_EN			BIT(7)
> +#define L1_INTR_STAT			0x007e
> +#define L1_INTR_STAT_INTR1		BIT(0)
> +#define INTR1_STAT			0x008f
> +#define INTR1_MASK			0x0095
> +#define INTR1_MONITOR_DETECT		(BIT(5) | BIT(6))
> +#define ZX_DDC_ADDR			0x00ed
> +#define ZX_DDC_SEGM			0x00ee
> +#define ZX_DDC_OFFSET			0x00ef
> +#define ZX_DDC_DIN_CNT1			0x00f0
> +#define ZX_DDC_DIN_CNT2			0x00f1
> +#define ZX_DDC_CMD			0x00f3
> +#define DDC_CMD_MASK			0xf
> +#define DDC_CMD_CLEAR_FIFO		0x9
> +#define DDC_CMD_SEQUENTIAL_READ		0x2
> +#define ZX_DDC_DATA			0x00f4
> +#define ZX_DDC_DOUT_CNT			0x00f5
> +#define DDC_DOUT_CNT_MASK		0x1f
> +#define TEST_TXCTRL			0x00f7
> +#define TEST_TXCTRL_HDMI_MODE		BIT(1)
> +#define HDMICTL4			0x0235
> +#define TPI_HPD_RSEN			0x063b
> +#define TPI_HPD_CONNECTION		(BIT(1) | BIT(2))
> +#define TPI_INFO_FSEL			0x06bf
> +#define FSEL_AVI			0
> +#define FSEL_GBD			1
> +#define FSEL_AUDIO			2
> +#define FSEL_SPD			3
> +#define FSEL_MPEG			4
> +#define FSEL_VSIF			5
> +#define TPI_INFO_B0			0x06c0
> +#define TPI_INFO_EN			0x06df
> +#define TPI_INFO_TRANS_EN		BIT(7)
> +#define TPI_INFO_TRANS_RPT		BIT(6)
> +#define TPI_DDC_MASTER_EN		0x06f8
> +#define HW_DDC_MASTER			BIT(7)
> +
> +#define ZX_HDMI_INFOFRAME_SIZE		31
> +
> +#define DDC_SEGMENT_ADDR		0x30
> +
> +struct zx_hdmi_i2c {
> +	struct i2c_adapter adap;
> +	struct mutex lock;
> +};
> +
> +struct zx_hdmi {
> +	struct drm_connector connector;
> +	struct drm_encoder encoder;
> +	struct zx_hdmi_i2c *ddc;
> +	struct device *dev;
> +	struct drm_device *drm;
> +	void __iomem *mmio;
> +	struct clk *cec_clk;
> +	struct clk *osc_clk;
> +	struct clk *xclk;
> +	bool sink_is_hdmi;
> +	bool sink_has_audio;
> +	const struct vou_inf *inf;
> +};
> +
> +#define to_zx_hdmi(x) container_of(x, struct zx_hdmi, x)
> +
> +static const struct vou_inf vou_inf_hdmi = {
> +	.id = VOU_HDMI,
> +	.data_sel = VOU_YUV444,
> +	.clocks_en_bits = BIT(24) | BIT(18) | BIT(6),
> +	.clocks_sel_bits = BIT(13) | BIT(2),
> +};
> +
> +static inline u8 hdmi_readb(struct zx_hdmi *hdmi, u16 offset)
> +{
> +	return readl_relaxed(hdmi->mmio + offset * 4);
> +}
> +
> +static inline void hdmi_writeb(struct zx_hdmi *hdmi, u16 offset, u8 val)
> +{
> +	writel_relaxed(val, hdmi->mmio + offset * 4);
> +}
> +
> +static inline void hdmi_writeb_mask(struct zx_hdmi *hdmi, u16 offset,
> +				    u8 mask, u8 val)
> +{
> +	u8 tmp;
> +
> +	tmp = hdmi_readb(hdmi, offset);
> +	tmp = (tmp & ~mask) | (val & mask);
> +	hdmi_writeb(hdmi, offset, tmp);
> +}
> +
> +static int zx_hdmi_infoframe_trans(struct zx_hdmi *hdmi,
> +				   union hdmi_infoframe *frame, u8 fsel)
> +{
> +	u8 buffer[ZX_HDMI_INFOFRAME_SIZE];
> +	int num;
> +	int i;
> +
> +	hdmi_writeb(hdmi, TPI_INFO_FSEL, fsel);
> +
> +	num = hdmi_infoframe_pack(frame, buffer, ZX_HDMI_INFOFRAME_SIZE);
> +	if (num < 0) {
> +		dev_err(hdmi->dev, "failed to pack infoframe: %d\n", num);
> +		return num;
> +	}
> +
> +	for (i = 0; i < num; i++)
> +		hdmi_writeb(hdmi, TPI_INFO_B0 + i, buffer[i]);
> +
> +	hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_RPT,
> +			 TPI_INFO_TRANS_RPT);
> +	hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_EN,
> +			 TPI_INFO_TRANS_EN);
> +
> +	return num;
> +}
> +
> +static int zx_hdmi_config_video_vsi(struct zx_hdmi *hdmi,
> +				    struct drm_display_mode *mode)
> +{
> +	union hdmi_infoframe frame;
> +	int ret;
> +
> +	ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
> +							  mode);
> +	if (ret) {
> +		dev_err(hdmi->dev, "failed to get vendor infoframe: %d\n", ret);
> +		return ret;
> +	}
> +
> +	return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_VSIF);
> +}
> +
> +static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi,
> +				    struct drm_display_mode *mode)
> +{
> +	union hdmi_infoframe frame;
> +	int ret;
> +
> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
> +	if (ret) {
> +		dev_err(hdmi->dev, "failed to get avi infoframe: %d\n", ret);
> +		return ret;
> +	}
> +
> +	/* We always use YUV444 for HDMI output. */
> +	frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
> +
> +	return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_AVI);
> +}
> +
> +static void zx_hdmi_encoder_mode_set(struct drm_encoder *encoder,
> +				     struct drm_display_mode *mode,
> +				     struct drm_display_mode *adj_mode)
> +{
> +	struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
> +
> +	if (hdmi->sink_is_hdmi) {
> +		zx_hdmi_config_video_avi(hdmi, mode);
> +		zx_hdmi_config_video_vsi(hdmi, mode);
> +	}
> +}
> +
> +static void zx_hdmi_encoder_enable(struct drm_encoder *encoder)
> +{
> +	struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
> +
> +	vou_inf_enable(hdmi->inf, encoder->crtc);
> +}
> +
> +static void zx_hdmi_encoder_disable(struct drm_encoder *encoder)
> +{
> +	struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
> +
> +	vou_inf_disable(hdmi->inf, encoder->crtc);
> +}
> +
> +static const struct drm_encoder_helper_funcs zx_hdmi_encoder_helper_funcs = {
> +	.enable	= zx_hdmi_encoder_enable,
> +	.disable = zx_hdmi_encoder_disable,
> +	.mode_set = zx_hdmi_encoder_mode_set,
> +};
> +
> +static const struct drm_encoder_funcs zx_hdmi_encoder_funcs = {
> +	.destroy = drm_encoder_cleanup,
> +};
> +
> +static int zx_hdmi_connector_get_modes(struct drm_connector *connector)
> +{
> +	struct zx_hdmi *hdmi = to_zx_hdmi(connector);
> +	struct edid *edid;
> +	int ret;
> +
> +	edid = drm_get_edid(connector, &hdmi->ddc->adap);
> +	if (!edid)
> +		return 0;
> +
> +	hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
> +	hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
> +	drm_mode_connector_update_edid_property(connector, edid);
> +	ret = drm_add_edid_modes(connector, edid);
> +	kfree(edid);
> +
> +	return ret;
> +}
> +
> +static enum drm_mode_status
> +zx_hdmi_connector_mode_valid(struct drm_connector *connector,
> +			     struct drm_display_mode *mode)
> +{
> +	return MODE_OK;
> +}
> +
> +static struct drm_connector_helper_funcs zx_hdmi_connector_helper_funcs = {
> +	.get_modes = zx_hdmi_connector_get_modes,
> +	.mode_valid = zx_hdmi_connector_mode_valid,
> +};
> +
> +static enum drm_connector_status
> +zx_hdmi_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	struct zx_hdmi *hdmi = to_zx_hdmi(connector);
> +
> +	return (hdmi_readb(hdmi, TPI_HPD_RSEN) & TPI_HPD_CONNECTION) ?
> +		connector_status_connected : connector_status_disconnected;
> +}
> +
> +static void zx_hdmi_connector_destroy(struct drm_connector *connector)
> +{
> +	drm_connector_unregister(connector);

drm_connector_unregister() is not needed anymore. DRM core will call it
for you.

> +	drm_connector_cleanup(connector);
> +}
> +
> +static const struct drm_connector_funcs zx_hdmi_connector_funcs = {
> +	.dpms = drm_atomic_helper_connector_dpms,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.detect = zx_hdmi_connector_detect,
> +	.destroy = zx_hdmi_connector_destroy,

Then here you can use drm_connector_cleanup() directly.

> +	.reset = drm_atomic_helper_connector_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int zx_hdmi_register(struct drm_device *drm, struct zx_hdmi *hdmi)
> +{
> +	struct drm_encoder *encoder = &hdmi->encoder;
> +
> +	encoder->possible_crtcs = VOU_CRTC_MASK;
> +
> +	drm_encoder_init(drm, encoder, &zx_hdmi_encoder_funcs,
> +			 DRM_MODE_ENCODER_TMDS, NULL);
> +	drm_encoder_helper_add(encoder, &zx_hdmi_encoder_helper_funcs);
> +
> +	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
> +
> +	drm_connector_init(drm, &hdmi->connector, &zx_hdmi_connector_funcs,
> +			   DRM_MODE_CONNECTOR_HDMIA);
> +	drm_connector_helper_add(&hdmi->connector,
> +				 &zx_hdmi_connector_helper_funcs);
> +
> +	drm_mode_connector_attach_encoder(&hdmi->connector, encoder);
> +
> +	return 0;
> +}
> +
> +static irqreturn_t zx_hdmi_irq_thread(int irq, void *dev_id)
> +{
> +	struct zx_hdmi *hdmi = dev_id;
> +
> +	drm_helper_hpd_irq_event(hdmi->connector.dev);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t zx_hdmi_irq_handler(int irq, void *dev_id)
> +{
> +	struct zx_hdmi *hdmi = dev_id;
> +	u8 lstat;
> +
> +	lstat = hdmi_readb(hdmi, L1_INTR_STAT);
> +
> +	/* Monitor detect/HPD interrupt */
> +	if (lstat & L1_INTR_STAT_INTR1) {
> +		u8 stat;
> +
> +		stat = hdmi_readb(hdmi, INTR1_STAT);
> +		hdmi_writeb(hdmi, INTR1_STAT, stat);
> +
> +		if (stat & INTR1_MONITOR_DETECT)
> +			return IRQ_WAKE_THREAD;
> +	}
> +
> +	return IRQ_NONE;
> +}
> +
> +static int zx_hdmi_i2c_read(struct zx_hdmi *hdmi, struct i2c_msg *msg)
> +{
> +	int len = msg->len;
> +	u8 *buf = msg->buf;
> +	int retry = 0;
> +	int ret = 0;
> +
> +	/* Bits [9:8] of bytes */
> +	hdmi_writeb(hdmi, ZX_DDC_DIN_CNT2, (len >> 8) & 0xff);
> +	/* Bits [7:0] of bytes */
> +	hdmi_writeb(hdmi, ZX_DDC_DIN_CNT1, len & 0xff);
> +
> +	/* Clear FIFO */
> +	hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK, DDC_CMD_CLEAR_FIFO);
> +
> +	/* Kick off the read */
> +	hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK,
> +			 DDC_CMD_SEQUENTIAL_READ);
> +
> +	while (len > 0) {
> +		int cnt, i;
> +
> +		/* FIFO needs some time to get ready */
> +		usleep_range(500, 1000);
> +
> +		cnt = hdmi_readb(hdmi, ZX_DDC_DOUT_CNT) & DDC_DOUT_CNT_MASK;
> +		if (cnt == 0) {
> +			if (++retry > 5) {
> +				dev_err(hdmi->dev, "DDC FIFO read timed out!");
> +				ret = -ETIMEDOUT;
> +				break;
> +			}
> +			continue;
> +		}
> +
> +		for (i = 0; i < cnt; i++)
> +			*buf++ = hdmi_readb(hdmi, ZX_DDC_DATA);
> +		len -= cnt;
> +	}
> +
> +	return ret;
> +}
> +
> +static int zx_hdmi_i2c_write(struct zx_hdmi *hdmi, struct i2c_msg *msg)
> +{
> +	/*
> +	 * The DDC I2C adapter is only for reading EDID data, so we assume
> +	 * that the write to this adapter must be the EDID data offset.
> +	 */
> +	if ((msg->len != 1) ||
> +	    ((msg->addr != DDC_ADDR) && (msg->addr != DDC_SEGMENT_ADDR)))
> +		return -EINVAL;
> +
> +	if (msg->addr == DDC_SEGMENT_ADDR)
> +		hdmi_writeb(hdmi, ZX_DDC_SEGM, msg->addr << 1);
> +	else if (msg->addr == DDC_ADDR)
> +		hdmi_writeb(hdmi, ZX_DDC_ADDR, msg->addr << 1);
> +
> +	hdmi_writeb(hdmi, ZX_DDC_OFFSET, msg->buf[0]);
> +
> +	return 0;
> +}
> +
> +static int zx_hdmi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
> +			    int num)
> +{
> +	struct zx_hdmi *hdmi = i2c_get_adapdata(adap);
> +	struct zx_hdmi_i2c *ddc = hdmi->ddc;
> +	int i, ret = 0;
> +
> +	mutex_lock(&ddc->lock);
> +
> +	/* Enable DDC master access */
> +	hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, HW_DDC_MASTER);
> +
> +	for (i = 0; i < num; i++) {
> +		dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n",
> +			i + 1, num, msgs[i].len, msgs[i].flags);
> +
> +		if (msgs[i].flags & I2C_M_RD)
> +			ret = zx_hdmi_i2c_read(hdmi, &msgs[i]);
> +		else
> +			ret = zx_hdmi_i2c_write(hdmi, &msgs[i]);
> +
> +		if (ret < 0)
> +			break;
> +	}
> +
> +	if (!ret)
> +		ret = num;
> +
> +	/* Disable DDC master access */
> +	hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, 0);
> +
> +	mutex_unlock(&ddc->lock);
> +
> +	return ret;
> +}
> +
> +static u32 zx_hdmi_i2c_func(struct i2c_adapter *adapter)
> +{
> +	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
> +}
> +
> +static const struct i2c_algorithm zx_hdmi_algorithm = {
> +	.master_xfer	= zx_hdmi_i2c_xfer,
> +	.functionality	= zx_hdmi_i2c_func,
> +};
> +
> +static int zx_hdmi_ddc_register(struct zx_hdmi *hdmi)
> +{
> +	struct i2c_adapter *adap;
> +	struct zx_hdmi_i2c *ddc;
> +	int ret;
> +
> +	ddc = devm_kzalloc(hdmi->dev, sizeof(*ddc), GFP_KERNEL);
> +	if (!ddc)
> +		return -ENOMEM;
> +
> +	hdmi->ddc = ddc;
> +	mutex_init(&ddc->lock);
> +
> +	adap = &ddc->adap;
> +	adap->owner = THIS_MODULE;
> +	adap->class = I2C_CLASS_DDC;
> +	adap->dev.parent = hdmi->dev;
> +	adap->algo = &zx_hdmi_algorithm;
> +	snprintf(adap->name, sizeof(adap->name), "zx hdmi i2c");
> +
> +	ret = i2c_add_adapter(adap);
> +	if (ret) {
> +		dev_err(hdmi->dev, "failed to add I2C adapter: %d\n", ret);
> +		return ret;
> +	}
> +
> +	i2c_set_adapdata(adap, hdmi);
> +
> +	return 0;
> +}
> +
> +static void zx_hdmi_phy_start(struct zx_hdmi *hdmi)
> +{
> +	/* Copy from ZTE BSP code */
> +	hdmi_writeb(hdmi, 0x222, 0x0);
> +	hdmi_writeb(hdmi, 0x224, 0x4);
> +	hdmi_writeb(hdmi, 0x909, 0x0);
> +	hdmi_writeb(hdmi, 0x7b0, 0x90);
> +	hdmi_writeb(hdmi, 0x7b1, 0x00);
> +	hdmi_writeb(hdmi, 0x7b2, 0xa7);
> +	hdmi_writeb(hdmi, 0x7b8, 0xaa);
> +	hdmi_writeb(hdmi, 0x7b2, 0xa7);
> +	hdmi_writeb(hdmi, 0x7b3, 0x0f);
> +	hdmi_writeb(hdmi, 0x7b4, 0x0f);
> +	hdmi_writeb(hdmi, 0x7b5, 0x55);
> +	hdmi_writeb(hdmi, 0x7b7, 0x03);
> +	hdmi_writeb(hdmi, 0x7b9, 0x12);
> +	hdmi_writeb(hdmi, 0x7ba, 0x32);
> +	hdmi_writeb(hdmi, 0x7bc, 0x68);
> +	hdmi_writeb(hdmi, 0x7be, 0x40);
> +	hdmi_writeb(hdmi, 0x7bf, 0x84);
> +	hdmi_writeb(hdmi, 0x7c1, 0x0f);
> +	hdmi_writeb(hdmi, 0x7c8, 0x02);
> +	hdmi_writeb(hdmi, 0x7c9, 0x03);
> +	hdmi_writeb(hdmi, 0x7ca, 0x40);
> +	hdmi_writeb(hdmi, 0x7dc, 0x31);
> +	hdmi_writeb(hdmi, 0x7e2, 0x04);
> +	hdmi_writeb(hdmi, 0x7e0, 0x06);
> +	hdmi_writeb(hdmi, 0x7cb, 0x68);
> +	hdmi_writeb(hdmi, 0x7f9, 0x02);
> +	hdmi_writeb(hdmi, 0x7b6, 0x02);
> +	hdmi_writeb(hdmi, 0x7f3, 0x0);
> +}
> +
> +static void zx_hdmi_hw_init(struct zx_hdmi *hdmi)
> +{
> +	/* Software reset */
> +	hdmi_writeb(hdmi, PWD_SRST, 1);
> +
> +	/* Enable pclk */
> +	hdmi_writeb_mask(hdmi, CLKPWD, CLKPWD_PDIDCK, CLKPWD_PDIDCK);
> +
> +	/* Enable HDMI for TX */
> +	hdmi_writeb_mask(hdmi, FUNC_SEL, FUNC_HDMI_EN, FUNC_HDMI_EN);
> +
> +	/* Enable deep color packet */
> +	hdmi_writeb_mask(hdmi, P2T_CTRL, P2T_DC_PKT_EN, P2T_DC_PKT_EN);
> +
> +	/* Enable HDMI/MHL mode for output */
> +	hdmi_writeb_mask(hdmi, TEST_TXCTRL, TEST_TXCTRL_HDMI_MODE,
> +			 TEST_TXCTRL_HDMI_MODE);
> +
> +	/* Configure reg_qc_sel */
> +	hdmi_writeb(hdmi, HDMICTL4, 0x3);
> +
> +	/* Enable interrupt */
> +	hdmi_writeb_mask(hdmi, INTR1_MASK, INTR1_MONITOR_DETECT,
> +			 INTR1_MONITOR_DETECT);
> +
> +	/* Clear reset for normal operation */
> +	hdmi_writeb(hdmi, PWD_SRST, 0);
> +
> +	/* Start up phy */
> +	zx_hdmi_phy_start(hdmi);
> +}
> +
> +static int zx_hdmi_bind(struct device *dev, struct device *master, void *data)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct drm_device *drm = data;
> +	struct resource *res;
> +	struct zx_hdmi *hdmi;
> +	int irq;
> +	int ret;
> +
> +	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
> +	if (!hdmi)
> +		return -ENOMEM;
> +
> +	hdmi->dev = dev;
> +	hdmi->drm = drm;
> +	hdmi->inf = &vou_inf_hdmi;
> +
> +	dev_set_drvdata(dev, hdmi);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	hdmi->mmio = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(hdmi->mmio)) {
> +		ret = PTR_ERR(hdmi->mmio);
> +		dev_err(dev, "failed to remap hdmi region: %d\n", ret);
> +		return ret;
> +	}
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0)
> +		return irq;
> +
> +	hdmi->cec_clk = devm_clk_get(hdmi->dev, "osc_cec");
> +	if (IS_ERR(hdmi->cec_clk)) {
> +		ret = PTR_ERR(hdmi->cec_clk);
> +		dev_err(dev, "failed to get cec_clk: %d\n", ret);
> +		return ret;
> +	}
> +
> +	hdmi->osc_clk = devm_clk_get(hdmi->dev, "osc_clk");
> +	if (IS_ERR(hdmi->osc_clk)) {
> +		ret = PTR_ERR(hdmi->osc_clk);
> +		dev_err(dev, "failed to get osc_clk: %d\n", ret);
> +		return ret;
> +	}
> +
> +	hdmi->xclk = devm_clk_get(hdmi->dev, "xclk");
> +	if (IS_ERR(hdmi->xclk)) {
> +		ret = PTR_ERR(hdmi->xclk);
> +		dev_err(dev, "failed to get xclk: %d\n", ret);
> +		return ret;
> +	}
> +
> +	zx_hdmi_hw_init(hdmi);
> +
> +	ret = clk_prepare_enable(hdmi->cec_clk);
> +	if (ret) {
> +		dev_err(dev, "failed to enable cec_clk: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = clk_prepare_enable(hdmi->osc_clk);
> +	if (ret) {
> +		dev_err(dev, "failed to enable osc_clk: %d\n", ret);
> +		goto disable_cec_clk;
> +	}
> +
> +	ret = clk_prepare_enable(hdmi->xclk);
> +	if (ret) {
> +		dev_err(dev, "failed to enable xclk: %d\n", ret);
> +		goto disable_osc_clk;
> +	}
> +
> +
> +	ret = zx_hdmi_ddc_register(hdmi);
> +	if (ret) {
> +		dev_err(dev, "failed to register ddc: %d\n", ret);
> +		goto disable_xclk;
> +	}
> +
> +	ret = zx_hdmi_register(drm, hdmi);
> +	if (ret) {
> +		dev_err(dev, "failed to register hdmi: %d\n", ret);
> +		goto disable_xclk;
> +	}
> +
> +	ret = devm_request_threaded_irq(dev, irq, zx_hdmi_irq_handler,
> +					zx_hdmi_irq_thread, IRQF_SHARED,
> +					dev_name(dev), hdmi);
> +	if (ret) {
> +		dev_err(dev, "failed to request threaded irq: %d\n", ret);
> +		goto disable_xclk;
> +	}
> +
> +	return 0;
> +
> +disable_xclk:
> +	clk_disable_unprepare(hdmi->xclk);
> +disable_osc_clk:
> +	clk_disable_unprepare(hdmi->osc_clk);
> +disable_cec_clk:
> +	clk_disable_unprepare(hdmi->cec_clk);
> +	return ret;
> +}
> +
> +static void zx_hdmi_unbind(struct device *dev, struct device *master,
> +			   void *data)
> +{
> +	struct zx_hdmi *hdmi = dev_get_drvdata(dev);
> +
> +	clk_disable_unprepare(hdmi->xclk);
> +	clk_disable_unprepare(hdmi->osc_clk);
> +	clk_disable_unprepare(hdmi->cec_clk);
> +}
> +
> +static const struct component_ops zx_hdmi_component_ops = {
> +	.bind = zx_hdmi_bind,
> +	.unbind = zx_hdmi_unbind,
> +};
> +
> +static int zx_hdmi_probe(struct platform_device *pdev)
> +{
> +	return component_add(&pdev->dev, &zx_hdmi_component_ops);
> +}
> +
> +static int zx_hdmi_remove(struct platform_device *pdev)
> +{
> +	component_del(&pdev->dev, &zx_hdmi_component_ops);
> +	return 0;
> +}
> +
> +static const struct of_device_id zx_hdmi_of_match[] = {
> +	{ .compatible = "zte,zx296718-hdmi", },
> +	{ /* end */ },
> +};
> +MODULE_DEVICE_TABLE(of, zx_hdmi_of_match);
> +
> +struct platform_driver zx_hdmi_driver = {
> +	.probe = zx_hdmi_probe,
> +	.remove = zx_hdmi_remove,
> +	.driver	= {
> +		.name = "zx-hdmi",
> +		.of_match_table	= zx_hdmi_of_match,
> +	},
> +};
> diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
> new file mode 100644
> index 000000000000..fdab1715bee5
> --- /dev/null
> +++ b/drivers/gpu/drm/zte/zx_plane.c
> @@ -0,0 +1,375 @@
> +/*
> + * Copyright 2016 Linaro Ltd.
> + * Copyright 2016 ZTE Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_modeset_helper_vtables.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drmP.h>
> +
> +#include "zx_drm_drv.h"
> +#include "zx_plane.h"
> +#include "zx_vou.h"
> +
> +/* GL registers */
> +#define GL_CTRL0			0x00
> +#define GL_UPDATE			BIT(5)
> +#define GL_CTRL1			0x04
> +#define GL_DATA_FMT_SHIFT		0
> +#define GL_DATA_FMT_MASK		(0xf << GL_DATA_FMT_SHIFT)
> +#define GL_FMT_ARGB8888			0
> +#define GL_FMT_RGB888			1
> +#define GL_FMT_RGB565			2
> +#define GL_FMT_ARGB1555			3
> +#define GL_FMT_ARGB4444			4
> +#define GL_CTRL2			0x08
> +#define GL_GLOBAL_ALPHA_SHIFT		8
> +#define GL_GLOBAL_ALPHA_MASK		(0xff << GL_GLOBAL_ALPHA_SHIFT)
> +#define GL_CTRL3			0x0c
> +#define GL_SCALER_BYPASS_MODE		BIT(0)
> +#define GL_STRIDE			0x18
> +#define GL_ADDR				0x1c
> +#define GL_SRC_SIZE			0x38
> +#define GL_SRC_W_SHIFT			16
> +#define GL_SRC_W_MASK			(0x3fff << GL_SRC_W_SHIFT)
> +#define GL_SRC_H_SHIFT			0
> +#define GL_SRC_H_MASK			(0x3fff << GL_SRC_H_SHIFT)
> +#define GL_POS_START			0x9c
> +#define GL_POS_END			0xa0
> +#define GL_POS_X_SHIFT			16
> +#define GL_POS_X_MASK			(0x1fff << GL_POS_X_SHIFT)
> +#define GL_POS_Y_SHIFT			0
> +#define GL_POS_Y_MASK			(0x1fff << GL_POS_Y_SHIFT)
> +
> +#define GL_SRC_W(x)	(((x) << GL_SRC_W_SHIFT) & GL_SRC_W_MASK)
> +#define GL_SRC_H(x)	(((x) << GL_SRC_H_SHIFT) & GL_SRC_H_MASK)
> +#define GL_POS_X(x)	(((x) << GL_POS_X_SHIFT) & GL_POS_X_MASK)
> +#define GL_POS_Y(x)	(((x) << GL_POS_Y_SHIFT) & GL_POS_Y_MASK)
> +
> +/* CSC registers */
> +#define CSC_CTRL0			0x30
> +#define CSC_COV_MODE_SHIFT		16
> +#define CSC_COV_MODE_MASK		(0xffff << CSC_COV_MODE_SHIFT)
> +#define CSC_BT601_IMAGE_RGB2YCBCR	0
> +#define CSC_BT601_IMAGE_YCBCR2RGB	1
> +#define CSC_BT601_VIDEO_RGB2YCBCR	2
> +#define CSC_BT601_VIDEO_YCBCR2RGB	3
> +#define CSC_BT709_IMAGE_RGB2YCBCR	4
> +#define CSC_BT709_IMAGE_YCBCR2RGB	5
> +#define CSC_BT709_VIDEO_RGB2YCBCR	6
> +#define CSC_BT709_VIDEO_YCBCR2RGB	7
> +#define CSC_BT2020_IMAGE_RGB2YCBCR	8
> +#define CSC_BT2020_IMAGE_YCBCR2RGB	9
> +#define CSC_BT2020_VIDEO_RGB2YCBCR	10
> +#define CSC_BT2020_VIDEO_YCBCR2RGB	11
> +#define CSC_WORK_ENABLE			BIT(0)
> +
> +/* RSZ registers */
> +#define RSZ_SRC_CFG			0x00
> +#define RSZ_DEST_CFG			0x04
> +#define RSZ_ENABLE_CFG			0x14
> +
> +#define RSZ_VER_SHIFT			16
> +#define RSZ_VER_MASK			(0xffff << RSZ_VER_SHIFT)
> +#define RSZ_HOR_SHIFT			0
> +#define RSZ_HOR_MASK			(0xffff << RSZ_HOR_SHIFT)
> +
> +#define RSZ_VER(x)	(((x) << RSZ_VER_SHIFT) & RSZ_VER_MASK)
> +#define RSZ_HOR(x)	(((x) << RSZ_HOR_SHIFT) & RSZ_HOR_MASK)
> +
> +/* HBSC registers */
> +#define HBSC_SATURATION			0x00
> +#define HBSC_HUE			0x04
> +#define HBSC_BRIGHT			0x08
> +#define HBSC_CONTRAST			0x0c
> +#define HBSC_THRESHOLD_COL1		0x10
> +#define HBSC_THRESHOLD_COL2		0x14
> +#define HBSC_THRESHOLD_COL3		0x18
> +#define HBSC_CTRL0			0x28
> +#define HBSC_CTRL_EN			BIT(2)
> +
> +struct zx_plane {
> +	struct drm_plane plane;
> +	void __iomem *layer;
> +	void __iomem *csc;
> +	void __iomem *hbsc;
> +	void __iomem *rsz;
> +};
> +
> +#define to_zx_plane(plane)	container_of(plane, struct zx_plane, plane)
> +
> +static const uint32_t gl_formats[] = {
> +	DRM_FORMAT_ARGB8888,
> +	DRM_FORMAT_XRGB8888,
> +	DRM_FORMAT_RGB888,
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_ARGB1555,
> +	DRM_FORMAT_ARGB4444,
> +};
> +
> +static int zx_gl_plane_atomic_check(struct drm_plane *plane,
> +				    struct drm_plane_state *plane_state)
> +{
> +	struct drm_framebuffer *fb = plane_state->fb;
> +	struct drm_crtc *crtc = plane_state->crtc;
> +	struct drm_crtc_state *crtc_state;
> +	struct drm_rect clip;
> +
> +	if (!crtc || !fb)
> +		return 0;
> +
> +	crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state,
> +							crtc);
> +	if (WARN_ON(!crtc_state))
> +		return -EINVAL;
> +
> +	/* plane must match crtc enable state */
> +	if (crtc_state->enable != !!plane_state->crtc)
> +		return -EINVAL;
> +
> +	/* nothing to check when disabling or disabled */
> +	if (!crtc_state->enable)
> +		return 0;
> +
> +	clip.x1 = 0;
> +	clip.y1 = 0;
> +	clip.x2 = crtc_state->adjusted_mode.hdisplay;
> +	clip.y2 = crtc_state->adjusted_mode.vdisplay;
> +
> +	return drm_plane_helper_check_state(plane_state, &clip,
> +					    DRM_PLANE_HELPER_NO_SCALING,
> +					    DRM_PLANE_HELPER_NO_SCALING,
> +					    false, true);
> +}
> +
> +static int zx_gl_get_fmt(uint32_t format)
> +{
> +	switch (format) {
> +	case DRM_FORMAT_ARGB8888:
> +	case DRM_FORMAT_XRGB8888:
> +		return GL_FMT_ARGB8888;
> +	case DRM_FORMAT_RGB888:
> +		return GL_FMT_RGB888;
> +	case DRM_FORMAT_RGB565:
> +		return GL_FMT_RGB565;
> +	case DRM_FORMAT_ARGB1555:
> +		return GL_FMT_ARGB1555;
> +	case DRM_FORMAT_ARGB4444:
> +		return GL_FMT_ARGB4444;
> +	default:
> +		WARN_ONCE(1, "invalid pixel format %d\n", format);
> +		return -EINVAL;
> +	}
> +}
> +
> +static inline void zx_gl_set_update(struct zx_plane *zplane)
> +{
> +	void __iomem *layer = zplane->layer;
> +
> +	zx_writel_mask(layer + GL_CTRL0, GL_UPDATE, GL_UPDATE);
> +}
> +
> +static inline void zx_gl_rsz_set_update(struct zx_plane *zplane)
> +{
> +	zx_writel(zplane->rsz + RSZ_ENABLE_CFG, 1);
> +}
> +
> +void zx_plane_set_update(struct drm_plane *plane)
> +{
> +	struct zx_plane *zplane = to_zx_plane(plane);
> +
> +	zx_gl_rsz_set_update(zplane);
> +	zx_gl_set_update(zplane);
> +}
> +
> +static void zx_gl_rsz_setup(struct zx_plane *zplane, u32 src_w, u32 src_h,
> +			    u32 dst_w, u32 dst_h)
> +{
> +	void __iomem *rsz = zplane->rsz;
> +
> +	zx_writel(rsz + RSZ_SRC_CFG, RSZ_VER(src_h - 1) | RSZ_HOR(src_w - 1));
> +	zx_writel(rsz + RSZ_DEST_CFG, RSZ_VER(dst_h - 1) | RSZ_HOR(dst_w - 1));
> +
> +	zx_gl_rsz_set_update(zplane);
> +}
> +
> +static void zx_gl_plane_atomic_update(struct drm_plane *plane,
> +				      struct drm_plane_state *old_state)
> +{
> +	struct zx_plane *zplane = to_zx_plane(plane);
> +	struct drm_framebuffer *fb = plane->state->fb;
> +	struct drm_gem_cma_object *cma_obj;
> +	void __iomem *layer = zplane->layer;
> +	void __iomem *csc = zplane->csc;
> +	void __iomem *hbsc = zplane->hbsc;
> +	u32 src_x, src_y, src_w, src_h;
> +	u32 dst_x, dst_y, dst_w, dst_h;
> +	unsigned int depth, bpp;
> +	uint32_t format;
> +	dma_addr_t paddr;
> +	u32 stride;
> +	int fmt;
> +
> +	if (!fb)
> +		return;
> +
> +	format = fb->pixel_format;
> +	stride = fb->pitches[0];
> +
> +	src_x = plane->state->src_x >> 16;
> +	src_y = plane->state->src_y >> 16;
> +	src_w = plane->state->src_w >> 16;
> +	src_h = plane->state->src_h >> 16;
> +
> +	dst_x = plane->state->crtc_x;
> +	dst_y = plane->state->crtc_y;
> +	dst_w = plane->state->crtc_w;
> +	dst_h = plane->state->crtc_h;
> +
> +	drm_fb_get_bpp_depth(format, &depth, &bpp);
> +
> +	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
> +	paddr = cma_obj->paddr + fb->offsets[0];
> +	paddr += src_y * stride + src_x * bpp / 8;
> +	zx_writel(layer + GL_ADDR, paddr);
> +
> +	/* Set up source height/width register */
> +	zx_writel(layer + GL_SRC_SIZE, GL_SRC_W(src_w) | GL_SRC_H(src_h));
> +
> +	/* Set up start position register */
> +	zx_writel(layer + GL_POS_START, GL_POS_X(dst_x) | GL_POS_Y(dst_y));
> +
> +	/* Set up end position register */
> +	zx_writel(layer + GL_POS_END,
> +		  GL_POS_X(dst_x + dst_w) | GL_POS_Y(dst_y + dst_h));
> +
> +	/* Set up stride register */
> +	zx_writel(layer + GL_STRIDE, stride & 0xffff);
> +
> +	/* Set up graphic layer data format */
> +	fmt = zx_gl_get_fmt(format);
> +	if (fmt >= 0)
> +		zx_writel_mask(layer + GL_CTRL1, GL_DATA_FMT_MASK,
> +			       fmt << GL_DATA_FMT_SHIFT);
> +
> +	/* Initialize global alpha with a sane value */
> +	zx_writel_mask(layer + GL_CTRL2, GL_GLOBAL_ALPHA_MASK,
> +		       0xff << GL_GLOBAL_ALPHA_SHIFT);
> +
> +	/* Setup CSC for the GL */
> +	if (dst_h > 720)
> +		zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
> +			       CSC_BT709_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT);
> +	else
> +		zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
> +			       CSC_BT601_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT);
> +	zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE, CSC_WORK_ENABLE);
> +
> +	/* Always use scaler since it exists (set for not bypass) */
> +	zx_writel_mask(layer + GL_CTRL3, GL_SCALER_BYPASS_MODE,
> +		       GL_SCALER_BYPASS_MODE);
> +
> +	zx_gl_rsz_setup(zplane, src_w, src_h, dst_w, dst_h);
> +
> +	/* Enable HBSC block */
> +	zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, HBSC_CTRL_EN);
> +
> +	zx_gl_set_update(zplane);
> +}
> +
> +static const struct drm_plane_helper_funcs zx_gl_plane_helper_funcs = {
> +	.atomic_check = zx_gl_plane_atomic_check,
> +	.atomic_update = zx_gl_plane_atomic_update,
> +};
> +
> +static void zx_plane_destroy(struct drm_plane *plane)
> +{
> +	drm_plane_helper_disable(plane);
> +	drm_plane_cleanup(plane);
> +}
> +
> +static const struct drm_plane_funcs zx_plane_funcs = {
> +	.update_plane = drm_atomic_helper_update_plane,
> +	.disable_plane = drm_atomic_helper_disable_plane,
> +	.destroy = zx_plane_destroy,
> +	.reset = drm_atomic_helper_plane_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
> +};
> +
> +static void zx_plane_hbsc_init(struct zx_plane *zplane)
> +{
> +	void __iomem *hbsc = zplane->hbsc;
> +
> +	/*
> +	 *  Initialize HBSC block with a sane configuration per recommedation
> +	 *  from ZTE BSP code.
> +	 */
> +	zx_writel(hbsc + HBSC_SATURATION, 0x200);
> +	zx_writel(hbsc + HBSC_HUE, 0x0);
> +	zx_writel(hbsc + HBSC_BRIGHT, 0x0);
> +	zx_writel(hbsc + HBSC_CONTRAST, 0x200);
> +
> +	zx_writel(hbsc + HBSC_THRESHOLD_COL1, (0x3ac << 16) | 0x40);
> +	zx_writel(hbsc + HBSC_THRESHOLD_COL2, (0x3c0 << 16) | 0x40);
> +	zx_writel(hbsc + HBSC_THRESHOLD_COL3, (0x3c0 << 16) | 0x40);
> +}
> +
> +struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
> +				struct zx_layer_data *data,
> +				enum drm_plane_type type)
> +{
> +	const struct drm_plane_helper_funcs *helper;
> +	struct zx_plane *zplane;
> +	struct drm_plane *plane;
> +	const uint32_t *formats;
> +	unsigned int format_count;
> +	int ret;
> +
> +	zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
> +	if (!zplane)
> +		return ERR_PTR(-ENOMEM);
> +
> +	plane = &zplane->plane;
> +
> +	zplane->layer = data->layer;
> +	zplane->hbsc = data->hbsc;
> +	zplane->csc = data->csc;
> +	zplane->rsz = data->rsz;
> +
> +	zx_plane_hbsc_init(zplane);
> +
> +	switch (type) {
> +	case DRM_PLANE_TYPE_PRIMARY:
> +		helper = &zx_gl_plane_helper_funcs;
> +		formats = gl_formats;
> +		format_count = ARRAY_SIZE(gl_formats);
> +		break;
> +	case DRM_PLANE_TYPE_OVERLAY:
> +		/* TODO: add video layer (vl) support */
> +		break;
> +	default:
> +		return ERR_PTR(-ENODEV);
> +	}
> +
> +	ret = drm_universal_plane_init(drm, plane, VOU_CRTC_MASK,
> +				       &zx_plane_funcs, formats, format_count,
> +				       type, NULL);
> +	if (ret) {
> +		dev_err(dev, "failed to init universal plane: %d\n", ret);
> +		return ERR_PTR(ret);
> +	}
> +
> +	drm_plane_helper_add(plane, helper);
> +
> +	return plane;
> +}
> diff --git a/drivers/gpu/drm/zte/zx_plane.h b/drivers/gpu/drm/zte/zx_plane.h
> new file mode 100644
> index 000000000000..2b82cd558d9d
> --- /dev/null
> +++ b/drivers/gpu/drm/zte/zx_plane.h
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright 2016 Linaro Ltd.
> + * Copyright 2016 ZTE Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#ifndef __ZX_PLANE_H__
> +#define __ZX_PLANE_H__
> +
> +struct zx_layer_data {
> +	void __iomem *layer;
> +	void __iomem *csc;
> +	void __iomem *hbsc;
> +	void __iomem *rsz;
> +};
> +
> +struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
> +				struct zx_layer_data *data,
> +				enum drm_plane_type type);
> +void zx_plane_set_update(struct drm_plane *plane);
> +
> +#endif /* __ZX_PLANE_H__ */
> diff --git a/drivers/gpu/drm/zte/zx_vou.c b/drivers/gpu/drm/zte/zx_vou.c
> new file mode 100644
> index 000000000000..676c750d6009
> --- /dev/null
> +++ b/drivers/gpu/drm/zte/zx_vou.c
> @@ -0,0 +1,799 @@
> +/*
> + * Copyright 2016 Linaro Ltd.
> + * Copyright 2016 ZTE Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/of_address.h>
> +#include <video/videomode.h>
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_of.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drmP.h>
> +
> +#include "zx_drm_drv.h"
> +#include "zx_plane.h"
> +#include "zx_vou.h"
> +
> +/* Sub-module offset */
> +#define MAIN_GL_OFFSET			0x130
> +#define MAIN_CSC_OFFSET			0x580
> +#define MAIN_HBSC_OFFSET		0x820
> +#define MAIN_RSZ_OFFSET			0x600 /* OTFPPU sub-module */
> +
> +#define AUX_GL_OFFSET			0x200
> +#define AUX_CSC_OFFSET			0x5d0
> +#define AUX_HBSC_OFFSET			0x860
> +#define AUX_RSZ_OFFSET			0x800
> +
> +/* OSD (GPC_GLOBAL) registers */
> +#define OSD_INT_STA			0x04
> +#define OSD_INT_CLRSTA			0x08
> +#define OSD_INT_MSK			0x0c
> +#define OSD_INT_AUX_UPT			BIT(14)
> +#define OSD_INT_MAIN_UPT		BIT(13)
> +#define OSD_INT_GL1_LBW			BIT(10)
> +#define OSD_INT_GL0_LBW			BIT(9)
> +#define OSD_INT_VL2_LBW			BIT(8)
> +#define OSD_INT_VL1_LBW			BIT(7)
> +#define OSD_INT_VL0_LBW			BIT(6)
> +#define OSD_INT_BUS_ERR			BIT(3)
> +#define OSD_INT_CFG_ERR			BIT(2)
> +#define OSD_INT_ERROR (\
> +	OSD_INT_GL1_LBW | OSD_INT_GL0_LBW | \
> +	OSD_INT_VL2_LBW | OSD_INT_VL1_LBW | OSD_INT_VL0_LBW | \
> +	OSD_INT_BUS_ERR | OSD_INT_CFG_ERR \
> +)
> +#define OSD_INT_ENABLE (OSD_INT_ERROR | OSD_INT_AUX_UPT | OSD_INT_MAIN_UPT)
> +#define OSD_CTRL0			0x10
> +#define OSD_CTRL0_GL0_EN		BIT(7)
> +#define OSD_CTRL0_GL0_SEL		BIT(6)
> +#define OSD_CTRL0_GL1_EN		BIT(5)
> +#define OSD_CTRL0_GL1_SEL		BIT(4)
> +#define OSD_RST_CLR			0x1c
> +#define RST_PER_FRAME			BIT(19)
> +
> +/* Main/Aux channel registers */
> +#define OSD_MAIN_CHN			0x470
> +#define OSD_AUX_CHN			0x4d0
> +#define CHN_CTRL0			0x00
> +#define CHN_ENABLE			BIT(0)
> +#define CHN_CTRL1			0x04
> +#define CHN_SCREEN_W_SHIFT		18
> +#define CHN_SCREEN_W_MASK		(0x1fff << CHN_SCREEN_W_SHIFT)
> +#define CHN_SCREEN_H_SHIFT		5
> +#define CHN_SCREEN_H_MASK		(0x1fff << CHN_SCREEN_H_SHIFT)
> +#define CHN_UPDATE			0x08
> +
> +/* TIMING_CTRL registers */
> +#define TIMING_TC_ENABLE		0x04
> +#define AUX_TC_EN			BIT(1)
> +#define MAIN_TC_EN			BIT(0)
> +#define FIR_MAIN_ACTIVE			0x08
> +#define FIR_AUX_ACTIVE			0x0c
> +#define V_ACTIVE_SHIFT			16
> +#define V_ACTIVE_MASK			(0xffff << V_ACTIVE_SHIFT)
> +#define H_ACTIVE_SHIFT			0
> +#define H_ACTIVE_MASK			(0xffff << H_ACTIVE_SHIFT)
> +#define FIR_MAIN_H_TIMING		0x10
> +#define FIR_MAIN_V_TIMING		0x14
> +#define FIR_AUX_H_TIMING		0x18
> +#define FIR_AUX_V_TIMING		0x1c
> +#define SYNC_WIDE_SHIFT			22
> +#define SYNC_WIDE_MASK			(0x3ff << SYNC_WIDE_SHIFT)
> +#define BACK_PORCH_SHIFT		11
> +#define BACK_PORCH_MASK			(0x7ff << BACK_PORCH_SHIFT)
> +#define FRONT_PORCH_SHIFT		0
> +#define FRONT_PORCH_MASK		(0x7ff << FRONT_PORCH_SHIFT)
> +#define TIMING_CTRL			0x20
> +#define AUX_POL_SHIFT			3
> +#define AUX_POL_MASK			(0x7 << AUX_POL_SHIFT)
> +#define MAIN_POL_SHIFT			0
> +#define MAIN_POL_MASK			(0x7 << MAIN_POL_SHIFT)
> +#define POL_DE_SHIFT			2
> +#define POL_VSYNC_SHIFT			1
> +#define POL_HSYNC_SHIFT			0
> +#define TIMING_INT_CTRL			0x24
> +#define TIMING_INT_STATE		0x28
> +#define TIMING_INT_AUX_FRAME		BIT(3)
> +#define TIMING_INT_MAIN_FRAME		BIT(1)
> +#define TIMING_INT_AUX_FRAME_SEL_VSW	(0x2 << 10)
> +#define TIMING_INT_MAIN_FRAME_SEL_VSW	(0x2 << 6)
> +#define TIMING_INT_ENABLE (\
> +	TIMING_INT_MAIN_FRAME_SEL_VSW | TIMING_INT_AUX_FRAME_SEL_VSW | \
> +	TIMING_INT_MAIN_FRAME | TIMING_INT_AUX_FRAME \
> +)
> +#define TIMING_MAIN_SHIFT		0x2c
> +#define TIMING_AUX_SHIFT		0x30
> +#define H_SHIFT_VAL			0x0048
> +#define TIMING_MAIN_PI_SHIFT		0x68
> +#define TIMING_AUX_PI_SHIFT		0x6c
> +#define H_PI_SHIFT_VAL			0x000f
> +
> +#define V_ACTIVE(x)	(((x) << V_ACTIVE_SHIFT) & V_ACTIVE_MASK)
> +#define H_ACTIVE(x)	(((x) << H_ACTIVE_SHIFT) & H_ACTIVE_MASK)
> +
> +#define SYNC_WIDE(x)	(((x) << SYNC_WIDE_SHIFT) & SYNC_WIDE_MASK)
> +#define BACK_PORCH(x)	(((x) << BACK_PORCH_SHIFT) & BACK_PORCH_MASK)
> +#define FRONT_PORCH(x)	(((x) << FRONT_PORCH_SHIFT) & FRONT_PORCH_MASK)
> +
> +/* DTRC registers */
> +#define DTRC_F0_CTRL			0x2c
> +#define DTRC_F1_CTRL			0x5c
> +#define DTRC_DECOMPRESS_BYPASS		BIT(17)
> +#define DTRC_DETILE_CTRL		0x68
> +#define TILE2RASTESCAN_BYPASS_MODE	BIT(30)
> +#define DETILE_ARIDR_MODE_MASK		(0x3 << 0)
> +#define DETILE_ARID_ALL			0
> +#define DETILE_ARID_IN_ARIDR		1
> +#define DETILE_ARID_BYP_BUT_ARIDR	2
> +#define DETILE_ARID_IN_ARIDR2		3
> +#define DTRC_ARID			0x6c
> +#define DTRC_ARID3_SHIFT		24
> +#define DTRC_ARID3_MASK			(0xff << DTRC_ARID3_SHIFT)
> +#define DTRC_ARID2_SHIFT		16
> +#define DTRC_ARID2_MASK			(0xff << DTRC_ARID2_SHIFT)
> +#define DTRC_ARID1_SHIFT		8
> +#define DTRC_ARID1_MASK			(0xff << DTRC_ARID1_SHIFT)
> +#define DTRC_ARID0_SHIFT		0
> +#define DTRC_ARID0_MASK			(0xff << DTRC_ARID0_SHIFT)
> +#define DTRC_DEC2DDR_ARID		0x70
> +
> +#define DTRC_ARID3(x)	(((x) << DTRC_ARID3_SHIFT) & DTRC_ARID3_MASK)
> +#define DTRC_ARID2(x)	(((x) << DTRC_ARID2_SHIFT) & DTRC_ARID2_MASK)
> +#define DTRC_ARID1(x)	(((x) << DTRC_ARID1_SHIFT) & DTRC_ARID1_MASK)
> +#define DTRC_ARID0(x)	(((x) << DTRC_ARID0_SHIFT) & DTRC_ARID0_MASK)
> +
> +/* VOU_CTRL registers */
> +#define VOU_INF_EN			0x00
> +#define VOU_INF_CH_SEL			0x04
> +#define VOU_INF_DATA_SEL		0x08
> +#define VOU_SOFT_RST			0x14
> +#define VOU_CLK_SEL			0x18
> +#define VOU_CLK_GL1_SEL			BIT(5)
> +#define VOU_CLK_GL0_SEL			BIT(4)
> +#define VOU_CLK_REQEN			0x20
> +#define VOU_CLK_EN			0x24
> +
> +/* OTFPPU_CTRL registers */
> +#define OTFPPU_RSZ_DATA_SOURCE		0x04
> +
> +#define GL_NUM				2
> +#define VL_NUM				3
> +
> +enum vou_chn_type {
> +	VOU_CHN_MAIN,
> +	VOU_CHN_AUX,
> +};
> +
> +struct zx_crtc_regs {
> +	u32 fir_active;
> +	u32 fir_htiming;
> +	u32 fir_vtiming;
> +	u32 timing_shift;
> +	u32 timing_pi_shift;
> +};
> +
> +static const struct zx_crtc_regs main_crtc_regs = {
> +	.fir_active = FIR_MAIN_ACTIVE,
> +	.fir_htiming = FIR_MAIN_H_TIMING,
> +	.fir_vtiming = FIR_MAIN_V_TIMING,
> +	.timing_shift = TIMING_MAIN_SHIFT,
> +	.timing_pi_shift = TIMING_MAIN_PI_SHIFT,
> +};
> +
> +static const struct zx_crtc_regs aux_crtc_regs = {
> +	.fir_active = FIR_AUX_ACTIVE,
> +	.fir_htiming = FIR_AUX_H_TIMING,
> +	.fir_vtiming = FIR_AUX_V_TIMING,
> +	.timing_shift = TIMING_AUX_SHIFT,
> +	.timing_pi_shift = TIMING_AUX_PI_SHIFT,
> +};
> +
> +struct zx_crtc_bits {
> +	u32 polarity_mask;
> +	u32 polarity_shift;
> +	u32 tc_enable;
> +	u32 gl_enable;
> +};
> +
> +static const struct zx_crtc_bits main_crtc_bits = {
> +	.polarity_mask = MAIN_POL_MASK,
> +	.polarity_shift = MAIN_POL_SHIFT,
> +	.tc_enable = MAIN_TC_EN,
> +	.gl_enable = OSD_CTRL0_GL0_EN,
> +};
> +
> +static const struct zx_crtc_bits aux_crtc_bits = {
> +	.polarity_mask = AUX_POL_MASK,
> +	.polarity_shift = AUX_POL_SHIFT,
> +	.tc_enable = AUX_TC_EN,
> +	.gl_enable = OSD_CTRL0_GL1_EN,
> +};
> +
> +struct zx_crtc {
> +	struct drm_crtc crtc;
> +	struct drm_plane *primary;
> +	struct zx_vou_hw *vou;
> +	void __iomem *chnreg;
> +	const struct zx_crtc_regs *regs;
> +	const struct zx_crtc_bits *bits;
> +	enum vou_chn_type chn_type;
> +	struct clk *pixclk;
> +};
> +
> +#define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
> +
> +struct zx_vou_hw {
> +	struct device *dev;
> +	void __iomem *osd;
> +	void __iomem *timing;
> +	void __iomem *vouctl;
> +	void __iomem *otfppu;
> +	void __iomem *dtrc;
> +	struct clk *axi_clk;
> +	struct clk *ppu_clk;
> +	struct clk *main_clk;
> +	struct clk *aux_clk;
> +	struct zx_crtc *main_crtc;
> +	struct zx_crtc *aux_crtc;
> +};
> +
> +static inline struct zx_vou_hw *crtc_to_vou(struct drm_crtc *crtc)
> +{
> +	struct zx_crtc *zcrtc = to_zx_crtc(crtc);
> +
> +	return zcrtc->vou;
> +}
> +
> +void vou_inf_enable(const struct vou_inf *inf, struct drm_crtc *crtc)
> +{
> +	struct zx_crtc *zcrtc = to_zx_crtc(crtc);
> +	struct zx_vou_hw *vou = zcrtc->vou;
> +	bool is_main = zcrtc->chn_type == VOU_CHN_MAIN;
> +	u32 data_sel_shift = inf->id << 1;
> +
> +	/* Select data format */
> +	zx_writel_mask(vou->vouctl + VOU_INF_DATA_SEL, 0x3 << data_sel_shift,
> +		       inf->data_sel << data_sel_shift);
> +
> +	/* Select channel */
> +	zx_writel_mask(vou->vouctl + VOU_INF_CH_SEL, 0x1 << inf->id,
> +		       zcrtc->chn_type << inf->id);
> +
> +	/* Select interface clocks */
> +	zx_writel_mask(vou->vouctl + VOU_CLK_SEL, inf->clocks_sel_bits,
> +		       is_main ? 0 : inf->clocks_sel_bits);
> +
> +	/* Enable interface clocks */
> +	zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits,
> +		       inf->clocks_en_bits);
> +
> +	/* Enable the device */
> +	zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << inf->id, 1 << inf->id);
> +}
> +
> +void vou_inf_disable(const struct vou_inf *inf, struct drm_crtc *crtc)
> +{
> +	struct zx_vou_hw *vou = crtc_to_vou(crtc);
> +
> +	/* Disable the device */
> +	zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << inf->id, 0);
> +
> +	/* Disable interface clocks */
> +	zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits, 0);
> +}
> +
> +static inline void vou_chn_set_update(struct zx_crtc *zcrtc)
> +{
> +	zx_writel(zcrtc->chnreg + CHN_UPDATE, 1);
> +}
> +
> +static void zx_crtc_enable(struct drm_crtc *crtc)
> +{
> +	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
> +	struct zx_crtc *zcrtc = to_zx_crtc(crtc);
> +	struct zx_vou_hw *vou = zcrtc->vou;
> +	const struct zx_crtc_regs *regs = zcrtc->regs;
> +	const struct zx_crtc_bits *bits = zcrtc->bits;
> +	struct videomode vm;
> +	u32 pol = 0;
> +	u32 val;
> +	int ret;
> +
> +	drm_display_mode_to_videomode(mode, &vm);
> +
> +	/* Set up timing parameters */
> +	val = V_ACTIVE(vm.vactive - 1);
> +	val |= H_ACTIVE(vm.hactive - 1);
> +	zx_writel(vou->timing + regs->fir_active, val);
> +
> +	val = SYNC_WIDE(vm.hsync_len - 1);
> +	val |= BACK_PORCH(vm.hback_porch - 1);
> +	val |= FRONT_PORCH(vm.hfront_porch - 1);
> +	zx_writel(vou->timing + regs->fir_htiming, val);
> +
> +	val = SYNC_WIDE(vm.vsync_len - 1);
> +	val |= BACK_PORCH(vm.vback_porch - 1);
> +	val |= FRONT_PORCH(vm.vfront_porch - 1);
> +	zx_writel(vou->timing + regs->fir_vtiming, val);
> +
> +	/* Set up polarities */
> +	if (vm.flags & DISPLAY_FLAGS_VSYNC_LOW)
> +		pol |= 1 << POL_VSYNC_SHIFT;
> +	if (vm.flags & DISPLAY_FLAGS_HSYNC_LOW)
> +		pol |= 1 << POL_HSYNC_SHIFT;
> +
> +	zx_writel_mask(vou->timing + TIMING_CTRL, bits->polarity_mask,
> +		       pol << bits->polarity_shift);
> +
> +	/* Setup SHIFT register by following what ZTE BSP does */
> +	zx_writel(vou->timing + regs->timing_shift, H_SHIFT_VAL);
> +	zx_writel(vou->timing + regs->timing_pi_shift, H_PI_SHIFT_VAL);
> +
> +	/* Enable TIMING_CTRL */
> +	zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable,
> +		       bits->tc_enable);
> +
> +	/* Configure channel screen size */
> +	zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_W_MASK,
> +		       vm.hactive << CHN_SCREEN_W_SHIFT);
> +	zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_H_MASK,
> +		       vm.vactive << CHN_SCREEN_H_SHIFT);
> +
> +	/* Update channel */
> +	vou_chn_set_update(zcrtc);
> +
> +	/* Enable channel */
> +	zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, CHN_ENABLE);
> +
> +	/* Enable Graphic Layer */
> +	zx_writel_mask(vou->osd + OSD_CTRL0, bits->gl_enable,
> +		       bits->gl_enable);
> +
> +	drm_crtc_vblank_on(crtc);
> +
> +	ret = clk_set_rate(zcrtc->pixclk, mode->clock * 1000);
> +	if (ret) {
> +		dev_warn(vou->dev, "failed to set pixclk rate: %d\n", ret);

DRM_WARN

> +		return;
> +	}
> +
> +	ret = clk_prepare_enable(zcrtc->pixclk);
> +	if (ret)
> +		dev_warn(vou->dev, "failed to enable pixclk: %d\n", ret);
> +}
> +
> +static void zx_crtc_disable(struct drm_crtc *crtc)
> +{
> +	struct zx_crtc *zcrtc = to_zx_crtc(crtc);
> +	const struct zx_crtc_bits *bits = zcrtc->bits;
> +	struct zx_vou_hw *vou = zcrtc->vou;
> +
> +	clk_disable_unprepare(zcrtc->pixclk);
> +
> +	drm_crtc_vblank_off(crtc);
> +
> +	/* Disable Graphic Layer */
> +	zx_writel_mask(vou->osd + OSD_CTRL0, bits->gl_enable, 0);
> +
> +	/* Disable channel */
> +	zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, 0);
> +
> +	/* Disable TIMING_CTRL */
> +	zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable, 0);
> +}
> +
> +static void zx_crtc_atomic_begin(struct drm_crtc *crtc,
> +				 struct drm_crtc_state *state)
> +{
> +	struct drm_pending_vblank_event *event = crtc->state->event;
> +
> +	if (!event)
> +		return;
> +
> +	crtc->state->event = NULL;
> +
> +	spin_lock_irq(&crtc->dev->event_lock);
> +	if (drm_crtc_vblank_get(crtc) == 0)
> +		drm_crtc_arm_vblank_event(crtc, event);
> +	else
> +		drm_crtc_send_vblank_event(crtc, event);
> +	spin_unlock_irq(&crtc->dev->event_lock);

I think you may want to send the vblank event to userspace after you
commit your planes, and not before.

> +}
> +
> +static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs = {
> +	.enable = zx_crtc_enable,
> +	.disable = zx_crtc_disable,
> +	.atomic_begin = zx_crtc_atomic_begin,
> +};
> +
> +static const struct drm_crtc_funcs zx_crtc_funcs = {
> +	.destroy = drm_crtc_cleanup,
> +	.set_config = drm_atomic_helper_set_config,
> +	.page_flip = drm_atomic_helper_page_flip,
> +	.reset = drm_atomic_helper_crtc_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> +};
> +
> +static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
> +			enum vou_chn_type chn_type)
> +{
> +	struct device *dev = vou->dev;
> +	struct zx_layer_data data;
> +	struct zx_crtc *zcrtc;
> +	int ret;
> +
> +	zcrtc = devm_kzalloc(dev, sizeof(*zcrtc), GFP_KERNEL);
> +	if (!zcrtc)
> +		return -ENOMEM;
> +
> +	zcrtc->vou = vou;
> +	zcrtc->chn_type = chn_type;
> +
> +	if (chn_type == VOU_CHN_MAIN) {
> +		data.layer = vou->osd + MAIN_GL_OFFSET;
> +		data.csc = vou->osd + MAIN_CSC_OFFSET;
> +		data.hbsc = vou->osd + MAIN_HBSC_OFFSET;
> +		data.rsz = vou->otfppu + MAIN_RSZ_OFFSET;
> +		zcrtc->chnreg = vou->osd + OSD_MAIN_CHN;
> +		zcrtc->regs = &main_crtc_regs;
> +		zcrtc->bits = &main_crtc_bits;
> +	} else {
> +		data.layer = vou->osd + AUX_GL_OFFSET;
> +		data.csc = vou->osd + AUX_CSC_OFFSET;
> +		data.hbsc = vou->osd + AUX_HBSC_OFFSET;
> +		data.rsz = vou->otfppu + AUX_RSZ_OFFSET;
> +		zcrtc->chnreg = vou->osd + OSD_AUX_CHN;
> +		zcrtc->regs = &aux_crtc_regs;
> +		zcrtc->bits = &aux_crtc_bits;
> +	}
> +
> +	zcrtc->pixclk = devm_clk_get(dev, (chn_type == VOU_CHN_MAIN) ?
> +					  "main_wclk" : "aux_wclk");
> +	if (IS_ERR(zcrtc->pixclk)) {
> +		ret = PTR_ERR(zcrtc->pixclk);
> +		dev_err(dev, "failed to get pix clk: %d\n", ret);

DRM_ERROR() - here and in other places in your patch

^ permalink raw reply

* Handling of enet_out on i.MX28
From: Andy Duan @ 2016-10-20 12:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161020091126.jdoexu6iuu3jjzsm@pengutronix.de>

From: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de> Sent: Thursday, October 20, 2016 5:11 PM
> To: Andy Duan <fugang.duan@nxp.com>; Fabio Estevam Estevam
> <fabio.estevam@nxp.com>; Shawn Guo <shawnguo@kernel.org>;
> devicetree at vger.kernel.org
> Cc: kernel at pengutronix.de; linux-arm-kernel at lists.infradead.org
> Subject: Handling of enet_out on i.MX28
> 
> Hello,
> 
> The i.MX28 reference manual specifies for HW_CLKCTRL_ENET.CLK_OUT_EN:
> "NOTE: This bit must be configured before ENET PLL is enabled.".
> 
> Currently this is not implemented: ENET PLL (aka pll2) is the parent of
> enet_out and so common clk enables the PLL first and only then sets
> HW_CLKCTRL_ENET.CLK_OUT_EN.
> 
> For now this is a theoretical problem because I don't see any issues. I only
> notice the discrepancy between manual and reality.
> 
> Do you think this is a problem?
> 
I don't know the history. But I think this is a problem. Maybe it bring some clock glitch that may cause PHY (with RMII)  abnormal.

> Apart from that I'm not happy with the handling of this clk. IMHO it should
> better be called "enet-ref" or similar (for the fec). imx28.dtsi specifies that
> the clk is in use[1] and if my machine doesn't I have to
> do:
> 
> 	&mac0 {
> 		...
> 		/* overwrite clocks and clock-names to remove enet_out */
> 		clocks = <&clks 57>, <&clks 57>;
> 		clock-names = "ipg", "ahb";
> 		...
> 	};
> 
> in my board.dts. This is ugly because I have to repeat stuff that is already in
> imx28.dtsi and it's not understandable without the comment.
> 
> It would be nice if dtc allowed to modify an array, then we could do:
> 
> 	clocks += <&clks 64>;
> 	clock-names = += "enet_out";
> 
> (assuming the included dtsi doesn't specify this clock).
> 
> I first though it would be a good idea to specify the enet-ref clk as
> follows:
> 
> 	&mac0 {
> 		...
> 		mdio {
> 			clocks = <&clks 64>;
> 			clock-names = "enet-ref";
> 			...
> 		};
> 	};
>
In RMII mode,  this clock is for phy and MAC reference clock.
It is better to specify this clock as "enet_clk_ref" and "enet_out" that is easy to understand.
In dtsi file, we can just define ipg and ahb clock.
clocks = <&clks 57>, <&clks 57>;
clock-names = "ipg","ahb";
In dts file, different boards may have design mode like RMII/MII, RMII mode needs to define enet_out and enet_clk_ref,  MII mode doesn't need this clocks.
So it depends on board design, we can overwrite the clock in dts board file.   
Like in RMII mode: 
clocks = <&clks 57>, <&clks 57>, <&clks 64>, <&clks 64>;
clock-names = "ipg","ahb", "enet_clk_ref","enet_out";
In MII mode: no necessary to overwrite them. 

> but while this makes it easier for the board.dts to add (or remove) it, it's not
> really right this way because the reference clock is needed for data RX and TX,
> not the mdio bus. Technically these are two different buses even though the
> "passengers" are often the same. (Even if two MACs are in use, the enet-ref
> signal is shared.)
> 
> What do you think?
> 
> Best regards
> Uwe
> 
> [1] clocks = <&clks 57>, <&clks 57>, <&clks 64>; clock-names = "ipg",
>     "ahb", "enet_out"; in &mac0.
> 
> --
> Pengutronix e.K.                           | Uwe Kleine-K?nig            |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply

* [PATCH 2/2] arm64/numa: fix incorrect print of end_pfn
From: Hanjun Guo @ 2016-10-20 12:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161020105130.GD24914@arm.com>

On 2016/10/20 18:51, Will Deacon wrote:
> On Thu, Oct 20, 2016 at 11:52:56AM +0800, Hanjun Guo wrote:
>> From: Hanjun Guo <hanjun.guo@linaro.org>
>>
>> When booting on NUMA system with memory-less node (no
>> memory dimm on this memory controller), the print
>> for setup_node_data() is incorrect:
>>
>> NUMA: Initmem setup node 2 [mem 0x00000000-0xffffffffffffffff]
>>
>> It should be 0, not 0xffffffffffffffff as there is
>> no memory on that node.
> Wouldn't it make more sense to print something useful, like "memory-less
> node"?

in the log,

[    0.000000] NUMA: Initmem setup node 0 [mem 0x00000000-0x13fbffffff]
[    0.000000] NUMA: NODE_DATA [mem 0x13fbffe500-0x13fbffffff]
[    0.000000] NUMA: Initmem setup node 1 [mem 0x1400000000-0x17fbffffff]
[    0.000000] NUMA: NODE_DATA [mem 0x17fbfec500-0x17fbfedfff]
[    0.000000] NUMA: Initmem setup node 2 [mem 0x00000000-0xffffffffffffffff]
[    0.000000] NUMA: NODE_DATA [mem 0x17fbfeaa00-0x17fbfec4ff]
[    0.000000] NUMA: NODE_DATA(2) on node 1
[    0.000000] NUMA: Initmem setup node 3 [mem 0x00000000-0xffffffffffffffff]
[    0.000000] NUMA: NODE_DATA [mem 0x17fbfe8f00-0x17fbfea9ff]
[    0.000000] NUMA: NODE_DATA(3) on node 1

if printing "NUMA: Initmem setup node 2 [mem 0x00000000-0x00000000]",
it will make the log consistent with others, and obvious it's a memory-less
node as memory range 0x00000000-0x00000000, what do you think?

Thanks
Hanjun

^ permalink raw reply

* [PATCH v2 1/6] ARM: at91: Documentation: add samx7 families
From: Alexandre Belloni @ 2016-10-20 12:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <ae042bfa-4e92-a3ac-386a-31aeb8798776@atmel.com>

On 20/10/2016 at 14:01:24 +0200, Nicolas Ferre wrote :
> Le 20/10/2016 ? 11:41, Alexandre Belloni a ?crit :
> > The Atmel sams70, samv70 and samv71 are Cortex-M7 based MCUs that can run
> > Linux (without MMU).
> > 
> > Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> > ---
> >  Documentation/arm/Atmel/README | 44 +++++++++++++++++++++++++++++++++++++++---
> >  1 file changed, 41 insertions(+), 3 deletions(-)
> > 
> > diff --git a/Documentation/arm/Atmel/README b/Documentation/arm/Atmel/README
> > index 6ca78f818dbf..e403697ee9fc 100644
> > --- a/Documentation/arm/Atmel/README
> > +++ b/Documentation/arm/Atmel/README
> > @@ -14,9 +14,9 @@ official Atmel product name. Anyway, files, directories, git trees,
> >  git branches/tags and email subject always contain this "at91" sub-string.
> >  
> >  
> > -AT91 SoCs
> 
> Nope: AT91 is our historical name within the Linux community, we will
> keep it.
> 

Well, this is explained just on the line before, I was thinking that was
enough but whatever, marketing stuff ;)

> > ----------
> > -Documentation and detailled datasheet for each product are available on
> > +SMART SoCs
> 
> And I'm not sure about the naming of the product line nowadays:
> Atmel | SMART MPUs?
> Microchip / Atmel | SMART MPUs?
> Microchip MPUs?
> 
> But SoC is definitively too generic and "SMART" not needed here: let's
> keep the MPUs/MCUs only difference for this document.
> 

So, AT91 MPUs and SMART MCUs ?
Or I can put everything under AT91 SoCs

> > +----------
> > +Documentation and detailed datasheet for each product are available on
> >  the Atmel website: http://www.atmel.com.
> >  
> >    Flavors:
> > @@ -101,6 +101,44 @@ the Atmel website: http://www.atmel.com.
> >          + Datasheet
> >            http://www.atmel.com/Images/Atmel-11267-32-bit-Cortex-A5-Microcontroller-SAMA5D2_Datasheet.pdf
> >  
> > +SMART MCUs
> > +----------
> > +    * ARM Cortex-M7 MCUs
> > +      - sams70 family
> > +        - sams70j19
> > +        - sams70j20
> > +        - sams70j21
> > +        - sams70n19
> > +        - sams70n20
> > +        - sams70n21
> > +        - sams70q19
> > +        - sams70q20
> > +        - sams70q21
> > +        + Datasheet
> > +          http://www.atmel.com/Images/Atmel-11242-32-bit-Cortex-M7-Microcontroller-SAM-S70Q-SAM-S70N-SAM-S70J_Datasheet.pdf
> > +
> > +      - samv70 family
> > +        - samv70j19
> > +        - samv70j20
> > +        - samv70n19
> > +        - samv70n20
> > +        - samv70q19
> > +        - samv70q20
> > +        + Datasheet
> > +          http://www.atmel.com/Images/Atmel-11297-32-bit-Cortex-M7-Microcontroller-SAM-V70Q-SAM-V70N-SAM-V70J_Datasheet.pdf
> > +
> > +      - samv71 family
> > +        - samv71j19
> > +        - samv71j20
> > +        - samv71j21
> > +        - samv71n19
> > +        - samv71n20
> > +        - samv71n21
> > +        - samv71q19
> > +        - samv71q20
> > +        - samv71q21
> > +        + Datasheet
> > +          http://www.atmel.com/Images/Atmel-44003-32-bit-Cortex-M7-Microcontroller-SAM-V71Q-SAM-V71N-SAM-V71J_Datasheet.pdf
> >  
> >  Linux kernel information
> >  ------------------------
> > 
> 
> 
> -- 
> Nicolas Ferre

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH 1/2] arm64/numa: fix pcpu_cpu_distance() to get correct CPU proximity
From: Hanjun Guo @ 2016-10-20 12:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161020104815.GC24914@arm.com>

On 2016/10/20 18:48, Will Deacon wrote:
> On Thu, Oct 20, 2016 at 11:52:55AM +0800, Hanjun Guo wrote:
>> From: Yisheng Xie <xieyisheng1@huawei.com>
>>
>> The pcpu_build_alloc_info() function group CPUs according to their
>> proximity, by call callback function @cpu_distance_fn from different
>> ARCHs.
>>
>> For arm64 the callback of @cpu_distance_fn is
>>     pcpu_cpu_distance(from, to)
>>         -> node_distance(from, to)
>> The @from and @to for function node_distance() should be nid.
>>
>> However, pcpu_cpu_distance() in arch/arm64/mm/numa.c just past the
>> cpu id for @from and @to.
>>
>> For this incorrect cpu proximity get from ARCH, it may cause each CPU
>> in one group and make group_cnt out of bound:
>>
>> 	setup_per_cpu_areas()
>> 		pcpu_embed_first_chunk()
>> 			pcpu_build_alloc_info()
>> in pcpu_build_alloc_info, since cpu_distance_fn will return
>> REMOTE_DISTANCE if we pass cpu ids (0,1,2...), so
>> cpu_distance_fn(cpu, tcpu) > LOCAL_DISTANCE will wrongly be ture.
>>
>> This may results in triggering the BUG_ON(unit != nr_units) later:
>>
>> [    0.000000] kernel BUG at mm/percpu.c:1916!
>> [    0.000000] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
>> [    0.000000] Modules linked in:
>> [    0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.9.0-rc1-00003-g14155ca-dirty #26
>> [    0.000000] Hardware name: Hisilicon Hi1616 Evaluation Board (DT)
>> [    0.000000] task: ffff000008d6e900 task.stack: ffff000008d60000
>> [    0.000000] PC is at pcpu_embed_first_chunk+0x420/0x704
>> [    0.000000] LR is at pcpu_embed_first_chunk+0x3bc/0x704
>> [    0.000000] pc : [<ffff000008c754f4>] lr : [<ffff000008c75490>] pstate: 800000c5
>> [    0.000000] sp : ffff000008d63eb0
>> [    0.000000] x29: ffff000008d63eb0 [    0.000000] x28: 0000000000000000
>> [    0.000000] x27: 0000000000000040 [    0.000000] x26: ffff8413fbfcef00
>> [    0.000000] x25: 0000000000000042 [    0.000000] x24: 0000000000000042
>> [    0.000000] x23: 0000000000001000 [    0.000000] x22: 0000000000000046
>> [    0.000000] x21: 0000000000000001 [    0.000000] x20: ffff000008cb3bc8
>> [    0.000000] x19: ffff8413fbfcf570 [    0.000000] x18: 0000000000000000
>> [    0.000000] x17: ffff000008e49ae0 [    0.000000] x16: 0000000000000003
>> [    0.000000] x15: 000000000000001e [    0.000000] x14: 0000000000000004
>> [    0.000000] x13: 0000000000000000 [    0.000000] x12: 000000000000006f
>> [    0.000000] x11: 00000413fbffff00 [    0.000000] x10: 0000000000000004
>> [    0.000000] x9 : 0000000000000000 [    0.000000] x8 : 0000000000000001
>> [    0.000000] x7 : ffff8413fbfcf63c [    0.000000] x6 : ffff000008d65d28
>> [    0.000000] x5 : ffff000008d65e50 [    0.000000] x4 : 0000000000000000
>> [    0.000000] x3 : ffff000008cb3cc8 [    0.000000] x2 : 0000000000000040
>> [    0.000000] x1 : 0000000000000040 [    0.000000] x0 : 0000000000000000
>> [...]
>> [    0.000000] Call trace:
>> [    0.000000] Exception stack(0xffff000008d63ce0 to 0xffff000008d63e10)
>> [    0.000000] 3ce0: ffff8413fbfcf570 0001000000000000 ffff000008d63eb0 ffff000008c754f4
>> [    0.000000] 3d00: ffff000008d63d50 ffff0000081af210 00000413fbfff010 0000000000001000
>> [    0.000000] 3d20: ffff000008d63d50 ffff0000081af220 00000413fbfff010 0000000000001000
>> [    0.000000] 3d40: 00000413fbfcef00 0000000000000004 ffff000008d63db0 ffff0000081af390
>> [    0.000000] 3d60: 00000413fbfcef00 0000000000001000 0000000000000000 0000000000001000
>> [    0.000000] 3d80: 0000000000000000 0000000000000040 0000000000000040 ffff000008cb3cc8
>> [    0.000000] 3da0: 0000000000000000 ffff000008d65e50 ffff000008d65d28 ffff8413fbfcf63c
>> [    0.000000] 3dc0: 0000000000000001 0000000000000000 0000000000000004 00000413fbffff00
>> [    0.000000] 3de0: 000000000000006f 0000000000000000 0000000000000004 000000000000001e
>> [    0.000000] 3e00: 0000000000000003 ffff000008e49ae0
>> [    0.000000] [<ffff000008c754f4>] pcpu_embed_first_chunk+0x420/0x704
>> [    0.000000] [<ffff000008c6658c>] setup_per_cpu_areas+0x38/0xc8
>> [    0.000000] [<ffff000008c608d8>] start_kernel+0x10c/0x390
>> [    0.000000] [<ffff000008c601d8>] __primary_switched+0x5c/0x64
>> [    0.000000] Code: b8018660 17ffffd7 6b16037f 54000080 (d4210000)
>> [    0.000000] ---[ end trace 0000000000000000 ]---
>> [    0.000000] Kernel panic - not syncing: Attempted to kill the idle task!
>>
>> Fix by getting CPUs proximity through its node. We only care about
>> whether it is LOCAL_DISTANCE or not, for pcpu_build_alloc_info() only
>> use this to group CPUs.
>>
>> Fixes: 7af3a0a99252 ("arm64/numa: support HAVE_SETUP_PER_CPU_AREA")
>> Signed-off-by: Yisheng Xie <xieyisheng1@huawei.com>
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Zhen Lei <thunder.leizhen@huawei.com>
>> ---
>>  arch/arm64/mm/numa.c | 5 ++++-
>>  1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
>> index 778a985..34415fc 100644
>> --- a/arch/arm64/mm/numa.c
>> +++ b/arch/arm64/mm/numa.c
>> @@ -147,7 +147,10 @@ static int __init early_cpu_to_node(int cpu)
>>  
>>  static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
>>  {
>> -	return node_distance(from, to);
>> +	if (early_cpu_to_node(from) == early_cpu_to_node(to))
>> +		return LOCAL_DISTANCE;
>> +	else
>> +		return REMOTE_DISTANCE;
> Why can't this be node_distance(early_cpu_to_node(from), early_cpu_to_node(to))?

It's really some coding style preference and the caller function is only care about
it's LOCAL_DISTANCE or not, as we said in the commit message.

But using node_distance() will save few lines of code and no functional change,
will update it.

Thanks
Hanjun

^ permalink raw reply

* [PATCH v2 1/6] ARM: at91: Documentation: add samx7 families
From: Nicolas Ferre @ 2016-10-20 12:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161020094135.18221-2-alexandre.belloni@free-electrons.com>

Le 20/10/2016 ? 11:41, Alexandre Belloni a ?crit :
> The Atmel sams70, samv70 and samv71 are Cortex-M7 based MCUs that can run
> Linux (without MMU).
> 
> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> ---
>  Documentation/arm/Atmel/README | 44 +++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 41 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/arm/Atmel/README b/Documentation/arm/Atmel/README
> index 6ca78f818dbf..e403697ee9fc 100644
> --- a/Documentation/arm/Atmel/README
> +++ b/Documentation/arm/Atmel/README
> @@ -14,9 +14,9 @@ official Atmel product name. Anyway, files, directories, git trees,
>  git branches/tags and email subject always contain this "at91" sub-string.
>  
>  
> -AT91 SoCs

Nope: AT91 is our historical name within the Linux community, we will
keep it.

> ----------
> -Documentation and detailled datasheet for each product are available on
> +SMART SoCs

And I'm not sure about the naming of the product line nowadays:
Atmel | SMART MPUs?
Microchip / Atmel | SMART MPUs?
Microchip MPUs?

But SoC is definitively too generic and "SMART" not needed here: let's
keep the MPUs/MCUs only difference for this document.

> +----------
> +Documentation and detailed datasheet for each product are available on
>  the Atmel website: http://www.atmel.com.
>  
>    Flavors:
> @@ -101,6 +101,44 @@ the Atmel website: http://www.atmel.com.
>          + Datasheet
>            http://www.atmel.com/Images/Atmel-11267-32-bit-Cortex-A5-Microcontroller-SAMA5D2_Datasheet.pdf
>  
> +SMART MCUs
> +----------
> +    * ARM Cortex-M7 MCUs
> +      - sams70 family
> +        - sams70j19
> +        - sams70j20
> +        - sams70j21
> +        - sams70n19
> +        - sams70n20
> +        - sams70n21
> +        - sams70q19
> +        - sams70q20
> +        - sams70q21
> +        + Datasheet
> +          http://www.atmel.com/Images/Atmel-11242-32-bit-Cortex-M7-Microcontroller-SAM-S70Q-SAM-S70N-SAM-S70J_Datasheet.pdf
> +
> +      - samv70 family
> +        - samv70j19
> +        - samv70j20
> +        - samv70n19
> +        - samv70n20
> +        - samv70q19
> +        - samv70q20
> +        + Datasheet
> +          http://www.atmel.com/Images/Atmel-11297-32-bit-Cortex-M7-Microcontroller-SAM-V70Q-SAM-V70N-SAM-V70J_Datasheet.pdf
> +
> +      - samv71 family
> +        - samv71j19
> +        - samv71j20
> +        - samv71j21
> +        - samv71n19
> +        - samv71n20
> +        - samv71n21
> +        - samv71q19
> +        - samv71q20
> +        - samv71q21
> +        + Datasheet
> +          http://www.atmel.com/Images/Atmel-44003-32-bit-Cortex-M7-Microcontroller-SAM-V71Q-SAM-V71N-SAM-V71J_Datasheet.pdf
>  
>  Linux kernel information
>  ------------------------
> 


-- 
Nicolas Ferre

^ permalink raw reply

* [PATCH] pinctrl: st: don't specify default interrupt trigger
From: Peter Griffin @ 2016-10-20 11:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <729ebc94-5476-65a7-cc17-eabfba0d2404@st.com>

Hi Patrice,

On Thu, 20 Oct 2016, Patrice Chotard wrote:

> 
> 
> On 10/18/2016 09:16 AM, patrice.chotard at st.com wrote:
> > From: Patrice Chotard <patrice.chotard@st.com>
> > 
> > Thanks to 332e99d5ae4 which now alerts of default
> > trigger usage when configuring interrupts.
> > 
> > Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> > ---
> >  drivers/pinctrl/pinctrl-st.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
> > index 99da4cf..b7bb371 100644
> > --- a/drivers/pinctrl/pinctrl-st.c
> > +++ b/drivers/pinctrl/pinctrl-st.c
> > @@ -1512,7 +1512,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
> >  	if (info->irqmux_base || gpio_irq > 0) {
> >  		err = gpiochip_irqchip_add(&bank->gpio_chip, &st_gpio_irqchip,
> >  					   0, handle_simple_irq,
> > -					   IRQ_TYPE_LEVEL_LOW);
> > +					   IRQ_TYPE_NONE);
> >  		if (err) {
> >  			gpiochip_remove(&bank->gpio_chip);
> >  			dev_info(dev, "could not add irqchip\n");
> > 
> 
> Hi Linus
> 
> I forgot to mention that this patch is dedicated for v4.9-rcs 

Wow, v4.9-rc is a noisy boot without this patch :)

Acked-by: Peter Griffin <peter.griffin@linaro.org>

^ permalink raw reply

* [PATCH 6/8] pinctrl: aspeed-g4: Capture SuperIO pinmux dependency
From: Linus Walleij @ 2016-10-20 11:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <b5f67ba76018314d08e240f95951751896687d37.1474986045.git-series.andrew@aj.id.au>

On Tue, Sep 27, 2016 at 4:50 PM, Andrew Jeffery <andrew@aj.id.au> wrote:

> Two LPC-related signals in the AST2400 depend on state in the SuperIO IP
> block. Use the recently added infrastructure to capture this
> relationship.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>

Patch applied for v4.10.
(Tell me if I'm applying patches in wrong order or something, and
I hope this doesn't clash with the fixes.)

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH] ARM64: defconfig: Enable MMC related configs
From: Neil Armstrong @ 2016-10-20 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

Enable MMC related defaults configs for MMC, PWM and PWM clock.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm64/configs/defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index dab2cb0..920f1e8 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -341,6 +341,7 @@ CONFIG_USB_RENESAS_USBHS_UDC=m
 CONFIG_MMC=y
 CONFIG_MMC_BLOCK_MINORS=32
 CONFIG_MMC_ARMMMCI=y
+CONFIG_MMC_MESON_GX=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ACPI=y
 CONFIG_MMC_SDHCI_PLTFM=y
@@ -387,6 +388,7 @@ CONFIG_XEN_GRANT_DEV_ALLOC=y
 CONFIG_COMMON_CLK_SCPI=y
 CONFIG_COMMON_CLK_CS2000_CP=y
 CONFIG_COMMON_CLK_S2MPS11=y
+CONFIG_COMMON_CLK_PWM=y
 CONFIG_CLK_QORIQ=y
 CONFIG_COMMON_CLK_QCOM=y
 CONFIG_MSM_GCC_8916=y
@@ -404,6 +406,7 @@ CONFIG_ARCH_TEGRA_210_SOC=y
 CONFIG_EXTCON_USB_GPIO=y
 CONFIG_PWM=y
 CONFIG_PWM_TEGRA=m
+CONFIG_PWM_MESON=m
 CONFIG_COMMON_RESET_HI6220=y
 CONFIG_PHY_RCAR_GEN3_USB2=y
 CONFIG_PHY_HI6220_USB=y
-- 
1.9.1

^ permalink raw reply related

* [PATCH 4/4] ARM64: dts: meson-gxbb: Add MMC nodes to Nexbox A95x
From: Neil Armstrong @ 2016-10-20 11:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476963777-1804-1-git-send-email-narmstrong@baylibre.com>

Add support for eMMC/SD/SDIO on the Nexbox A95x.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 .../boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts    | 122 +++++++++++++++++++++
 1 file changed, 122 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
index 399d85f..9696820 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
@@ -87,6 +87,61 @@
 			gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_LOW>;
 		};
 	};
+
+	vddio_card: gpio-regulator {
+		compatible = "regulator-gpio";
+
+		regulator-name = "VDDIO_CARD";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+
+		/* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
+		states = <1800000 0
+			  3300000 1>;
+	};
+
+	vddio_boot: regulator-vddio_boot {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_BOOT";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	vddao_3v3: regulator-vddao_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDAO_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc_3v3: regulator-vcc_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
+
+	wifi32k: wifi32k {
+		compatible = "pwm-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+		clocks = <&wifi32k>;
+		clock-names = "ext_clock";
+	};
 };
 
 &uart_AO {
@@ -107,3 +162,70 @@
 	pinctrl-0 = <&remote_input_ao_pins>;
 	pinctrl-names = "default";
 };
+
+/* Wireless SDIO Module */
+&sd_emmc_a {
+	status = "okay";
+	pinctrl-0 = <&sdio_pins>;
+	pinctrl-names = "default";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+
+	non-removable;
+	disable-wp;
+
+	mmc-pwrseq = <&sdio_pwrseq>;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
+
+/* SD card */
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+	disable-wp;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_card>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	cap-mmc-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vcc_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
+
+&pwm_ef {
+	status = "okay";
+	pinctrl-0 = <&pwm_e_pins>;
+	pinctrl-names = "default";
+	clocks = <&clkc CLKID_FCLK_DIV4>;
+	clock-names = "clkin0";
+};
-- 
1.9.1

^ permalink raw reply related

* [PATCH 3/4] ARM64: dts: meson-gxbb: Add P20x Wifi SDIO support
From: Neil Armstrong @ 2016-10-20 11:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476963777-1804-1-git-send-email-narmstrong@baylibre.com>

Add Wifi module support on the Amlogic P20x boards on the SDIO port.
The Wifi module also needs a 32768Hz clock provided by the PWM E port
through a pwm-clock node in it's power sequence.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index 6861b0a..203be28 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -118,6 +118,13 @@
 		clock-frequency = <32768>;
 		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
 	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+		clocks = <&wifi32k>;
+		clock-names = "ext_clock";
+	};
 };
 
 /* This UART is brought out to the DB9 connector */
@@ -171,8 +178,15 @@
 	non-removable;
 	disable-wp;
 
+	mmc-pwrseq = <&sdio_pwrseq>;
+
 	vmmc-supply = <&vddao_3v3>;
 	vqmmc-supply = <&vddio_boot>;
+
+	brcmf: bcrmf at 1 {
+		reg = <1>;
+		compatible = "brcm,bcm4329-fmac";
+	};
 };
 
 /* SD card */
-- 
1.9.1

^ permalink raw reply related

* [PATCH 2/4] ARM64: dts: meson-gxbb: Add Wifi 32K clock for p20x boards
From: Neil Armstrong @ 2016-10-20 11:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476963777-1804-1-git-send-email-narmstrong@baylibre.com>

Add a 32768Hz clock generated by the PWM E port used by the WiFi module.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index 86e740f..6861b0a 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -111,6 +111,13 @@
 		compatible = "mmc-pwrseq-emmc";
 		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
 	};
+
+	wifi32k: wifi32k {
+		compatible = "pwm-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+	};
 };
 
 /* This UART is brought out to the DB9 connector */
@@ -205,3 +212,11 @@
 	vmmc-supply = <&vcc_3v3>;
 	vqmmc-supply = <&vddio_boot>;
 };
+
+&pwm_ef {
+	status = "okay";
+	pinctrl-0 = <&pwm_e_pins>;
+	pinctrl-names = "default";
+	clocks = <&clkc CLKID_FCLK_DIV4>;
+	clock-names = "clkin0";
+};
-- 
1.9.1

^ permalink raw reply related

* [PATCH 1/4] ARM64: dts: meson-gxbb: add MMC support
From: Neil Armstrong @ 2016-10-20 11:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476963777-1804-1-git-send-email-narmstrong@baylibre.com>

From: Kevin Hilman <khilman@baylibre.com>

Add binding and basic support for the SD/eMMC controller on Amlogic
S905/GXBB devices.

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Kevin Hilman <khilman@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gx.dtsi          | 21 +++++
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 88 +++++++++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   | 98 ++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        | 24 +++++-
 4 files changed, 230 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
index a6cd953..fd1d0de 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
@@ -203,6 +203,27 @@
 			#address-cells = <2>;
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
+
+			sd_emmc_a: mmc at 70000 {
+				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x70000 0x0 0x2000>;
+				interrupts = <GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+
+			sd_emmc_b: mmc at 72000 {
+				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x72000 0x0 0x2000>;
+				interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+
+			sd_emmc_c: mmc at 74000 {
+				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x74000 0x0 0x2000>;
+				interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
 		};
 	};
 };
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index a45d101..238fbea 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -85,6 +85,56 @@
 			default-state = "off";
 		};
 	};
+
+	tflash_vdd: regulator-tflash_vdd {
+		/*
+		 * signal name from schematics: TFLASH_VDD_EN
+		 */
+		compatible = "regulator-fixed";
+
+		regulator-name = "TFLASH_VDD";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio_ao GPIOAO_12 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	tf_io: gpio-regulator-tf_io {
+		compatible = "regulator-gpio";
+
+		regulator-name = "TF_IO";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		/*
+		 * signal name from schematics: TF_3V3N_1V8_EN
+		 */
+		gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
+		gpios-states = <0>;
+
+		states = <3300000 0
+			  1800000 1>;
+	};
+
+	vcc1v8: regulator-vcc1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC1V8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	vcc3v3: regulator-vcc3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
 };
 
 &uart_AO {
@@ -127,3 +177,41 @@
 &usb1 {
 	status = "okay";
 };
+
+/* SD */
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+	disable-wp;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&tflash_vdd>;
+	vqmmc-supply = <&tf_io>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	cap-mmc-highspeed;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vcc3v3>;
+	vqmmc-supply = <&vcc1v8>;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index 031d69b..86e740f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -70,6 +70,47 @@
 		gpio = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 	};
+
+	vddio_card: gpio-regulator {
+		compatible = "regulator-gpio";
+
+		regulator-name = "VDDIO_CARD";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+
+		/* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
+		states = <1800000 0
+			  3300000 1>;
+	};
+
+	vddio_boot: regulator-vddio_boot {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_BOOT";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	vddao_3v3: regulator-vddao_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDAO_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc_3v3: regulator-vcc_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
 };
 
 /* This UART is brought out to the DB9 connector */
@@ -107,3 +148,60 @@
 &usb1 {
 	status = "okay";
 };
+
+/* Wireless SDIO Module */
+&sd_emmc_a {
+	status = "okay";
+	pinctrl-0 = <&sdio_pins>;
+	pinctrl-names = "default";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+
+	non-removable;
+	disable-wp;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
+
+/* SD card */
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+	disable-wp;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_card>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	cap-mmc-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vcc_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index aad639a..22940bb 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -349,7 +349,8 @@
 			mux {
 				groups = "emmc_nand_d07",
 				       "emmc_cmd",
-				       "emmc_clk";
+				       "emmc_clk",
+				       "emmc_ds";
 				function = "emmc";
 			};
 		};
@@ -545,3 +546,24 @@
 		#mbox-cells = <1>;
 	};
 };
+
+&sd_emmc_a {
+	clocks = <&clkc CLKID_SD_EMMC_A>,
+		 <&xtal>,
+		 <&clkc CLKID_FCLK_DIV2>;
+	clock-names = "core", "clkin0", "clkin1";
+};
+
+&sd_emmc_b {
+	clocks = <&clkc CLKID_SD_EMMC_B>,
+		 <&xtal>,
+		 <&clkc CLKID_FCLK_DIV2>;
+	clock-names = "core", "clkin0", "clkin1";
+};
+
+&sd_emmc_c {
+	clocks = <&clkc CLKID_SD_EMMC_C>,
+		 <&xtal>,
+		 <&clkc CLKID_FCLK_DIV2>;
+	clock-names = "core", "clkin0", "clkin1";
+};
-- 
1.9.1

^ permalink raw reply related

* [PATCH 0/4] ARM64: dts: meson-gxbb: Add MMC and Wifi support
From: Neil Armstrong @ 2016-10-20 11:42 UTC (permalink / raw)
  To: linux-arm-kernel

This patchsets adds the MMC nodes in the GX dtsi and adds the GXBB clocks
attributes in the GXBB dtsi.
Then MMC/SD/SDIO support is added to :
 - p20x : SD, SDIO, MMC
 - a95x : SD, SDIO, MMC
 - Odroid-C2 : SD, MMC

WiFi support is also added by enabling the 32768Hz clock generated by PWM
on p20x and A95x and adding the SDIO power sequence.

This patchset is based on Kevin Hilman's amlogic v4.10/dt64 tree at [1]

[1] git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-amlogic.git

Kevin Hilman (1):
  ARM64: dts: meson-gxbb: add MMC support

Neil Armstrong (3):
  ARM64: dts: meson-gxbb: Add Wifi 32K clock for p20x boards
  ARM64: dts: meson-gxbb: Add P20x Wifi SDIO support
  ARM64: dts: meson-gxbb: Add MMC nodes to Nexbox A95x

 arch/arm64/boot/dts/amlogic/meson-gx.dtsi          |  21 ++++
 .../boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts    | 122 ++++++++++++++++++++
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts |  88 ++++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   | 127 +++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  24 +++-
 5 files changed, 381 insertions(+), 1 deletion(-)

-- 
1.9.1

^ permalink raw reply

* [PATCH] pinctrl: st: don't specify default interrupt trigger
From: Patrice Chotard @ 2016-10-20 11:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476774988-13484-1-git-send-email-patrice.chotard@st.com>



On 10/18/2016 09:16 AM, patrice.chotard at st.com wrote:
> From: Patrice Chotard <patrice.chotard@st.com>
> 
> Thanks to 332e99d5ae4 which now alerts of default
> trigger usage when configuring interrupts.
> 
> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> ---
>  drivers/pinctrl/pinctrl-st.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
> index 99da4cf..b7bb371 100644
> --- a/drivers/pinctrl/pinctrl-st.c
> +++ b/drivers/pinctrl/pinctrl-st.c
> @@ -1512,7 +1512,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
>  	if (info->irqmux_base || gpio_irq > 0) {
>  		err = gpiochip_irqchip_add(&bank->gpio_chip, &st_gpio_irqchip,
>  					   0, handle_simple_irq,
> -					   IRQ_TYPE_LEVEL_LOW);
> +					   IRQ_TYPE_NONE);
>  		if (err) {
>  			gpiochip_remove(&bank->gpio_chip);
>  			dev_info(dev, "could not add irqchip\n");
> 

Hi Linus

I forgot to mention that this patch is dedicated for v4.9-rcs 

Thanks

Patrice

^ permalink raw reply

* [PATCH v3 0/5] Cavium ThunderX uncore PMU support
From: Peter Zijlstra @ 2016-10-20 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161020112351.GC13708@hardcore>

On Thu, Oct 20, 2016 at 01:23:51PM +0200, Jan Glauber wrote:
> On Thu, Oct 20, 2016 at 12:37:07PM +0200, Peter Zijlstra wrote:
> > On Thu, Oct 20, 2016 at 11:30:36AM +0200, Jan Glauber wrote:
> > > Note:
> > > I'm using perf_sw_context in difference to perf_invalid_context
> > > (see WARN_ON in perf_pmu_register). Reason is that with perf_invalid_context
> > > add() is never called and the counter results are shown as "unsupported" by
> > > perf. With perf_sw_context everything works as expected.
> > 
> > What?! All the uncore PMUs use perf_invalid_context. What doesn't work
> > for you?
> 
> OK, so using perf_invalid_context and "-a" seems to work.
> 
> But I must say that I hate that from a user perspective. The user needs to know about
> the type of PMU behind the event and then provide "-a" or get a "<not supported"
> as counter value?

This really boils down to the fact that users really had better know
what they're on about.

There's only so much you can let clueless people do.

The fact is, they already _manually_ select your (uncore) PMU, so they
had then better also know what its limitations are.

^ permalink raw reply

* [PATCH 3/3] arm64: suspend: Reconfigure PSTATE after resume from idle
From: Lorenzo Pieralisi @ 2016-10-20 11:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476786468-2173-4-git-send-email-james.morse@arm.com>

On Tue, Oct 18, 2016 at 11:27:48AM +0100, James Morse wrote:
> The suspend/resume path in kernel/sleep.S, as used by cpu-idle, does not
> save/restore PSTATE. As a result of this cpufeatures that were detected
> and have bits in PSTATE get lost when we resume from idle.
> 
> UAO gets set appropriately on the next context switch. PAN will be
> re-enabled next time we return from user-space, but on a preemptible
> kernel we may run work accessing user space before this point.
> 
> Add code to re-enable theses two features in __cpu_suspend_exit().
> We re-use uao_thread_switch() passing current.
> 
> Signed-off-by: James Morse <james.morse@arm.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> 
> ---
> This patch applies to linux-stable v4.7.8, but with some fuzz...
> but 'git am' rejects it.
> 
> asm/exec.h is my best guess at the appropriate header file. Contradictions
> welcome.

uaccess.h ? It is a shame you have to export uao_thread_switch() (see
below for a possible solution) but I agree that prevents useless code
duplication and that this needs fixing.

>  arch/arm64/include/asm/exec.h |  3 +++
>  arch/arm64/kernel/process.c   |  3 ++-
>  arch/arm64/kernel/suspend.c   | 11 +++++++++++
>  3 files changed, 16 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/exec.h b/arch/arm64/include/asm/exec.h
> index db0563c23482..f7865dd9d868 100644
> --- a/arch/arm64/include/asm/exec.h
> +++ b/arch/arm64/include/asm/exec.h
> @@ -18,6 +18,9 @@
>  #ifndef __ASM_EXEC_H
>  #define __ASM_EXEC_H
>  
> +#include <linux/sched.h>
> +
>  extern unsigned long arch_align_stack(unsigned long sp);
> +void uao_thread_switch(struct task_struct *next);
>  
>  #endif	/* __ASM_EXEC_H */
> diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> index 27b2f1387df4..4f186c56c5eb 100644
> --- a/arch/arm64/kernel/process.c
> +++ b/arch/arm64/kernel/process.c
> @@ -49,6 +49,7 @@
>  #include <asm/alternative.h>
>  #include <asm/compat.h>
>  #include <asm/cacheflush.h>
> +#include <asm/exec.h>
>  #include <asm/fpsimd.h>
>  #include <asm/mmu_context.h>
>  #include <asm/processor.h>
> @@ -301,7 +302,7 @@ static void tls_thread_switch(struct task_struct *next)
>  }
>  
>  /* Restore the UAO state depending on next's addr_limit */
> -static void uao_thread_switch(struct task_struct *next)
> +void uao_thread_switch(struct task_struct *next)
>  {
>  	if (IS_ENABLED(CONFIG_ARM64_UAO)) {
>  		if (task_thread_info(next)->addr_limit == KERNEL_DS)
> diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
> index ad734142070d..bb0cd787a9d3 100644
> --- a/arch/arm64/kernel/suspend.c
> +++ b/arch/arm64/kernel/suspend.c
> @@ -1,8 +1,11 @@
>  #include <linux/ftrace.h>
>  #include <linux/percpu.h>
>  #include <linux/slab.h>
> +#include <asm/alternative.h>
>  #include <asm/cacheflush.h>
> +#include <asm/cpufeature.h>
>  #include <asm/debug-monitors.h>
> +#include <asm/exec.h>
>  #include <asm/pgtable.h>
>  #include <asm/memory.h>
>  #include <asm/mmu_context.h>
> @@ -50,6 +53,14 @@ void notrace __cpu_suspend_exit(void)
>  	set_my_cpu_offset(per_cpu_offset(cpu));
>  
>  	/*
> +	 * PSTATE was not saved over suspend/resume, re-enable any detected
> +	 * features that might not have been set correctly.
> +	 */
> +	asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,
> +			CONFIG_ARM64_PAN));
> +	uao_thread_switch(current);

set_fs(get_fs());

would do (?), but that's horrendous to say the least, maybe you can
refactor the code in asm/uaccess.h to achieve the same goal (ie you
factor out the code setting UAO from set_fs() in a separate inline that
you can also reuse in uao_thread_switch() and here).

Other than that:

Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

> +
> +	/*
>  	 * Restore HW breakpoint registers to sane values
>  	 * before debug exceptions are possibly reenabled
>  	 * through local_dbg_restore.
> -- 
> 2.8.0.rc3
> 

^ permalink raw reply

* [PATCH v2 1/3] efi: add support for seeding the RNG from a UEFI config table
From: Ard Biesheuvel @ 2016-10-20 11:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476962486-18368-2-git-send-email-ard.biesheuvel@linaro.org>

On 20 October 2016 at 12:21, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> Specify a Linux specific UEFI configuration table that carries some
> random bits, and use the contents during early boot to seed the kernel's
> random number generator. This allows much strong random numbers to be
> generated early on.
>
> The entropy is fed to the kernel using add_device_randomness(), which is
> documented as being appropriate for being called very early.
>
> Since UEFI configuration tables may also be consumed by kexec'd kernels,
> register a reboot notifier that updates the seed in the table.
>
> Note that the config table could be generated by the EFI stub or by any
> other UEFI driver or application (e.g., GRUB), but the random seed table
> GUID and the associated functionality should be considered an internal
> kernel interface (unless it is promoted to ABI later on)
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  drivers/firmware/efi/efi.c | 67 ++++++++++++++++++++
>  include/linux/efi.h        |  8 +++
>  2 files changed, 75 insertions(+)
>
> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index 1ac199cd75e7..47937ffd9f2f 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -24,6 +24,8 @@
>  #include <linux/of_fdt.h>
>  #include <linux/io.h>
>  #include <linux/platform_device.h>
> +#include <linux/random.h>
> +#include <linux/reboot.h>
>  #include <linux/slab.h>
>  #include <linux/acpi.h>
>  #include <linux/ucs2_string.h>
> @@ -48,6 +50,7 @@ struct efi __read_mostly efi = {
>         .esrt                   = EFI_INVALID_TABLE_ADDR,
>         .properties_table       = EFI_INVALID_TABLE_ADDR,
>         .mem_attr_table         = EFI_INVALID_TABLE_ADDR,
> +       .rng_seed               = EFI_INVALID_TABLE_ADDR,
>  };
>  EXPORT_SYMBOL(efi);
>
> @@ -438,6 +441,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
>         {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
>         {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
>         {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
> +       {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
>         {NULL_GUID, NULL, NULL},
>  };
>
> @@ -499,6 +503,29 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
>         pr_cont("\n");
>         set_bit(EFI_CONFIG_TABLES, &efi.flags);
>
> +       if (efi.rng_seed != EFI_INVALID_TABLE_ADDR) {
> +               struct linux_efi_random_seed *seed;
> +               u32 size = 0;
> +
> +               seed = early_memremap(efi.rng_seed, sizeof(*seed));
> +               if (seed != NULL) {
> +                       size = seed->size;
> +                       early_memunmap(seed, sizeof(*seed));
> +               } else {
> +                       pr_err("Could not map UEFI random seed!\n");
> +               }
> +               if (size > 0) {
> +                       seed = early_memremap(efi.rng_seed,
> +                                             sizeof(*seed) + size);
> +                       if (seed != NULL) {
> +                               add_device_randomness(seed->bits, seed->size);
> +                               early_memunmap(seed, sizeof(*seed) + size);
> +                       } else {
> +                               pr_err("Could not map UEFI random seed!\n");
> +                       }
> +               }
> +       }
> +
>         /* Parse the EFI Properties table if it exists */
>         if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
>                 efi_properties_table_t *tbl;
> @@ -822,3 +849,43 @@ int efi_status_to_err(efi_status_t status)
>
>         return err;
>  }
> +
> +#ifdef CONFIG_KEXEC
> +static int update_efi_random_seed(struct notifier_block *nb,
> +                                 unsigned long code, void *unused)
> +{
> +       struct linux_efi_random_seed *seed;
> +       u32 size = 0;
> +

I forgot to git-add this bit here:

+       if (!kexec_in_progress)
+               return NOTIFY_DONE;
+

> +       seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
> +       if (seed != NULL) {
> +               size = seed->size;
> +               memunmap(seed);
> +       } else {
> +               pr_err("Could not map UEFI random seed!\n");
> +       }
> +       if (size > 0) {
> +               seed = memremap(efi.rng_seed, sizeof(*seed) + size,
> +                               MEMREMAP_WB);
> +               if (seed != NULL) {
> +                       get_random_bytes(seed->bits, seed->size);
> +                       memunmap(seed);
> +               } else {
> +                       pr_err("Could not map UEFI random seed!\n");
> +               }
> +       }
> +       return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block efi_random_seed_nb = {
> +       .notifier_call = update_efi_random_seed,
> +};
> +
> +static int register_update_efi_random_seed(void)
> +{
> +       if (efi.rng_seed == EFI_INVALID_TABLE_ADDR)
> +               return 0;
> +       return register_reboot_notifier(&efi_random_seed_nb);
> +}
> +late_initcall(register_update_efi_random_seed);
> +#endif
> diff --git a/include/linux/efi.h b/include/linux/efi.h
> index 2d089487d2da..85e28b138cdd 100644
> --- a/include/linux/efi.h
> +++ b/include/linux/efi.h
> @@ -599,6 +599,7 @@ void efi_native_runtime_setup(void);
>   */
>  #define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID   EFI_GUID(0xe03fc20a, 0x85dc, 0x406e,  0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
>  #define LINUX_EFI_LOADER_ENTRY_GUID            EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf,  0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
> +#define LINUX_EFI_RANDOM_SEED_TABLE_GUID       EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2,  0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
>
>  typedef struct {
>         efi_guid_t guid;
> @@ -872,6 +873,7 @@ extern struct efi {
>         unsigned long esrt;             /* ESRT table */
>         unsigned long properties_table; /* properties table */
>         unsigned long mem_attr_table;   /* memory attributes table */
> +       unsigned long rng_seed;         /* UEFI firmware random seed */
>         efi_get_time_t *get_time;
>         efi_set_time_t *set_time;
>         efi_get_wakeup_time_t *get_wakeup_time;
> @@ -1493,4 +1495,10 @@ efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table,
>                                     struct efi_boot_memmap *map,
>                                     void *priv,
>                                     efi_exit_boot_map_processing priv_func);
> +
> +struct linux_efi_random_seed {
> +       u32     size;
> +       u8      bits[];
> +};
> +
>  #endif /* _LINUX_EFI_H */
> --
> 2.7.4
>

^ permalink raw reply

* [PATCH] arm64: remove pr_cont abuse from mem_init
From: Mark Rutland @ 2016-10-20 11:24 UTC (permalink / raw)
  To: linux-arm-kernel

All the lines printed by mem_init are independent, with each ending with
a newline. While they logically form a large block, none are actually
continuations of previous lines.

The kernel-side printk code and the userspace demsg tool differ in their
handling of KERN_CONT following a newline, and while this isn't always a
problem kernel-side, it does cause difficulty for userspace. Using
pr_cont causes the userspace tool to not print line prefix (e.g.
timestamps) even when following a newline, mis-aligning the output and
making it harder to read, e.g.

[    0.000000] Virtual kernel memory layout:
[    0.000000]     modules : 0xffff000000000000 - 0xffff000008000000   (   128 MB)
    vmalloc : 0xffff000008000000 - 0xffff7dffbfff0000   (129022 GB)
      .text : 0xffff000008080000 - 0xffff0000088b0000   (  8384 KB)
    .rodata : 0xffff0000088b0000 - 0xffff000008c50000   (  3712 KB)
      .init : 0xffff000008c50000 - 0xffff000008d50000   (  1024 KB)
      .data : 0xffff000008d50000 - 0xffff000008e25200   (   853 KB)
       .bss : 0xffff000008e25200 - 0xffff000008e6bec0   (   284 KB)
    fixed   : 0xffff7dfffe7fd000 - 0xffff7dfffec00000   (  4108 KB)
    PCI I/O : 0xffff7dfffee00000 - 0xffff7dffffe00000   (    16 MB)
    vmemmap : 0xffff7e0000000000 - 0xffff800000000000   (  2048 GB maximum)
              0xffff7e0000000000 - 0xffff7e0026000000   (   608 MB actual)
    memory  : 0xffff800000000000 - 0xffff800980000000   ( 38912 MB)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=6, Nodes=1

Fix this by using pr_notice consistently for all lines, which both the
kernel and userspace are happy with.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
Cc: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/mm/init.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 21c489b..212c4d1 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -421,35 +421,35 @@ void __init mem_init(void)
 
 	pr_notice("Virtual kernel memory layout:\n");
 #ifdef CONFIG_KASAN
-	pr_cont("    kasan   : 0x%16lx - 0x%16lx   (%6ld GB)\n",
+	pr_notice("    kasan   : 0x%16lx - 0x%16lx   (%6ld GB)\n",
 		MLG(KASAN_SHADOW_START, KASAN_SHADOW_END));
 #endif
-	pr_cont("    modules : 0x%16lx - 0x%16lx   (%6ld MB)\n",
+	pr_notice("    modules : 0x%16lx - 0x%16lx   (%6ld MB)\n",
 		MLM(MODULES_VADDR, MODULES_END));
-	pr_cont("    vmalloc : 0x%16lx - 0x%16lx   (%6ld GB)\n",
+	pr_notice("    vmalloc : 0x%16lx - 0x%16lx   (%6ld GB)\n",
 		MLG(VMALLOC_START, VMALLOC_END));
-	pr_cont("      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+	pr_notice("      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n",
 		MLK_ROUNDUP(_text, _etext));
-	pr_cont("    .rodata : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+	pr_notice("    .rodata : 0x%p" " - 0x%p" "   (%6ld KB)\n",
 		MLK_ROUNDUP(__start_rodata, __init_begin));
-	pr_cont("      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+	pr_notice("      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n",
 		MLK_ROUNDUP(__init_begin, __init_end));
-	pr_cont("      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+	pr_notice("      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n",
 		MLK_ROUNDUP(_sdata, _edata));
-	pr_cont("       .bss : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+	pr_notice("       .bss : 0x%p" " - 0x%p" "   (%6ld KB)\n",
 		MLK_ROUNDUP(__bss_start, __bss_stop));
-	pr_cont("    fixed   : 0x%16lx - 0x%16lx   (%6ld KB)\n",
+	pr_notice("    fixed   : 0x%16lx - 0x%16lx   (%6ld KB)\n",
 		MLK(FIXADDR_START, FIXADDR_TOP));
-	pr_cont("    PCI I/O : 0x%16lx - 0x%16lx   (%6ld MB)\n",
+	pr_notice("    PCI I/O : 0x%16lx - 0x%16lx   (%6ld MB)\n",
 		MLM(PCI_IO_START, PCI_IO_END));
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
-	pr_cont("    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n",
+	pr_notice("    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n",
 		MLG(VMEMMAP_START, VMEMMAP_START + VMEMMAP_SIZE));
-	pr_cont("              0x%16lx - 0x%16lx   (%6ld MB actual)\n",
+	pr_notice("              0x%16lx - 0x%16lx   (%6ld MB actual)\n",
 		MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()),
 		    (unsigned long)virt_to_page(high_memory)));
 #endif
-	pr_cont("    memory  : 0x%16lx - 0x%16lx   (%6ld MB)\n",
+	pr_notice("    memory  : 0x%16lx - 0x%16lx   (%6ld MB)\n",
 		MLM(__phys_to_virt(memblock_start_of_DRAM()),
 		    (unsigned long)high_memory));
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 0/5] Cavium ThunderX uncore PMU support
From: Jan Glauber @ 2016-10-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161020103707.GB3175@twins.programming.kicks-ass.net>

On Thu, Oct 20, 2016 at 12:37:07PM +0200, Peter Zijlstra wrote:
> On Thu, Oct 20, 2016 at 11:30:36AM +0200, Jan Glauber wrote:
> > Note:
> > I'm using perf_sw_context in difference to perf_invalid_context
> > (see WARN_ON in perf_pmu_register). Reason is that with perf_invalid_context
> > add() is never called and the counter results are shown as "unsupported" by
> > perf. With perf_sw_context everything works as expected.
> 
> What?! All the uncore PMUs use perf_invalid_context. What doesn't work
> for you?

OK, so using perf_invalid_context and "-a" seems to work.

But I must say that I hate that from a user perspective. The user needs to know about
the type of PMU behind the event and then provide "-a" or get a "<not supported"
as counter value?

^ permalink raw reply

* [PATCH] arm64: fix show_regs fallout from KERN_CONT changes
From: Mark Rutland @ 2016-10-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

Recently in commit 4bcc595ccd80decb ("printk: reinstate KERN_CONT for
printing continuation lines"), the behaviour of printk changed w.r.t.
KERN_CONT. Now, KERN_CONT is mandatory to continue existing lines.
Without this, prefixes are inserted, making output illegible, e.g.

[ 1007.069010] pc : [<ffff00000871898c>] lr : [<ffff000008718948>] pstate: 40000145
[ 1007.076329] sp : ffff000008d53ec0
[ 1007.079606] x29: ffff000008d53ec0 [ 1007.082797] x28: 0000000080c50018
[ 1007.086160]
[ 1007.087630] x27: ffff000008e0c7f8 [ 1007.090820] x26: ffff80097631ca00
[ 1007.094183]
[ 1007.095653] x25: 0000000000000001 [ 1007.098843] x24: 000000ea68b61cac
[ 1007.102206]

... or when dumped with the userpace dmesg tool, which has slightly
different implicit newline behaviour. e.g.

[ 1007.069010] pc : [<ffff00000871898c>] lr : [<ffff000008718948>] pstate: 40000145
[ 1007.076329] sp : ffff000008d53ec0
[ 1007.079606] x29: ffff000008d53ec0
[ 1007.082797] x28: 0000000080c50018
[ 1007.086160]
[ 1007.087630] x27: ffff000008e0c7f8
[ 1007.090820] x26: ffff80097631ca00
[ 1007.094183]
[ 1007.095653] x25: 0000000000000001
[ 1007.098843] x24: 000000ea68b61cac
[ 1007.102206]

We can't simply always use KERN_CONT for lines which may or may not be
continuations. That causes line prefixes (e.g. timestamps) to be
supressed, and the alignment of all but the first line will be broken.

For even more fun, we can't simply insert some dummy empty-string printk
calls, as GCC warns for an empty printk string, and even if we pass
KERN_DEFAULT explcitly to silence the warning, the prefix gets swallowed
unless there is an additional part to the string.

Instead, we must manually iterate over pairs of registers, which gives
us the legible output we want in either case, e.g.

[  169.771790] pc : [<ffff00000871898c>] lr : [<ffff000008718948>] pstate: 40000145
[  169.779109] sp : ffff000008d53ec0
[  169.782386] x29: ffff000008d53ec0 x28: 0000000080c50018
[  169.787650] x27: ffff000008e0c7f8 x26: ffff80097631de00
[  169.792913] x25: 0000000000000001 x24: 00000027827b2cf4

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/kernel/process.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index ddce61b..3f31cf93 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -187,10 +187,19 @@ void __show_regs(struct pt_regs *regs)
 	printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n",
 	       regs->pc, lr, regs->pstate);
 	printk("sp : %016llx\n", sp);
-	for (i = top_reg; i >= 0; i--) {
+
+	i = top_reg;
+
+	while (i >= 0) {
 		printk("x%-2d: %016llx ", i, regs->regs[i]);
-		if (i % 2 == 0)
-			printk("\n");
+		i--;
+
+		if (i % 2 == 0) {
+			pr_cont("x%-2d: %016llx ", i, regs->regs[i]);
+			i--;
+		}
+
+		pr_cont("\n");
 	}
 	printk("\n");
 }
-- 
1.9.1

^ permalink raw reply related

* [PATCH v2 3/3] efi/arm*: libstub: invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table
From: Ard Biesheuvel @ 2016-10-20 11:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476962486-18368-1-git-send-email-ard.biesheuvel@linaro.org>

Invoke the EFI_RNG_PROTOCOL protocol in the context of the stub and
install the Linux-specific RNG seed UEFI config table. This will be
picked up by the EFI routines in the core kernel to seed the kernel
entropy pool.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 drivers/firmware/efi/libstub/arm-stub.c |  2 +
 drivers/firmware/efi/libstub/efistub.h  |  2 +
 drivers/firmware/efi/libstub/random.c   | 48 ++++++++++++++++++++
 include/linux/efi.h                     |  1 +
 4 files changed, 53 insertions(+)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 993aa56755f6..b4f7d78f9e8b 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -340,6 +340,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
 	if (status != EFI_SUCCESS)
 		pr_efi_err(sys_table, "Failed initrd from command line!\n");
 
+	efi_random_get_seed(sys_table);
+
 	new_fdt_addr = fdt_addr;
 	status = allocate_new_fdt_and_exit_boot(sys_table, handle,
 				&new_fdt_addr, dram_base + MAX_FDT_OFFSET,
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index fe1f22584c69..b98824e3800a 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -71,4 +71,6 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
 
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
 
+efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
+
 #endif
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index 0c9f58c5ba50..4aa35c4fe029 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -141,3 +141,51 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
 
 	return status;
 }
+
+#define RANDOM_SEED_SIZE	32
+
+efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
+{
+	efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
+	efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
+	efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
+	struct efi_rng_protocol *rng;
+	struct linux_efi_random_seed *seed;
+	efi_status_t status;
+
+	status = efi_call_early(locate_protocol, &rng_proto, NULL,
+				(void **)&rng);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
+				sizeof(*seed) + RANDOM_SEED_SIZE,
+				(void **)&seed);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	status = rng->get_rng(rng, &rng_algo_raw, RANDOM_SEED_SIZE,
+			      seed->bits);
+	if (status == EFI_UNSUPPORTED)
+		/*
+		 * Use whatever algorithm we have available if the raw algorithm
+		 * is not implemented.
+		 */
+		status = rng->get_rng(rng, NULL, RANDOM_SEED_SIZE,
+				      seed->bits);
+
+	if (status != EFI_SUCCESS)
+		goto err_freepool;
+
+	seed->size = RANDOM_SEED_SIZE;
+	status = efi_call_early(install_configuration_table, &rng_table_guid,
+				seed);
+	if (status != EFI_SUCCESS)
+		goto err_freepool;
+
+	return EFI_SUCCESS;
+
+err_freepool:
+	efi_call_early(free_pool, seed);
+	return status;
+}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 85e28b138cdd..f5a821d9b90c 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -589,6 +589,7 @@ void efi_native_runtime_setup(void);
 #define DEVICE_TREE_GUID			EFI_GUID(0xb1b621d5, 0xf19c, 0x41a5,  0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0)
 #define EFI_PROPERTIES_TABLE_GUID		EFI_GUID(0x880aaca3, 0x4adc, 0x4a04,  0x90, 0x79, 0xb7, 0x47, 0x34, 0x08, 0x25, 0xe5)
 #define EFI_RNG_PROTOCOL_GUID			EFI_GUID(0x3152bca5, 0xeade, 0x433d,  0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44)
+#define EFI_RNG_ALGORITHM_RAW			EFI_GUID(0xe43176d7, 0xb6e8, 0x4827,  0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61)
 #define EFI_MEMORY_ATTRIBUTES_TABLE_GUID	EFI_GUID(0xdcfa911d, 0x26eb, 0x469f,  0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20)
 #define EFI_CONSOLE_OUT_DEVICE_GUID		EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4,  0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 2/3] efi/libstub: add random.c to ARM build
From: Ard Biesheuvel @ 2016-10-20 11:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476962486-18368-1-git-send-email-ard.biesheuvel@linaro.org>

Make random.c build for ARM by moving the fallback definition of
EFI_ALLOC_ALIGN to efistub.h

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 drivers/firmware/efi/libstub/Makefile          | 4 ++--
 drivers/firmware/efi/libstub/efi-stub-helper.c | 9 ---------
 drivers/firmware/efi/libstub/efistub.h         | 9 +++++++++
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index c06945160a41..40ddf8f763a8 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -36,11 +36,11 @@ arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c
 $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
 	$(call if_changed_rule,cc_o_c)
 
-lib-$(CONFIG_EFI_ARMSTUB)	+= arm-stub.o fdt.o string.o \
+lib-$(CONFIG_EFI_ARMSTUB)	+= arm-stub.o fdt.o string.o random.o \
 				   $(patsubst %.c,lib-%.o,$(arm-deps))
 
 lib-$(CONFIG_ARM)		+= arm32-stub.o
-lib-$(CONFIG_ARM64)		+= arm64-stub.o random.o
+lib-$(CONFIG_ARM64)		+= arm64-stub.o
 CFLAGS_arm64-stub.o 		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 #
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index aded10662020..3c2fe209bbfe 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -32,15 +32,6 @@
 
 static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
-/*
- * Allow the platform to override the allocation granularity: this allows
- * systems that have the capability to run with a larger page size to deal
- * with the allocations for initrd and fdt more efficiently.
- */
-#ifndef EFI_ALLOC_ALIGN
-#define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
-#endif
-
 #define EFI_MMAP_NR_SLACK_SLOTS	8
 
 struct file_info {
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index ee49cd23ee63..fe1f22584c69 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -15,6 +15,15 @@
  */
 #undef __init
 
+/*
+ * Allow the platform to override the allocation granularity: this allows
+ * systems that have the capability to run with a larger page size to deal
+ * with the allocations for initrd and fdt more efficiently.
+ */
+#ifndef EFI_ALLOC_ALIGN
+#define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
+#endif
+
 void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
 
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
-- 
2.7.4

^ permalink raw reply related


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