From Joao.Pinto at synopsys.com  Tue Mar  1 02:57:24 2016
From: Joao.Pinto at synopsys.com (Joao Pinto)
Date: Tue, 1 Mar 2016 10:57:24 +0000
Subject: [PATCH v11 0/4] ARC: Add PCI support
In-Reply-To: <20160229192211.GA10370@localhost>
References: <20160226162554.11964.96983.stgit@bhelgaas-glaptop2.roam.corp.google.com>
 <6C7E76B729B341419CE4B84926C1D2CD010BCE1D@DE02WEMBXB.internal.synopsys.com>
 <20160229192211.GA10370@localhost>
Message-ID: <56D57594.8000004@synopsys.com>

Hi!

On 2/29/2016 7:22 PM, Bjorn Helgaas wrote:
> On Mon, Feb 29, 2016 at 06:30:52PM +0000, Joao Pinto wrote:
>> Hi Bjorn!
>>
>> Is it possible to pull this patch set into 4.5?
> 
> No, it's a little late for v4.5.  We're already at v4.5-rc6, so it's
> only critical bug fixes until the v4.6 merge window opens.

Ok, makes sense!

>
> Bjorn
>

Thanks!
Joao


From Alexey.Brodkin at synopsys.com  Thu Mar  3 05:58:18 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 3 Mar 2016 13:58:18 +0000
Subject: [PATCH 2/4] drm: Add DT bindings documentation for ARC PGU
 display controller
In-Reply-To: <20160223203841.GA15744@rob-hp-laptop>
References: <1455887034-7739-1-git-send-email-abrodkin@synopsys.com>
 <1455887034-7739-3-git-send-email-abrodkin@synopsys.com>
 <20160223203841.GA15744@rob-hp-laptop>
Message-ID: <1457013497.3005.99.camel@synopsys.com>

Hi Rob,

On Tue, 2016-02-23 at 14:38 -0600, Rob Herring wrote:
> On Fri, Feb 19, 2016 at 04:03:52PM +0300, Alexey Brodkin wrote:
> > 
> > This add DT bindings documentation for ARC PGU display controller.
> > 
> > Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
> > Cc: Rob Herring <robh+dt at kernel.org>
> > Cc: Pawel Moll <pawel.moll at arm.com>
> > Cc: Mark Rutland <mark.rutland at arm.com>
> > Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
> > Cc: Kumar Gala <galak at codeaurora.org>
> > Cc: devicetree at vger.kernel.org
> > Cc: linux-snps-arc at lists.infradead.org
> > ---
> > ?.../devicetree/bindings/display/snps,arcpgu.txt????| 74 ++++++++++++++++++++++
> > ?1 file changed, 74 insertions(+)
> > ?create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> > b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> > new file mode 100644
> > index 0000000..c8382fb
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> > @@ -0,0 +1,74 @@
> > +ARC PGU
> > +
> > +This is a display controller found on several development boards produced
> > +by Synopsys. The ARC PGU is an RGB streamer that reads the data from a
> > +framebuffer and sends it to a single digital encoder (usually HDMI).
> > +
> > +Required properties:
> > +??- compatible: "snps,arcpgu"
> Seems like this should be more specific. Is there some sort or?
> versioning with ARC blocks?

Well as of today there's only one and only version of PGU.
So is there a real need for "snps,arcpgu-1.0"?

> > 
> > +??- reg: Physical base address and length of the controller's registers.
> > +??- clocks: A list of phandle + clock-specifier pairs, one for each
> > +????entry in 'clock-names'.
> > +??- clock-names: A list of clock names. For ARC PGU it should contain:
> > +??????- "pxlclk" for the clock feeding the output PLL of the controller.
> > +??- encoder-slave: Phandle of encoder chip.
> This is unnecessary with the OF graph.

Do you mean I may drop "encoder-slave" from bindings description?
I actually thought about that because in case of simulation platform where
this device is also used there's no encoder as well as no connector - we're
dealing with memory area which is read by host and then displayed on host's
display.

> > +
> > +/ {
> > +	...
> > +
> > +	pgu at 0xXXXXXXXX {
> Unit address should not have '0x'

Correct, let me fix it.

> > +
> > +	/* HDMI encoder on I2C bus */
> > +	i2c at 0xXXXXXXXX {
> > +		compatible = "...";
> > +
> > +		encoder_node:encoder_node at 0xXXXXXXXX{
> I2C addresses would be 8-bit only.

Indeed - copy-paste is evil :)

-Alexey


From Alexey.Brodkin at synopsys.com  Thu Mar  3 06:39:12 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu,  3 Mar 2016 17:39:12 +0300
Subject: [PATCH 0/4 v2] drm: Add support of ARC PGU display controller
Message-ID: <1457015956-30708-1-git-send-email-abrodkin@synopsys.com>

This series add support of ARC PGU display controller.
ARC PGU is a quite simple byte streamer that gets data from the framebuffer
and pushes it to hte connected encoder (DP or HDMI).

It was tested on ARC SDP boards (axs101 in particular).

Changes v1 -> v2:
 * Clean-up of DT bindings documentation
 * Added missing "pxlclk" clock in axs10x_mb.dtsi

Cc: David Airlie <airlied at linux.ie>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: linux-snps-arc at lists.infradead.org
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Vineet Gupta <vgupta at synopsys.com>

Alexey Brodkin (4):
  drm: Add support of ARC PGU display controller
  drm: Add DT bindings documentation for ARC PGU display controller
  arc: axs10x - add support of ARC PGU
  MAINTAINERS: Add maintainer for ARC PGU display controller

 .../devicetree/bindings/display/snps,arcpgu.txt    |  33 +++
 MAINTAINERS                                        |   6 +
 arch/arc/boot/dts/axs10x_mb.dtsi                   |  61 +++++
 drivers/gpu/drm/Kconfig                            |   2 +
 drivers/gpu/drm/Makefile                           |   1 +
 drivers/gpu/drm/arc/Kconfig                        |  10 +
 drivers/gpu/drm/arc/Makefile                       |   2 +
 drivers/gpu/drm/arc/arcpgu.h                       |  47 ++++
 drivers/gpu/drm/arc/arcpgu_crtc.c                  | 274 +++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_drv.c                   | 239 ++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_hdmi.c                  | 204 +++++++++++++++
 drivers/gpu/drm/arc/arcpgu_regs.h                  |  36 +++
 12 files changed, 915 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt
 create mode 100644 drivers/gpu/drm/arc/Kconfig
 create mode 100644 drivers/gpu/drm/arc/Makefile
 create mode 100644 drivers/gpu/drm/arc/arcpgu.h
 create mode 100644 drivers/gpu/drm/arc/arcpgu_crtc.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_drv.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_hdmi.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_regs.h

-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Thu Mar  3 06:39:15 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu,  3 Mar 2016 17:39:15 +0300
Subject: [PATCH 3/4 v2] arc: axs10x - add support of ARC PGU
In-Reply-To: <1457015956-30708-1-git-send-email-abrodkin@synopsys.com>
References: <1457015956-30708-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1457015956-30708-4-git-send-email-abrodkin@synopsys.com>

Synopsys DesignWare ARC SDP boards sport ARC SDP display
controller attached to ADV7511 HDMI encoder.

That change adds desctiption of both ARC PGU and ADV7511 in
ARC SDP'd base-board Device Tree.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: Vineet Gupta <vgupta at synopsys.com>
Cc: devicetree at vger.kernel.org
Cc: linux-snps-arc at lists.infradead.org
---

Changes v1 -> v2:
 * Added missing "pxlclk" clock in axs10x_mb.dtsi

 arch/arc/boot/dts/axs10x_mb.dtsi | 61 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
index 44a578c..6e639c9 100644
--- a/arch/arc/boot/dts/axs10x_mb.dtsi
+++ b/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -34,6 +34,12 @@
 				clock-frequency = <50000000>;
 				#clock-cells = <0>;
 			};
+
+			pguclk: pguclk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <74440000>;
+			};
 		};
 
 		ethernet at 0x18000 {
@@ -147,6 +153,37 @@
 			clocks = <&i2cclk>;
 			interrupts = <16>;
 
+			adv7511:adv7511 at 0x39{
+				compatible="adi,adv7511";
+				reg = <0x39>;
+				interrupts = <23>;
+				adi,input-depth = <8>;
+				adi,input-colorspace = "rgb";
+				adi,input-clock = "1x";
+				adi,clock-delay = <0x03>;
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					/* RGB/YUV input */
+					port at 0 {
+						reg = <0>;
+						adv7511_input:endpoint {
+						remote-endpoint = <&pgu_output>;
+						};
+					};
+
+					/* HDMI output */
+					port at 1 {
+						reg = <1>;
+						adv7511_output: endpoint {
+							remote-endpoint = <&hdmi_connector_in>;
+						};
+					};
+				};
+			};
+
 			eeprom at 0x54{
 				compatible = "24c01";
 				reg = <0x54>;
@@ -160,6 +197,16 @@
 			};
 		};
 
+		hdmi0: connector {
+			compatible = "hdmi-connector";
+			type = "a";
+			port {
+				hdmi_connector_in: endpoint {
+					remote-endpoint = <&adv7511_output>;
+				};
+			};
+		};
+
 		gpio0:gpio at 13000 {
 			compatible = "snps,dw-apb-gpio";
 			reg = <0x13000 0x1000>;
@@ -221,5 +268,19 @@
 				reg = <2>;
 			};
 		};
+
+		pgu at 0x17000 {
+			compatible = "snps,arcpgu";
+			reg = <0x17000 0x400>;
+			encoder-slave = <&adv7511>;
+			clocks = <&pguclk>;
+			clock-names = "pxlclk";
+
+			port {
+				pgu_output: endpoint {
+					remote-endpoint = <&adv7511_input>;
+				};
+			};
+		};
 	};
 };
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Thu Mar  3 06:39:14 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu,  3 Mar 2016 17:39:14 +0300
Subject: [PATCH 2/4 v2] drm: Add DT bindings documentation for ARC PGU display
 controller
In-Reply-To: <1457015956-30708-1-git-send-email-abrodkin@synopsys.com>
References: <1457015956-30708-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1457015956-30708-3-git-send-email-abrodkin@synopsys.com>

This add DT bindings documentation for ARC PGU display controller.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: devicetree at vger.kernel.org
Cc: linux-snps-arc at lists.infradead.org
---

Changes v1 -> v2:
 * Clean-up

 .../devicetree/bindings/display/snps,arcpgu.txt    | 33 ++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt

diff --git a/Documentation/devicetree/bindings/display/snps,arcpgu.txt b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
new file mode 100644
index 0000000..57f3bc8
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
@@ -0,0 +1,33 @@
+ARC PGU
+
+This is a display controller found on several development boards produced
+by Synopsys. The ARC PGU is an RGB streamer that reads the data from a
+framebuffer and sends it to a single digital encoder (usually HDMI).
+
+Required properties:
+  - compatible: "snps,arcpgu"
+  - reg: Physical base address and length of the controller's registers.
+  - clocks: A list of phandle + clock-specifier pairs, one for each
+    entry in 'clock-names'.
+  - clock-names: A list of clock names. For ARC PGU it should contain:
+      - "pxlclk" for the clock feeding the output PLL of the controller.
+
+Required sub-nodes:
+  - port: The PGU connection to an encoder chip. The connection is modelled
+    using the OF graph bindings specified in
+    Documentation/devicetree/bindings/graph.txt.
+
+Example:
+
+/ {
+	...
+
+	pgu at XXXXXXXX {
+		compatible = "snps,arcpgu";
+		reg = <0xXXXXXXXX 0x400>;
+		clocks = <&clock_node>;
+		clock-names = "pxlclk";
+	};
+
+	...
+};
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Thu Mar  3 06:39:13 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu,  3 Mar 2016 17:39:13 +0300
Subject: [PATCH 1/4 v2] drm: Add support of ARC PGU display controller
In-Reply-To: <1457015956-30708-1-git-send-email-abrodkin@synopsys.com>
References: <1457015956-30708-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1457015956-30708-2-git-send-email-abrodkin@synopsys.com>

ARC PGU could be found on some development boards from Synopsys.
This is a simple byte streamer that reads data from a framebuffer
and sends data to the single encoder.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: David Airlie <airlied at linux.ie>
Cc: dri-devel at lists.freedesktop.org
Cc: linux-snps-arc at lists.infradead.org
---

No changes since v1.

 drivers/gpu/drm/Kconfig           |   2 +
 drivers/gpu/drm/Makefile          |   1 +
 drivers/gpu/drm/arc/Kconfig       |  10 ++
 drivers/gpu/drm/arc/Makefile      |   2 +
 drivers/gpu/drm/arc/arcpgu.h      |  47 +++++++
 drivers/gpu/drm/arc/arcpgu_crtc.c | 274 ++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_drv.c  | 239 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_hdmi.c | 204 ++++++++++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_regs.h |  36 +++++
 9 files changed, 815 insertions(+)
 create mode 100644 drivers/gpu/drm/arc/Kconfig
 create mode 100644 drivers/gpu/drm/arc/Makefile
 create mode 100644 drivers/gpu/drm/arc/arcpgu.h
 create mode 100644 drivers/gpu/drm/arc/arcpgu_crtc.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_drv.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_hdmi.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_regs.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 08706f0..654a9cb 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -279,3 +279,5 @@ source "drivers/gpu/drm/imx/Kconfig"
 source "drivers/gpu/drm/vc4/Kconfig"
 
 source "drivers/gpu/drm/etnaviv/Kconfig"
+
+source "drivers/gpu/drm/arc/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 6eb94fc..c338d04 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -78,3 +78,4 @@ obj-y			+= panel/
 obj-y			+= bridge/
 obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
 obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
+obj-$(CONFIG_DRM_ARCPGU)+= arc/
diff --git a/drivers/gpu/drm/arc/Kconfig b/drivers/gpu/drm/arc/Kconfig
new file mode 100644
index 0000000..f9a13b6
--- /dev/null
+++ b/drivers/gpu/drm/arc/Kconfig
@@ -0,0 +1,10 @@
+config DRM_ARCPGU
+	tristate "ARC PGU"
+	depends on DRM && OF
+	select DRM_KMS_CMA_HELPER
+	select DRM_KMS_FB_HELPER
+	select DRM_KMS_HELPER
+	help
+	  Choose this option if you have an ARC PGU controller.
+
+	  If M is selected the module will be called arcpgu.
diff --git a/drivers/gpu/drm/arc/Makefile b/drivers/gpu/drm/arc/Makefile
new file mode 100644
index 0000000..d48fda7
--- /dev/null
+++ b/drivers/gpu/drm/arc/Makefile
@@ -0,0 +1,2 @@
+arcpgu-y := arcpgu_crtc.o arcpgu_hdmi.o arcpgu_drv.o
+obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o
diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h
new file mode 100644
index 0000000..d6a5cf5
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu.h
@@ -0,0 +1,47 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ARCPGU_H_
+#define _ARCPGU_H_
+
+struct arcpgu_drm_private {
+	void __iomem		*regs;
+	struct clk		*clk;
+	struct drm_fbdev_cma	*fbdev;
+	struct drm_framebuffer	*fb;
+	struct list_head	event_list;
+	struct drm_crtc		crtc;
+	struct drm_plane	*plane;
+};
+
+#define crtc_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, crtc)
+
+static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu,
+				 unsigned int reg, u32 value)
+{
+	iowrite32(value, arcpgu->regs + reg);
+}
+
+static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu,
+			       unsigned int reg)
+{
+	return ioread32(arcpgu->regs + reg);
+}
+
+int arc_pgu_setup_crtc(struct drm_device *dev);
+int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np);
+
+#endif
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
new file mode 100644
index 0000000..0fe5c8a
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
@@ -0,0 +1,274 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <linux/clk.h>
+#include <linux/platform_data/simplefb.h>
+
+#include "arcpgu.h"
+#include "arcpgu_regs.h"
+
+#define ENCODE_PGU_XY(x, y)	((((x) - 1) << 16) | ((y) - 1))
+
+static struct simplefb_format supported_formats[] = {
+	{ "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0}, DRM_FORMAT_RGB565 },
+	{ "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 },
+};
+
+static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	uint32_t pixel_format = crtc->primary->state->fb->pixel_format;
+	struct simplefb_format *format = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
+		if (supported_formats[i].fourcc == pixel_format)
+			format = &supported_formats[i];
+	}
+
+	if (WARN_ON(!format))
+		return;
+
+	if (format->fourcc == DRM_FORMAT_RGB888)
+		arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+			      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) |
+					   ARCPGU_MODE_RGB888_MASK);
+
+}
+
+static const struct drm_crtc_funcs arc_pgu_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 void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	struct drm_display_mode *m = &crtc->state->adjusted_mode;
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_FMT,
+		      ENCODE_PGU_XY(m->crtc_htotal, m->crtc_vtotal));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_HSYNC,
+		      ENCODE_PGU_XY(m->crtc_hsync_start - m->crtc_hdisplay,
+				    m->crtc_hsync_end - m->crtc_hdisplay));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_VSYNC,
+		      ENCODE_PGU_XY(m->crtc_vsync_start - m->crtc_vdisplay,
+				    m->crtc_vsync_end - m->crtc_vdisplay));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_ACTIVE,
+		      ENCODE_PGU_XY(m->crtc_hblank_end - m->crtc_hblank_start,
+				    m->crtc_vblank_end - m->crtc_vblank_start));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_STRIDE, 0);
+	arc_pgu_write(arcpgu, ARCPGU_REG_START_SET, 1);
+
+	arc_pgu_set_pxl_fmt(crtc);
+
+	clk_set_rate(arcpgu->clk, m->crtc_clock * 1000);
+}
+
+static void arc_pgu_crtc_enable(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+
+	clk_prepare_enable(arcpgu->clk);
+	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+		      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) |
+		      ARCPGU_CTRL_ENABLE_MASK);
+}
+
+static void arc_pgu_crtc_disable(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+
+	if (!crtc->primary->fb)
+		return;
+
+	clk_disable_unprepare(arcpgu->clk);
+	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+			      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) &
+			      ~ARCPGU_CTRL_ENABLE_MASK);
+}
+
+static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc,
+				     struct drm_crtc_state *state)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	struct drm_display_mode *mode = &state->adjusted_mode;
+	long rate, clk_rate = mode->clock * 1000;
+
+	rate = clk_round_rate(arcpgu->clk, clk_rate);
+	if (rate != clk_rate)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
+				      struct drm_crtc_state *state)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	unsigned long flags;
+
+	if (crtc->state->event) {
+		struct drm_pending_vblank_event *event = crtc->state->event;
+
+		crtc->state->event = NULL;
+		event->pipe = drm_crtc_index(crtc);
+
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+		spin_lock_irqsave(&crtc->dev->event_lock, flags);
+		list_add_tail(&event->base.link, &arcpgu->event_list);
+		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+	}
+}
+
+static void arc_pgu_crtc_atomic_flush(struct drm_crtc *crtc,
+				      struct drm_crtc_state *state)
+{
+}
+
+static bool arc_pgu_crtc_mode_fixup(struct drm_crtc *crtc,
+				    const struct drm_display_mode *mode,
+				    struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
+	.mode_fixup	= arc_pgu_crtc_mode_fixup,
+	.mode_set	= drm_helper_crtc_mode_set,
+	.mode_set_base	= drm_helper_crtc_mode_set_base,
+	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
+	.enable		= arc_pgu_crtc_enable,
+	.disable	= arc_pgu_crtc_disable,
+	.prepare	= arc_pgu_crtc_disable,
+	.commit		= arc_pgu_crtc_enable,
+	.atomic_check	= arc_pgu_crtc_atomic_check,
+	.atomic_begin	= arc_pgu_crtc_atomic_begin,
+	.atomic_flush	= arc_pgu_crtc_atomic_flush,
+};
+
+static int arc_pgu_plane_atomic_check(struct drm_plane *plane,
+				      struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void arc_pgu_plane_atomic_update(struct drm_plane *plane,
+					struct drm_plane_state *state)
+{
+	struct arcpgu_drm_private *arcpgu;
+	struct drm_gem_cma_object *gem;
+
+	if (!plane->state->crtc || !plane->state->fb)
+		return;
+
+	arcpgu = crtc_to_arcpgu_priv(plane->state->crtc);
+	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
+	arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr);
+}
+
+static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = {
+	.prepare_fb = NULL,
+	.cleanup_fb = NULL,
+	.atomic_check = arc_pgu_plane_atomic_check,
+	.atomic_update = arc_pgu_plane_atomic_update,
+};
+
+static void arc_pgu_plane_destroy(struct drm_plane *plane)
+{
+	drm_plane_helper_disable(plane);
+	drm_plane_cleanup(plane);
+}
+
+static const struct drm_plane_funcs arc_pgu_plane_funcs = {
+	.update_plane		= drm_atomic_helper_update_plane,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.destroy		= arc_pgu_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 struct drm_plane *arc_pgu_plane_init(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_plane *plane = NULL;
+	u32 formats[ARRAY_SIZE(supported_formats)], i;
+	int ret;
+
+	plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
+	if (!plane)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(supported_formats); i++)
+		formats[i] = supported_formats[i].fourcc;
+
+	ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs,
+				       formats, ARRAY_SIZE(formats),
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_plane_helper_add(plane, &arc_pgu_plane_helper_funcs);
+	arcpgu->plane = plane;
+
+	return plane;
+}
+
+void arc_pgu_crtc_suspend(struct drm_crtc *crtc)
+{
+	arc_pgu_crtc_disable(crtc);
+}
+
+void arc_pgu_crtc_resume(struct drm_crtc *crtc)
+{
+	arc_pgu_crtc_enable(crtc);
+}
+
+int arc_pgu_setup_crtc(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_plane *primary;
+	int ret;
+
+	primary = arc_pgu_plane_init(drm);
+	if (IS_ERR(primary))
+		return PTR_ERR(primary);
+
+	ret = drm_crtc_init_with_planes(drm, &arcpgu->crtc, primary, NULL,
+					&arc_pgu_crtc_funcs, NULL);
+	if (ret) {
+		arc_pgu_plane_destroy(primary);
+		return ret;
+	}
+
+	drm_crtc_helper_add(&arcpgu->crtc, &arc_pgu_crtc_helper_funcs);
+	return 0;
+}
diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c
new file mode 100644
index 0000000..31bfb3f
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_drv.c
@@ -0,0 +1,239 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "arcpgu.h"
+#include "arcpgu_regs.h"
+
+static void arcpgu_fb_output_poll_changed(struct drm_device *dev)
+{
+	struct arcpgu_drm_private *arcpgu = dev->dev_private;
+
+	if (arcpgu->fbdev)
+		drm_fbdev_cma_hotplug_event(arcpgu->fbdev);
+}
+
+static int arcpgu_atomic_commit(struct drm_device *dev,
+				    struct drm_atomic_state *state, bool async)
+{
+	return drm_atomic_helper_commit(dev, state, false);
+}
+
+static struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = {
+	.fb_create  = drm_fb_cma_create,
+	.output_poll_changed = arcpgu_fb_output_poll_changed,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = arcpgu_atomic_commit,
+};
+
+static void arcpgu_setup_mode_config(struct drm_device *drm)
+{
+	drm_mode_config_init(drm);
+	drm->mode_config.min_width = 0;
+	drm->mode_config.min_height = 0;
+	drm->mode_config.max_width = 1920;
+	drm->mode_config.max_height = 1080;
+	drm->mode_config.funcs = &arcpgu_drm_modecfg_funcs;
+}
+
+static const struct file_operations arcpgu_drm_ops = {
+	.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 = no_llseek,
+	.mmap = drm_gem_cma_mmap,
+};
+
+static void arcpgu_preclose(struct drm_device *drm, struct drm_file *file)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_pending_vblank_event *e, *t;
+	unsigned long flags;
+
+	spin_lock_irqsave(&drm->event_lock, flags);
+	list_for_each_entry_safe(e, t, &arcpgu->event_list, base.link) {
+		if (e->base.file_priv != file)
+			continue;
+		list_del(&e->base.link);
+		e->base.destroy(&e->base);
+	}
+	spin_unlock_irqrestore(&drm->event_lock, flags);
+}
+
+static void arcpgu_lastclose(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+
+	drm_fbdev_cma_restore_mode(arcpgu->fbdev);
+}
+
+static int arcpgu_load(struct drm_device *drm, unsigned long flags)
+{
+	struct platform_device *pdev = drm->platformdev;
+	struct arcpgu_drm_private *arcpgu;
+	struct device_node *encoder_node;
+	struct resource *res;
+	int ret;
+
+	arcpgu = devm_kzalloc(&pdev->dev, sizeof(*arcpgu), GFP_KERNEL);
+	if (arcpgu == NULL)
+		return -ENOMEM;
+
+	drm->dev_private = arcpgu;
+
+	arcpgu->clk = devm_clk_get(drm->dev, "pxlclk");
+	if (IS_ERR(arcpgu->clk))
+		return PTR_ERR(arcpgu->clk);
+
+	INIT_LIST_HEAD(&arcpgu->event_list);
+
+	arcpgu_setup_mode_config(drm);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	arcpgu->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(arcpgu->regs)) {
+		dev_err(drm->dev, "Could not remap IO mem\n");
+		return PTR_ERR(arcpgu->regs);
+	}
+
+	dev_info(drm->dev, "arc_pgu ID: 0x%x\n",
+		 arc_pgu_read(arcpgu, ARCPGU_REG_ID));
+
+	if (dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32)))
+		return -ENODEV;
+
+	if (arc_pgu_setup_crtc(drm) < 0)
+		return -ENODEV;
+
+	/* find the encoder node and initialize it */
+	encoder_node = of_parse_phandle(drm->dev->of_node, "encoder-slave", 0);
+	if (!encoder_node) {
+		dev_err(drm->dev, "failed to get an encoder slave node\n");
+		return -ENODEV;
+	}
+
+	ret = arcpgu_drm_hdmi_init(drm, encoder_node);
+	if (ret < 0)
+		return ret;
+
+	drm_mode_config_reset(drm);
+	drm_kms_helper_poll_init(drm);
+
+	arcpgu->fbdev = drm_fbdev_cma_init(drm, 16, drm->mode_config.num_crtc,
+					  drm->mode_config.num_connector);
+	if (IS_ERR(arcpgu->fbdev)) {
+		ret = PTR_ERR(arcpgu->fbdev);
+		arcpgu->fbdev = NULL;
+		return -ENODEV;
+	}
+
+	platform_set_drvdata(pdev, arcpgu);
+	return 0;
+}
+
+int arcpgu_unload(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+
+	if (arcpgu->fbdev) {
+		drm_fbdev_cma_fini(arcpgu->fbdev);
+		arcpgu->fbdev = NULL;
+	}
+	drm_kms_helper_poll_fini(drm);
+	drm_vblank_cleanup(drm);
+	drm_mode_config_cleanup(drm);
+
+	return 0;
+}
+
+static struct drm_driver arcpgu_drm_driver = {
+	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
+			   DRIVER_ATOMIC,
+	.preclose = arcpgu_preclose,
+	.lastclose = arcpgu_lastclose,
+	.name = "drm-arcpgu",
+	.desc = "ARC PGU Controller",
+	.date = "20160219",
+	.major = 1,
+	.minor = 0,
+	.patchlevel = 0,
+	.fops = &arcpgu_drm_ops,
+	.load = arcpgu_load,
+	.unload = arcpgu_unload,
+	.dumb_create = drm_gem_cma_dumb_create,
+	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
+	.dumb_destroy = drm_gem_dumb_destroy,
+	.get_vblank_counter = drm_vblank_no_hw_counter,
+	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+	.gem_free_object = drm_gem_cma_free_object,
+	.gem_vm_ops = &drm_gem_cma_vm_ops,
+	.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,
+};
+
+static int arcpgu_probe(struct platform_device *pdev)
+{
+	return drm_platform_init(&arcpgu_drm_driver, pdev);
+}
+
+static int arcpgu_remove(struct platform_device *pdev)
+{
+	struct drm_device *drm = dev_get_drvdata(&pdev->dev);
+
+	drm_put_dev(drm);
+
+	return 0;
+}
+
+static const struct of_device_id arcpgu_of_table[] = {
+	{.compatible = "snps,arcpgu"},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, arcpgu_drm_of_table);
+
+static struct platform_driver arcpgu_platform_driver = {
+	.probe = arcpgu_probe,
+	.remove = arcpgu_remove,
+	.driver = {
+		   .name = "arcpgu",
+		   .owner = THIS_MODULE,
+		   .of_match_table = arcpgu_of_table,
+		   },
+};
+
+module_platform_driver(arcpgu_platform_driver);
+
+MODULE_AUTHOR("Carlos Palminha <palminha at synopsys.com");
+MODULE_DESCRIPTION("ARC PGU DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c
new file mode 100644
index 0000000..623a5c1
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c
@@ -0,0 +1,204 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "arcpgu.h"
+
+struct arcpgu_drm_connector {
+	struct drm_connector connector;
+	struct drm_encoder_slave *encoder_slave;
+};
+
+static int arcpgu_drm_connector_get_modes(struct drm_connector *connector)
+{
+	const struct drm_encoder_slave_funcs *sfuncs;
+	struct drm_encoder_slave *slave;
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_get_modes: cannot find slave encoder for connector\n");
+		return 0;
+	}
+
+	sfuncs = slave->slave_funcs;
+	if (sfuncs->get_modes == NULL)
+		return 0;
+
+	return sfuncs->get_modes(&slave->base, connector);
+}
+
+struct drm_encoder *
+arcpgu_drm_connector_best_encoder(struct drm_connector *connector)
+{
+	struct drm_encoder_slave *slave;
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_best_encoder: cannot find slave encoder for connector\n");
+		return NULL;
+	}
+
+	return &slave->base;
+}
+
+static enum drm_connector_status
+arcpgu_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	enum drm_connector_status status = connector_status_unknown;
+	const struct drm_encoder_slave_funcs *sfuncs;
+	struct drm_encoder_slave *slave;
+
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_detect: cannot find slave encoder for connector\n");
+		return status;
+	}
+
+	sfuncs = slave->slave_funcs;
+	if (sfuncs && sfuncs->detect)
+		return sfuncs->detect(&slave->base, connector);
+
+	dev_err(connector->dev->dev, "connector_detect: could not detect slave funcs\n");
+	return status;
+}
+
+static void arcpgu_drm_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_helper_funcs arcpgu_drm_connector_helper_funcs = {
+	.get_modes = arcpgu_drm_connector_get_modes,
+	.best_encoder = arcpgu_drm_connector_best_encoder,
+};
+
+static const struct drm_connector_funcs arcpgu_drm_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = arcpgu_drm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = arcpgu_drm_connector_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static struct drm_encoder_helper_funcs arcpgu_drm_encoder_helper_funcs = {
+	.dpms = drm_i2c_encoder_dpms,
+	.mode_fixup = drm_i2c_encoder_mode_fixup,
+	.mode_set = drm_i2c_encoder_mode_set,
+	.prepare = drm_i2c_encoder_prepare,
+	.commit = drm_i2c_encoder_commit,
+	.detect = drm_i2c_encoder_detect,
+};
+
+static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np)
+{
+	struct arcpgu_drm_connector *arcpgu_connector;
+	struct drm_i2c_encoder_driver *driver;
+	struct drm_encoder_slave *encoder;
+	struct drm_connector *connector;
+	struct i2c_client *i2c_slave;
+	int ret;
+
+	encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL);
+	if (encoder == NULL)
+		return -ENOMEM;
+
+	i2c_slave = of_find_i2c_device_by_node(np);
+	if (!i2c_slave || !i2c_get_clientdata(i2c_slave)) {
+		dev_err(drm->dev, "failed to find i2c slave encoder\n");
+		return -EPROBE_DEFER;
+	}
+
+	if (i2c_slave->dev.driver == NULL) {
+		dev_err(drm->dev, "failed to find i2c slave driver\n");
+		return -EPROBE_DEFER;
+	}
+
+	driver =
+	    to_drm_i2c_encoder_driver(to_i2c_driver(i2c_slave->dev.driver));
+	ret = driver->encoder_init(i2c_slave, drm, encoder);
+	if (ret) {
+		dev_err(drm->dev, "failed to initialize i2c encoder slave\n");
+		return ret;
+	}
+
+	encoder->base.possible_crtcs = 1;
+	encoder->base.possible_clones = 0;
+	ret = drm_encoder_init(drm, &encoder->base, &arcpgu_drm_encoder_funcs,
+			       DRM_MODE_ENCODER_TMDS, NULL);
+	if (ret)
+		return ret;
+
+	drm_encoder_helper_add(&encoder->base,
+			       &arcpgu_drm_encoder_helper_funcs);
+
+	arcpgu_connector = devm_kzalloc(drm->dev, sizeof(*arcpgu_connector),
+					GFP_KERNEL);
+	if (!arcpgu_connector)
+		return -ENOMEM;
+
+	connector = &arcpgu_connector->connector;
+	drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs);
+	ret = drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs,
+			DRM_MODE_CONNECTOR_HDMIA);
+	if (ret < 0) {
+		dev_err(drm->dev, "failed to initialize drm connector\n");
+		goto error_encoder_cleanup;
+	}
+
+	ret = drm_connector_register(connector);
+	if (ret < 0) {
+		dev_err(drm->dev, "failed to regiter DRM connector and helper funcs\n");
+		goto error_connector_cleanup;
+	}
+
+	ret = drm_mode_connector_attach_encoder(connector, &encoder->base);
+	if (ret < 0) {
+		dev_err(drm->dev, "could not attach connector to encoder\n");
+		drm_connector_unregister(connector);
+		goto error_connector_cleanup;
+	}
+
+	arcpgu_connector->encoder_slave = encoder;
+
+	return 0;
+
+error_connector_cleanup:
+	drm_connector_cleanup(connector);
+
+error_encoder_cleanup:
+	drm_encoder_cleanup(&encoder->base);
+	return ret;
+}
diff --git a/drivers/gpu/drm/arc/arcpgu_regs.h b/drivers/gpu/drm/arc/arcpgu_regs.h
new file mode 100644
index 0000000..f04165f
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_regs.h
@@ -0,0 +1,36 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ARC_PGU_REGS_H_
+#define _ARC_PGU_REGS_H_
+
+#define ARCPGU_REG_CTRL		0x00
+#define ARCPGU_REG_STAT		0x04
+#define ARCPGU_REG_FMT		0x10
+#define ARCPGU_REG_HSYNC	0x14
+#define ARCPGU_REG_VSYNC	0x18
+#define ARCPGU_REG_ACTIVE	0x1c
+#define ARCPGU_REG_BUF0_ADDR	0x40
+#define ARCPGU_REG_STRIDE	0x50
+#define ARCPGU_REG_START_SET	0x84
+
+#define ARCPGU_REG_ID		0x3FC
+
+#define ARCPGU_CTRL_ENABLE_MASK	0x02
+#define ARCPGU_MODE_RGB888_MASK	0x04
+#define ARCPGU_STAT_BUSY_MASK	0x02
+
+#endif
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Thu Mar  3 06:39:16 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu,  3 Mar 2016 17:39:16 +0300
Subject: [PATCH 4/4 v2] MAINTAINERS: Add maintainer for ARC PGU display
 controller
In-Reply-To: <1457015956-30708-1-git-send-email-abrodkin@synopsys.com>
References: <1457015956-30708-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1457015956-30708-5-git-send-email-abrodkin@synopsys.com>

This updates MAINTEINERS file with information about maintainer of
ARC PGU display controller driver.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: linux-snps-arc at lists.infradead.org
---

No changes since v1.

 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 28cd72b..26ac58c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -847,6 +847,12 @@ S:	Maintained
 F:	drivers/net/arcnet/
 F:	include/uapi/linux/if_arcnet.h
 
+ARC PGU DRM DRIVER
+M:	Alexey Brodkin <abrodkin at synopsys.com>
+S:	Supported
+F:	drivers/gpu/drm/arc/
+F:	Documentation/devicetree/bindings/display/snps,arcpgu.txt
+
 ARM HDLCD DRM DRIVER
 M:	Liviu Dudau <liviu.dudau at arm.com>
 S:	Supported
-- 
2.5.0



From lkp at intel.com  Thu Mar  3 09:51:21 2016
From: lkp at intel.com (kbuild test robot)
Date: Fri, 4 Mar 2016 01:51:21 +0800
Subject: [PATCH 1/4 v2] drm: Add support of ARC PGU display controller
In-Reply-To: <1457015956-30708-2-git-send-email-abrodkin@synopsys.com>
Message-ID: <201603040105.D1aOLTzI%fengguang.wu@intel.com>

Hi Alexey,

[auto build test ERROR on drm/drm-next]
[also build test ERROR on v4.5-rc6 next-20160303]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Alexey-Brodkin/drm-Add-support-of-ARC-PGU-display-controller/20160303-224311
base:   git://people.freedesktop.org/~airlied/linux.git drm-next
config: openrisc-allmodconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=openrisc 

All errors (new ones prefixed by >>):

   drivers/gpu/drm/arc/arcpgu_drv.c:223:1: error: 'arcpgu_drm_of_table' undeclared here (not in a function)
>> drivers/gpu/drm/arc/arcpgu_drv.c:223:1: error: type defaults to 'int' in declaration of '__mod_of__arcpgu_drm_of_table_device_table'
>> drivers/gpu/drm/arc/arcpgu_drv.c:223:1: error: '__mod_of__arcpgu_drm_of_table_device_table' aliased to undefined symbol 'arcpgu_drm_of_table'
>> drivers/gpu/drm/arc/arcpgu_drv.c:223:1: error: '__mod_of__arcpgu_drm_of_table_device_table' aliased to undefined symbol 'arcpgu_drm_of_table'

vim +223 drivers/gpu/drm/arc/arcpgu_drv.c

   217	
   218	static const struct of_device_id arcpgu_of_table[] = {
   219		{.compatible = "snps,arcpgu"},
   220		{}
   221	};
   222	
 > 223	MODULE_DEVICE_TABLE(of, arcpgu_drm_of_table);
   224	
   225	static struct platform_driver arcpgu_platform_driver = {
   226		.probe = arcpgu_probe,

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 36576 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-snps-arc/attachments/20160304/4dc3b527/attachment-0001.obj>

From lkp at intel.com  Thu Mar  3 09:08:29 2016
From: lkp at intel.com (kbuild test robot)
Date: Fri, 4 Mar 2016 01:08:29 +0800
Subject: [PATCH 1/4 v2] drm: Add support of ARC PGU display controller
In-Reply-To: <1457015956-30708-2-git-send-email-abrodkin@synopsys.com>
Message-ID: <201603040144.Y4lTRkUP%fengguang.wu@intel.com>

Hi Alexey,

[auto build test ERROR on drm/drm-next]
[also build test ERROR on v4.5-rc6 next-20160303]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Alexey-Brodkin/drm-Add-support-of-ARC-PGU-display-controller/20160303-224311
base:   git://people.freedesktop.org/~airlied/linux.git drm-next
config: i386-allmodconfig (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   In file included from include/drm/drm_vma_manager.h:29:0,
                    from include/drm/drmP.h:75,
                    from include/drm/drm_gem_cma_helper.h:4,
                    from drivers/gpu/drm/arc/arcpgu_drv.c:20:
>> drivers/gpu/drm/arc/arcpgu_drv.c:223:25: error: 'arcpgu_drm_of_table' undeclared here (not in a function)
    MODULE_DEVICE_TABLE(of, arcpgu_drm_of_table);
                            ^
>> drivers/gpu/drm/arc/arcpgu_drv.c:223:1: note: in expansion of macro 'MODULE_DEVICE_TABLE'
    MODULE_DEVICE_TABLE(of, arcpgu_drm_of_table);
    ^
>> include/linux/module.h:223:27: error: '__mod_of__arcpgu_drm_of_table_device_table' aliased to undefined symbol 'arcpgu_drm_of_table'
    extern const typeof(name) __mod_##type##__##name##_device_table  \
                              ^
>> drivers/gpu/drm/arc/arcpgu_drv.c:223:1: note: in expansion of macro 'MODULE_DEVICE_TABLE'
    MODULE_DEVICE_TABLE(of, arcpgu_drm_of_table);
    ^

vim +/arcpgu_drm_of_table +223 drivers/gpu/drm/arc/arcpgu_drv.c

   217	
   218	static const struct of_device_id arcpgu_of_table[] = {
   219		{.compatible = "snps,arcpgu"},
   220		{}
   221	};
   222	
 > 223	MODULE_DEVICE_TABLE(of, arcpgu_drm_of_table);
   224	
   225	static struct platform_driver arcpgu_platform_driver = {
   226		.probe = arcpgu_probe,

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 53493 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-snps-arc/attachments/20160304/55457f60/attachment-0001.obj>

From Vineet.Gupta1 at synopsys.com  Thu Mar  3 20:05:24 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 4 Mar 2016 04:05:24 +0000
Subject: [PATCH] ARC: Fix misspellings in comments.
References: <1456269895-25714-1-git-send-email-adam.buchbinder@gmail.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E8DB46@us01wembx1.internal.synopsys.com>

On Wednesday 24 February 2016 04:55 AM, Adam Buchbinder wrote:
> Signed-off-by: Adam Buchbinder <adam.buchbinder at gmail.com>

Applied to for-next.

Thx for the fixes Adam.

-Vineet


From Vineet.Gupta1 at synopsys.com  Fri Mar  4 03:22:17 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 4 Mar 2016 16:52:17 +0530
Subject: [PATCH] rt_sigaction.h: adjust for ARC
Message-ID: <1457090537-23825-1-git-send-email-vgupta@synopsys.com>

ARC uses the no-legacy syscall ABI where there is no need for
kernel_sigaction interworking.

Further we rely on default SA_RESTORER in libc for sigreturn.

To me all the song-and-dance in ltp_rt_sigaction() doesn't make sense.
The intent it to test whatever platform libc + kernel combination
provides and to that end any fixups in LTP seem odd to me.
So for ARC just call what libc provides and don't claim to support
more/less.

e.g. rt_sigaction02 fails for ARC, since libc sigaction does following

| int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
| {
|	struct sigaction kact;
|
|	if (act && !(act->sa_flags & SA_RESTORER)) {
|		kact.sa_restorer = __default_rt_sa_restorer;

So we don't get the EFAULT for @act == -1 which kernel would provide.
Instead we get a segv rightawat. But that's fine, that is how our system
works.

Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 include/lapi/rt_sigaction.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/lapi/rt_sigaction.h b/include/lapi/rt_sigaction.h
index 3a5a763ce094..12af3c3b7b27 100644
--- a/include/lapi/rt_sigaction.h
+++ b/include/lapi/rt_sigaction.h
@@ -155,6 +155,13 @@ static void __attribute__((used)) __sigreturn_stub(void)
 static int ltp_rt_sigaction(int signum, const struct sigaction *act,
 			struct sigaction *oact, size_t sigsetsize)
 {
+#ifdef __arc__
+	/*
+	 * No playing games with various internals of sigaction / fields
+	 * just use whatever libc + kernel provide
+	 */
+	return sigaction(signum, act, oact);
+#else
 	int ret;
 	struct kernel_sigaction kact, koact;
 	struct kernel_sigaction *kact_p = NULL;
@@ -218,6 +225,7 @@ static int ltp_rt_sigaction(int signum, const struct sigaction *act,
 	}
 
 	return ret;
+#endif
 }
 
 #endif /* LTP_RT_SIGACTION_H */
-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Fri Mar  4 03:55:09 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 4 Mar 2016 17:25:09 +0530
Subject: [PATCH] ARC: build: Better way to detect ISA compatible toolchain
In-Reply-To: <1456475361-7754-2-git-send-email-vgupta@synopsys.com>
References: <1456475361-7754-1-git-send-email-vgupta@synopsys.com>
 <1456475361-7754-2-git-send-email-vgupta@synopsys.com>
Message-ID: <56D9779D.2040307@synopsys.com>

Hi Michal,

Can u please take a look at patch below !

Thx,
-Vineet

On Friday 26 February 2016 01:59 PM, Vineet Gupta wrote:
> ARC architecture has 2 instruction sets: ARCompact/ARCv2.
> While same gcc supports compiling for either (using appropriate toggles),
> we can't use the same toolchain to build kernel because libgcc needs
> to be unique and the toolchian (uClibc based) is not multilibed.
> 
> uClibc toolchain is convenient since it allows all userspace and
> kernel to be built with a single install for an ISA.
> 
> This however means 2 gnu installs (with same triplet prefix) are needed
> for building for 2 ISA and need to be in PATH.
> As developers we keep switching the builds, but would occassionally fail
> to update the PATH leading to usage of wrong tools. And this would only
> show up at the end of kernel build when linking incompatible libgcc.
> 
> So the initial solution was to have gcc define a special preprocessor macro
> DEFAULT_CPU_xxx which is unique for default toolchain configuration.
> Claudiu proposed using grep for an existing preprocessor macro which is
> again uniquely defined per ISA.
> 
> Cc: Michal Marek <mmarek at suse.cz>
> Suggested-by: Claudiu Zissulescu <claziss at synopsys.com>
> Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
> ---
>  arch/arc/Makefile              | 14 ++++++++++++++
>  arch/arc/include/asm/arcregs.h |  6 ------
>  2 files changed, 14 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arc/Makefile b/arch/arc/Makefile
> index c8230f3395f2..21682e047c00 100644
> --- a/arch/arc/Makefile
> +++ b/arch/arc/Makefile
> @@ -18,6 +18,20 @@ cflags-y	+= -fno-common -pipe -fno-builtin -D__linux__
>  cflags-$(CONFIG_ISA_ARCOMPACT)	+= -mA7
>  cflags-$(CONFIG_ISA_ARCV2)	+= -mcpu=archs
>  
> +is_700 = $(shell $(CC) -dM -E - < /dev/null | grep -q "ARC700" && echo 1 || echo 0)
> +
> +ifdef CONFIG_ISA_ARCOMPACT
> +ifeq ($(is_700), 0)
> +    $(error Toolchain not configured for ARCompact builds)
> +endif
> +endif
> +
> +ifdef CONFIG_ISA_ARCV2
> +ifeq ($(is_700), 1)
> +    $(error Toolchain not configured for ARCv2 builds)
> +endif
> +endif
> +
>  ifdef CONFIG_ARC_CURR_IN_REG
>  # For a global register defintion, make sure it gets passed to every file
>  # We had a customer reported bug where some code built in kernel was NOT using
> diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
> index f9f4c6f59fdb..7fbaea00a336 100644
> --- a/arch/arc/include/asm/arcregs.h
> +++ b/arch/arc/include/asm/arcregs.h
> @@ -381,12 +381,6 @@ static inline int is_isa_arcompact(void)
>  	return IS_ENABLED(CONFIG_ISA_ARCOMPACT);
>  }
>  
> -#if defined(CONFIG_ISA_ARCOMPACT) && !defined(_CPU_DEFAULT_A7)
> -#error "Toolchain not configured for ARCompact builds"
> -#elif defined(CONFIG_ISA_ARCV2) && !defined(_CPU_DEFAULT_HS)
> -#error "Toolchain not configured for ARCv2 builds"
> -#endif
> -
>  #endif /* __ASEMBLY__ */
>  
>  #endif /* _ASM_ARC_ARCREGS_H */
> 



From robh at kernel.org  Fri Mar  4 20:30:01 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 4 Mar 2016 22:30:01 -0600
Subject: [PATCH 2/4 v2] drm: Add DT bindings documentation for ARC PGU
 display controller
In-Reply-To: <1457015956-30708-3-git-send-email-abrodkin@synopsys.com>
References: <1457015956-30708-1-git-send-email-abrodkin@synopsys.com>
 <1457015956-30708-3-git-send-email-abrodkin@synopsys.com>
Message-ID: <20160305043001.GB13525@rob-hp-laptop>

On Thu, Mar 03, 2016 at 05:39:14PM +0300, Alexey Brodkin wrote:
> This add DT bindings documentation for ARC PGU display controller.
> 
> Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
> Cc: Rob Herring <robh+dt at kernel.org>
> Cc: Pawel Moll <pawel.moll at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
> Cc: Kumar Gala <galak at codeaurora.org>
> Cc: devicetree at vger.kernel.org
> Cc: linux-snps-arc at lists.infradead.org
> ---
> 
> Changes v1 -> v2:
>  * Clean-up

Not really useful. What we like to see is what changed. Maintainers have 
short memories and don't remember what they said previously (unless 
comments are ignored).

> 
>  .../devicetree/bindings/display/snps,arcpgu.txt    | 33 ++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt
> 
> diff --git a/Documentation/devicetree/bindings/display/snps,arcpgu.txt b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> new file mode 100644
> index 0000000..57f3bc8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> @@ -0,0 +1,33 @@
> +ARC PGU
> +
> +This is a display controller found on several development boards produced
> +by Synopsys. The ARC PGU is an RGB streamer that reads the data from a
> +framebuffer and sends it to a single digital encoder (usually HDMI).
> +
> +Required properties:
> +  - compatible: "snps,arcpgu"
> +  - reg: Physical base address and length of the controller's registers.
> +  - clocks: A list of phandle + clock-specifier pairs, one for each
> +    entry in 'clock-names'.
> +  - clock-names: A list of clock names. For ARC PGU it should contain:
> +      - "pxlclk" for the clock feeding the output PLL of the controller.
> +
> +Required sub-nodes:
> +  - port: The PGU connection to an encoder chip. The connection is modelled
> +    using the OF graph bindings specified in
> +    Documentation/devicetree/bindings/graph.txt.
> +
> +Example:
> +
> +/ {
> +	...
> +
> +	pgu at XXXXXXXX {
> +		compatible = "snps,arcpgu";
> +		reg = <0xXXXXXXXX 0x400>;
> +		clocks = <&clock_node>;
> +		clock-names = "pxlclk";

Where's the port? Didn't you previously say it was optional?

> +	};
> +
> +	...
> +};
> -- 
> 2.5.0
> 


From Vineet.Gupta1 at synopsys.com  Mon Mar  7 02:39:27 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Mon, 7 Mar 2016 10:39:27 +0000
Subject: [LTP] [PATCH] rt_sigaction.h: adjust for ARC
References: <1457090537-23825-1-git-send-email-vgupta@synopsys.com>
 <20160307101319.GB3559@rei.suse.cz>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E8E55A@us01wembx1.internal.synopsys.com>

On Monday 07 March 2016 03:45 PM, Cyril Hrubis wrote:
> Hi!
>> To me all the song-and-dance in ltp_rt_sigaction() doesn't make sense.
> These are required if you call the raw rt_sigaction syscall. Since
> before signal handler is called the process context is saved on the
> user-space stack and once signal is done it has to be restored. In order
> to do that signal trampoline is called which calls sigreturn to restore
> the context. And the way trapoline is executed is platform specific and
> sometimes in the sa_restorer.

I'm well aware of all that having fixed a bunch of kernel issues in this exact
area back in 2008 and also added the uClibc userspace default sigrestorer....
The point is why is LTP calling raw rt_sigaction syscall at all. It needs to call
sigaction which is the posix API and see how it behaves. I can understand the
usage of raw syscalls for things which won't be present in a libc (e.g newer
syscalls or perhaps obsoleted syscalls). sigaction is fairly standard. No ?

>> The intent it to test whatever platform libc + kernel combination
>> provides and to that end any fixups in LTP seem odd to me.
>> So for ARC just call what libc provides and don't claim to support
>> more/less.
> These testcases are testing kernel syscall and some of the testcases
> will not work with the libc wrapper.

I understand you want to test the -EFAULT code path in the kernel - but any arch
with default sa restorer in libc can't do that at all.
They have to provide the default sa restorer to successfully return from signal
handler to invoke the sigreturn syscall.
Look in uClibc - ARC is not the exception: ARM, Xtensa, MIPS, x86 all use such
userspace default restorers and are all plagued by same issue.

Before this patch, we had rt_sigaction01 crash on ARC - this was because it passed
the test itself, but for sigreturn it went off to lala land since there was no
restorer. So it failed anyways. With this patch we have that as passing: actually
4 passes, 2 failures. I don't care abt this +4/-2. More importantly this is true
reflection of how ARC GNU stack behaves. If you call sigaction(num, -1, 0) it will
NOT return -EFAULT but crash.

-rt_sigaction01 rt_sigaction01
-rt_sigprocmask01 rt_sigprocmask01
-rt_sigsuspend01 rt_sigsuspend01
+rt_sigaction02 rt_sigaction02
+rt_sigaction03 rt_sigaction03
-signal_test_04 signal_test_04


>  So NACK on the patch.

But this patch only changes how ARC works - so whats the problem ? There are
already arch specifix quirks in this file, there so how does one more hurt.

-Vineet


From Vineet.Gupta1 at synopsys.com  Mon Mar  7 03:50:52 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Mon, 7 Mar 2016 11:50:52 +0000
Subject: [LTP] [PATCH] rt_sigaction.h: adjust for ARC
References: <1457090537-23825-1-git-send-email-vgupta@synopsys.com>
 <20160307101319.GB3559@rei.suse.cz>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8E55A@us01wembx1.internal.synopsys.com>
 <20160307105747.GC3559@rei.suse.cz>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E8E5B7@us01wembx1.internal.synopsys.com>

On Monday 07 March 2016 04:29 PM, Cyril Hrubis wrote:
> We also check that we got EINVAL if the sigsetsize is wrong, which
> cannot be done with the libc wrapper.
>
> And we several testscases for the libc wrapper as well. Two in
> testcases/syscalls/sigaction/ directory and much more in
> testcases/open_posix_testsuite/conformance/interfaces/sigaction/.
>
> So both raw syscall and libc call are covered in LTP.

Fair enough - so LTP was a "Linux" test project - testing the raw kernel ABI makes
sense to check for correctness.
Although users will complain that sigaction(n, -1, 0) doesn't return with -EFAULT
but crashes. Oh well !

>>>> So for ARC just call what libc provides and don't claim to support
>>>> more/less.
> I do not understand, looking at:
>
> https://github.com/foss-for-synopsys-dwc-arc-processors/uClibc/blob/314dd3440686d6225ef1b93b5c5bdce852747a6b/libc/sysdeps/linux/arc/sigaction.c
>
> All you have to do in sa_restorer for arc is to call __NR_rt_sigreturn.
>
> Looking at the INTERNAL_SYSCALL_NCS it's just a few lines of inline
> assembler. So all you have to do to support this properly in LTP is to
> create restorer function taking the assembler and passing NR_sigreturn
> as syscall number to it.

Will do in next patch !

Thx,
-Vineet




From Vineet.Gupta1 at synopsys.com  Mon Mar  7 03:51:53 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Mon, 7 Mar 2016 17:21:53 +0530
Subject: [PATCH] rt_sigaction.h: ARC: Provide default sa_restorer
Message-ID: <1457351513-8310-1-git-send-email-vgupta@synopsys.com>

LTP tests the raw (non libc) sigaction ABI to kernel such as validation
of various params.

sigaction on ARC relies on default userspace sa restorer to invoke a
sigreturn syscall when returning from a signal handler. Thus libc provides
a default sa restorer.

LTP tests the raw sigaction syscall ABI (w/o libc) hence needs the
restorer userspace infrastructure, which this patch provides for ARC.

Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 include/lapi/rt_sigaction.h | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/include/lapi/rt_sigaction.h b/include/lapi/rt_sigaction.h
index 3a5a763ce094..c7fb04fc25be 100644
--- a/include/lapi/rt_sigaction.h
+++ b/include/lapi/rt_sigaction.h
@@ -145,6 +145,30 @@ static void __attribute__((used)) __sigreturn_stub(void)
 # endif
 #endif /* __sparc__ */
 
+#ifdef __arc__
+
+#undef SA_RESTORER
+#define SA_RESTORER     0x04000000
+
+/*
+ * based on uClibc/libc/sysdeps/linux/arc/sigaction.c
+ */
+static void
+__attribute__ ((optimize("Os"))) __attribute__((used)) restore_rt(void)
+{
+	__asm__ (
+		"mov r8, %0	\n\t"
+#ifdef __ARCHS__
+		"trap_s	0	\n\t"
+#else
+		"trap0	\n\t"
+#endif
+		: /* no outputs */
+		: "i" (__NR_rt_sigreturn)
+		: "r8");
+}
+#endif
+
 /* This is a wrapper for __NR_rt_sigaction syscall.
  * act/oact values of INVAL_SA_PTR is used to pass
  * an invalid pointer to syscall(__NR_rt_sigaction)
@@ -176,8 +200,10 @@ static int ltp_rt_sigaction(int signum, const struct sigaction *act,
 	else if (oact)
 		koact_p = &koact;
 
+#if defined __x86_64__ || defined __arc__
 #ifdef __x86_64__
 	sig_initial(signum);
+#endif
 	kact.sa_flags |= SA_RESTORER;
 	kact.sa_restorer = restore_rt;
 #endif
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Mon Mar  7 06:53:12 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Mon, 7 Mar 2016 14:53:12 +0000
Subject: [PATCH 2/4 v2] drm: Add DT bindings documentation for ARC PGU
 display controller
In-Reply-To: <20160305043001.GB13525@rob-hp-laptop>
References: <1457015956-30708-1-git-send-email-abrodkin@synopsys.com>
 <1457015956-30708-3-git-send-email-abrodkin@synopsys.com>
 <20160305043001.GB13525@rob-hp-laptop>
Message-ID: <1457362392.2932.49.camel@synopsys.com>

Hi Rob,

On Fri, 2016-03-04 at 22:30 -0600, Rob Herring wrote:
> On Thu, Mar 03, 2016 at 05:39:14PM +0300, Alexey Brodkin wrote:
> > 
> > This add DT bindings documentation for ARC PGU display controller.
> > 
> > Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
> > Cc: Rob Herring <robh+dt at kernel.org>
> > Cc: Pawel Moll <pawel.moll at arm.com>
> > Cc: Mark Rutland <mark.rutland at arm.com>
> > Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
> > Cc: Kumar Gala <galak at codeaurora.org>
> > Cc: devicetree at vger.kernel.org
> > Cc: linux-snps-arc at lists.infradead.org
> > ---
> > 
> > Changes v1 -> v2:
> > ?* Clean-up
> Not really useful. What we like to see is what changed. Maintainers have?
> short memories and don't remember what they said previously (unless?
> comments are ignored).

That's understood :)

> > 
> > 
> > ?.../devicetree/bindings/display/snps,arcpgu.txt????| 33 ++++++++++++++++++++++
> > ?1 file changed, 33 insertions(+)
> > ?create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> > b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> > new file mode 100644
> > index 0000000..57f3bc8
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> > @@ -0,0 +1,33 @@
> > +ARC PGU
> > +
> > +This is a display controller found on several development boards produced
> > +by Synopsys. The ARC PGU is an RGB streamer that reads the data from a
> > +framebuffer and sends it to a single digital encoder (usually HDMI).
> > +
> > +Required properties:
> > +??- compatible: "snps,arcpgu"
> > +??- reg: Physical base address and length of the controller's registers.
> > +??- clocks: A list of phandle + clock-specifier pairs, one for each
> > +????entry in 'clock-names'.
> > +??- clock-names: A list of clock names. For ARC PGU it should contain:
> > +??????- "pxlclk" for the clock feeding the output PLL of the controller.
> > +
> > +Required sub-nodes:
> > +??- port: The PGU connection to an encoder chip. The connection is modelled
> > +????using the OF graph bindings specified in
> > +????Documentation/devicetree/bindings/graph.txt.
> > +
> > +Example:
> > +
> > +/ {
> > +	...
> > +
> > +	pgu at XXXXXXXX {
> > +		compatible = "snps,arcpgu";
> > +		reg = <0xXXXXXXXX 0x400>;
> > +		clocks = <&clock_node>;
> > +		clock-names = "pxlclk";
> Where's the port? Didn't you previously say it was optional?

Well I wanted to get rid of anything except bare minimal that is required for
that driver.

What I did miss in that clean-up is description above.
In particular "Required subnodes" section that still lists "port".

And frankly now I'm a bit lost with what should I put in that binding
description and what should not. Any comments here are much appreciated.

-Alexey

From Vineet.Gupta1 at synopsys.com  Mon Mar  7 21:32:04 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 8 Mar 2016 11:02:04 +0530
Subject: [PATCH] sort the open posix tests before executing
Message-ID: <1457415124-5023-1-git-send-email-vgupta@synopsys.com>

Helps do a simple diff of output logs !

Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 testcases/open_posix_testsuite/bin/run-posix-option-group-test.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/testcases/open_posix_testsuite/bin/run-posix-option-group-test.sh b/testcases/open_posix_testsuite/bin/run-posix-option-group-test.sh
index 0477bd7059bc..7cf2b09a47d2 100755
--- a/testcases/open_posix_testsuite/bin/run-posix-option-group-test.sh
+++ b/testcases/open_posix_testsuite/bin/run-posix-option-group-test.sh
@@ -22,7 +22,7 @@ EOF
 
 run_option_group_tests()
 {
-	for test_script in $(find $1 -name run.sh); do
+	for test_script in $(find $1 -name run.sh | sort); do
 		(cd "$(dirname "$test_script")" && ./$(basename "$test_script"))
 	done
 }
-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Tue Mar  8 04:26:04 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 8 Mar 2016 17:56:04 +0530
Subject: [PATCH v2 1/9] ARC: [dts] Add clk feeding into timers to DTs
In-Reply-To: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
References: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
Message-ID: <1457439972-20285-2-git-send-email-vgupta@synopsys.com>

This allows us to introduce timers in DT in next commit

Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Cc: Rob Herring <robh at kernel.org>
Cc: devicetree at vger.kernel.org
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/boot/dts/axc001.dtsi         | 6 ++++++
 arch/arc/boot/dts/axc003.dtsi         | 6 ++++++
 arch/arc/boot/dts/axc003_idu.dtsi     | 6 ++++++
 arch/arc/boot/dts/nsim_700.dts        | 6 ++++++
 arch/arc/boot/dts/nsim_hs.dts         | 6 ++++++
 arch/arc/boot/dts/nsim_hs_idu.dts     | 6 ++++++
 arch/arc/boot/dts/nsimosci.dts        | 6 ++++++
 arch/arc/boot/dts/nsimosci_hs.dts     | 6 ++++++
 arch/arc/boot/dts/nsimosci_hs_idu.dts | 6 ++++++
 arch/arc/boot/dts/vdk_axc003.dtsi     | 6 ++++++
 arch/arc/boot/dts/vdk_axc003_idu.dtsi | 6 ++++++
 11 files changed, 66 insertions(+)

diff --git a/arch/arc/boot/dts/axc001.dtsi b/arch/arc/boot/dts/axc001.dtsi
index e7a83d19c5a3..40bcecfc3687 100644
--- a/arch/arc/boot/dts/axc001.dtsi
+++ b/arch/arc/boot/dts/axc001.dtsi
@@ -26,6 +26,12 @@
 
 		ranges = <0x00000000 0xf0000000 0x10000000>;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <750000000>;
+		};
+
 		core_intc: arc700-intc at cpu {
 			compatible = "snps,arc700-intc";
 			interrupt-controller;
diff --git a/arch/arc/boot/dts/axc003.dtsi b/arch/arc/boot/dts/axc003.dtsi
index b0e3ccdf8fc7..cabe0deeb2d8 100644
--- a/arch/arc/boot/dts/axc003.dtsi
+++ b/arch/arc/boot/dts/axc003.dtsi
@@ -25,6 +25,12 @@
 
 		ranges = <0x00000000 0xf0000000 0x10000000>;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <90000000>;
+		};
+
 		core_intc: archs-intc at cpu {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
diff --git a/arch/arc/boot/dts/axc003_idu.dtsi b/arch/arc/boot/dts/axc003_idu.dtsi
index f87ae409c8ed..8955881db794 100644
--- a/arch/arc/boot/dts/axc003_idu.dtsi
+++ b/arch/arc/boot/dts/axc003_idu.dtsi
@@ -25,6 +25,12 @@
 
 		ranges = <0x00000000 0xf0000000 0x10000000>;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <90000000>;
+		};
+
 		core_intc: archs-intc at cpu {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
diff --git a/arch/arc/boot/dts/nsim_700.dts b/arch/arc/boot/dts/nsim_700.dts
index 987921f711c1..5d5e373e0ebc 100644
--- a/arch/arc/boot/dts/nsim_700.dts
+++ b/arch/arc/boot/dts/nsim_700.dts
@@ -32,6 +32,12 @@
 		/* child and parent address space 1:1 mapped */
 		ranges;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <80000000>;
+		};
+
 		core_intc: interrupt-controller {
 			compatible = "snps,arc700-intc";
 			interrupt-controller;
diff --git a/arch/arc/boot/dts/nsim_hs.dts b/arch/arc/boot/dts/nsim_hs.dts
index bd46aec88c6a..cbd08fa38339 100644
--- a/arch/arc/boot/dts/nsim_hs.dts
+++ b/arch/arc/boot/dts/nsim_hs.dts
@@ -38,6 +38,12 @@
 		/* only perip space at end of low mem accessible */
 		ranges = <0x80000000 0x0 0x80000000 0x80000000>;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <80000000>;
+		};
+
 		core_intc: core-interrupt-controller {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
diff --git a/arch/arc/boot/dts/nsim_hs_idu.dts b/arch/arc/boot/dts/nsim_hs_idu.dts
index cc82781727a1..99eabe1a2bf6 100644
--- a/arch/arc/boot/dts/nsim_hs_idu.dts
+++ b/arch/arc/boot/dts/nsim_hs_idu.dts
@@ -29,6 +29,12 @@
 		/* child and parent address space 1:1 mapped */
 		ranges;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <80000000>;
+		};
+
 		core_intc: core-interrupt-controller {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
diff --git a/arch/arc/boot/dts/nsimosci.dts b/arch/arc/boot/dts/nsimosci.dts
index 1c169dc74ad1..bc3161ab8f82 100644
--- a/arch/arc/boot/dts/nsimosci.dts
+++ b/arch/arc/boot/dts/nsimosci.dts
@@ -35,6 +35,12 @@
 		/* child and parent address space 1:1 mapped */
 		ranges;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <20000000>;
+		};
+
 		intc: interrupt-controller {
 			compatible = "snps,arc700-intc";
 			interrupt-controller;
diff --git a/arch/arc/boot/dts/nsimosci_hs.dts b/arch/arc/boot/dts/nsimosci_hs.dts
index 9444956156d9..273dcce2cc66 100644
--- a/arch/arc/boot/dts/nsimosci_hs.dts
+++ b/arch/arc/boot/dts/nsimosci_hs.dts
@@ -35,6 +35,12 @@
 		/* child and parent address space 1:1 mapped */
 		ranges;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <20000000>;
+		};
+
 		core_intc: core-interrupt-controller {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
diff --git a/arch/arc/boot/dts/nsimosci_hs_idu.dts b/arch/arc/boot/dts/nsimosci_hs_idu.dts
index ff11388ee484..8fe60967a4c5 100644
--- a/arch/arc/boot/dts/nsimosci_hs_idu.dts
+++ b/arch/arc/boot/dts/nsimosci_hs_idu.dts
@@ -33,6 +33,12 @@
 		/* child and parent address space 1:1 mapped */
 		ranges;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <5000000>;
+		};
+
 		core_intc: core-interrupt-controller {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
diff --git a/arch/arc/boot/dts/vdk_axc003.dtsi b/arch/arc/boot/dts/vdk_axc003.dtsi
index 035759ee62a5..ad4ee43bd2ac 100644
--- a/arch/arc/boot/dts/vdk_axc003.dtsi
+++ b/arch/arc/boot/dts/vdk_axc003.dtsi
@@ -25,6 +25,12 @@
 
 		ranges = <0x00000000 0xf0000000 0x10000000>;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <50000000>;
+		};
+
 		core_intc: archs-intc at cpu {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
diff --git a/arch/arc/boot/dts/vdk_axc003_idu.dtsi b/arch/arc/boot/dts/vdk_axc003_idu.dtsi
index 90e18f404889..a3cb6263c581 100644
--- a/arch/arc/boot/dts/vdk_axc003_idu.dtsi
+++ b/arch/arc/boot/dts/vdk_axc003_idu.dtsi
@@ -26,6 +26,12 @@
 
 		ranges = <0x00000000 0xf0000000 0x10000000>;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <50000000>;
+		};
+
 		core_intc: archs-intc at cpu {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Tue Mar  8 04:26:05 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 8 Mar 2016 17:56:05 +0530
Subject: [PATCH v2 2/9] ARC: [dts] Introduce Timer bindings
In-Reply-To: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
References: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
Message-ID: <1457439972-20285-3-git-send-email-vgupta@synopsys.com>

ARC Timers have historically been probed directly.
As precursor to start probing Timers thru DT introduce these bindings
Note that to keep series bisectable, these bindings are not yet used in
code.

Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Cc: Rob Herring <robh at kernel.org>
Cc: devicetree at vger.kernel.org
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
Changes v1 -> v2
 - snps,arc-timer[0-1] folded into single snps-arc-timer	[Rob]
 - Node name in DT example fixed:				[Rob]
     "timer1: timer_clksrc {" -> timer at 1 {
 - Introduced 64bit RTC in skeleton_hs.dtsi			[Vineet]

v1:
 - http://lists.infradead.org/pipermail/linux-snps-arc/2016-February/000447.html

Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 .../devicetree/bindings/timer/snps,arc-timer.txt   | 26 ++++++++++++++++++++++
 .../devicetree/bindings/timer/snps,archs-gfrc.txt  | 14 ++++++++++++
 .../devicetree/bindings/timer/snps,archs-rtc.txt   | 14 ++++++++++++
 arch/arc/boot/dts/abilis_tb10x.dtsi                | 14 ++++++++++++
 arch/arc/boot/dts/skeleton.dtsi                    | 14 ++++++++++++
 arch/arc/boot/dts/skeleton_hs.dtsi                 | 20 +++++++++++++++++
 arch/arc/boot/dts/skeleton_hs_idu.dtsi             | 14 ++++++++++++
 7 files changed, 116 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/snps,arc-timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
 create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-rtc.txt

diff --git a/Documentation/devicetree/bindings/timer/snps,arc-timer.txt b/Documentation/devicetree/bindings/timer/snps,arc-timer.txt
new file mode 100644
index 000000000000..9e02be24e805
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/snps,arc-timer.txt
@@ -0,0 +1,26 @@
+Synopsys ARC Local Timer with Interrupt Capabilities
+- Found on all ARC CPUs (ARC700/ARCHS)
+- Can be optionally programmed to interrupt on Limit
+- Two idential copies TIMER0 and TIMER1 exist in ARC cores and historically
+  TIMER0 used as clockevent provider (true for all ARC cores)
+  TIMER1 used for clocksource (mandatory for ARC700, optional for ARC HS)
+
+Required properties:
+
+- compatible : should be "snps,arc-timer"
+- interrupts : single Interrupt going into parent intc
+	       (16 for ARCHS cores, 3 for ARC700 cores)
+- clocks     : phandle to the source clock
+
+Optional properties:
+
+- interrupt-parent : phandle to parent intc
+
+Example:
+
+	timer at 0 {
+		compatible = "snps,arc-timer0";
+		interrupts = <3>;
+		interrupt-parent = <&core_intc>;
+		clocks = <&core_clk>;
+	};
diff --git a/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt b/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
new file mode 100644
index 000000000000..aaab100f54e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
@@ -0,0 +1,14 @@
+Synopsys ARC Free Running 64-bit Global Timer for ARC HS CPUs
+- clocksource provider for SMP SoC
+
+Required properties:
+
+- compatible : should be "snps,archs-gfrc"
+- clocks     : phandle to the source clock
+
+Example:
+
+	timer at 1 {
+		compatible = "snps,archs-gfrc";
+		clocks = <&core_clk>;
+	};
diff --git a/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt b/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt
new file mode 100644
index 000000000000..13f756fa1d6d
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt
@@ -0,0 +1,14 @@
+Synopsys ARC Free Running 64-bit Local Timer for ARC HS CPUs
+- clocksource provider for UP SoC
+
+Required properties:
+
+- compatible : should be "snps,archs-rtc"
+- clocks     : phandle to the source clock
+
+Example:
+
+	timer at 1 {
+		compatible = "snps,arc-rtc";
+		clocks = <&core_clk>;
+	};
diff --git a/arch/arc/boot/dts/abilis_tb10x.dtsi b/arch/arc/boot/dts/abilis_tb10x.dtsi
index cfb5052239a1..eadbe71dfa22 100644
--- a/arch/arc/boot/dts/abilis_tb10x.dtsi
+++ b/arch/arc/boot/dts/abilis_tb10x.dtsi
@@ -35,6 +35,20 @@
 		};
 	};
 
+	/* TIMER0 with interrupt for clockevent */
+	timer at 0 {
+		compatible = "snps,arc-timer";
+		interrupts = <3>;
+		interrupt-parent = <&intc>;
+		clocks = <&cpu_clk>;
+	};
+
+	/* TIMER1 for free running clocksource */
+	timer at 1 {
+		compatible = "snps,arc-timer";
+		clocks = <&cpu_clk>;
+	};
+
 	soc100 {
 		#address-cells	= <1>;
 		#size-cells	= <1>;
diff --git a/arch/arc/boot/dts/skeleton.dtsi b/arch/arc/boot/dts/skeleton.dtsi
index 296d371a335c..f6109c2feba7 100644
--- a/arch/arc/boot/dts/skeleton.dtsi
+++ b/arch/arc/boot/dts/skeleton.dtsi
@@ -30,6 +30,20 @@
 		};
 	};
 
+	/* TIMER0 with interrupt for clockevent */
+	timer at 0 {
+		compatible = "snps,arc-timer";
+		interrupts = <3>;
+		interrupt-parent = <&core_intc>;
+		clocks = <&core_clk>;
+	};
+
+	/* TIMER1 for free running clocksource */
+	timer at 1 {
+		compatible = "snps,arc-timer";
+		clocks = <&core_clk>;
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x80000000 0x10000000>;	/* 256M */
diff --git a/arch/arc/boot/dts/skeleton_hs.dtsi b/arch/arc/boot/dts/skeleton_hs.dtsi
index a53876669030..49caeabca37a 100644
--- a/arch/arc/boot/dts/skeleton_hs.dtsi
+++ b/arch/arc/boot/dts/skeleton_hs.dtsi
@@ -25,6 +25,26 @@
 		};
 	};
 
+	/* TIMER0 with interrupt for clockevent */
+	timer at 0 {
+		compatible = "snps,arc-timer";
+		interrupts = <16>;
+		interrupt-parent = <&core_intc>;
+		clocks = <&core_clk>;
+	};
+
+	/* 64-bit Local RTC: preferred clocksource for UP */
+	timer at 1 {
+		compatible = "snps,archs-timer-rtc";
+		clocks = <&core_clk>;
+	};
+
+	/* TIMER1 for free running clocksource: Fallback if rtc not found */
+	timer at 2 {
+		compatible = "snps,arc-timer";
+		clocks = <&core_clk>;
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x80000000 0x10000000>;	/* 256M */
diff --git a/arch/arc/boot/dts/skeleton_hs_idu.dtsi b/arch/arc/boot/dts/skeleton_hs_idu.dtsi
index 74898d017f7a..7e301ff16200 100644
--- a/arch/arc/boot/dts/skeleton_hs_idu.dtsi
+++ b/arch/arc/boot/dts/skeleton_hs_idu.dtsi
@@ -25,6 +25,20 @@
 		};
 	};
 
+	/* TIMER0 with interrupt for clockevent */
+	timer at 0 {
+		compatible = "snps,arc-timer";
+		interrupts = <16>;
+		interrupt-parent = <&core_intc>;
+		clocks = <&core_clk>;
+	};
+
+	/* 64-bit Global Free Running Counter */
+	timer at 1 {
+		compatible = "snps,archs-timer-gfrc";
+		clocks = <&core_clk>;
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x80000000 0x10000000>;	/* 256M */
-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Tue Mar  8 04:26:06 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 8 Mar 2016 17:56:06 +0530
Subject: [PATCH v2 3/9] ARC: clockevent: switch to cpu notifier for clockevent
 setup
In-Reply-To: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
References: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
Message-ID: <1457439972-20285-4-git-send-email-vgupta@synopsys.com>

From: Noam Camus <noamc at ezchip.com>

ARC Timers so far have been handled as "legacy" w/o explicit description
in DT. This poses challenge for newer platforms wanting to use them.
This series will eventually help move timers over to DT.

This patch does a small change of using a CPU notifier to set clockevent
on non-boot CPUs. So explicit setup is done only on boot CPU (which will
later be done by DT)

Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Signed-off-by: Noam Camus <noamc at ezchip.com>
[vgupta: broken off from a bigger patch]
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
Changes v1 -> v2
 - Rebased on 4.5-rc6 (some changes due to interim changes)
 - Reduced the extraneous header includes
 - Fixed @ret handling in arc_clockevent_setup()
 - Fix snafu in a adapting patch from EZChip tree:
    nps_timer_cpu_nb -> arc_timer_cpu_nb

v1:
 - http://lists.infradead.org/pipermail/linux-snps-arc/2016-February/000454.html

Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/include/asm/irq.h |  1 -
 arch/arc/kernel/smp.c      |  2 --
 arch/arc/kernel/time.c     | 62 ++++++++++++++++++++++++++++++----------------
 3 files changed, 41 insertions(+), 24 deletions(-)

diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index f9c735ede4fc..5c0b5abda67a 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -25,6 +25,5 @@
 #include <asm-generic/irq.h>
 
 extern void arc_init_IRQ(void);
-void arc_local_timer_setup(void);
 
 #endif
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index 96cb0d8887e5..74e7ce4c1508 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -138,8 +138,6 @@ void start_kernel_secondary(void)
 	if (machine_desc->init_per_cpu)
 		machine_desc->init_per_cpu(cpu);
 
-	arc_local_timer_setup();
-
 	local_irq_enable();
 	preempt_disable();
 	cpu_startup_entry(CPUHP_ONLINE);
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index 146da3cbcc99..e97be743d47b 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -29,17 +29,14 @@
  * which however is currently broken
  */
 
-#include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
 #include <linux/init.h>
-#include <linux/timex.h>
-#include <linux/profile.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/cpu.h>
 #include <asm/irq.h>
 #include <asm/arcregs.h>
 #include <asm/clk.h>
@@ -183,6 +180,8 @@ static struct clocksource arc_counter = {
 
 /********** Clock Event Device *********/
 
+static int arc_timer_irq = TIMER0_IRQ;
+
 /*
  * Arm the timer to interrupt after @cycles
  * The distinction for oneshot/periodic is done in arc_event_timer_ack() below
@@ -218,7 +217,6 @@ static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = {
 	.features		= CLOCK_EVT_FEAT_ONESHOT |
 				  CLOCK_EVT_FEAT_PERIODIC,
 	.rating			= 300,
-	.irq			= TIMER0_IRQ,	/* hardwired, no need for resources */
 	.set_next_event		= arc_clkevent_set_next_event,
 	.set_state_periodic	= arc_clkevent_set_periodic,
 };
@@ -244,29 +242,52 @@ static irqreturn_t timer_irq_handler(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static int arc_timer_cpu_notify(struct notifier_block *self,
+				unsigned long action, void *hcpu)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
+
+	evt->cpumask = cpumask_of(smp_processor_id());
+
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		clockevents_config_and_register(evt, arc_get_core_freq(),
+						0, ULONG_MAX);
+		enable_percpu_irq(arc_timer_irq, 0);
+		break;
+	case CPU_DYING:
+		disable_percpu_irq(arc_timer_irq);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block arc_timer_cpu_nb = {
+	.notifier_call = arc_timer_cpu_notify,
+};
+
 /*
- * Setup the local event timer for @cpu
+ * clockevent setup for boot CPU
  */
-void arc_local_timer_setup()
+static void __init arc_clockevent_setup(void)
 {
 	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
-	int cpu = smp_processor_id();
-	int irq = TIMER0_IRQ;
+	int ret;
 
-	evt->cpumask = cpumask_of(cpu);
+	register_cpu_notifier(&arc_timer_cpu_nb);
+
+	evt->cpumask = cpumask_of(smp_processor_id());
 	clockevents_config_and_register(evt, arc_get_core_freq(),
 					0, ARC_TIMER_MAX);
 
-	if (!cpu) {
-		int rc;
-
-		rc = request_percpu_irq(irq, timer_irq_handler,
-					"Timer0 (per-cpu-tick)", evt);
-		if (rc)
-			panic("Percpu IRQ request failed for TIMER\n");
-	}
+	/* Needs apriori irq_set_percpu_devid() done in intc map function */
+	ret = request_percpu_irq(arc_timer_irq, timer_irq_handler,
+				 "Timer0 (per-cpu-tick)", evt);
+	if (ret)
+		pr_err("Unable to register interrupt\n");
 
-	enable_percpu_irq(irq, 0);
+	enable_percpu_irq(arc_timer_irq, 0);
 }
 
 /*
@@ -291,6 +312,5 @@ void __init time_init(void)
 		 */
 		clocksource_register_hz(&arc_counter, arc_get_core_freq());
 
-	/* sets up the periodic event timer */
-	arc_local_timer_setup();
+	arc_clockevent_setup();
 }
-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Tue Mar  8 04:26:08 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 8 Mar 2016 17:56:08 +0530
Subject: [PATCH v2 5/9] ARC: clockevent: DT based probe
In-Reply-To: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
References: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
Message-ID: <1457439972-20285-6-git-send-email-vgupta@synopsys.com>

 - timer frequency is derived from DT (no longer rely on top level
   DT "clock-frequency" probed early and exported by asm/clk.h)

 - TIMER0_IRQ need not be exported across arch code, confided to intc as
   it is property of same

Cc: Noam Camus <noamc at ezchip.com>
Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
Changes v1 -> v2
 - Rebased on 4.5-rc6
 - Fix snafu in a adapting patch from EZChip tree

v1:
 - http://lists.infradead.org/pipermail/linux-snps-arc/2016-February/000449.html

Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/include/asm/irq.h     |  9 --------
 arch/arc/kernel/intc-compact.c |  2 ++
 arch/arc/kernel/time.c         | 49 +++++++++++++++++++++++++++++-------------
 3 files changed, 36 insertions(+), 24 deletions(-)

diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index 5c0b5abda67a..a6ac89dc228f 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -12,15 +12,6 @@
 #define NR_CPU_IRQS	32  /* number of interrupt lines of ARC770 CPU */
 #define NR_IRQS		128 /* allow some CPU external IRQ handling */
 
-/* Platform Independent IRQs */
-#ifdef CONFIG_ISA_ARCOMPACT
-#define TIMER0_IRQ      3
-#define TIMER1_IRQ      4
-#else
-#define TIMER0_IRQ      16
-#define TIMER1_IRQ      17
-#endif
-
 #include <linux/interrupt.h>
 #include <asm-generic/irq.h>
 
diff --git a/arch/arc/kernel/intc-compact.c b/arch/arc/kernel/intc-compact.c
index 4195eedeb6d1..d31bc647146d 100644
--- a/arch/arc/kernel/intc-compact.c
+++ b/arch/arc/kernel/intc-compact.c
@@ -14,6 +14,8 @@
 #include <linux/irqchip.h>
 #include <asm/irq.h>
 
+#define TIMER0_IRQ	3	/* Fixed by ISA */
+
 /*
  * Early Hardware specific Interrupt setup
  * -Platform independent, needed for each CPU (not foldable into init_IRQ)
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index 848353a27ac8..693545df9827 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -30,19 +30,15 @@
  */
 
 #include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/cpu.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 #include <asm/irq.h>
 #include <asm/arcregs.h>
-#include <asm/clk.h>
-#include <asm/mach_desc.h>
 
 #include <asm/mcip.h>
 
@@ -59,6 +55,24 @@
 
 #define ARC_TIMER_MAX	0xFFFFFFFF
 
+static unsigned long arc_timer_freq;
+
+static void noinline arc_get_timer_clk(struct device_node *node)
+{
+	struct clk *clk;
+	int ret;
+
+	clk = of_clk_get(node, 0);
+	if (IS_ERR(clk))
+		panic("Can't get timer clock");
+
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		pr_err("Couldn't enable parent clock\n");
+
+	arc_timer_freq = clk_get_rate(clk);
+}
+
 /********** Clock Source Device *********/
 
 #ifdef CONFIG_ARC_HAS_GFRC
@@ -182,7 +196,7 @@ static struct clocksource arc_counter = {
 
 /********** Clock Event Device *********/
 
-static int arc_timer_irq = TIMER0_IRQ;
+static int arc_timer_irq;
 
 /*
  * Arm the timer to interrupt after @cycles
@@ -210,7 +224,7 @@ static int arc_clkevent_set_periodic(struct clock_event_device *dev)
 	 * At X Hz, 1 sec = 1000ms -> X cycles;
 	 *		      10ms -> X / 100 cycles
 	 */
-	arc_timer_event_setup(arc_get_core_freq() / HZ);
+	arc_timer_event_setup(arc_timer_freq / HZ);
 	return 0;
 }
 
@@ -253,7 +267,7 @@ static int arc_timer_cpu_notify(struct notifier_block *self,
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_STARTING:
-		clockevents_config_and_register(evt, arc_get_core_freq(),
+		clockevents_config_and_register(evt, arc_timer_freq,
 						0, ULONG_MAX);
 		enable_percpu_irq(arc_timer_irq, 0);
 		break;
@@ -272,15 +286,22 @@ static struct notifier_block arc_timer_cpu_nb = {
 /*
  * clockevent setup for boot CPU
  */
-static void __init arc_clockevent_setup(void)
+static void __init arc_clockevent_setup(struct device_node *node)
 {
 	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
 	int ret;
 
 	register_cpu_notifier(&arc_timer_cpu_nb);
 
+	arc_timer_irq = irq_of_parse_and_map(node, 0);
+	if (arc_timer_irq <= 0)
+		panic("Can't parse IRQ");
+
+	arc_get_timer_clk(node);
+
+	evt->irq = arc_timer_irq;
 	evt->cpumask = cpumask_of(smp_processor_id());
-	clockevents_config_and_register(evt, arc_get_core_freq(),
+	clockevents_config_and_register(evt, arc_timer_freq,
 					0, ARC_TIMER_MAX);
 
 	/* Needs apriori irq_set_percpu_devid() done in intc map function */
@@ -291,6 +312,7 @@ static void __init arc_clockevent_setup(void)
 
 	enable_percpu_irq(arc_timer_irq, 0);
 }
+CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_clockevent_setup);
 
 /*
  * Called from start_kernel() - boot CPU only
@@ -299,7 +321,6 @@ static void __init arc_clockevent_setup(void)
  * -Also sets up any global state needed for timer subsystem:
  *    - for "counting" timer, registers a clocksource, usable across CPUs
  *      (provided that underlying counter h/w is synchronized across cores)
- *    - for "event" timer, sets up TIMER0 IRQ (as that is platform agnostic)
  */
 void __init time_init(void)
 {
@@ -315,7 +336,5 @@ void __init time_init(void)
 		 * CLK upto 4.29 GHz can be safely represented in 32 bits
 		 * because Max 32 bit number is 4,294,967,295
 		 */
-		clocksource_register_hz(&arc_counter, arc_get_core_freq());
-
-	arc_clockevent_setup();
+		clocksource_register_hz(&arc_counter, arc_timer_freq);
 }
-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Tue Mar  8 04:26:09 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 8 Mar 2016 17:56:09 +0530
Subject: [PATCH v2 6/9] ARC: clocksource: DT based probe
In-Reply-To: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
References: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
Message-ID: <1457439972-20285-7-git-send-email-vgupta@synopsys.com>

- Remove explicit clocksource setup and let it be done by OF framework
  by defining CLOCKSOURCE_OF_DECLARE() for various timers

- This allows multiple clocksources to be potentially registered
  simultaneouly: previously we could only do one - as all of them had
  same arc_counter_setup() routine for registration

- Setup routines also ensure that the underlying timer actually exists.

- Remove some of the panic() calls if underlying timer is NOT detected as
  fallback clocksource might still be available
  1. If GRFC doesn't exist, jiffies clocksource gets registered anyways
  2. if RTC doesn't exist, TIMER1 can take over (as it is always
     present)

Cc: Rob Herring <robh at kernel.org>
Cc: Noam Camus <noamc at ezchip.com>
Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
Changes v1 -> v2
 - Introduce arc_of_timer_init() to handle two instances of     [Rob]
   snps,arc-timer one for clockevent, other for clksrc

v1:
 - http://lists.infradead.org/pipermail/linux-snps-arc/2016-February/000450.html

Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/kernel/mcip.c  |   4 +-
 arch/arc/kernel/setup.c |   3 --
 arch/arc/kernel/time.c  | 124 +++++++++++++++++++++++++++---------------------
 3 files changed, 72 insertions(+), 59 deletions(-)

diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index c41c364b926c..262d9c3771e6 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -116,15 +116,13 @@ static void mcip_probe_n_setup(void)
 		IS_AVAIL1(mp.dbg, "DEBUG "),
 		IS_AVAIL1(mp.gfrc, "GFRC"));
 
+	cpuinfo_arc700[0].extn.gfrc = mp.gfrc;
 	idu_detected = mp.idu;
 
 	if (mp.dbg) {
 		__mcip_cmd_data(CMD_DEBUG_SET_SELECT, 0, 0xf);
 		__mcip_cmd_data(CMD_DEBUG_SET_MASK, 0xf, 0xf);
 	}
-
-	if (IS_ENABLED(CONFIG_ARC_HAS_GFRC) && !mp.gfrc)
-		panic("kernel trying to use non-existent GFRC\n");
 }
 
 struct plat_smp_ops plat_smp_ops = {
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 2dad49c71c09..b2921a3bd924 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -323,9 +323,6 @@ static void arc_chk_core_config(void)
 	if (!cpu->extn.timer1)
 		panic("Timer1 is not present!\n");
 
-	if (IS_ENABLED(CONFIG_ARC_HAS_RTC) && !cpu->extn.rtc)
-		panic("RTC is not present\n");
-
 #ifdef CONFIG_ARC_HAS_DCCM
 	/*
 	 * DCCM can be arbit placed in hardware.
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index 693545df9827..72f023440739 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -77,12 +77,7 @@ static void noinline arc_get_timer_clk(struct device_node *node)
 
 #ifdef CONFIG_ARC_HAS_GFRC
 
-static int arc_counter_setup(void)
-{
-	return 1;
-}
-
-static cycle_t arc_counter_read(struct clocksource *cs)
+static cycle_t arc_read_gfrc(struct clocksource *cs)
 {
 	unsigned long flags;
 	union {
@@ -107,15 +102,28 @@ static cycle_t arc_counter_read(struct clocksource *cs)
 	return stamp.full;
 }
 
-static struct clocksource arc_counter = {
+static struct clocksource arc_counter_gfrc = {
 	.name   = "ARConnect GFRC",
 	.rating = 400,
-	.read   = arc_counter_read,
+	.read   = arc_read_gfrc,
 	.mask   = CLOCKSOURCE_MASK(64),
 	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-#else
+static void __init arc_cs_setup_gfrc(struct device_node *node)
+{
+	int exists = cpuinfo_arc700[0].extn.gfrc;
+
+	if (WARN(!exists, "Global-64-bit-Ctr clocksource not detected"))
+		return;
+
+	arc_get_timer_clk(node);
+
+	clocksource_register_hz(&arc_counter_gfrc, arc_timer_freq);
+}
+CLOCKSOURCE_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc);
+
+#endif
 
 #ifdef CONFIG_ARC_HAS_RTC
 
@@ -123,15 +131,7 @@ static struct clocksource arc_counter = {
 #define AUX_RTC_LOW	0x104
 #define AUX_RTC_HIGH	0x105
 
-int arc_counter_setup(void)
-{
-	write_aux_reg(AUX_RTC_CTRL, 1);
-
-	/* Not usable in SMP */
-	return !IS_ENABLED(CONFIG_SMP);
-}
-
-static cycle_t arc_counter_read(struct clocksource *cs)
+static cycle_t arc_read_rtc(struct clocksource *cs)
 {
 	unsigned long status;
 	union {
@@ -155,44 +155,66 @@ static cycle_t arc_counter_read(struct clocksource *cs)
 	return stamp.full;
 }
 
-static struct clocksource arc_counter = {
+static struct clocksource arc_counter_rtc = {
 	.name   = "ARCv2 RTC",
 	.rating = 350,
-	.read   = arc_counter_read,
+	.read   = arc_read_rtc,
 	.mask   = CLOCKSOURCE_MASK(64),
 	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-#else /* !CONFIG_ARC_HAS_RTC */
-
-/*
- * set 32bit TIMER1 to keep counting monotonically and wraparound
- */
-int arc_counter_setup(void)
+static void __init arc_cs_setup_rtc(struct device_node *node)
 {
-	write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMER_MAX);
-	write_aux_reg(ARC_REG_TIMER1_CNT, 0);
-	write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH);
+	int exists = cpuinfo_arc700[smp_processor_id()].extn.rtc;
+
+	if (WARN(!exists, "Local-64-bit-Ctr clocksource not detected"))
+		return;
+
+	/* Local to CPU hence not usable in SMP */
+	if (WARN(IS_ENABLED(CONFIG_SMP), "Local-64-bit-Ctr not usable in SMP"))
+		return;
+
+	arc_get_timer_clk(node);
 
-	/* Not usable in SMP */
-	return !IS_ENABLED(CONFIG_SMP);
+	write_aux_reg(AUX_RTC_CTRL, 1);
+
+	clocksource_register_hz(&arc_counter_rtc, arc_timer_freq);
 }
+CLOCKSOURCE_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc);
+
+#endif
+
+/*
+ * 32bit TIMER1 to keep counting monotonically and wraparound
+ */
 
-static cycle_t arc_counter_read(struct clocksource *cs)
+static cycle_t arc_read_timer1(struct clocksource *cs)
 {
 	return (cycle_t) read_aux_reg(ARC_REG_TIMER1_CNT);
 }
 
-static struct clocksource arc_counter = {
+static struct clocksource arc_counter_timer1 = {
 	.name   = "ARC Timer1",
 	.rating = 300,
-	.read   = arc_counter_read,
+	.read   = arc_read_timer1,
 	.mask   = CLOCKSOURCE_MASK(32),
 	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-#endif
-#endif
+static void __init arc_cs_setup_timer1(struct device_node *node)
+{
+	/* Local to CPU hence not usable in SMP */
+	if (IS_ENABLED(CONFIG_SMP))
+		return;
+
+	arc_get_timer_clk(node);
+
+	write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMER_MAX);
+	write_aux_reg(ARC_REG_TIMER1_CNT, 0);
+	write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH);
+
+	clocksource_register_hz(&arc_counter_timer1, arc_timer_freq);
+}
 
 /********** Clock Event Device *********/
 
@@ -312,29 +334,25 @@ static void __init arc_clockevent_setup(struct device_node *node)
 
 	enable_percpu_irq(arc_timer_irq, 0);
 }
-CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_clockevent_setup);
+
+static void __init arc_of_timer_init(struct device_node *np)
+{
+	static int init_count = 0;
+
+	if (!init_count) {
+		init_count = 1;
+		arc_clockevent_setup(np);
+	} else {
+		arc_cs_setup_timer1(np);
+	}
+}
+CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_of_timer_init);
 
 /*
  * Called from start_kernel() - boot CPU only
- *
- * -Sets up h/w timers as applicable on boot cpu
- * -Also sets up any global state needed for timer subsystem:
- *    - for "counting" timer, registers a clocksource, usable across CPUs
- *      (provided that underlying counter h/w is synchronized across cores)
  */
 void __init time_init(void)
 {
 	of_clk_init(NULL);
 	clocksource_probe();
-
-	/*
-	 * sets up the timekeeping free-flowing counter which also returns
-	 * whether the counter is usable as clocksource
-	 */
-	if (arc_counter_setup())
-		/*
-		 * CLK upto 4.29 GHz can be safely represented in 32 bits
-		 * because Max 32 bit number is 4,294,967,295
-		 */
-		clocksource_register_hz(&arc_counter, arc_timer_freq);
 }
-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Tue Mar  8 04:26:10 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 8 Mar 2016 17:56:10 +0530
Subject: [PATCH v2 7/9] ARC: use fixed frequencies in arc_set_early_base_baud()
In-Reply-To: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
References: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
Message-ID: <1457439972-20285-8-git-send-email-vgupta@synopsys.com>

From: Alexey Brodkin <abrodkin at synopsys.com>

UARTs usually have fixed clock so we're switching to use of
constant values instead of something derived from core clock
frequency.

Among other things this will allow us to get rid of
arc_{get|set}_core_freq() and switch to generic clock
framework later on.

Cc: Christian Ruppert <christian.ruppert at alitech.com>
Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
Changes v1 -> v2
 - Base baud TB10x needs to be 166.66 not 166.67	[Christian]

v1:
 - http://lists.infradead.org/pipermail/linux-snps-arc/2016-February/000453.html

Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/kernel/devtree.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
index 7e844fd8213f..fecbc96df828 100644
--- a/arch/arc/kernel/devtree.c
+++ b/arch/arc/kernel/devtree.c
@@ -28,14 +28,12 @@ unsigned int __init arc_early_base_baud(void)
 
 static void __init arc_set_early_base_baud(unsigned long dt_root)
 {
-	unsigned int core_clk = arc_get_core_freq();
-
 	if (of_flat_dt_is_compatible(dt_root, "abilis,arc-tb10x"))
-		arc_base_baud = core_clk/3;
+		arc_base_baud = 166666666;	/* Fixed 166.6MHz clk (TB10x) */
 	else if (of_flat_dt_is_compatible(dt_root, "snps,arc-sdp"))
 		arc_base_baud = 33333333;	/* Fixed 33MHz clk (AXS10x) */
 	else
-		arc_base_baud = core_clk;
+		arc_base_baud = 50000000;	/* Fixed default 50MHz */
 }
 #else
 #define arc_set_early_base_baud(dt_root)
-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Tue Mar  8 04:26:07 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 8 Mar 2016 17:56:07 +0530
Subject: [PATCH v2 4/9] ARC: clockevent: Prepare for DT based probe
In-Reply-To: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
References: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
Message-ID: <1457439972-20285-5-git-send-email-vgupta@synopsys.com>

From: Noam Camus <noamc at ezchip.com>

 - call clocksource_probe()
 - This in turns needs of_clk_init() to be called earlier

Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Signed-off-by: Noam Camus <noamc at ezchip.com>
[vgupta: broken off from a bigger patch]
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
Changes v1 -> v2
 - Rebased on 4.5-rc6
 - Removed now not relevant header from setup.c

v1:
 - http://lists.infradead.org/pipermail/linux-snps-arc/2016-February/000448.html

Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/Kconfig        | 3 ++-
 arch/arc/kernel/setup.c | 2 --
 arch/arc/kernel/time.c  | 5 +++++
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 8a188bc1786a..74689dfde0ae 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -10,8 +10,9 @@ config ARC
 	def_bool y
 	select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC
 	select BUILDTIME_EXTABLE_SORT
-	select COMMON_CLK
+	select CLKSRC_OF
 	select CLONE_BACKWARDS
+	select COMMON_CLK
 	select GENERIC_ATOMIC64
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_FIND_FIRST_BIT
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index cdc821df1809..2dad49c71c09 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -13,7 +13,6 @@
 #include <linux/console.h>
 #include <linux/module.h>
 #include <linux/cpu.h>
-#include <linux/clk-provider.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 #include <linux/cache.h>
@@ -459,7 +458,6 @@ void __init setup_arch(char **cmdline_p)
 
 static int __init customize_machine(void)
 {
-	of_clk_init(NULL);
 	/*
 	 * Traverses flattened DeviceTree - registering platform devices
 	 * (if any) complete with their resources
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index e97be743d47b..848353a27ac8 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -34,6 +34,8 @@
 #include <linux/kernel.h>
 #include <linux/time.h>
 #include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/cpu.h>
@@ -301,6 +303,9 @@ static void __init arc_clockevent_setup(void)
  */
 void __init time_init(void)
 {
+	of_clk_init(NULL);
+	clocksource_probe();
+
 	/*
 	 * sets up the timekeeping free-flowing counter which also returns
 	 * whether the counter is usable as clocksource
-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Tue Mar  8 04:26:03 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 8 Mar 2016 17:56:03 +0530
Subject: [PATCH v2 0/9] ARC clockevent/clocksource modernization
Message-ID: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>

Hi,

This mini-series came out as a result of discussions during EZChip platform
code review.

This switches ARC timers to DT based probe and removes the homebrew clk API
we had before.

@Rob could you please take a look at the DT bindings.
@Daniel any comments would be appreciated !

Thx,
-Vineet

changes since v1:
- Primarily timer0/timer1 folded into one (more details in respective patches)

[v1]
http://lists.infradead.org/pipermail/linux-snps-arc/2016-February/000445.html

Alexey Brodkin (3):
  ARC: use fixed frequencies in arc_set_early_base_baud()
  ARC: [plat-axs] Don't use arc_{get|set}_core_freq() for manipulating
    core clk
  ARC: RIP arc_{get|set}_core_freq() clk API

Noam Camus (2):
  ARC: clockevent: switch to cpu notifier for clockevent setup
  ARC: clockevent: Prepare for DT based probe

Vineet Gupta (4):
  ARC: [dts] Add clk feeding into timers to DTs
  ARC: [dts] Introduce Timer bindings
  ARC: clockevent: DT based probe
  ARC: clocksource: DT based probe

 .../devicetree/bindings/timer/snps,arc-timer.txt   |  26 +++
 .../devicetree/bindings/timer/snps,archs-gfrc.txt  |  14 ++
 .../devicetree/bindings/timer/snps,archs-rtc.txt   |  14 ++
 arch/arc/Kconfig                                   |   3 +-
 arch/arc/boot/dts/abilis_tb10x.dtsi                |  14 ++
 arch/arc/boot/dts/axc001.dtsi                      |   6 +
 arch/arc/boot/dts/axc003.dtsi                      |   6 +
 arch/arc/boot/dts/axc003_idu.dtsi                  |   6 +
 arch/arc/boot/dts/nsim_700.dts                     |   6 +
 arch/arc/boot/dts/nsim_hs.dts                      |   6 +
 arch/arc/boot/dts/nsim_hs_idu.dts                  |   6 +
 arch/arc/boot/dts/nsimosci.dts                     |   6 +
 arch/arc/boot/dts/nsimosci_hs.dts                  |   6 +
 arch/arc/boot/dts/nsimosci_hs_idu.dts              |   6 +
 arch/arc/boot/dts/skeleton.dtsi                    |  14 ++
 arch/arc/boot/dts/skeleton_hs.dtsi                 |  20 ++
 arch/arc/boot/dts/skeleton_hs_idu.dtsi             |  14 ++
 arch/arc/boot/dts/vdk_axc003.dtsi                  |   6 +
 arch/arc/boot/dts/vdk_axc003_idu.dtsi              |   6 +
 arch/arc/include/asm/clk.h                         |  22 --
 arch/arc/include/asm/irq.h                         |  10 -
 arch/arc/kernel/Makefile                           |   2 +-
 arch/arc/kernel/clk.c                              |  21 --
 arch/arc/kernel/devtree.c                          |  13 +-
 arch/arc/kernel/intc-compact.c                     |   2 +
 arch/arc/kernel/mcip.c                             |   4 +-
 arch/arc/kernel/setup.c                            |  17 +-
 arch/arc/kernel/smp.c                              |   2 -
 arch/arc/kernel/time.c                             | 224 +++++++++++++--------
 arch/arc/plat-axs10x/axs10x.c                      |  27 ++-
 30 files changed, 361 insertions(+), 168 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/timer/snps,arc-timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
 create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-rtc.txt
 delete mode 100644 arch/arc/include/asm/clk.h
 delete mode 100644 arch/arc/kernel/clk.c

-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Tue Mar  8 04:26:12 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 8 Mar 2016 17:56:12 +0530
Subject: [PATCH v2 9/9] ARC: RIP arc_{get|set}_core_freq() clk API
In-Reply-To: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
References: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
Message-ID: <1457439972-20285-10-git-send-email-vgupta@synopsys.com>

From: Alexey Brodkin <abrodkin at synopsys.com>

There are no more users of this - so RIP!

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
[vgupta: update changelog]
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>

Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/include/asm/clk.h | 22 ----------------------
 arch/arc/kernel/Makefile   |  2 +-
 arch/arc/kernel/clk.c      | 21 ---------------------
 arch/arc/kernel/devtree.c  |  7 -------
 4 files changed, 1 insertion(+), 51 deletions(-)
 delete mode 100644 arch/arc/include/asm/clk.h
 delete mode 100644 arch/arc/kernel/clk.c

diff --git a/arch/arc/include/asm/clk.h b/arch/arc/include/asm/clk.h
deleted file mode 100644
index bf9d29f5bd53..000000000000
--- a/arch/arc/include/asm/clk.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
- *
- * 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 _ASM_ARC_CLK_H
-#define _ASM_ARC_CLK_H
-
-/* Although we can't really hide core_freq, the accessor is still better way */
-extern unsigned long core_freq;
-
-static inline unsigned long arc_get_core_freq(void)
-{
-	return core_freq;
-}
-
-extern int arc_set_core_freq(unsigned long);
-
-#endif
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index e7f3625a19b5..4f16967a0871 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -9,7 +9,7 @@
 CFLAGS_ptrace.o		+= -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
 obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o process.o devtree.o
-obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o clk.o
+obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o
 obj-$(CONFIG_ISA_ARCOMPACT)		+= entry-compact.o intc-compact.o
 obj-$(CONFIG_ISA_ARCV2)			+= entry-arcv2.o intc-arcv2.o
 
diff --git a/arch/arc/kernel/clk.c b/arch/arc/kernel/clk.c
deleted file mode 100644
index 10c7b0b5a079..000000000000
--- a/arch/arc/kernel/clk.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
- *
- * 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 <asm/clk.h>
-
-unsigned long core_freq = 80000000;
-
-/*
- * As of now we default to device-tree provided clock
- * In future we can determine this in early boot
- */
-int arc_set_core_freq(unsigned long freq)
-{
-	core_freq = freq;
-	return 0;
-}
diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
index fecbc96df828..f1e07c2344f8 100644
--- a/arch/arc/kernel/devtree.c
+++ b/arch/arc/kernel/devtree.c
@@ -14,7 +14,6 @@
 #include <linux/memblock.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
-#include <asm/clk.h>
 #include <asm/mach_desc.h>
 
 #ifdef CONFIG_SERIAL_EARLYCON
@@ -63,8 +62,6 @@ const struct machine_desc * __init setup_machine_fdt(void *dt)
 {
 	const struct machine_desc *mdesc;
 	unsigned long dt_root;
-	const void *clk;
-	int len;
 
 	if (!early_init_dt_scan(dt))
 		return NULL;
@@ -74,10 +71,6 @@ const struct machine_desc * __init setup_machine_fdt(void *dt)
 		machine_halt();
 
 	dt_root = of_get_flat_dt_root();
-	clk = of_get_flat_dt_prop(dt_root, "clock-frequency", &len);
-	if (clk)
-		arc_set_core_freq(of_read_ulong(clk, len/4));
-
 	arc_set_early_base_baud(dt_root);
 
 	return mdesc;
-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Tue Mar  8 04:26:11 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 8 Mar 2016 17:56:11 +0530
Subject: [PATCH v2 8/9] ARC: [plat-axs] Don't use arc_{get|set}_core_freq()
 for manipulating core clk
In-Reply-To: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
References: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
Message-ID: <1457439972-20285-9-git-send-email-vgupta@synopsys.com>

From: Alexey Brodkin <abrodkin at synopsys.com>

For AXS103, certain bitfile configurations may not work with stock
"clock-frequency" specified in DT. Instead of duplicating the DT files, we
fixup the DT in-place.

This used to be done differently - as in top level "clock-frequency" was
read very early from FDT and exported using arc_{get|set}_core_freq()
also used in setting up clockevent/clocksource timers

This homebrew clk API served well for legacy timer probe (non DT)

However TIMERS are now probed from DT and use "core_clk" defined in DT,
and thus can no longer use the top level "clock-frequency".
This change reduces the number of users of ARC clk hack and paves way
for removal.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
[vgupta: broken out of from bigger patch]
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>

Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/kernel/setup.c       | 12 +++++++-----
 arch/arc/plat-axs10x/axs10x.c | 27 +++++++++++++++++++++------
 2 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index b2921a3bd924..6fff28be695d 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -23,7 +23,6 @@
 #include <asm/page.h>
 #include <asm/irq.h>
 #include <asm/unwind.h>
-#include <asm/clk.h>
 #include <asm/mach_desc.h>
 #include <asm/smp.h>
 
@@ -229,10 +228,6 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
 	if (tbl->info.id == 0)
 		n += scnprintf(buf + n, len - n, "UNKNOWN ARC Processor\n");
 
-	n += scnprintf(buf + n, len - n, "CPU speed\t: %u.%02u Mhz\n",
-		       (unsigned int)(arc_get_core_freq() / 1000000),
-		       (unsigned int)(arc_get_core_freq() / 10000) % 100);
-
 	n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ",
 		       IS_AVAIL1(cpu->extn.timer0, "Timer0 "),
 		       IS_AVAIL1(cpu->extn.timer1, "Timer1 "),
@@ -487,6 +482,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 {
 	char *str;
 	int cpu_id = ptr_to_cpu(v);
+	struct device_node *pll = of_find_node_by_name(NULL, "core_clk");
+	u32 freq;
+
+	of_property_read_u32(pll, "clock-frequency", &freq);
 
 	if (!cpu_online(cpu_id)) {
 		seq_printf(m, "processor [%d]\t: Offline\n", cpu_id);
@@ -498,6 +497,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 		goto done;
 
 	seq_printf(m, arc_cpu_mumbojumbo(cpu_id, str, PAGE_SIZE));
+	seq_printf(m, "CPU speed\t: %u.%02u Mhz\n",
+		   (unsigned int)(freq / 1000000),
+		   (unsigned int)(freq / 10000) % 100);
 
 	seq_printf(m, "Bogo MIPS\t: %lu.%02lu\n",
 		   loops_per_jiffy / (500000 / HZ),
diff --git a/arch/arc/plat-axs10x/axs10x.c b/arch/arc/plat-axs10x/axs10x.c
index 1b0f0f458a2b..9701c93f315d 100644
--- a/arch/arc/plat-axs10x/axs10x.c
+++ b/arch/arc/plat-axs10x/axs10x.c
@@ -14,10 +14,11 @@
  *
  */
 
+#include <linux/of_fdt.h>
 #include <linux/of_platform.h>
+#include <linux/libfdt.h>
 
 #include <asm/asm-offsets.h>
-#include <asm/clk.h>
 #include <asm/io.h>
 #include <asm/mach_desc.h>
 #include <asm/mcip.h>
@@ -389,6 +390,13 @@ axs103_set_freq(unsigned int id, unsigned int fd, unsigned int od)
 
 static void __init axs103_early_init(void)
 {
+	int offset = fdt_path_offset(initial_boot_params, "/cpu_card/core_clk");
+	const struct fdt_property *prop = fdt_get_property(initial_boot_params,
+							   offset,
+							   "clock-frequency",
+							   NULL);
+	u32 freq = be32_to_cpu(*(u32*)(prop->data)) / 1000000, orig = freq;
+
 	/*
 	 * AXS103 configurations for SMP/QUAD configurations share device tree
 	 * which defaults to 90 MHz. However recent failures of Quad config
@@ -401,12 +409,12 @@ static void __init axs103_early_init(void)
 #ifdef CONFIG_ARC_MCIP
 	unsigned int num_cores = (read_aux_reg(ARC_REG_MCIP_BCR) >> 16) & 0x3F;
 	if (num_cores > 2)
-		arc_set_core_freq(50 * 1000000);
+		freq = 50;
 	else if (num_cores == 2)
-		arc_set_core_freq(75 * 1000000);
+		freq = 75;
 #endif
 
-	switch (arc_get_core_freq()/1000000) {
+	switch (freq) {
 	case 33:
 		axs103_set_freq(1, 1, 1);
 		break;
@@ -431,11 +439,18 @@ static void __init axs103_early_init(void)
 		 * DT "clock-frequency" might not match with board value.
 		 * Hence update it to match the board value.
 		 */
-		arc_set_core_freq(axs103_get_freq() * 1000000);
+		freq = axs103_get_freq();
 		break;
 	}
 
-	pr_info("Freq is %dMHz\n", axs103_get_freq());
+	pr_info("Freq is %dMHz\n", freq);
+
+	/* Patching .dtb in-place with new core clock value */
+	if (freq != orig ) {
+		freq = cpu_to_be32(freq * 1000000);
+		fdt_setprop_inplace(initial_boot_params, offset,
+				    "clock-frequency", &freq, sizeof(freq));
+	}
 
 	/* Memory maps already config in pre-bootloader */
 
-- 
2.5.0



From christian.ruppert at alitech.com  Tue Mar  8 05:56:29 2016
From: christian.ruppert at alitech.com (christian.ruppert at alitech.com)
Date: Tue, 8 Mar 2016 14:56:29 +0100
Subject: [PATCH v2 7/9] ARC: use fixed frequencies in
 arc_set_early_base_baud()
In-Reply-To: <1457439972-20285-8-git-send-email-vgupta@synopsys.com>
References: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
 <1457439972-20285-8-git-send-email-vgupta@synopsys.com>
Message-ID: <OF2E92DD14.F9BD34D1-ONC1257F70.004C6256-C1257F70.004C737A@alitech.com>

Vineet Gupta <Vineet.Gupta1 at synopsys.com> wrote on 08.03.2016 13:26:10:
> From: Alexey Brodkin <abrodkin at synopsys.com>
> 
> UARTs usually have fixed clock so we're switching to use of
> constant values instead of something derived from core clock
> frequency.
> 
> Among other things this will allow us to get rid of
> arc_{get|set}_core_freq() and switch to generic clock
> framework later on.
> 
> Cc: Christian Ruppert <christian.ruppert at alitech.com>
> Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
> Signed-off-by: Vineet Gupta <vgupta at synopsys.com>

Acked-by: Christian Ruppert <christian.ruppert at alitech.com>

> ---
> Changes v1 -> v2
>  - Base baud TB10x needs to be 166.66 not 166.67   [Christian]
> 
> v1:
>  - http://lists.infradead.org/pipermail/linux-snps-arc/2016-
> February/000453.html
> 
> Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
> ---
>  arch/arc/kernel/devtree.c | 6 ++----
>  1 file changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
> index 7e844fd8213f..fecbc96df828 100644
> --- a/arch/arc/kernel/devtree.c
> +++ b/arch/arc/kernel/devtree.c
> @@ -28,14 +28,12 @@ unsigned int __init arc_early_base_baud(void)
> 
>  static void __init arc_set_early_base_baud(unsigned long dt_root)
>  {
> -   unsigned int core_clk = arc_get_core_freq();
> -
>     if (of_flat_dt_is_compatible(dt_root, "abilis,arc-tb10x"))
> -      arc_base_baud = core_clk/3;
> +      arc_base_baud = 166666666;   /* Fixed 166.6MHz clk (TB10x) */
>     else if (of_flat_dt_is_compatible(dt_root, "snps,arc-sdp"))
>        arc_base_baud = 33333333;   /* Fixed 33MHz clk (AXS10x) */
>     else
> -      arc_base_baud = core_clk;
> +      arc_base_baud = 50000000;   /* Fixed default 50MHz */
>  }
>  #else
>  #define arc_set_early_base_baud(dt_root)
> -- 
> 2.5.0
> 




From Vineet.Gupta1 at synopsys.com  Tue Mar  8 06:30:57 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 8 Mar 2016 20:00:57 +0530
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
Message-ID: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>

We observed livelocks on ARC SMP setup when running hackbench with SLUB.
This hardware configuration lacks atomic instructions (LLOCK/SCOND) thus
kernel resorts to a central @smp_bitops_lock to protect any R-M-W ops
suh as test_and_set_bit()

The spinlock itself is implemented using Atomic [EX]change instruction
which is always available.

The race happened when both cores tried to slab_lock() the same page.

   c1		    c0
-----------	-----------
slab_lock
		slab_lock
slab_unlock
		Not observing the unlock

This in turn happened because slab_unlock() doesn't serialize properly
(doesn't use atomic clear) with a concurrent running
slab_lock()->test_and_set_bit()

Cc: Christoph Lameter <cl at linux.com>
Cc: Pekka Enberg <penberg at kernel.org>
Cc: David Rientjes <rientjes at google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim at lge.com>
Cc: Andrew Morton <akpm at linux-foundation.org>
Cc: Noam Camus <noamc at ezchip.com>
Cc: <stable at vger.kernel.org>
Cc: <linux-mm at kvack.org>
Cc: <linux-kernel at vger.kernel.org>
Cc: <linux-snps-arc at lists.infradead.org>
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 mm/slub.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/slub.c b/mm/slub.c
index d8fbd4a6ed59..b7d345a508dc 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -345,7 +345,7 @@ static __always_inline void slab_lock(struct page *page)
 static __always_inline void slab_unlock(struct page *page)
 {
 	VM_BUG_ON_PAGE(PageTail(page), page);
-	__bit_spin_unlock(PG_locked, &page->flags);
+	bit_spin_unlock(PG_locked, &page->flags);
 }
 
 static inline void set_page_slub_counters(struct page *page, unsigned long counters_new)
-- 
2.5.0



From cl at linux.com  Tue Mar  8 07:00:57 2016
From: cl at linux.com (Christoph Lameter)
Date: Tue, 8 Mar 2016 09:00:57 -0600 (CST)
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
Message-ID: <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>

On Tue, 8 Mar 2016, Vineet Gupta wrote:

> This in turn happened because slab_unlock() doesn't serialize properly
> (doesn't use atomic clear) with a concurrent running
> slab_lock()->test_and_set_bit()

This is intentional because of the increased latency of atomic
instructions. Why would the unlock need to be atomic? This patch will
cause regressions.

Guess this is an architecture specific issue of modified
cachelines not becoming visible to other processors?



From vbabka at suse.cz  Tue Mar  8 07:32:29 2016
From: vbabka at suse.cz (Vlastimil Babka)
Date: Tue, 8 Mar 2016 16:32:29 +0100
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
Message-ID: <56DEF08D.607@suse.cz>

On 03/08/2016 03:30 PM, Vineet Gupta wrote:
> We observed livelocks on ARC SMP setup when running hackbench with SLUB.
> This hardware configuration lacks atomic instructions (LLOCK/SCOND) thus
> kernel resorts to a central @smp_bitops_lock to protect any R-M-W ops
> suh as test_and_set_bit()

Sounds like this architecture should then redefine __clear_bit_unlock
and perhaps other non-atomic __X_bit() variants to be atomic, and not
defer this requirement to places that use the API?

> The spinlock itself is implemented using Atomic [EX]change instruction
> which is always available.
> 
> The race happened when both cores tried to slab_lock() the same page.
> 
>    c1		    c0
> -----------	-----------
> slab_lock
> 		slab_lock
> slab_unlock
> 		Not observing the unlock
> 
> This in turn happened because slab_unlock() doesn't serialize properly
> (doesn't use atomic clear) with a concurrent running
> slab_lock()->test_and_set_bit()
> 
> Cc: Christoph Lameter <cl at linux.com>
> Cc: Pekka Enberg <penberg at kernel.org>
> Cc: David Rientjes <rientjes at google.com>
> Cc: Joonsoo Kim <iamjoonsoo.kim at lge.com>
> Cc: Andrew Morton <akpm at linux-foundation.org>
> Cc: Noam Camus <noamc at ezchip.com>
> Cc: <stable at vger.kernel.org>
> Cc: <linux-mm at kvack.org>
> Cc: <linux-kernel at vger.kernel.org>
> Cc: <linux-snps-arc at lists.infradead.org>
> Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
> ---
>  mm/slub.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/mm/slub.c b/mm/slub.c
> index d8fbd4a6ed59..b7d345a508dc 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -345,7 +345,7 @@ static __always_inline void slab_lock(struct page *page)
>  static __always_inline void slab_unlock(struct page *page)
>  {
>  	VM_BUG_ON_PAGE(PageTail(page), page);
> -	__bit_spin_unlock(PG_locked, &page->flags);
> +	bit_spin_unlock(PG_locked, &page->flags);
>  }
>  
>  static inline void set_page_slub_counters(struct page *page, unsigned long counters_new)
> 



From vgupta at synopsys.com  Tue Mar  8 07:46:27 2016
From: vgupta at synopsys.com (Vineet Gupta)
Date: Tue, 8 Mar 2016 21:16:27 +0530
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
Message-ID: <56DEF3D3.6080008@synopsys.com>

On Tuesday 08 March 2016 08:30 PM, Christoph Lameter wrote:
> On Tue, 8 Mar 2016, Vineet Gupta wrote:
> 
>> This in turn happened because slab_unlock() doesn't serialize properly
>> (doesn't use atomic clear) with a concurrent running
>> slab_lock()->test_and_set_bit()
> 
> This is intentional because of the increased latency of atomic
> instructions. Why would the unlock need to be atomic? This patch will
> cause regressions.
> 
> Guess this is an architecture specific issue of modified
> cachelines not becoming visible to other processors?

Absolutely not - we verified with the hardware coherency tracing that there was no
foul play there. And I would dare not point finger at code which was last updated
in 2011 w/o being absolutely sure.

Let me explain this in bit more detail. Like I mentioned in commitlog, this config
of ARC doesn't have exclusive load/stores (LLOCK/SCOND) so atomic ops are
implemented using a "central" spin lock. The spin lock itself is implemented using
EX instruction (atomic R-W)

Generated code for slab_lock() - essentially bit_spin_lock() is below (I've
removed generated code for CONFIG_PREEMPT for simplicity)

80543b0c <slab_lock>:
80543b0c:	push_s     blink
...
80543b3a:	mov_s      r15,0x809de168   <-- @smp_bitops_lock
80543b40:	mov_s      r17,1
80543b46:	mov_s      r16,0

# spin lock() inside test_and_set_bit() - see arc bitops.h (!LLSC code)
80543b78:	clri       r4
80543b7c:	dmb        3
80543b80:	mov_s      r2,r17
80543b82:	ex         r2,[r15]
80543b86:	breq       r2,1,80543b82
80543b8a:	dmb        3

# set the bit
80543b8e:	ld_s       r2,[r13,0] <--- (A) Finds PG_locked is set
80543b90:	or         r3,r2,1    <--- (B) other core unlocks right here
80543b94:	st_s       r3,[r13,0] <--- (C) sets PG_locked (overwrites unlock)

# spin_unlock
80543b96:	dmb        3
80543b9a:	mov_s      r3,r16
80543b9c:	ex         r3,[r15]
80543ba0:	dmb        3
80543ba4:	seti       r4

# check the old bit
80543ba8:	bbit0      r2,0,80543bb8   <--- bit was set, branch not taken
80543bac:	b_s        80543b68        <--- enter the test_bit() loop

   80543b68:	ld_s       r2,[r13,0]	   <-- (C) reads the bit, set by SELF
   80543b6a:	bbit1    r2,0,80543b68              spins infinitely

...


Now using hardware coherency tracing (and using the cycle timestamps) we verified
(A) and (B)

Thing is with exclusive load/store this race can't just happen since the
intervening ST will cause the ST in (C) to NOT commit and the LD/ST will be retried.

And there will be very few production systems which are SMP but lack exclusive
load/stores.

Are you convinced now !

-Vineet


From cl at linux.com  Tue Mar  8 12:40:52 2016
From: cl at linux.com (Christoph Lameter)
Date: Tue, 8 Mar 2016 14:40:52 -0600 (CST)
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <56DEF3D3.6080008@synopsys.com>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
Message-ID: <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>

On Tue, 8 Mar 2016, Vineet Gupta wrote:

> # set the bit
> 80543b8e:	ld_s       r2,[r13,0] <--- (A) Finds PG_locked is set
> 80543b90:	or         r3,r2,1    <--- (B) other core unlocks right here
> 80543b94:	st_s       r3,[r13,0] <--- (C) sets PG_locked (overwrites unlock)

Duh. Guess you  need to take the spinlock also in the arch specific
implementation of __bit_spin_unlock(). This is certainly not the only case
in which we use the __ op to unlock.

You need a true atomic op or you need to take the "spinlock" in all
cases where you modify the bit. If you take the lock in __bit_spin_unlock
then the race cannot happen.

> Are you convinced now !

Yes, please fix your arch specific code.



From Vineet.Gupta1 at synopsys.com  Tue Mar  8 22:43:16 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Wed, 9 Mar 2016 12:13:16 +0530
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
 <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
Message-ID: <56DFC604.6070407@synopsys.com>

+CC linux-arch, parisc folks, PeterZ

On Wednesday 09 March 2016 02:10 AM, Christoph Lameter wrote:
> On Tue, 8 Mar 2016, Vineet Gupta wrote:
> 
>> # set the bit
>> 80543b8e:	ld_s       r2,[r13,0] <--- (A) Finds PG_locked is set
>> 80543b90:	or         r3,r2,1    <--- (B) other core unlocks right here
>> 80543b94:	st_s       r3,[r13,0] <--- (C) sets PG_locked (overwrites unlock)
> 
> Duh. Guess you  need to take the spinlock also in the arch specific
> implementation of __bit_spin_unlock(). This is certainly not the only case
> in which we use the __ op to unlock.

__bit_spin_lock() by definition is *not* required to be atomic, bit_spin_lock() is
- so I don't think we need a spinlock there.

There is clearly a problem in slub code that it is pairing a test_and_set_bit()
with a __clear_bit(). Latter can obviously clobber former if they are not a single
instruction each unlike x86 or they use llock/scond kind of instructions where the
interim store from other core is detected and causes a retry of whole llock/scond
sequence.

BTW ARC is not the only arch which suffers from this - other arches potentially
also are. AFAIK PARISC also doesn't have atomic r-m-w and also uses a set of
external hashed spinlocks to protect the r-m-w sequences.

https://lkml.org/lkml/2014/6/1/178

So there also we have the same race because the outer spin lock is not taken for
slab_unlock() -> __bit_spin_lock() -> __clear_bit.

Arguably I can fix the ARC !LLSC variant of test_and_set_bit() to not set the bit
unconditionally but only if it was clear (PARISC does the same). That would be a
slight micro-optimization as we won't need another snoop transaction to make line
writable and that would also elide this problem, but I think there is a
fundamental problem here in slub which is pairing atomic and non atomic ops - for
performance reasons. It doesn't work on all arches and/or configurations.

> You need a true atomic op or you need to take the "spinlock" in all
> cases where you modify the bit.

No we don't in __bit_spin_lock and we already do in bit_spin_lock.

> If you take the lock in __bit_spin_unlock
> then the race cannot happen.

Of course it won't but that means we penalize all non atomic callers of the API
with a superfluous spinlock which is not require din first place given the
definition of API.


>> Are you convinced now !
> 
> Yes, please fix your arch specific code.





From peterz at infradead.org  Wed Mar  9 02:13:49 2016
From: peterz at infradead.org (Peter Zijlstra)
Date: Wed, 9 Mar 2016 11:13:49 +0100
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <56DFC604.6070407@synopsys.com>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
 <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
 <56DFC604.6070407@synopsys.com>
Message-ID: <20160309101349.GJ6344@twins.programming.kicks-ass.net>

On Wed, Mar 09, 2016 at 12:13:16PM +0530, Vineet Gupta wrote:
> +CC linux-arch, parisc folks, PeterZ
> 
> On Wednesday 09 March 2016 02:10 AM, Christoph Lameter wrote:
> > On Tue, 8 Mar 2016, Vineet Gupta wrote:
> > 
> >> # set the bit
> >> 80543b8e:	ld_s       r2,[r13,0] <--- (A) Finds PG_locked is set
> >> 80543b90:	or         r3,r2,1    <--- (B) other core unlocks right here
> >> 80543b94:	st_s       r3,[r13,0] <--- (C) sets PG_locked (overwrites unlock)
> > 
> > Duh. Guess you  need to take the spinlock also in the arch specific
> > implementation of __bit_spin_unlock(). This is certainly not the only case
> > in which we use the __ op to unlock.
> 
> __bit_spin_lock() by definition is *not* required to be atomic, bit_spin_lock() is
> - so I don't think we need a spinlock there.

Agreed. The double underscore prefixed instructions are not required to
be atomic in any way shape or form.

> There is clearly a problem in slub code that it is pairing a test_and_set_bit()
> with a __clear_bit(). Latter can obviously clobber former if they are not a single
> instruction each unlike x86 or they use llock/scond kind of instructions where the
> interim store from other core is detected and causes a retry of whole llock/scond
> sequence.

Yes, test_and_set_bit() + __clear_bit() is broken.

> > If you take the lock in __bit_spin_unlock
> > then the race cannot happen.
> 
> Of course it won't but that means we penalize all non atomic callers of the API
> with a superfluous spinlock which is not require din first place given the
> definition of API.

Quite. _However_, your arch is still broken, but not by your fault. Its
the generic-asm code that is wrong.

The thing is that __bit_spin_unlock() uses __clear_bit_unlock(), which
defaults to __clear_bit(). Which is wrong.

---
Subject: bitops: Do not default to __clear_bit() for __clear_bit_unlock()

__clear_bit_unlock() is a special little snowflake. While it carries the
non-atomic '__' prefix, it is specifically documented to pair with
test_and_set_bit() and therefore should be 'somewhat' atomic.

Therefore the generic implementation of __clear_bit_unlock() cannot use
the fully non-atomic __clear_bit() as a default.

If an arch is able to do better; is must provide an implementation of
__clear_bit_unlock() itself.

Reported-by: Vineet Gupta <Vineet.Gupta1 at synopsys.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz at infradead.org>
---
 include/asm-generic/bitops/lock.h | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/asm-generic/bitops/lock.h b/include/asm-generic/bitops/lock.h
index c30266e94806..8ef0ccbf8167 100644
--- a/include/asm-generic/bitops/lock.h
+++ b/include/asm-generic/bitops/lock.h
@@ -29,16 +29,16 @@ do {					\
  * @nr: the bit to set
  * @addr: the address to start counting from
  *
- * This operation is like clear_bit_unlock, however it is not atomic.
- * It does provide release barrier semantics so it can be used to unlock
- * a bit lock, however it would only be used if no other CPU can modify
- * any bits in the memory until the lock is released (a good example is
- * if the bit lock itself protects access to the other bits in the word).
+ * A weaker form of clear_bit_unlock() as used by __bit_lock_unlock(). If all
+ * the bits in the word are protected by this lock some archs can use weaker
+ * ops to safely unlock.
+ *
+ * See for example x86's implementation.
  */
 #define __clear_bit_unlock(nr, addr)	\
 do {					\
-	smp_mb();			\
-	__clear_bit(nr, addr);		\
+	smp_mb__before_atomic();	\
+	clear_bit(nr, addr);		\
 } while (0)
 
 #endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */




From peterz at infradead.org  Wed Mar  9 02:31:43 2016
From: peterz at infradead.org (Peter Zijlstra)
Date: Wed, 9 Mar 2016 11:31:43 +0100
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <20160309101349.GJ6344@twins.programming.kicks-ass.net>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
 <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
 <56DFC604.6070407@synopsys.com>
 <20160309101349.GJ6344@twins.programming.kicks-ass.net>
Message-ID: <20160309103143.GF25010@twins.programming.kicks-ass.net>

On Wed, Mar 09, 2016 at 11:13:49AM +0100, Peter Zijlstra wrote:
> ---
> Subject: bitops: Do not default to __clear_bit() for __clear_bit_unlock()
> 
> __clear_bit_unlock() is a special little snowflake. While it carries the
> non-atomic '__' prefix, it is specifically documented to pair with
> test_and_set_bit() and therefore should be 'somewhat' atomic.
> 
> Therefore the generic implementation of __clear_bit_unlock() cannot use
> the fully non-atomic __clear_bit() as a default.
> 
> If an arch is able to do better; is must provide an implementation of
> __clear_bit_unlock() itself.
> 

FWIW, we could probably undo this if we unified all the spinlock based
atomic ops implementations (there's a whole bunch doing essentially the
same), and special cased __clear_bit_unlock() for that.

Collapsing them is probably a good idea anyway, just a fair bit of
non-trivial work to figure out all the differences and if they matter
etc..


From Vineet.Gupta1 at synopsys.com  Wed Mar  9 03:00:31 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Wed, 9 Mar 2016 16:30:31 +0530
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <20160309101349.GJ6344@twins.programming.kicks-ass.net>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
 <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
 <56DFC604.6070407@synopsys.com>
 <20160309101349.GJ6344@twins.programming.kicks-ass.net>
Message-ID: <56E0024F.4070401@synopsys.com>

On Wednesday 09 March 2016 03:43 PM, Peter Zijlstra wrote:
>>> If you take the lock in __bit_spin_unlock
>>> then the race cannot happen.
>>
>> Of course it won't but that means we penalize all non atomic callers of the API
>> with a superfluous spinlock which is not require din first place given the
>> definition of API.
> 
> Quite. _However_, your arch is still broken, but not by your fault. Its
> the generic-asm code that is wrong.
> 
> The thing is that __bit_spin_unlock() uses __clear_bit_unlock(), which
> defaults to __clear_bit(). Which is wrong.
> 
> ---
> Subject: bitops: Do not default to __clear_bit() for __clear_bit_unlock()
> 
> __clear_bit_unlock() is a special little snowflake. While it carries the
> non-atomic '__' prefix, it is specifically documented to pair with
> test_and_set_bit() and therefore should be 'somewhat' atomic.
> 
> Therefore the generic implementation of __clear_bit_unlock() cannot use
> the fully non-atomic __clear_bit() as a default.
> 
> If an arch is able to do better; is must provide an implementation of
> __clear_bit_unlock() itself.
> 
> Reported-by: Vineet Gupta <Vineet.Gupta1 at synopsys.com>

This needs to be CCed stable as it fixes a real bug for ARC.

> Signed-off-by: Peter Zijlstra (Intel) <peterz at infradead.org>

Tested-by: Vineet Gupta <Vineet.Gupta1 at synopsys.com>

FWIW, could we add some background to commit log, specifically what prompted this.
Something like below...

---->8------
This came up as a result of hackbench livelock'ing in slab_lock() on ARC with SMP
+ SLUB + !LLSC.

The issue was incorrect pairing of atomic ops.

slab_lock() -> bit_spin_lock() -> test_and_set_bit()
slab_unlock() -> __bit_spin_unlock() -> __clear_bit()

The non serializing __clear_bit() was getting "lost"

80543b8e:	ld_s       r2,[r13,0] <--- (A) Finds PG_locked is set
80543b90:	or         r3,r2,1    <--- (B) other core unlocks right here
80543b94:	st_s       r3,[r13,0] <--- (C) sets PG_locked (overwrites unlock)

Fixes ARC STAR 9000817404
---->8------

> ---
>  include/asm-generic/bitops/lock.h | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/include/asm-generic/bitops/lock.h b/include/asm-generic/bitops/lock.h
> index c30266e94806..8ef0ccbf8167 100644
> --- a/include/asm-generic/bitops/lock.h
> +++ b/include/asm-generic/bitops/lock.h
> @@ -29,16 +29,16 @@ do {					\
>   * @nr: the bit to set
>   * @addr: the address to start counting from
>   *
> - * This operation is like clear_bit_unlock, however it is not atomic.
> - * It does provide release barrier semantics so it can be used to unlock
> - * a bit lock, however it would only be used if no other CPU can modify
> - * any bits in the memory until the lock is released (a good example is
> - * if the bit lock itself protects access to the other bits in the word).
> + * A weaker form of clear_bit_unlock() as used by __bit_lock_unlock(). If all
> + * the bits in the word are protected by this lock some archs can use weaker
> + * ops to safely unlock.
> + *
> + * See for example x86's implementation.
>   */

To be able to override/use-generic don't we need #ifndef ....

>  #define __clear_bit_unlock(nr, addr)	\
>  do {					\
> -	smp_mb();			\
> -	__clear_bit(nr, addr);		\
> +	smp_mb__before_atomic();	\
> +	clear_bit(nr, addr);		\
>  } while (0)
>  
>  #endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */
> 



From Vineet.Gupta1 at synopsys.com  Wed Mar  9 03:12:43 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Wed, 9 Mar 2016 16:42:43 +0530
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <20160309103143.GF25010@twins.programming.kicks-ass.net>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
 <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
 <56DFC604.6070407@synopsys.com>
 <20160309101349.GJ6344@twins.programming.kicks-ass.net>
 <20160309103143.GF25010@twins.programming.kicks-ass.net>
Message-ID: <56E0052B.3080304@synopsys.com>

On Wednesday 09 March 2016 04:01 PM, Peter Zijlstra wrote:
> On Wed, Mar 09, 2016 at 11:13:49AM +0100, Peter Zijlstra wrote:
>> ---
>> Subject: bitops: Do not default to __clear_bit() for __clear_bit_unlock()
>>
>> __clear_bit_unlock() is a special little snowflake. While it carries the
>> non-atomic '__' prefix, it is specifically documented to pair with
>> test_and_set_bit() and therefore should be 'somewhat' atomic.
>>
>> Therefore the generic implementation of __clear_bit_unlock() cannot use
>> the fully non-atomic __clear_bit() as a default.
>>
>> If an arch is able to do better; is must provide an implementation of
>> __clear_bit_unlock() itself.
>>
> 
> FWIW, we could probably undo this if we unified all the spinlock based
> atomic ops implementations (there's a whole bunch doing essentially the
> same), and special cased __clear_bit_unlock() for that.
> 
> Collapsing them is probably a good idea anyway, just a fair bit of
> non-trivial work to figure out all the differences and if they matter
> etc..

Indeed I thought about this when we first did the SMP port. The only issue was
somewhat more generated code with the hashed spinlocks (vs. my dumb 2 spin locks -
which as I see now will also cause false sharing - likely ending up in the same
cache line), but I was more of a micro-optimization freak then than I'm now :-)

So yeah I agree !






From peterz at infradead.org  Wed Mar  9 03:40:54 2016
From: peterz at infradead.org (Peter Zijlstra)
Date: Wed, 9 Mar 2016 12:40:54 +0100
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <56E0024F.4070401@synopsys.com>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
 <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
 <56DFC604.6070407@synopsys.com>
 <20160309101349.GJ6344@twins.programming.kicks-ass.net>
 <56E0024F.4070401@synopsys.com>
Message-ID: <20160309114054.GJ6356@twins.programming.kicks-ass.net>

On Wed, Mar 09, 2016 at 04:30:31PM +0530, Vineet Gupta wrote:
> FWIW, could we add some background to commit log, specifically what prompted this.
> Something like below...

Sure.. find below.

> > +++ b/include/asm-generic/bitops/lock.h
> > @@ -29,16 +29,16 @@ do {					\
> >   * @nr: the bit to set
> >   * @addr: the address to start counting from
> >   *
> > + * A weaker form of clear_bit_unlock() as used by __bit_lock_unlock(). If all
> > + * the bits in the word are protected by this lock some archs can use weaker
> > + * ops to safely unlock.
> > + *
> > + * See for example x86's implementation.
> >   */
> 
> To be able to override/use-generic don't we need #ifndef ....

I did not follow through the maze, I think the few archs implementing
this simply do not include this file at all.

I'll let the first person that cares about this worry about that :-)

---
Subject: bitops: Do not default to __clear_bit() for __clear_bit_unlock()

__clear_bit_unlock() is a special little snowflake. While it carries the
non-atomic '__' prefix, it is specifically documented to pair with
test_and_set_bit() and therefore should be 'somewhat' atomic.

Therefore the generic implementation of __clear_bit_unlock() cannot use
the fully non-atomic __clear_bit() as a default.

If an arch is able to do better; is must provide an implementation of
__clear_bit_unlock() itself.

Specifically, this came up as a result of hackbench livelock'ing in
slab_lock() on ARC with SMP + SLUB + !LLSC.

The issue was incorrect pairing of atomic ops.

slab_lock() -> bit_spin_lock() -> test_and_set_bit()
slab_unlock() -> __bit_spin_unlock() -> __clear_bit()

The non serializing __clear_bit() was getting "lost"

80543b8e:	ld_s       r2,[r13,0] <--- (A) Finds PG_locked is set
80543b90:	or         r3,r2,1    <--- (B) other core unlocks right here
80543b94:	st_s       r3,[r13,0] <--- (C) sets PG_locked (overwrites unlock)

Fixes ARC STAR 9000817404 (and probably more).

Cc: stable at vger.kernel.org
Reported-by: Vineet Gupta <Vineet.Gupta1 at synopsys.com>
Tested-by: Vineet Gupta <Vineet.Gupta1 at synopsys.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz at infradead.org>
---
 include/asm-generic/bitops/lock.h | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/asm-generic/bitops/lock.h b/include/asm-generic/bitops/lock.h
index c30266e94806..8ef0ccbf8167 100644
--- a/include/asm-generic/bitops/lock.h
+++ b/include/asm-generic/bitops/lock.h
@@ -29,16 +29,16 @@ do {					\
  * @nr: the bit to set
  * @addr: the address to start counting from
  *
- * This operation is like clear_bit_unlock, however it is not atomic.
- * It does provide release barrier semantics so it can be used to unlock
- * a bit lock, however it would only be used if no other CPU can modify
- * any bits in the memory until the lock is released (a good example is
- * if the bit lock itself protects access to the other bits in the word).
+ * A weaker form of clear_bit_unlock() as used by __bit_lock_unlock(). If all
+ * the bits in the word are protected by this lock some archs can use weaker
+ * ops to safely unlock.
+ *
+ * See for example x86's implementation.
  */
 #define __clear_bit_unlock(nr, addr)	\
 do {					\
-	smp_mb();			\
-	__clear_bit(nr, addr);		\
+	smp_mb__before_atomic();	\
+	clear_bit(nr, addr);		\
 } while (0)
 
 #endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */


From Vineet.Gupta1 at synopsys.com  Wed Mar  9 03:53:26 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Wed, 9 Mar 2016 17:23:26 +0530
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <20160309114054.GJ6356@twins.programming.kicks-ass.net>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
 <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
 <56DFC604.6070407@synopsys.com>
 <20160309101349.GJ6344@twins.programming.kicks-ass.net>
 <56E0024F.4070401@synopsys.com>
 <20160309114054.GJ6356@twins.programming.kicks-ass.net>
Message-ID: <56E00EB6.4000201@synopsys.com>

On Wednesday 09 March 2016 05:10 PM, Peter Zijlstra wrote:
> On Wed, Mar 09, 2016 at 04:30:31PM +0530, Vineet Gupta wrote:
>> FWIW, could we add some background to commit log, specifically what prompted this.
>> Something like below...
> 
> Sure.. find below.
> 
>>> +++ b/include/asm-generic/bitops/lock.h
>>> @@ -29,16 +29,16 @@ do {					\
>>>   * @nr: the bit to set
>>>   * @addr: the address to start counting from
>>>   *
>>> + * A weaker form of clear_bit_unlock() as used by __bit_lock_unlock(). If all
>>> + * the bits in the word are protected by this lock some archs can use weaker
>>> + * ops to safely unlock.
>>> + *
>>> + * See for example x86's implementation.
>>>   */
>>
>> To be able to override/use-generic don't we need #ifndef ....
> 
> I did not follow through the maze, I think the few archs implementing
> this simply do not include this file at all.
> 
> I'll let the first person that cares about this worry about that :-)

Ok - that's be me :-) although I really don't see much gains in case of ARC LLSC.

For us, LD + BCLR + ST is very similar to LLOCK + BCLR + SCOND atleast in terms of
cache coherency transactions !

> 
> ---
> Subject: bitops: Do not default to __clear_bit() for __clear_bit_unlock()
> 
> __clear_bit_unlock() is a special little snowflake. While it carries the
> non-atomic '__' prefix, it is specifically documented to pair with
> test_and_set_bit() and therefore should be 'somewhat' atomic.
> 
> Therefore the generic implementation of __clear_bit_unlock() cannot use
> the fully non-atomic __clear_bit() as a default.
> 
> If an arch is able to do better; is must provide an implementation of
> __clear_bit_unlock() itself.
> 
> Specifically, this came up as a result of hackbench livelock'ing in
> slab_lock() on ARC with SMP + SLUB + !LLSC.
> 
> The issue was incorrect pairing of atomic ops.
> 
> slab_lock() -> bit_spin_lock() -> test_and_set_bit()
> slab_unlock() -> __bit_spin_unlock() -> __clear_bit()
> 
> The non serializing __clear_bit() was getting "lost"
> 
> 80543b8e:	ld_s       r2,[r13,0] <--- (A) Finds PG_locked is set
> 80543b90:	or         r3,r2,1    <--- (B) other core unlocks right here
> 80543b94:	st_s       r3,[r13,0] <--- (C) sets PG_locked (overwrites unlock)
> 
> Fixes ARC STAR 9000817404 (and probably more).
> 
> Cc: stable at vger.kernel.org
> Reported-by: Vineet Gupta <Vineet.Gupta1 at synopsys.com>
> Tested-by: Vineet Gupta <Vineet.Gupta1 at synopsys.com>
> Signed-off-by: Peter Zijlstra (Intel) <peterz at infradead.org>

LGTM. Thx a bunch Peter !

-Vineet

> ---
>  include/asm-generic/bitops/lock.h | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/include/asm-generic/bitops/lock.h b/include/asm-generic/bitops/lock.h
> index c30266e94806..8ef0ccbf8167 100644
> --- a/include/asm-generic/bitops/lock.h
> +++ b/include/asm-generic/bitops/lock.h
> @@ -29,16 +29,16 @@ do {					\
>   * @nr: the bit to set
>   * @addr: the address to start counting from
>   *
> - * This operation is like clear_bit_unlock, however it is not atomic.
> - * It does provide release barrier semantics so it can be used to unlock
> - * a bit lock, however it would only be used if no other CPU can modify
> - * any bits in the memory until the lock is released (a good example is
> - * if the bit lock itself protects access to the other bits in the word).
> + * A weaker form of clear_bit_unlock() as used by __bit_lock_unlock(). If all
> + * the bits in the word are protected by this lock some archs can use weaker
> + * ops to safely unlock.
> + *
> + * See for example x86's implementation.
>   */
>  #define __clear_bit_unlock(nr, addr)	\
>  do {					\
> -	smp_mb();			\
> -	__clear_bit(nr, addr);		\
> +	smp_mb__before_atomic();	\
> +	clear_bit(nr, addr);		\
>  } while (0)
>  
>  #endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */
> 



From peterz at infradead.org  Wed Mar  9 04:22:17 2016
From: peterz at infradead.org (Peter Zijlstra)
Date: Wed, 9 Mar 2016 13:22:17 +0100
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <56E00EB6.4000201@synopsys.com>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
 <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
 <56DFC604.6070407@synopsys.com>
 <20160309101349.GJ6344@twins.programming.kicks-ass.net>
 <56E0024F.4070401@synopsys.com>
 <20160309114054.GJ6356@twins.programming.kicks-ass.net>
 <56E00EB6.4000201@synopsys.com>
Message-ID: <20160309122217.GK6356@twins.programming.kicks-ass.net>

On Wed, Mar 09, 2016 at 05:23:26PM +0530, Vineet Gupta wrote:
> > I did not follow through the maze, I think the few archs implementing
> > this simply do not include this file at all.
> > 
> > I'll let the first person that cares about this worry about that :-)
> 
> Ok - that's be me :-) although I really don't see much gains in case of ARC LLSC.
> 
> For us, LD + BCLR + ST is very similar to LLOCK + BCLR + SCOND atleast in terms of
> cache coherency transactions !

The win would be in not having to ever retry the SCOND. Although in this
case, the contending CPU would be doing reads -- which I assume will not
cause a SCOND to fail, so it might indeed not make any difference.


From Vineet.Gupta1 at synopsys.com  Wed Mar  9 05:22:45 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Wed, 9 Mar 2016 18:52:45 +0530
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <20160309101349.GJ6344@twins.programming.kicks-ass.net>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
 <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
 <56DFC604.6070407@synopsys.com>
 <20160309101349.GJ6344@twins.programming.kicks-ass.net>
Message-ID: <56E023A5.2000105@synopsys.com>

On Wednesday 09 March 2016 03:43 PM, Peter Zijlstra wrote:
>> There is clearly a problem in slub code that it is pairing a test_and_set_bit()
>> with a __clear_bit(). Latter can obviously clobber former if they are not a single
>> instruction each unlike x86 or they use llock/scond kind of instructions where the
>> interim store from other core is detected and causes a retry of whole llock/scond
>> sequence.
> 
> Yes, test_and_set_bit() + __clear_bit() is broken.

But in SLUB: bit_spin_lock() + __bit_spin_unlock() is acceptable ? How so
(ignoring the performance thing for discussion sake, which is a side effect of
this implementation).

So despite the comment below in bit_spinlock.h I don't quite comprehend how this
is allowable. And if say, by deduction, this is fine for LLSC or lock prefixed
cases, then isn't this true in general for lot more cases in kernel, i.e. pairing
atomic lock with non-atomic unlock ? I'm missing something !

| /*
|  *  bit-based spin_unlock()
|  *  non-atomic version, which can be used eg. if the bit lock itself is
|  *  protecting the rest of the flags in the word.
|  */
| static inline void __bit_spin_unlock(int bitnum, unsigned long *addr)




From peterz at infradead.org  Wed Mar  9 06:51:19 2016
From: peterz at infradead.org (Peter Zijlstra)
Date: Wed, 9 Mar 2016 15:51:19 +0100
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <56E023A5.2000105@synopsys.com>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
 <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
 <56DFC604.6070407@synopsys.com>
 <20160309101349.GJ6344@twins.programming.kicks-ass.net>
 <56E023A5.2000105@synopsys.com>
Message-ID: <20160309145119.GN6356@twins.programming.kicks-ass.net>

On Wed, Mar 09, 2016 at 06:52:45PM +0530, Vineet Gupta wrote:
> On Wednesday 09 March 2016 03:43 PM, Peter Zijlstra wrote:
> >> There is clearly a problem in slub code that it is pairing a test_and_set_bit()
> >> with a __clear_bit(). Latter can obviously clobber former if they are not a single
> >> instruction each unlike x86 or they use llock/scond kind of instructions where the
> >> interim store from other core is detected and causes a retry of whole llock/scond
> >> sequence.
> > 
> > Yes, test_and_set_bit() + __clear_bit() is broken.
> 
> But in SLUB: bit_spin_lock() + __bit_spin_unlock() is acceptable ? How so
> (ignoring the performance thing for discussion sake, which is a side effect of
> this implementation).

The sort answer is: Per definition. They are defined to work together,
which is what makes __clear_bit_unlock() such a special function.

> So despite the comment below in bit_spinlock.h I don't quite comprehend how this
> is allowable. And if say, by deduction, this is fine for LLSC or lock prefixed
> cases, then isn't this true in general for lot more cases in kernel, i.e. pairing
> atomic lock with non-atomic unlock ? I'm missing something !

x86 (and others) do in fact use non-atomic instructions for
spin_unlock(). But as this is all arch specific, we can make these
assumptions. Its just that generic code cannot rely on it.

So let me try and explain.


The problem as identified is:

CPU0						CPU1

bit_spin_lock()					__bit_spin_unlock()
1:
	/* fetch_or, r1 holds the old value */
	spin_lock
	load	r1, addr
						load	r1, addr
						bclr	r2, r1, 1
						store	r2, addr
	or	r2, r1, 1
	store	r2, addr	/* lost the store from CPU1 */
	spin_unlock

	and	r1, 1
	bnz	2	/* it was set, go wait */
	ret

2:
	load	r1, addr
	and	r1, 1
	bnz	2	/* wait until its not set */

	b	1	/* try again */



For LL/SC we replace:

	spin_lock
	load	r1, addr

	...

	store	r2, addr
	spin_unlock

With the (obvious):

1:
	load-locked	r1, addr

	...

	store-cond	r2, addr
	bnz		1 /* or whatever branch instruction is required to retry */


In this case the failure cannot happen, because the store from CPU1
would have invalidated the lock from CPU0 and caused the
store-cond to fail and retry the loop, observing the new value.




From Lada.Trimasova at synopsys.com  Wed Mar  9 09:21:04 2016
From: Lada.Trimasova at synopsys.com (Lada Trimasova)
Date: Wed,  9 Mar 2016 20:21:04 +0300
Subject: [PATCH] arc: use little endian accesses
Message-ID: <1457544064-16167-1-git-send-email-ltrimas@synopsys.com>

Memory access primitives should use cpu_to_le16, cpu_to_le32, le16_to_cpu
and le32_to_cpu because it is not really guaranteed that drivers handles
any ordering themselves.
For example, serial port driver doesn't work when kernel is build for
arc big endian architecture.

Signed-off-by: Lada Trimasova <ltrimas at synopsys.com>
Cc: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/include/asm/io.h | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
index 694ece8..0b3d5ea 100644
--- a/arch/arc/include/asm/io.h
+++ b/arch/arc/include/asm/io.h
@@ -129,15 +129,17 @@ static inline void __raw_writel(u32 w, volatile void __iomem *addr)
 #define writel(v,c)		({ __iowmb(); writel_relaxed(v,c); })
 
 /*
- * Relaxed API for drivers which can handle any ordering themselves
+ * This are defined to perform little endian accesses
  */
 #define readb_relaxed(c)	__raw_readb(c)
-#define readw_relaxed(c)	__raw_readw(c)
-#define readl_relaxed(c)	__raw_readl(c)
+#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
+					__raw_readw(c)); __r; })
+#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
+					__raw_readl(c)); __r; })
 
 #define writeb_relaxed(v,c)	__raw_writeb(v,c)
-#define writew_relaxed(v,c)	__raw_writew(v,c)
-#define writel_relaxed(v,c)	__raw_writel(v,c)
+#define writew_relaxed(v,c)	__raw_writew((__force u16) cpu_to_le16(v),c)
+#define writel_relaxed(v,c)	__raw_writel((__force u32) cpu_to_le32(v),c)
 
 #include <asm-generic/io.h>
 
-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Wed Mar  9 21:05:46 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Thu, 10 Mar 2016 05:05:46 +0000
Subject: [PATCH] arc: use little endian accesses
References: <1457544064-16167-1-git-send-email-ltrimas@synopsys.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E8EDF9@us01wembx1.internal.synopsys.com>

+CC Noam

On Wednesday 09 March 2016 10:51 PM, Lada Trimasova wrote:
> Memory access primitives should use cpu_to_le16, cpu_to_le32, le16_to_cpu
> and le32_to_cpu because it is not really guaranteed that drivers handles
> any ordering themselves.

That is the driver issue. readxx as API simply returns data in native endianness.
We've had EZChip running big endian and so far and they didn't need this change.

> For example, serial port driver doesn't work when kernel is build for
> arc big endian architecture.

Last I tested Big Endian on SDP with 8250 part + 8250 driver it was working fine.
I presume this is the systemC model for device and standard 8250 driver and very
likely the model is not fixed endian or something.

Alexey knows about this stuff - this was discussed on lkml back in 2013 when he
was fighting the Xilinx systemAce driver endian issues

> Signed-off-by: Lada Trimasova <ltrimas at synopsys.com>

Sorry NACK on this ! If you still think we need it I need more data / details on
what exactly is failing in 8250 and how !

-Vineet

> Cc: Alexey Brodkin <abrodkin at synopsys.com>
> Cc: Vineet Gupta <vgupta at synopsys.com>
> ---
>  arch/arc/include/asm/io.h | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
> index 694ece8..0b3d5ea 100644
> --- a/arch/arc/include/asm/io.h
> +++ b/arch/arc/include/asm/io.h
> @@ -129,15 +129,17 @@ static inline void __raw_writel(u32 w, volatile void __iomem *addr)
>  #define writel(v,c)		({ __iowmb(); writel_relaxed(v,c); })
>  
>  /*
> - * Relaxed API for drivers which can handle any ordering themselves
> + * This are defined to perform little endian accesses
>   */
>  #define readb_relaxed(c)	__raw_readb(c)
> -#define readw_relaxed(c)	__raw_readw(c)
> -#define readl_relaxed(c)	__raw_readl(c)
> +#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
> +					__raw_readw(c)); __r; })
> +#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
> +					__raw_readl(c)); __r; })
>  
>  #define writeb_relaxed(v,c)	__raw_writeb(v,c)
> -#define writew_relaxed(v,c)	__raw_writew(v,c)
> -#define writel_relaxed(v,c)	__raw_writel(v,c)
> +#define writew_relaxed(v,c)	__raw_writew((__force u16) cpu_to_le16(v),c)
> +#define writel_relaxed(v,c)	__raw_writel((__force u32) cpu_to_le32(v),c)
>  
>  #include <asm-generic/io.h>
>  



From Vineet.Gupta1 at synopsys.com  Wed Mar  9 21:19:37 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Thu, 10 Mar 2016 05:19:37 +0000
Subject: [PATCH] arc: use little endian accesses
References: <1457544064-16167-1-git-send-email-ltrimas@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8EDF9@us01wembx1.internal.synopsys.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E8EE1D@us01wembx1.internal.synopsys.com>

On Thursday 10 March 2016 10:35 AM, Vineet Gupta wrote:
> +CC Noam
>
> On Wednesday 09 March 2016 10:51 PM, Lada Trimasova wrote:
>> > Memory access primitives should use cpu_to_le16, cpu_to_le32, le16_to_cpu
>> > and le32_to_cpu because it is not really guaranteed that drivers handles
>> > any ordering themselves.
> That is the driver issue. readxx as API simply returns data in native endianness.
> We've had EZChip running big endian and so far and they didn't need this change.
>
>> > For example, serial port driver doesn't work when kernel is build for
>> > arc big endian architecture.
> Last I tested Big Endian on SDP with 8250 part + 8250 driver it was working fine.
> I presume this is the systemC model for device and standard 8250 driver and very
> likely the model is not fixed endian or something.
>
> Alexey knows about this stuff - this was discussed on lkml back in 2013 when he
> was fighting the Xilinx systemAce driver endian issues
>

Do you need "native-endian" DT entry in nsimosci DT bindings for uart ?


From Vineet.Gupta1 at synopsys.com  Wed Mar  9 21:51:21 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Thu, 10 Mar 2016 11:21:21 +0530
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <20160309145119.GN6356@twins.programming.kicks-ass.net>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
 <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
 <56DFC604.6070407@synopsys.com>
 <20160309101349.GJ6344@twins.programming.kicks-ass.net>
 <56E023A5.2000105@synopsys.com>
 <20160309145119.GN6356@twins.programming.kicks-ass.net>
Message-ID: <56E10B59.1060700@synopsys.com>

On Wednesday 09 March 2016 08:21 PM, Peter Zijlstra wrote:
>> But in SLUB: bit_spin_lock() + __bit_spin_unlock() is acceptable ? How so
>> (ignoring the performance thing for discussion sake, which is a side effect of
>> this implementation).
> 
> The sort answer is: Per definition. They are defined to work together,
> which is what makes __clear_bit_unlock() such a special function.
> 
>> So despite the comment below in bit_spinlock.h I don't quite comprehend how this
>> is allowable. And if say, by deduction, this is fine for LLSC or lock prefixed
>> cases, then isn't this true in general for lot more cases in kernel, i.e. pairing
>> atomic lock with non-atomic unlock ? I'm missing something !
> 
> x86 (and others) do in fact use non-atomic instructions for
> spin_unlock(). But as this is all arch specific, we can make these
> assumptions. Its just that generic code cannot rely on it.

OK despite being obvious now, I was not seeing the similarity between spin_*lock()
and bit_spin*lock() :-(

ARC also uses standard ST for spin_unlock() so by analogy __bit_spin_unlock() (for
LLSC case) would be correctly paired with bit_spin_lock().

But then why would anyone need bit_spin_unlock() at all. Specially after this
patch from you which tightens __bit_spin_lock() even more for the general case.

Thing is if the API exists majority of people would would use the more
conservative version w/o understand all these nuances. Can we pursue the path of
moving bit_spin_unlock() over to __bit_spin_lock(): first changing the backend
only and if proven stable replacing the call-sites themselves.

> 
> So let me try and explain.
> 
> 
> The problem as identified is:
> 
> CPU0						CPU1
> 
> bit_spin_lock()					__bit_spin_unlock()
> 1:
> 	/* fetch_or, r1 holds the old value */
> 	spin_lock
> 	load	r1, addr
> 						load	r1, addr
> 						bclr	r2, r1, 1
> 						store	r2, addr
> 	or	r2, r1, 1
> 	store	r2, addr	/* lost the store from CPU1 */
> 	spin_unlock
> 
> 	and	r1, 1
> 	bnz	2	/* it was set, go wait */
> 	ret
> 
> 2:
> 	load	r1, addr
> 	and	r1, 1
> 	bnz	2	/* wait until its not set */
> 
> 	b	1	/* try again */
> 
> 
> 
> For LL/SC we replace:
> 
> 	spin_lock
> 	load	r1, addr
> 
> 	...
> 
> 	store	r2, addr
> 	spin_unlock
> 
> With the (obvious):
> 
> 1:
> 	load-locked	r1, addr
> 
> 	...
> 
> 	store-cond	r2, addr
> 	bnz		1 /* or whatever branch instruction is required to retry */
> 
> 
> In this case the failure cannot happen, because the store from CPU1
> would have invalidated the lock from CPU0 and caused the
> store-cond to fail and retry the loop, observing the new value. 

You did it again, A picture is worth thousand words !

Thx,
-Vineet


From Alexey.Brodkin at synopsys.com  Wed Mar  9 23:44:06 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 10 Mar 2016 07:44:06 +0000
Subject: [PATCH] arc: use little endian accesses
In-Reply-To: <C2D7FE5348E1B147BCA15975FBA23075F4E8EDF9@us01wembx1.internal.synopsys.com>
References: <1457544064-16167-1-git-send-email-ltrimas@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8EDF9@us01wembx1.internal.synopsys.com>
Message-ID: <1457595846.2868.10.camel@synopsys.com>

Hi Vineet,

On Thu, 2016-03-10 at 05:05 +0000, Vineet Gupta wrote:
> +CC Noam
> 
> On Wednesday 09 March 2016 10:51 PM, Lada Trimasova wrote:
> > 
> > Memory access primitives should use cpu_to_le16, cpu_to_le32, le16_to_cpu
> > and le32_to_cpu because it is not really guaranteed that drivers handles
> > any ordering themselves.
> That is the driver issue. readxx as API simply returns data in native endianness.
> We've had EZChip running big endian and so far and they didn't need this change.

Let me disagree with you here.
See what is said in "include/asm-generic/io.h":
---------------------->8---------------------
/*
?* __raw_{read,write}{b,w,l,q}() access memory in native endianness.
?*
?* On some architectures memory mapped IO needs to be accessed differently.
?* On the simple architectures, we just read/write the memory location
?* directly.
?*/

...

/*
?* {read,write}{b,w,l,q}() access little endian memory and return result in
?* native endianness.
?*/
---------------------->8---------------------

And that's an implementation we have for ARC:
---------------------->8---------------------
#define readb(c)		({ u8??__v = readb_relaxed(c); __iormb(); __v; })
#define readw(c)		({ u16 __v = readw_relaxed(c); __iormb(); __v; })
#define readl(c)		({ u32 __v = readl_relaxed(c); __iormb(); __v; })

#define writeb(v,c)		({ __iowmb(); writeb_relaxed(v,c); })
#define writew(v,c)		({ __iowmb(); writew_relaxed(v,c); })
#define writel(v,c)		({ __iowmb(); writel_relaxed(v,c); })

/*
?* Relaxed API for drivers which can handle any ordering themselves
?*/
#define readb_relaxed(c)	__raw_readb(c)
#define readw_relaxed(c)	__raw_readw(c)
#define readl_relaxed(c)	__raw_readl(c)

#define writeb_relaxed(v,c)	__raw_writeb(v,c)
#define writew_relaxed(v,c)	__raw_writew(v,c)
#define writel_relaxed(v,c)	__raw_writel(v,c)
---------------------->8---------------------

Which is effectively (related to endianess discussion):
---------------------->8---------------------
#define readX(c)	__raw_readX(c)
#define writeX(v,c)	__raw_writeX(v,c)
---------------------->8---------------------

That looks IMHO incorrect if we read API description in "include/asm-generic/io.h".
BTW description of {read,write}{b,w,l,q}() is a bit misleading in part saying
"... and return result in __native_endianness__".

But real implementation of {read,write}{b,w,l,q}() in "include/asm-generic/io.h"
really shows what was meant - note?__leXX_to_cpu() and?cpu_to_leXX are used.

> > 
> > For example, serial port driver doesn't work when kernel is build for
> > arc big endian architecture.
> Last I tested Big Endian on SDP with 8250 part + 8250 driver it was working fine.
> I presume this is the systemC model for device and standard 8250 driver and very
> likely the model is not fixed endian or something.

Model is indeed little-endian. We build it only once and than changing
only "nsim_isa_big_endian" property (which changes only CPU core endianess) may use
it equally well with little- and big-endian builds of Linux kernel.

-Alexey

From arnd at arndb.de  Wed Mar  9 23:45:30 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 10 Mar 2016 08:45:30 +0100
Subject: [PATCH] arc: use little endian accesses
In-Reply-To: <C2D7FE5348E1B147BCA15975FBA23075F4E8EDF9@us01wembx1.internal.synopsys.com>
References: <1457544064-16167-1-git-send-email-ltrimas@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8EDF9@us01wembx1.internal.synopsys.com>
Message-ID: <201603100845.30602.arnd@arndb.de>

On Thursday 10 March 2016, Vineet Gupta wrote:
> On Wednesday 09 March 2016 10:51 PM, Lada Trimasova wrote:
> > Memory access primitives should use cpu_to_le16, cpu_to_le32, le16_to_cpu
> > and le32_to_cpu because it is not really guaranteed that drivers handles
> > any ordering themselves.
> 
> That is the driver issue. readxx as API simply returns data in native endianness.
> We've had EZChip running big endian and so far and they didn't need this change.

Most drivers using readl() or readl_relaxed() expect those to perform byte
swaps on big-endian architectures, as the registers tend to be fixed endian,
so the change seems reasonable.

It depends a little bit on how endian mode is implemented in the CPU: do you
follow the normal model of swapping byte order in the load/store instructions
of the CPU when running big-endian, or is the CPU always running little-endian
but the bus addresses get mangled on byte accesses to give the illusion
of a big-endian system?

	Arnd


From peterz at infradead.org  Thu Mar 10 01:10:58 2016
From: peterz at infradead.org (Peter Zijlstra)
Date: Thu, 10 Mar 2016 10:10:58 +0100
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <56E10B59.1060700@synopsys.com>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
 <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
 <56DFC604.6070407@synopsys.com>
 <20160309101349.GJ6344@twins.programming.kicks-ass.net>
 <56E023A5.2000105@synopsys.com>
 <20160309145119.GN6356@twins.programming.kicks-ass.net>
 <56E10B59.1060700@synopsys.com>
Message-ID: <20160310091058.GQ6344@twins.programming.kicks-ass.net>

On Thu, Mar 10, 2016 at 11:21:21AM +0530, Vineet Gupta wrote:
> On Wednesday 09 March 2016 08:21 PM, Peter Zijlstra wrote:
> >> But in SLUB: bit_spin_lock() + __bit_spin_unlock() is acceptable ? How so
> >> (ignoring the performance thing for discussion sake, which is a side effect of
> >> this implementation).
> > 
> > The sort answer is: Per definition. They are defined to work together,
> > which is what makes __clear_bit_unlock() such a special function.
> > 
> >> So despite the comment below in bit_spinlock.h I don't quite comprehend how this
> >> is allowable. And if say, by deduction, this is fine for LLSC or lock prefixed
> >> cases, then isn't this true in general for lot more cases in kernel, i.e. pairing
> >> atomic lock with non-atomic unlock ? I'm missing something !
> > 
> > x86 (and others) do in fact use non-atomic instructions for
> > spin_unlock(). But as this is all arch specific, we can make these
> > assumptions. Its just that generic code cannot rely on it.
> 
> OK despite being obvious now, I was not seeing the similarity between spin_*lock()
> and bit_spin*lock() :-(
> 
> ARC also uses standard ST for spin_unlock() so by analogy __bit_spin_unlock() (for
> LLSC case) would be correctly paired with bit_spin_lock().
> 
> But then why would anyone need bit_spin_unlock() at all. Specially after this
> patch from you which tightens __bit_spin_lock() even more for the general case.
> 
> Thing is if the API exists majority of people would would use the more
> conservative version w/o understand all these nuances. Can we pursue the path of
> moving bit_spin_unlock() over to __bit_spin_lock(): first changing the backend
> only and if proven stable replacing the call-sites themselves.

So the thing is, __bit_spin_unlock() is not safe if other bits in that
word can have concurrent modifications.

Only if the bitlock locks the whole word (or something else ensures no
other bits will change) can you use __bit_spin_unlock() to clear the
lock bit.


From Vineet.Gupta1 at synopsys.com  Thu Mar 10 01:55:49 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Thu, 10 Mar 2016 09:55:49 +0000
Subject: [PATCH] arc: use little endian accesses
References: <1457544064-16167-1-git-send-email-ltrimas@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8EDF9@us01wembx1.internal.synopsys.com>
 <1457595846.2868.10.camel@synopsys.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E8F1A0@us01wembx1.internal.synopsys.com>

On Thursday 10 March 2016 01:14 PM, Alexey Brodkin wrote:
>>> For example, serial port driver doesn't work when kernel is build for
>>> arc big endian architecture.
>> Last I tested Big Endian on SDP with 8250 part + 8250 driver it was working fine.
>> I presume this is the systemC model for device and standard 8250 driver and very
>> likely the model is not fixed endian or something.
> Model is indeed little-endian. We build it only once and than changing
> only "nsim_isa_big_endian" property (which changes only CPU core endianess) may use
> it equally well with little- and big-endian builds of Linux kernel.

Can you or Lada provide more details as to exactly what is not working - what
driver to be precise 8250 or dw-8250.
And where exactly the failure shows up. I want to understand this more
Noam told me off list that he has no issues with both big endian ARC + 8250 in
systemc model or silicon.

-Vineet


From Lada.Trimasova at synopsys.com  Thu Mar 10 10:57:48 2016
From: Lada.Trimasova at synopsys.com (Lada Trimasova)
Date: Thu, 10 Mar 2016 18:57:48 +0000
Subject: [PATCH] arc: use little endian accesses
In-Reply-To: <C2D7FE5348E1B147BCA15975FBA23075F4E8F1A0@us01wembx1.internal.synopsys.com>
References: <1457544064-16167-1-git-send-email-ltrimas@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8EDF9@us01wembx1.internal.synopsys.com>
 <1457595846.2868.10.camel@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8F1A0@us01wembx1.internal.synopsys.com>
Message-ID: <1457636268.457.34.camel@synopsys.com>

Hi Vineet, Alexey, Arnd,
On Thu, 2016-03-10 at 09:55 +0000, Vineet Gupta wrote:

Can you or Lada provide more details as to exactly what is not working - what
driver to be precise 8250 or dw-8250.
And where exactly the failure shows up. I want to understand this more
Noam told me off list that he has no issues with both big endian ARC + 8250 in
systemc model or silicon.

-Vineet



Driver is 8250, kernel is built for BE arc, nsim option in model "nsim_isa_big_endian = 1".

With current "readl" and "writel" implementation for ARC we read word from memory without any endianess manipulation. So in case of little endian architecture we get what we want: the first memory byte is the low byte in the word. But in case of big endian architecture the word endianess is swapped: the first memory byte is the high word byte.

And for example, let's see what happens when we use "readl" in  function "serial8250_early_in" in driver/tty/serial/8250.

Take a look to one line from memory dump:
0xf0000010: 0x0b    0x00    0x00    0x00    0x60    0x00    0x00    0x00

When kernel is built for little endian architecture, we read this data in status register in function "serial_putc" using "readl" function in driver/tty/serial/8250 as:
r0: 0x0000006
The low byte is 0x0b, so the condition "if ((status & BOTH_EMPTY) == BOTH_EMPTY)"  is true, as BOTH_EMPTY is some mask with low bytes set.

When kernel is built with "CPU_BIG_ENDIAN" and model nsim option is "nsim_isa_big_endian=1", we read this data as:
r0: 0x6000000
So as you can see the low byte is 0x00 and above mentioned condition never becomes true, we can't continue initialization.


Regards,
Lada

From arnd at arndb.de  Thu Mar 10 11:23:59 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 10 Mar 2016 20:23:59 +0100
Subject: [PATCH] arc: use little endian accesses
In-Reply-To: <1457636268.457.34.camel@synopsys.com>
References: <1457544064-16167-1-git-send-email-ltrimas@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8F1A0@us01wembx1.internal.synopsys.com>
 <1457636268.457.34.camel@synopsys.com>
Message-ID: <201603102023.59425.arnd@arndb.de>

On Thursday 10 March 2016, Lada Trimasova wrote:
> Driver is 8250, kernel is built for BE arc, nsim option in model "nsim_isa_big_endian = 1".
> 
> With current "readl" and "writel" implementation for ARC we read word from memory without any endianess manipulation. So in case of little endian architecture we get what we want: the first memory byte is the low byte in the word. But in case of big endian architecture the word endianess is swapped: the first memory byte is the high word byte.
> 
> And for example, let's see what happens when we use "readl" in  function "serial8250_early_in" in driver/tty/serial/8250.
> 
> Take a look to one line from memory dump:
> 0xf0000010: 0x0b    0x00    0x00    0x00    0x60    0x00    0x00    0x00
> 
> When kernel is built for little endian architecture, we read this data in status register in function "serial_putc" using "readl" function in driver/tty/serial/8250 as:
> r0: 0x0000006
> The low byte is 0x0b, so the condition "if ((status & BOTH_EMPTY) == BOTH_EMPTY)"  is true, as BOTH_EMPTY is some mask with low bytes set.
> 
> When kernel is built with "CPU_BIG_ENDIAN" and model nsim option is "nsim_isa_big_endian=1", we read this data as:
> r0: 0x6000000
> So as you can see the low byte is 0x00 and above mentioned condition never becomes true, we can't continue initialization.
> 

Ok, this sounds like a completely normal architecture implementation then,
and your patch looks correct.

If some other driver breaks because of this change, you should investigate
what went wrong there, and treat it as a driver specific problem.

	Arnd


From Vineet.Gupta1 at synopsys.com  Thu Mar 10 20:19:23 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 11 Mar 2016 04:19:23 +0000
Subject: [PATCH v2 2/9] ARC: [dts] Introduce Timer bindings
References: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
 <1457439972-20285-3-git-send-email-vgupta@synopsys.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E8F330@us01wembx1.internal.synopsys.com>

On Tuesday 08 March 2016 05:56 PM, Vineet Gupta wrote:
> ARC Timers have historically been probed directly.
> As precursor to start probing Timers thru DT introduce these bindings
> Note that to keep series bisectable, these bindings are not yet used in
> code.
>
> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
> Cc: Rob Herring <robh at kernel.org>
> Cc: devicetree at vger.kernel.org
> Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
> ---
> Changes v1 -> v2
>  - snps,arc-timer[0-1] folded into single snps-arc-timer	[Rob]
>  - Node name in DT example fixed:				[Rob]
>      "timer1: timer_clksrc {" -> timer at 1 {
>  - Introduced 64bit RTC in skeleton_hs.dtsi			[Vineet]
>
> v1:
>  - http://lists.infradead.org/pipermail/linux-snps-arc/2016-February/000447.html
>
> Signed-off-by: Vineet Gupta <vgupta at synopsys.com>

Rob, sorry for pinging you sooner than I should. This must be busy time ahead of
merge window. However if you can take a quick look at the DT bindings, we might be
able to squeeze this into 4.6
This code seems to be functionally working well and stable !

> ---
>  .../devicetree/bindings/timer/snps,arc-timer.txt   | 26 ++++++++++++++++++++++
>  .../devicetree/bindings/timer/snps,archs-gfrc.txt  | 14 ++++++++++++
>  .../devicetree/bindings/timer/snps,archs-rtc.txt   | 14 ++++++++++++
>  arch/arc/boot/dts/abilis_tb10x.dtsi                | 14 ++++++++++++
>  arch/arc/boot/dts/skeleton.dtsi                    | 14 ++++++++++++
>  arch/arc/boot/dts/skeleton_hs.dtsi                 | 20 +++++++++++++++++
>  arch/arc/boot/dts/skeleton_hs_idu.dtsi             | 14 ++++++++++++
>  7 files changed, 116 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/timer/snps,arc-timer.txt
>  create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
>  create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-rtc.txt
>
> diff --git a/Documentation/devicetree/bindings/timer/snps,arc-timer.txt b/Documentation/devicetree/bindings/timer/snps,arc-timer.txt
> new file mode 100644
> index 000000000000..9e02be24e805
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/snps,arc-timer.txt
> @@ -0,0 +1,26 @@
> +Synopsys ARC Local Timer with Interrupt Capabilities
> +- Found on all ARC CPUs (ARC700/ARCHS)
> +- Can be optionally programmed to interrupt on Limit
> +- Two idential copies TIMER0 and TIMER1 exist in ARC cores and historically
> +  TIMER0 used as clockevent provider (true for all ARC cores)
> +  TIMER1 used for clocksource (mandatory for ARC700, optional for ARC HS)
> +
> +Required properties:
> +
> +- compatible : should be "snps,arc-timer"
> +- interrupts : single Interrupt going into parent intc
> +	       (16 for ARCHS cores, 3 for ARC700 cores)
> +- clocks     : phandle to the source clock
> +
> +Optional properties:
> +
> +- interrupt-parent : phandle to parent intc
> +
> +Example:
> +
> +	timer at 0 {
> +		compatible = "snps,arc-timer0";
> +		interrupts = <3>;
> +		interrupt-parent = <&core_intc>;
> +		clocks = <&core_clk>;
> +	};
> diff --git a/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt b/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
> new file mode 100644
> index 000000000000..aaab100f54e7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
> @@ -0,0 +1,14 @@
> +Synopsys ARC Free Running 64-bit Global Timer for ARC HS CPUs
> +- clocksource provider for SMP SoC
> +
> +Required properties:
> +
> +- compatible : should be "snps,archs-gfrc"
> +- clocks     : phandle to the source clock
> +
> +Example:
> +
> +	timer at 1 {
> +		compatible = "snps,archs-gfrc";
> +		clocks = <&core_clk>;
> +	};
> diff --git a/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt b/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt
> new file mode 100644
> index 000000000000..13f756fa1d6d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt
> @@ -0,0 +1,14 @@
> +Synopsys ARC Free Running 64-bit Local Timer for ARC HS CPUs
> +- clocksource provider for UP SoC
> +
> +Required properties:
> +
> +- compatible : should be "snps,archs-rtc"
> +- clocks     : phandle to the source clock
> +
> +Example:
> +
> +	timer at 1 {
> +		compatible = "snps,arc-rtc";
> +		clocks = <&core_clk>;
> +	};
> diff --git a/arch/arc/boot/dts/abilis_tb10x.dtsi b/arch/arc/boot/dts/abilis_tb10x.dtsi
> index cfb5052239a1..eadbe71dfa22 100644
> --- a/arch/arc/boot/dts/abilis_tb10x.dtsi
> +++ b/arch/arc/boot/dts/abilis_tb10x.dtsi
> @@ -35,6 +35,20 @@
>  		};
>  	};
>  
> +	/* TIMER0 with interrupt for clockevent */
> +	timer at 0 {
> +		compatible = "snps,arc-timer";
> +		interrupts = <3>;
> +		interrupt-parent = <&intc>;
> +		clocks = <&cpu_clk>;
> +	};
> +
> +	/* TIMER1 for free running clocksource */
> +	timer at 1 {
> +		compatible = "snps,arc-timer";
> +		clocks = <&cpu_clk>;
> +	};
> +
>  	soc100 {
>  		#address-cells	= <1>;
>  		#size-cells	= <1>;
> diff --git a/arch/arc/boot/dts/skeleton.dtsi b/arch/arc/boot/dts/skeleton.dtsi
> index 296d371a335c..f6109c2feba7 100644
> --- a/arch/arc/boot/dts/skeleton.dtsi
> +++ b/arch/arc/boot/dts/skeleton.dtsi
> @@ -30,6 +30,20 @@
>  		};
>  	};
>  
> +	/* TIMER0 with interrupt for clockevent */
> +	timer at 0 {
> +		compatible = "snps,arc-timer";
> +		interrupts = <3>;
> +		interrupt-parent = <&core_intc>;
> +		clocks = <&core_clk>;
> +	};
> +
> +	/* TIMER1 for free running clocksource */
> +	timer at 1 {
> +		compatible = "snps,arc-timer";
> +		clocks = <&core_clk>;
> +	};
> +
>  	memory {
>  		device_type = "memory";
>  		reg = <0x80000000 0x10000000>;	/* 256M */
> diff --git a/arch/arc/boot/dts/skeleton_hs.dtsi b/arch/arc/boot/dts/skeleton_hs.dtsi
> index a53876669030..49caeabca37a 100644
> --- a/arch/arc/boot/dts/skeleton_hs.dtsi
> +++ b/arch/arc/boot/dts/skeleton_hs.dtsi
> @@ -25,6 +25,26 @@
>  		};
>  	};
>  
> +	/* TIMER0 with interrupt for clockevent */
> +	timer at 0 {
> +		compatible = "snps,arc-timer";
> +		interrupts = <16>;
> +		interrupt-parent = <&core_intc>;
> +		clocks = <&core_clk>;
> +	};
> +
> +	/* 64-bit Local RTC: preferred clocksource for UP */
> +	timer at 1 {
> +		compatible = "snps,archs-timer-rtc";
> +		clocks = <&core_clk>;
> +	};
> +
> +	/* TIMER1 for free running clocksource: Fallback if rtc not found */
> +	timer at 2 {
> +		compatible = "snps,arc-timer";
> +		clocks = <&core_clk>;
> +	};
> +
>  	memory {
>  		device_type = "memory";
>  		reg = <0x80000000 0x10000000>;	/* 256M */
> diff --git a/arch/arc/boot/dts/skeleton_hs_idu.dtsi b/arch/arc/boot/dts/skeleton_hs_idu.dtsi
> index 74898d017f7a..7e301ff16200 100644
> --- a/arch/arc/boot/dts/skeleton_hs_idu.dtsi
> +++ b/arch/arc/boot/dts/skeleton_hs_idu.dtsi
> @@ -25,6 +25,20 @@
>  		};
>  	};
>  
> +	/* TIMER0 with interrupt for clockevent */
> +	timer at 0 {
> +		compatible = "snps,arc-timer";
> +		interrupts = <16>;
> +		interrupt-parent = <&core_intc>;
> +		clocks = <&core_clk>;
> +	};
> +
> +	/* 64-bit Global Free Running Counter */
> +	timer at 1 {
> +		compatible = "snps,archs-timer-gfrc";
> +		clocks = <&core_clk>;
> +	};
> +
>  	memory {
>  		device_type = "memory";
>  		reg = <0x80000000 0x10000000>;	/* 256M */



From noamca at mellanox.com  Thu Mar 10 21:07:09 2016
From: noamca at mellanox.com (Noam Camus)
Date: Fri, 11 Mar 2016 05:07:09 +0000
Subject: [PATCH] arc: use little endian accesses
In-Reply-To: <1457636268.457.34.camel@synopsys.com>
References: <1457544064-16167-1-git-send-email-ltrimas@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8EDF9@us01wembx1.internal.synopsys.com>
 <1457595846.2868.10.camel@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8F1A0@us01wembx1.internal.synopsys.com>,
 <1457636268.457.34.camel@synopsys.com>
Message-ID: <HE1PR05MB1625869B55C8FB5657477812AAB50@HE1PR05MB1625.eurprd05.prod.outlook.com>

> From: Lada Trimasova <Lada.Trimasova at synopsys.com>
> Sent: Thursday, March 10, 2016 8:57 PM

> And for example, let's see what happens when we use "readl" in  function "serial8250_early_in" in driver/tty/serial/8250.

Is your DTS entry includes for serial node following entries:
reg-io-width = <4>
native-endian;

if answer is yes you should expect (in case of big endian compilation) that:
port->iotype would be equal to UPIO_MEM32BE, hence no readl() use for this case.

This is how it works for me here, it sounds like your case is similar.

Regards,
Noam

From Vineet.Gupta1 at synopsys.com  Thu Mar 10 21:18:32 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 11 Mar 2016 05:18:32 +0000
Subject: [PATCH] arc: use little endian accesses
References: <1457544064-16167-1-git-send-email-ltrimas@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8EDF9@us01wembx1.internal.synopsys.com>
 <201603100845.30602.arnd@arndb.de>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E8F5FE@us01wembx1.internal.synopsys.com>

On Thursday 10 March 2016 01:15 PM, Arnd Bergmann wrote:
> On Thursday 10 March 2016, Vineet Gupta wrote:
>> On Wednesday 09 March 2016 10:51 PM, Lada Trimasova wrote:
>>> Memory access primitives should use cpu_to_le16, cpu_to_le32, le16_to_cpu
>>> and le32_to_cpu because it is not really guaranteed that drivers handles
>>> any ordering themselves.
>> That is the driver issue. readxx as API simply returns data in native endianness.
>> We've had EZChip running big endian and so far and they didn't need this change.
> Most drivers using readl() or readl_relaxed() expect those to perform byte
> swaps on big-endian architectures, as the registers tend to be fixed endian,
> so the change seems reasonable.
>
> It depends a little bit on how endian mode is implemented in the CPU: do you
> follow the normal model of swapping byte order in the load/store instructions
> of the CPU when running big-endian, or is the CPU always running little-endian
> but the bus addresses get mangled on byte accesses to give the illusion
> of a big-endian system?

OK I got the response from hardware guys that we follow the normal mode of
swapping byte order for big-endian mode. Arnd can u please explain how that might
impact the io accessors, it at all.

And what exactly are semantics of readX() and ioreadX() - even if arch specific
and I'd be glad to change that for ARC.

I can also help with documenting them properly some where as went digging into
mailing list first thing Lada posted this patch :-)

Thx,
-Vineet


From Vineet.Gupta1 at synopsys.com  Thu Mar 10 22:47:54 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 11 Mar 2016 06:47:54 +0000
Subject: big endian builds
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E8F650@us01wembx1.internal.synopsys.com>

So for big endian kernel builds, just selecting the CONFIG_CPU_BIG_ENDIAN is not
sufficient, we also need to manually change the CROSS_COMPILE prefix to arceb-xxx.

@Anton, is that what you do for verification builds !

@Noam I presume your defconfig has CONFIG_CROSS_COMPILE or you have set in env
variable ?


The kernel build system needs to take take care of that. Do you guys have issues
with patch below

------------>
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index c8230f3395f2..4abcdb89e391 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -9,8 +9,12 @@
 UTS_MACHINE := arc
 
 ifeq ($(CROSS_COMPILE),)
+ifndef CONFIG_CPU_BIG_ENDIAN
+CROSS_COMPILE := arceb-linux-
+else
 CROSS_COMPILE := arc-linux-
 endif
+endif



From Vineet.Gupta1 at synopsys.com  Thu Mar 10 22:52:40 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 11 Mar 2016 06:52:40 +0000
Subject: big endian builds
References: <C2D7FE5348E1B147BCA15975FBA23075F4E8F650@us01wembx1.internal.synopsys.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E8F662@us01wembx1.internal.synopsys.com>

On Friday 11 March 2016 12:18 PM, Vineet Gupta wrote:
> So for big endian kernel builds, just selecting the CONFIG_CPU_BIG_ENDIAN is not
> sufficient, we also need to manually change the CROSS_COMPILE prefix to arceb-xxx.
>
> @Anton, is that what you do for verification builds !
>
> @Noam I presume your defconfig has CONFIG_CROSS_COMPILE or you have set in env
> variable ?
>
>
> The kernel build system needs to take take care of that. Do you guys have issues
> with patch below
>
> ------------>
> diff --git a/arch/arc/Makefile b/arch/arc/Makefile
> index c8230f3395f2..4abcdb89e391 100644
> --- a/arch/arc/Makefile
> +++ b/arch/arc/Makefile
> @@ -9,8 +9,12 @@
>  UTS_MACHINE := arc
>  
>  ifeq ($(CROSS_COMPILE),)
> +ifndef CONFIG_CPU_BIG_ENDIAN
> +CROSS_COMPILE := arceb-linux-
> +else

Please pardon this nonsense as lack of caffeine - despite the obvious fixup, I
still need to change the .config.
I think we need to revert the defconfig patch for fixing the CROSS_COMPILE prefix
after all !

>  CROSS_COMPILE := arc-linux-
>  endif
> +endif
>
>
> _______________________________________________
> linux-snps-arc mailing list
> linux-snps-arc at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-snps-arc
>



From Vineet.Gupta1 at synopsys.com  Fri Mar 11 01:27:19 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 11 Mar 2016 14:57:19 +0530
Subject: [PATCH 0/2] Big Endian build cleanups
Message-ID: <1457688441-31337-1-git-send-email-vgupta@synopsys.com>

Vineet Gupta (2):
  ARC: [BE] Select correct CROSS_COMPILE prefix
  ARC: [*defconfig] No need to specify CONFIG_CROSS_COMPILE

 arch/arc/Makefile                          | 4 ++++
 arch/arc/configs/axs101_defconfig          | 1 -
 arch/arc/configs/axs103_defconfig          | 1 -
 arch/arc/configs/axs103_smp_defconfig      | 1 -
 arch/arc/configs/nsim_700_defconfig        | 1 -
 arch/arc/configs/nsim_hs_defconfig         | 1 -
 arch/arc/configs/nsim_hs_smp_defconfig     | 1 -
 arch/arc/configs/nsimosci_defconfig        | 1 -
 arch/arc/configs/nsimosci_hs_defconfig     | 1 -
 arch/arc/configs/nsimosci_hs_smp_defconfig | 1 -
 arch/arc/configs/tb10x_defconfig           | 1 -
 arch/arc/configs/vdk_hs38_defconfig        | 1 -
 arch/arc/configs/vdk_hs38_smp_defconfig    | 1 -
 13 files changed, 4 insertions(+), 12 deletions(-)

-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Fri Mar 11 01:27:20 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 11 Mar 2016 14:57:20 +0530
Subject: [PATCH 1/2] ARC: [BE] Select correct CROSS_COMPILE prefix
In-Reply-To: <1457688441-31337-1-git-send-email-vgupta@synopsys.com>
References: <1457688441-31337-1-git-send-email-vgupta@synopsys.com>
Message-ID: <1457688441-31337-2-git-send-email-vgupta@synopsys.com>

This allows CONFIG_CPU_BIG_ENDIAN=y to build correctly out of the box,
w/o any other tweaks.

Cc: Noam Camus <noamc at ezchip.com>
Cc: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Anton Kolesov <akolesov at synosys.com>
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/Makefile | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index c8230f3395f2..babc09c61c6c 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -9,7 +9,11 @@
 UTS_MACHINE := arc
 
 ifeq ($(CROSS_COMPILE),)
+ifndef CONFIG_CPU_BIG_ENDIAN
 CROSS_COMPILE := arc-linux-
+else
+CROSS_COMPILE := arceb-linux-
+endif
 endif
 
 KBUILD_DEFCONFIG := nsim_700_defconfig
-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Fri Mar 11 01:27:21 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 11 Mar 2016 14:57:21 +0530
Subject: [PATCH 2/2] ARC: [*defconfig] No need to specify CONFIG_CROSS_COMPILE
In-Reply-To: <1457688441-31337-1-git-send-email-vgupta@synopsys.com>
References: <1457688441-31337-1-git-send-email-vgupta@synopsys.com>
Message-ID: <1457688441-31337-3-git-send-email-vgupta@synopsys.com>

The problem is with CONFIG_CPU_BIG_ENDIAN=y we still needed .config
fixup to override the the defconfig prefix to arceb-linux-

So remove these from defconfig and let user pass this via CROSS_COMPILE
environment var or use the default for ENDIAN (per previous patch)

No other arch carries them in defconfigs anyways !

Cc: Noam Camus <noamc at ezchip.com>
Cc: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Anton Kolesov <akolesov at synosys.com>
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/configs/axs101_defconfig          | 1 -
 arch/arc/configs/axs103_defconfig          | 1 -
 arch/arc/configs/axs103_smp_defconfig      | 1 -
 arch/arc/configs/nsim_700_defconfig        | 1 -
 arch/arc/configs/nsim_hs_defconfig         | 1 -
 arch/arc/configs/nsim_hs_smp_defconfig     | 1 -
 arch/arc/configs/nsimosci_defconfig        | 1 -
 arch/arc/configs/nsimosci_hs_defconfig     | 1 -
 arch/arc/configs/nsimosci_hs_smp_defconfig | 1 -
 arch/arc/configs/tb10x_defconfig           | 1 -
 arch/arc/configs/vdk_hs38_defconfig        | 1 -
 arch/arc/configs/vdk_hs38_smp_defconfig    | 1 -
 12 files changed, 12 deletions(-)

diff --git a/arch/arc/configs/axs101_defconfig b/arch/arc/configs/axs101_defconfig
index 5d4e2a07ad3e..6cdffea3a914 100644
--- a/arch/arc/configs/axs101_defconfig
+++ b/arch/arc/configs/axs101_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CROSS_COMPILE="arc-linux-"
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
diff --git a/arch/arc/configs/axs103_defconfig b/arch/arc/configs/axs103_defconfig
index 87ee46b237ef..f8b396c9aedb 100644
--- a/arch/arc/configs/axs103_defconfig
+++ b/arch/arc/configs/axs103_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CROSS_COMPILE="arc-linux-"
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
diff --git a/arch/arc/configs/axs103_smp_defconfig b/arch/arc/configs/axs103_smp_defconfig
index d80daf4f7e73..56128ea2b748 100644
--- a/arch/arc/configs/axs103_smp_defconfig
+++ b/arch/arc/configs/axs103_smp_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CROSS_COMPILE="arc-linux-"
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
diff --git a/arch/arc/configs/nsim_700_defconfig b/arch/arc/configs/nsim_700_defconfig
index f41095340b6a..7314f538847b 100644
--- a/arch/arc/configs/nsim_700_defconfig
+++ b/arch/arc/configs/nsim_700_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
diff --git a/arch/arc/configs/nsim_hs_defconfig b/arch/arc/configs/nsim_hs_defconfig
index cfaa33cb5921..a99dc7a3f0af 100644
--- a/arch/arc/configs/nsim_hs_defconfig
+++ b/arch/arc/configs/nsim_hs_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
diff --git a/arch/arc/configs/nsim_hs_smp_defconfig b/arch/arc/configs/nsim_hs_smp_defconfig
index bb2a8dc778b5..59f221fc9a41 100644
--- a/arch/arc/configs/nsim_hs_smp_defconfig
+++ b/arch/arc/configs/nsim_hs_smp_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
diff --git a/arch/arc/configs/nsimosci_defconfig b/arch/arc/configs/nsimosci_defconfig
index 646182e93753..0972e753101a 100644
--- a/arch/arc/configs/nsimosci_defconfig
+++ b/arch/arc/configs/nsimosci_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
diff --git a/arch/arc/configs/nsimosci_hs_defconfig b/arch/arc/configs/nsimosci_hs_defconfig
index ceca2541950d..24d9d0e18232 100644
--- a/arch/arc/configs/nsimosci_hs_defconfig
+++ b/arch/arc/configs/nsimosci_hs_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
diff --git a/arch/arc/configs/nsimosci_hs_smp_defconfig b/arch/arc/configs/nsimosci_hs_smp_defconfig
index 4b6da90f6f26..6746d01b6d7b 100644
--- a/arch/arc/configs/nsimosci_hs_smp_defconfig
+++ b/arch/arc/configs/nsimosci_hs_smp_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CROSS_COMPILE="arc-linux-"
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
diff --git a/arch/arc/configs/tb10x_defconfig b/arch/arc/configs/tb10x_defconfig
index 9b342eaf95ae..4c5118384eb5 100644
--- a/arch/arc/configs/tb10x_defconfig
+++ b/arch/arc/configs/tb10x_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="tb10x"
 CONFIG_SYSVIPC=y
diff --git a/arch/arc/configs/vdk_hs38_defconfig b/arch/arc/configs/vdk_hs38_defconfig
index a07f20de221b..c0d6a010751a 100644
--- a/arch/arc/configs/vdk_hs38_defconfig
+++ b/arch/arc/configs/vdk_hs38_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_CROSS_MEMORY_ATTACH is not set
diff --git a/arch/arc/configs/vdk_hs38_smp_defconfig b/arch/arc/configs/vdk_hs38_smp_defconfig
index 735985974a31..52ec315dc5c9 100644
--- a/arch/arc/configs/vdk_hs38_smp_defconfig
+++ b/arch/arc/configs/vdk_hs38_smp_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_CROSS_MEMORY_ATTACH is not set
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Fri Mar 11 01:56:56 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Fri, 11 Mar 2016 09:56:56 +0000
Subject: [PATCH 2/2] ARC: [*defconfig] No need to specify
 CONFIG_CROSS_COMPILE
In-Reply-To: <1457688441-31337-3-git-send-email-vgupta@synopsys.com>
References: <1457688441-31337-1-git-send-email-vgupta@synopsys.com>
 <1457688441-31337-3-git-send-email-vgupta@synopsys.com>
Message-ID: <1457690216.3255.1.camel@synopsys.com>

Hi Vineet,

On Fri, 2016-03-11 at 14:57 +0530, Vineet Gupta wrote:
> The problem is with CONFIG_CPU_BIG_ENDIAN=y we still needed .config
> fixup to override the the defconfig prefix to arceb-linux-
> 
> So remove these from defconfig and let user pass this via CROSS_COMPILE
> environment var or use the default for ENDIAN (per previous patch)
> 
> No other arch carries them in defconfigs anyways !
> 
> Cc: Noam Camus <noamc at ezchip.com>
> Cc: Alexey Brodkin <abrodkin at synopsys.com>
> Cc: Anton Kolesov <akolesov at synosys.com>
> Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
> ---

Acked-by: Alexey Brodkin <abrodkin at synopsys.com>

From Alexey.Brodkin at synopsys.com  Fri Mar 11 01:56:37 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Fri, 11 Mar 2016 09:56:37 +0000
Subject: [PATCH 1/2] ARC: [BE] Select correct CROSS_COMPILE prefix
In-Reply-To: <1457688441-31337-2-git-send-email-vgupta@synopsys.com>
References: <1457688441-31337-1-git-send-email-vgupta@synopsys.com>
 <1457688441-31337-2-git-send-email-vgupta@synopsys.com>
Message-ID: <1457690197.3255.0.camel@synopsys.com>

Hi Vineet,

On Fri, 2016-03-11 at 14:57 +0530, Vineet Gupta wrote:
> This allows CONFIG_CPU_BIG_ENDIAN=y to build correctly out of the box,
> w/o any other tweaks.
> 
> Cc: Noam Camus <noamc at ezchip.com>
> Cc: Alexey Brodkin <abrodkin at synopsys.com>
> Cc: Anton Kolesov <akolesov at synosys.com>
> Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
> ---

Acked-by: Alexey Brodkin <abrodkin at synopsys.com>

From Anton.Kolesov at synopsys.com  Fri Mar 11 04:13:57 2016
From: Anton.Kolesov at synopsys.com (Anton Kolesov)
Date: Fri, 11 Mar 2016 12:13:57 +0000
Subject: big endian builds
In-Reply-To: <C2D7FE5348E1B147BCA15975FBA23075F4E8F662@us01wembx1.internal.synopsys.com>
References: <C2D7FE5348E1B147BCA15975FBA23075F4E8F650@us01wembx1.internal.synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8F662@us01wembx1.internal.synopsys.com>
Message-ID: <39A54937CC95F24AA2F794E2D2B66B13580BBABA@DE02WEMBXB.internal.synopsys.com>

Nightly verification script modifies CONFIG_CROSS_COMPILE in the .config file before build Linux - little or big endian doesn't matter, so path to tools is always correct. It sets full path in .config, instead of prepending PATH. CONFIG_CPU_BIG_ENDIAN is set accordingly.

--------8<--------

# Generate proper .config file from defconfig
make $MAKEFLAGS -C $src_dir/linux O=$odir ARCH=arc olddefconfig

# Set toolchain path
sed -i \
    -e "s|CONFIG_CROSS_COMPILE=\".*\"|CONFIG_CROSS_COMPILE=\"$build_dir/$target_toolchain/bin/$target_prefix\"|" \
    $odir/.config

# Set proper endianness. It's necessary to set it explicitly because
# we are not sure what value for CONFIG_CPU_BIG_ENDIAN flag is set
# because of impact of allnoconfig or allyesconfig configurations.
if [ $target_endian = eb ]; then
    kconfig_enable_option $odir CONFIG_CPU_BIG_ENDIAN
else
    kconfig_disable_option $odir CONFIG_CPU_BIG_ENDIAN
fi


# Regenerate .config with new CONFIG_CPU_BIG_ENDIAN option value. It's
# necessary because this option may be not presented in platforms defconfigs
# thus sed cannot fix it before generating the first version of .config.
make $MAKEFLAGS -C $src_dir/linux O=$odir ARCH=arc olddefconfig

--------8<--------

Anton

> -----Original Message-----
> From: Vineet Gupta [mailto:vgupta at synopsys.com]
> Sent: Friday, March 11, 2016 9:53 AM
> To: Vineet Gupta <Vineet.Gupta1 at synopsys.com>; Anton Kolesov <Anton.Kolesov at synopsys.com>; Alexey
> Brodkin <Alexey.Brodkin at synopsys.com>; Noam Camus <noamc at ezchip.com>
> Cc: arcml <linux-snps-arc at lists.infradead.org>
> Subject: Re: big endian builds
> 
> On Friday 11 March 2016 12:18 PM, Vineet Gupta wrote:
> > So for big endian kernel builds, just selecting the CONFIG_CPU_BIG_ENDIAN is not
> > sufficient, we also need to manually change the CROSS_COMPILE prefix to arceb-xxx.
> >
> > @Anton, is that what you do for verification builds !
> >
> > @Noam I presume your defconfig has CONFIG_CROSS_COMPILE or you have set in env
> > variable ?
> >
> >
> > The kernel build system needs to take take care of that. Do you guys have issues
> > with patch below
> >
> > ------------>
> > diff --git a/arch/arc/Makefile b/arch/arc/Makefile
> > index c8230f3395f2..4abcdb89e391 100644
> > --- a/arch/arc/Makefile
> > +++ b/arch/arc/Makefile
> > @@ -9,8 +9,12 @@
> >  UTS_MACHINE := arc
> >
> >  ifeq ($(CROSS_COMPILE),)
> > +ifndef CONFIG_CPU_BIG_ENDIAN
> > +CROSS_COMPILE := arceb-linux-
> > +else
> 
> Please pardon this nonsense as lack of caffeine - despite the obvious fixup, I
> still need to change the .config.
> I think we need to revert the defconfig patch for fixing the CROSS_COMPILE prefix
> after all !
> 
> >  CROSS_COMPILE := arc-linux-
> >  endif
> > +endif
> >
> >
> > _______________________________________________
> > linux-snps-arc mailing list
> > linux-snps-arc at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-snps-arc
> >



From Vineet.Gupta1 at synopsys.com  Fri Mar 11 04:44:28 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 11 Mar 2016 12:44:28 +0000
Subject: [PATCH] arc: use little endian accesses
References: <1457544064-16167-1-git-send-email-ltrimas@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8F1A0@us01wembx1.internal.synopsys.com>
 <1457636268.457.34.camel@synopsys.com> <201603102023.59425.arnd@arndb.de>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E8F790@us01wembx1.internal.synopsys.com>

On Friday 11 March 2016 12:54 AM, Arnd Bergmann wrote:
> On Thursday 10 March 2016, Lada Trimasova wrote:
>> Driver is 8250, kernel is built for BE arc, nsim option in model "nsim_isa_big_endian = 1".
>>
>> With current "readl" and "writel" implementation for ARC we read word from memory without any endianess manipulation. So in case of little endian architecture we get what we want: the first memory byte is the low byte in the word. But in case of big endian architecture the word endianess is swapped: the first memory byte is the high word byte.
>>
>> And for example, let's see what happens when we use "readl" in  function "serial8250_early_in" in driver/tty/serial/8250.
>>
>> Take a look to one line from memory dump:
>> 0xf0000010: 0x0b    0x00    0x00    0x00    0x60    0x00    0x00    0x00
>>
>> When kernel is built for little endian architecture, we read this data in status register in function "serial_putc" using "readl" function in driver/tty/serial/8250 as:
>> r0: 0x0000006
>> The low byte is 0x0b, so the condition "if ((status & BOTH_EMPTY) == BOTH_EMPTY)"  is true, as BOTH_EMPTY is some mask with low bytes set.
>>
>> When kernel is built with "CPU_BIG_ENDIAN" and model nsim option is "nsim_isa_big_endian=1", we read this data as:
>> r0: 0x6000000
>> So as you can see the low byte is 0x00 and above mentioned condition never becomes true, we can't continue initialization.
>>
> Ok, this sounds like a completely normal architecture implementation then,
> and your patch looks correct.
>
> If some other driver breaks because of this change, you should investigate
> what went wrong there, and treat it as a driver specific problem.

Although I believe Arnd the most, I was not convinced abt this (see below why) so
did a bit of investigation and looks like this patch is indeed correct and Arnd as
always is right :-)

The current upstream kernel doesn't boot on BE configured AXS103 is stuck
similarly in uart. With this patch it comes up fine. My trouble was I'd seen BE
work (w/o this patch) in our internal 3.18 branch. Turns out that in 3.18, ARC
io.h used the asm-generic version of readX(). My patch b8a033023994 ("ARCv2:
barriers") to upstream introduced the io barriers for ARCHS and in the process
introduced our own readX() accessors, which were not the same as correct
asm-generic ver. Thus I inadvertently introduced this bug.

@Lada I will fix up the changelog to add some of the background behind this
change, and mark this for stable backport as well.

Thx,
-Vineet

>
> 	Arnd
>



From Alexey.Brodkin at synopsys.com  Fri Mar 11 07:42:35 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Fri, 11 Mar 2016 18:42:35 +0300
Subject: [PATCH 0/4 v3] drm: Add support of ARC PGU display controller
Message-ID: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>

This series add support of ARC PGU display controller.
ARC PGU is a quite simple byte streamer that gets data from the framebuffer
and pushes it to hte connected encoder (DP or HDMI).

It was tested on ARC SDP boards (axs101 in particular).

Changes v2 -> v3:
 * Improved failure path if arcpgu_connector wasn't allocated.
 * Fixed driver building as module.
 * Implemented uncached mapping of user-space FB pages.
 * Again updated DT bindings docs.

Changes v1 -> v2:
 * Clean-up of DT bindings documentation.
 * Added missing "pxlclk" clock in axs10x_mb.dtsi.

Cc: David Airlie <airlied at linux.ie>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: linux-snps-arc at lists.infradead.org
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Vineet Gupta <vgupta at synopsys.com>

Alexey Brodkin (4):
  drm: Add support of ARC PGU display controller
  drm: Add DT bindings documentation for ARC PGU display controller
  arc: axs10x - add support of ARC PGU
  MAINTAINERS: Add maintainer for ARC PGU display controller

 .../devicetree/bindings/display/snps,arcpgu.txt    |  72 ++++++
 MAINTAINERS                                        |   6 +
 arch/arc/boot/dts/axs10x_mb.dtsi                   |  61 +++++
 drivers/gpu/drm/Kconfig                            |   2 +
 drivers/gpu/drm/Makefile                           |   1 +
 drivers/gpu/drm/arc/Kconfig                        |  10 +
 drivers/gpu/drm/arc/Makefile                       |   2 +
 drivers/gpu/drm/arc/arcpgu.h                       |  50 ++++
 drivers/gpu/drm/arc/arcpgu_crtc.c                  | 274 +++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_drv.c                   | 252 +++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_fbdev.c                 | 245 ++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_hdmi.c                  | 207 ++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_regs.h                  |  36 +++
 13 files changed, 1218 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt
 create mode 100644 drivers/gpu/drm/arc/Kconfig
 create mode 100644 drivers/gpu/drm/arc/Makefile
 create mode 100644 drivers/gpu/drm/arc/arcpgu.h
 create mode 100644 drivers/gpu/drm/arc/arcpgu_crtc.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_drv.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_fbdev.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_hdmi.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_regs.h

-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Fri Mar 11 07:42:36 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Fri, 11 Mar 2016 18:42:36 +0300
Subject: [PATCH 1/4 v3] drm: Add support of ARC PGU display controller
In-Reply-To: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1457710959-9562-2-git-send-email-abrodkin@synopsys.com>

ARC PGU could be found on some development boards from Synopsys.
This is a simple byte streamer that reads data from a framebuffer
and sends data to the single encoder.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: David Airlie <airlied at linux.ie>
Cc: dri-devel at lists.freedesktop.org
Cc: linux-snps-arc at lists.infradead.org
Cc: Jose Abreu <joabreu at synopsys.com>
---

Changes v2 -> v3:
 * Improved failure path if arcpgu_connector wasn't allocated (thanks Jose).
 * Fixed driver building as module (reported by 0-DAY kernel test infrastruct.)
 * Implemented uncached mapping of user-space FB pages.

No changes v1 -> v2.

 drivers/gpu/drm/Kconfig            |   2 +
 drivers/gpu/drm/Makefile           |   1 +
 drivers/gpu/drm/arc/Kconfig        |  10 ++
 drivers/gpu/drm/arc/Makefile       |   2 +
 drivers/gpu/drm/arc/arcpgu.h       |  50 +++++++
 drivers/gpu/drm/arc/arcpgu_crtc.c  | 274 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_drv.c   | 252 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_fbdev.c | 245 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_hdmi.c  | 207 ++++++++++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_regs.h  |  36 +++++
 10 files changed, 1079 insertions(+)
 create mode 100644 drivers/gpu/drm/arc/Kconfig
 create mode 100644 drivers/gpu/drm/arc/Makefile
 create mode 100644 drivers/gpu/drm/arc/arcpgu.h
 create mode 100644 drivers/gpu/drm/arc/arcpgu_crtc.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_drv.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_fbdev.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_hdmi.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_regs.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index f2a74d0..9e4f2f1 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -281,3 +281,5 @@ source "drivers/gpu/drm/imx/Kconfig"
 source "drivers/gpu/drm/vc4/Kconfig"
 
 source "drivers/gpu/drm/etnaviv/Kconfig"
+
+source "drivers/gpu/drm/arc/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 6eb94fc..c338d04 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -78,3 +78,4 @@ obj-y			+= panel/
 obj-y			+= bridge/
 obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
 obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
+obj-$(CONFIG_DRM_ARCPGU)+= arc/
diff --git a/drivers/gpu/drm/arc/Kconfig b/drivers/gpu/drm/arc/Kconfig
new file mode 100644
index 0000000..f9a13b6
--- /dev/null
+++ b/drivers/gpu/drm/arc/Kconfig
@@ -0,0 +1,10 @@
+config DRM_ARCPGU
+	tristate "ARC PGU"
+	depends on DRM && OF
+	select DRM_KMS_CMA_HELPER
+	select DRM_KMS_FB_HELPER
+	select DRM_KMS_HELPER
+	help
+	  Choose this option if you have an ARC PGU controller.
+
+	  If M is selected the module will be called arcpgu.
diff --git a/drivers/gpu/drm/arc/Makefile b/drivers/gpu/drm/arc/Makefile
new file mode 100644
index 0000000..736ee6f
--- /dev/null
+++ b/drivers/gpu/drm/arc/Makefile
@@ -0,0 +1,2 @@
+arcpgu-y := arcpgu_crtc.o arcpgu_hdmi.o arcpgu_fbdev.o arcpgu_drv.o
+obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o
diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h
new file mode 100644
index 0000000..86574b6
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu.h
@@ -0,0 +1,50 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ARCPGU_H_
+#define _ARCPGU_H_
+
+struct arcpgu_drm_private {
+	void __iomem		*regs;
+	struct clk		*clk;
+	struct drm_fbdev_cma	*fbdev;
+	struct drm_framebuffer	*fb;
+	struct list_head	event_list;
+	struct drm_crtc		crtc;
+	struct drm_plane	*plane;
+};
+
+#define crtc_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, crtc)
+
+static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu,
+				 unsigned int reg, u32 value)
+{
+	iowrite32(value, arcpgu->regs + reg);
+}
+
+static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu,
+			       unsigned int reg)
+{
+	return ioread32(arcpgu->regs + reg);
+}
+
+int arc_pgu_setup_crtc(struct drm_device *dev);
+int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np);
+struct drm_fbdev_cma *arcpgu_fbdev_cma_init(struct drm_device *dev,
+	unsigned int preferred_bpp, unsigned int num_crtc,
+	unsigned int max_conn_count);
+
+#endif
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
new file mode 100644
index 0000000..0fe5c8a
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
@@ -0,0 +1,274 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <linux/clk.h>
+#include <linux/platform_data/simplefb.h>
+
+#include "arcpgu.h"
+#include "arcpgu_regs.h"
+
+#define ENCODE_PGU_XY(x, y)	((((x) - 1) << 16) | ((y) - 1))
+
+static struct simplefb_format supported_formats[] = {
+	{ "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0}, DRM_FORMAT_RGB565 },
+	{ "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 },
+};
+
+static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	uint32_t pixel_format = crtc->primary->state->fb->pixel_format;
+	struct simplefb_format *format = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
+		if (supported_formats[i].fourcc == pixel_format)
+			format = &supported_formats[i];
+	}
+
+	if (WARN_ON(!format))
+		return;
+
+	if (format->fourcc == DRM_FORMAT_RGB888)
+		arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+			      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) |
+					   ARCPGU_MODE_RGB888_MASK);
+
+}
+
+static const struct drm_crtc_funcs arc_pgu_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 void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	struct drm_display_mode *m = &crtc->state->adjusted_mode;
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_FMT,
+		      ENCODE_PGU_XY(m->crtc_htotal, m->crtc_vtotal));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_HSYNC,
+		      ENCODE_PGU_XY(m->crtc_hsync_start - m->crtc_hdisplay,
+				    m->crtc_hsync_end - m->crtc_hdisplay));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_VSYNC,
+		      ENCODE_PGU_XY(m->crtc_vsync_start - m->crtc_vdisplay,
+				    m->crtc_vsync_end - m->crtc_vdisplay));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_ACTIVE,
+		      ENCODE_PGU_XY(m->crtc_hblank_end - m->crtc_hblank_start,
+				    m->crtc_vblank_end - m->crtc_vblank_start));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_STRIDE, 0);
+	arc_pgu_write(arcpgu, ARCPGU_REG_START_SET, 1);
+
+	arc_pgu_set_pxl_fmt(crtc);
+
+	clk_set_rate(arcpgu->clk, m->crtc_clock * 1000);
+}
+
+static void arc_pgu_crtc_enable(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+
+	clk_prepare_enable(arcpgu->clk);
+	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+		      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) |
+		      ARCPGU_CTRL_ENABLE_MASK);
+}
+
+static void arc_pgu_crtc_disable(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+
+	if (!crtc->primary->fb)
+		return;
+
+	clk_disable_unprepare(arcpgu->clk);
+	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+			      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) &
+			      ~ARCPGU_CTRL_ENABLE_MASK);
+}
+
+static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc,
+				     struct drm_crtc_state *state)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	struct drm_display_mode *mode = &state->adjusted_mode;
+	long rate, clk_rate = mode->clock * 1000;
+
+	rate = clk_round_rate(arcpgu->clk, clk_rate);
+	if (rate != clk_rate)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
+				      struct drm_crtc_state *state)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	unsigned long flags;
+
+	if (crtc->state->event) {
+		struct drm_pending_vblank_event *event = crtc->state->event;
+
+		crtc->state->event = NULL;
+		event->pipe = drm_crtc_index(crtc);
+
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+		spin_lock_irqsave(&crtc->dev->event_lock, flags);
+		list_add_tail(&event->base.link, &arcpgu->event_list);
+		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+	}
+}
+
+static void arc_pgu_crtc_atomic_flush(struct drm_crtc *crtc,
+				      struct drm_crtc_state *state)
+{
+}
+
+static bool arc_pgu_crtc_mode_fixup(struct drm_crtc *crtc,
+				    const struct drm_display_mode *mode,
+				    struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
+	.mode_fixup	= arc_pgu_crtc_mode_fixup,
+	.mode_set	= drm_helper_crtc_mode_set,
+	.mode_set_base	= drm_helper_crtc_mode_set_base,
+	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
+	.enable		= arc_pgu_crtc_enable,
+	.disable	= arc_pgu_crtc_disable,
+	.prepare	= arc_pgu_crtc_disable,
+	.commit		= arc_pgu_crtc_enable,
+	.atomic_check	= arc_pgu_crtc_atomic_check,
+	.atomic_begin	= arc_pgu_crtc_atomic_begin,
+	.atomic_flush	= arc_pgu_crtc_atomic_flush,
+};
+
+static int arc_pgu_plane_atomic_check(struct drm_plane *plane,
+				      struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void arc_pgu_plane_atomic_update(struct drm_plane *plane,
+					struct drm_plane_state *state)
+{
+	struct arcpgu_drm_private *arcpgu;
+	struct drm_gem_cma_object *gem;
+
+	if (!plane->state->crtc || !plane->state->fb)
+		return;
+
+	arcpgu = crtc_to_arcpgu_priv(plane->state->crtc);
+	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
+	arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr);
+}
+
+static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = {
+	.prepare_fb = NULL,
+	.cleanup_fb = NULL,
+	.atomic_check = arc_pgu_plane_atomic_check,
+	.atomic_update = arc_pgu_plane_atomic_update,
+};
+
+static void arc_pgu_plane_destroy(struct drm_plane *plane)
+{
+	drm_plane_helper_disable(plane);
+	drm_plane_cleanup(plane);
+}
+
+static const struct drm_plane_funcs arc_pgu_plane_funcs = {
+	.update_plane		= drm_atomic_helper_update_plane,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.destroy		= arc_pgu_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 struct drm_plane *arc_pgu_plane_init(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_plane *plane = NULL;
+	u32 formats[ARRAY_SIZE(supported_formats)], i;
+	int ret;
+
+	plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
+	if (!plane)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(supported_formats); i++)
+		formats[i] = supported_formats[i].fourcc;
+
+	ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs,
+				       formats, ARRAY_SIZE(formats),
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_plane_helper_add(plane, &arc_pgu_plane_helper_funcs);
+	arcpgu->plane = plane;
+
+	return plane;
+}
+
+void arc_pgu_crtc_suspend(struct drm_crtc *crtc)
+{
+	arc_pgu_crtc_disable(crtc);
+}
+
+void arc_pgu_crtc_resume(struct drm_crtc *crtc)
+{
+	arc_pgu_crtc_enable(crtc);
+}
+
+int arc_pgu_setup_crtc(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_plane *primary;
+	int ret;
+
+	primary = arc_pgu_plane_init(drm);
+	if (IS_ERR(primary))
+		return PTR_ERR(primary);
+
+	ret = drm_crtc_init_with_planes(drm, &arcpgu->crtc, primary, NULL,
+					&arc_pgu_crtc_funcs, NULL);
+	if (ret) {
+		arc_pgu_plane_destroy(primary);
+		return ret;
+	}
+
+	drm_crtc_helper_add(&arcpgu->crtc, &arc_pgu_crtc_helper_funcs);
+	return 0;
+}
diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c
new file mode 100644
index 0000000..d47481d
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_drv.c
@@ -0,0 +1,252 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "arcpgu.h"
+#include "arcpgu_regs.h"
+
+static void arcpgu_fb_output_poll_changed(struct drm_device *dev)
+{
+	struct arcpgu_drm_private *arcpgu = dev->dev_private;
+
+	if (arcpgu->fbdev)
+		drm_fbdev_cma_hotplug_event(arcpgu->fbdev);
+}
+
+static int arcpgu_atomic_commit(struct drm_device *dev,
+				    struct drm_atomic_state *state, bool async)
+{
+	return drm_atomic_helper_commit(dev, state, false);
+}
+
+static struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = {
+	.fb_create  = drm_fb_cma_create,
+	.output_poll_changed = arcpgu_fb_output_poll_changed,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = arcpgu_atomic_commit,
+};
+
+static void arcpgu_setup_mode_config(struct drm_device *drm)
+{
+	drm_mode_config_init(drm);
+	drm->mode_config.min_width = 0;
+	drm->mode_config.min_height = 0;
+	drm->mode_config.max_width = 1920;
+	drm->mode_config.max_height = 1080;
+	drm->mode_config.funcs = &arcpgu_drm_modecfg_funcs;
+}
+
+int arcpgu_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	int ret;
+
+	ret = drm_gem_mmap(filp, vma);
+	if (ret)
+		return ret;
+
+	vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags));
+	return 0;
+}
+
+static const struct file_operations arcpgu_drm_ops = {
+	.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 = no_llseek,
+	.mmap = arcpgu_gem_mmap,
+};
+
+static void arcpgu_preclose(struct drm_device *drm, struct drm_file *file)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_pending_vblank_event *e, *t;
+	unsigned long flags;
+
+	spin_lock_irqsave(&drm->event_lock, flags);
+	list_for_each_entry_safe(e, t, &arcpgu->event_list, base.link) {
+		if (e->base.file_priv != file)
+			continue;
+		list_del(&e->base.link);
+		e->base.destroy(&e->base);
+	}
+	spin_unlock_irqrestore(&drm->event_lock, flags);
+}
+
+static void arcpgu_lastclose(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+
+	drm_fbdev_cma_restore_mode(arcpgu->fbdev);
+}
+
+static int arcpgu_load(struct drm_device *drm, unsigned long flags)
+{
+	struct platform_device *pdev = drm->platformdev;
+	struct arcpgu_drm_private *arcpgu;
+	struct device_node *encoder_node;
+	struct resource *res;
+	int ret;
+
+	arcpgu = devm_kzalloc(&pdev->dev, sizeof(*arcpgu), GFP_KERNEL);
+	if (arcpgu == NULL)
+		return -ENOMEM;
+
+	drm->dev_private = arcpgu;
+
+	arcpgu->clk = devm_clk_get(drm->dev, "pxlclk");
+	if (IS_ERR(arcpgu->clk))
+		return PTR_ERR(arcpgu->clk);
+
+	INIT_LIST_HEAD(&arcpgu->event_list);
+
+	arcpgu_setup_mode_config(drm);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	arcpgu->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(arcpgu->regs)) {
+		dev_err(drm->dev, "Could not remap IO mem\n");
+		return PTR_ERR(arcpgu->regs);
+	}
+
+	dev_info(drm->dev, "arc_pgu ID: 0x%x\n",
+		 arc_pgu_read(arcpgu, ARCPGU_REG_ID));
+
+	if (dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32)))
+		return -ENODEV;
+
+	if (arc_pgu_setup_crtc(drm) < 0)
+		return -ENODEV;
+
+	/* find the encoder node and initialize it */
+	encoder_node = of_parse_phandle(drm->dev->of_node, "encoder-slave", 0);
+	if (!encoder_node) {
+		dev_err(drm->dev, "failed to get an encoder slave node\n");
+		return -ENODEV;
+	}
+
+	ret = arcpgu_drm_hdmi_init(drm, encoder_node);
+	if (ret < 0)
+		return ret;
+
+	drm_mode_config_reset(drm);
+	drm_kms_helper_poll_init(drm);
+
+	arcpgu->fbdev = arcpgu_fbdev_cma_init(drm, 16,
+					      drm->mode_config.num_crtc,
+					      drm->mode_config.num_connector);
+	if (IS_ERR(arcpgu->fbdev)) {
+		ret = PTR_ERR(arcpgu->fbdev);
+		arcpgu->fbdev = NULL;
+		return -ENODEV;
+	}
+
+	platform_set_drvdata(pdev, arcpgu);
+	return 0;
+}
+
+int arcpgu_unload(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+
+	if (arcpgu->fbdev) {
+		drm_fbdev_cma_fini(arcpgu->fbdev);
+		arcpgu->fbdev = NULL;
+	}
+	drm_kms_helper_poll_fini(drm);
+	drm_vblank_cleanup(drm);
+	drm_mode_config_cleanup(drm);
+
+	return 0;
+}
+
+static struct drm_driver arcpgu_drm_driver = {
+	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
+			   DRIVER_ATOMIC,
+	.preclose = arcpgu_preclose,
+	.lastclose = arcpgu_lastclose,
+	.name = "drm-arcpgu",
+	.desc = "ARC PGU Controller",
+	.date = "20160219",
+	.major = 1,
+	.minor = 0,
+	.patchlevel = 0,
+	.fops = &arcpgu_drm_ops,
+	.load = arcpgu_load,
+	.unload = arcpgu_unload,
+	.dumb_create = drm_gem_cma_dumb_create,
+	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
+	.dumb_destroy = drm_gem_dumb_destroy,
+	.get_vblank_counter = drm_vblank_no_hw_counter,
+	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+	.gem_free_object = drm_gem_cma_free_object,
+	.gem_vm_ops = &drm_gem_cma_vm_ops,
+	.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,
+};
+
+static int arcpgu_probe(struct platform_device *pdev)
+{
+	return drm_platform_init(&arcpgu_drm_driver, pdev);
+}
+
+static int arcpgu_remove(struct platform_device *pdev)
+{
+	struct drm_device *drm = dev_get_drvdata(&pdev->dev);
+
+	drm_put_dev(drm);
+
+	return 0;
+}
+
+static const struct of_device_id arcpgu_of_table[] = {
+	{.compatible = "snps,arcpgu"},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, arcpgu_of_table);
+
+static struct platform_driver arcpgu_platform_driver = {
+	.probe = arcpgu_probe,
+	.remove = arcpgu_remove,
+	.driver = {
+		   .name = "arcpgu",
+		   .owner = THIS_MODULE,
+		   .of_match_table = arcpgu_of_table,
+		   },
+};
+
+module_platform_driver(arcpgu_platform_driver);
+
+MODULE_AUTHOR("Carlos Palminha <palminha at synopsys.com");
+MODULE_DESCRIPTION("ARC PGU DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/arc/arcpgu_fbdev.c b/drivers/gpu/drm/arc/arcpgu_fbdev.c
new file mode 100644
index 0000000..6f67706
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_fbdev.c
@@ -0,0 +1,245 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <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>
+
+struct drm_fb_cma {
+	struct drm_framebuffer		fb;
+	struct drm_gem_cma_object	*obj[4];
+};
+
+struct drm_fbdev_cma {
+	struct drm_fb_helper	fb_helper;
+	struct drm_fb_cma	*fb;
+};
+
+static inline struct drm_fbdev_cma *to_fbdev_cma(struct drm_fb_helper *helper)
+{
+	return container_of(helper, struct drm_fbdev_cma, fb_helper);
+}
+
+static inline struct drm_fb_cma *to_fb_cma(struct drm_framebuffer *fb)
+{
+	return container_of(fb, struct drm_fb_cma, fb);
+}
+
+static void drm_fb_cma_destroy(struct drm_framebuffer *fb)
+{
+	struct drm_fb_cma *fb_cma = to_fb_cma(fb);
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		if (fb_cma->obj[i])
+			drm_gem_object_unreference_unlocked(&fb_cma->obj[i]->base);
+	}
+
+	drm_framebuffer_cleanup(fb);
+	kfree(fb_cma);
+}
+
+static int drm_fb_cma_create_handle(struct drm_framebuffer *fb,
+	struct drm_file *file_priv, unsigned int *handle)
+{
+	struct drm_fb_cma *fb_cma = to_fb_cma(fb);
+
+	return drm_gem_handle_create(file_priv,
+			&fb_cma->obj[0]->base, handle);
+}
+
+static struct drm_framebuffer_funcs drm_fb_cma_funcs = {
+	.destroy	= drm_fb_cma_destroy,
+	.create_handle	= drm_fb_cma_create_handle,
+};
+
+static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev,
+	const struct drm_mode_fb_cmd2 *mode_cmd,
+	struct drm_gem_cma_object **obj,
+	unsigned int num_planes)
+{
+	struct drm_fb_cma *fb_cma;
+	int ret;
+	int i;
+
+	fb_cma = kzalloc(sizeof(*fb_cma), GFP_KERNEL);
+	if (!fb_cma)
+		return ERR_PTR(-ENOMEM);
+
+	drm_helper_mode_fill_fb_struct(&fb_cma->fb, mode_cmd);
+
+	for (i = 0; i < num_planes; i++)
+		fb_cma->obj[i] = obj[i];
+
+	ret = drm_framebuffer_init(dev, &fb_cma->fb, &drm_fb_cma_funcs);
+	if (ret) {
+		dev_err(dev->dev, "Failed to initialize framebuffer: %d\n", ret);
+		kfree(fb_cma);
+		return ERR_PTR(ret);
+	}
+
+	return fb_cma;
+}
+
+/*
+ * This function is the only reason to have a copy of drm_fbdev_cma_init()
+ * here in this driver.
+ *
+ * In its turn this mmap() is required to mark user-space page as non-cached
+ * because it is just a mirror or real hardware frame-buffer.
+ */
+static int arcpgu_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	return vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
+}
+
+static struct fb_ops drm_fbdev_cma_ops = {
+	.owner		= THIS_MODULE,
+	.fb_mmap	= arcpgu_mmap,
+	.fb_fillrect	= drm_fb_helper_sys_fillrect,
+	.fb_copyarea	= drm_fb_helper_sys_copyarea,
+	.fb_imageblit	= drm_fb_helper_sys_imageblit,
+	.fb_check_var	= drm_fb_helper_check_var,
+	.fb_set_par	= drm_fb_helper_set_par,
+	.fb_blank	= drm_fb_helper_blank,
+	.fb_pan_display	= drm_fb_helper_pan_display,
+	.fb_setcmap	= drm_fb_helper_setcmap,
+};
+
+static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
+	struct drm_fb_helper_surface_size *sizes)
+{
+	struct drm_fbdev_cma *fbdev_cma = to_fbdev_cma(helper);
+	struct drm_mode_fb_cmd2 mode_cmd = { 0 };
+	struct drm_device *dev = helper->dev;
+	struct drm_gem_cma_object *obj;
+	struct drm_framebuffer *fb;
+	unsigned int bytes_per_pixel;
+	unsigned long offset;
+	struct fb_info *fbi;
+	size_t size;
+	int ret;
+
+	DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
+			sizes->surface_width, sizes->surface_height,
+			sizes->surface_bpp);
+
+	bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height;
+	mode_cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
+	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+		sizes->surface_depth);
+
+	size = mode_cmd.pitches[0] * mode_cmd.height;
+	obj = drm_gem_cma_create(dev, size);
+	if (IS_ERR(obj))
+		return -ENOMEM;
+
+	fbi = drm_fb_helper_alloc_fbi(helper);
+	if (IS_ERR(fbi)) {
+		ret = PTR_ERR(fbi);
+		goto err_gem_free_object;
+	}
+
+	fbdev_cma->fb = drm_fb_cma_alloc(dev, &mode_cmd, &obj, 1);
+	if (IS_ERR(fbdev_cma->fb)) {
+		dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
+		ret = PTR_ERR(fbdev_cma->fb);
+		goto err_fb_info_destroy;
+	}
+
+	fb = &fbdev_cma->fb->fb;
+	helper->fb = fb;
+
+	fbi->par = helper;
+	fbi->flags = FBINFO_FLAG_DEFAULT;
+	fbi->fbops = &drm_fbdev_cma_ops;
+
+	drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
+	drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
+
+	offset = fbi->var.xoffset * bytes_per_pixel;
+	offset += fbi->var.yoffset * fb->pitches[0];
+
+	dev->mode_config.fb_base = (resource_size_t)obj->paddr;
+	fbi->screen_base = obj->vaddr + offset;
+	fbi->fix.smem_start = (unsigned long)(obj->paddr + offset);
+	fbi->screen_size = size;
+	fbi->fix.smem_len = size;
+
+	return 0;
+
+err_fb_info_destroy:
+	drm_fb_helper_release_fbi(helper);
+err_gem_free_object:
+	dev->driver->gem_free_object(&obj->base);
+	return ret;
+}
+
+static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
+	.fb_probe = drm_fbdev_cma_create,
+};
+
+struct drm_fbdev_cma *arcpgu_fbdev_cma_init(struct drm_device *dev,
+	unsigned int preferred_bpp, unsigned int num_crtc,
+	unsigned int max_conn_count)
+{
+	struct drm_fbdev_cma *fbdev_cma;
+	struct drm_fb_helper *helper;
+	int ret;
+
+	fbdev_cma = kzalloc(sizeof(*fbdev_cma), GFP_KERNEL);
+	if (!fbdev_cma) {
+		dev_err(dev->dev, "Failed to allocate drm fbdev.\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	helper = &fbdev_cma->fb_helper;
+
+	drm_fb_helper_prepare(dev, helper, &drm_fb_cma_helper_funcs);
+
+	ret = drm_fb_helper_init(dev, helper, num_crtc, max_conn_count);
+	if (ret < 0) {
+		dev_err(dev->dev, "Failed to initialize drm fb helper.\n");
+		goto err_free;
+	}
+
+	ret = drm_fb_helper_single_add_all_connectors(helper);
+	if (ret < 0) {
+		dev_err(dev->dev, "Failed to add connectors.\n");
+		goto err_drm_fb_helper_fini;
+
+	}
+
+	ret = drm_fb_helper_initial_config(helper, preferred_bpp);
+	if (ret < 0) {
+		dev_err(dev->dev, "Failed to set initial hw configuration.\n");
+		goto err_drm_fb_helper_fini;
+	}
+
+	return fbdev_cma;
+
+err_drm_fb_helper_fini:
+	drm_fb_helper_fini(helper);
+err_free:
+	kfree(fbdev_cma);
+
+	return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c
new file mode 100644
index 0000000..7adafa3
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c
@@ -0,0 +1,207 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "arcpgu.h"
+
+struct arcpgu_drm_connector {
+	struct drm_connector connector;
+	struct drm_encoder_slave *encoder_slave;
+};
+
+static int arcpgu_drm_connector_get_modes(struct drm_connector *connector)
+{
+	const struct drm_encoder_slave_funcs *sfuncs;
+	struct drm_encoder_slave *slave;
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_get_modes: cannot find slave encoder for connector\n");
+		return 0;
+	}
+
+	sfuncs = slave->slave_funcs;
+	if (sfuncs->get_modes == NULL)
+		return 0;
+
+	return sfuncs->get_modes(&slave->base, connector);
+}
+
+struct drm_encoder *
+arcpgu_drm_connector_best_encoder(struct drm_connector *connector)
+{
+	struct drm_encoder_slave *slave;
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_best_encoder: cannot find slave encoder for connector\n");
+		return NULL;
+	}
+
+	return &slave->base;
+}
+
+static enum drm_connector_status
+arcpgu_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	enum drm_connector_status status = connector_status_unknown;
+	const struct drm_encoder_slave_funcs *sfuncs;
+	struct drm_encoder_slave *slave;
+
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_detect: cannot find slave encoder for connector\n");
+		return status;
+	}
+
+	sfuncs = slave->slave_funcs;
+	if (sfuncs && sfuncs->detect)
+		return sfuncs->detect(&slave->base, connector);
+
+	dev_err(connector->dev->dev, "connector_detect: could not detect slave funcs\n");
+	return status;
+}
+
+static void arcpgu_drm_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_helper_funcs
+arcpgu_drm_connector_helper_funcs = {
+	.get_modes = arcpgu_drm_connector_get_modes,
+	.best_encoder = arcpgu_drm_connector_best_encoder,
+};
+
+static const struct drm_connector_funcs arcpgu_drm_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = arcpgu_drm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = arcpgu_drm_connector_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static struct drm_encoder_helper_funcs arcpgu_drm_encoder_helper_funcs = {
+	.dpms = drm_i2c_encoder_dpms,
+	.mode_fixup = drm_i2c_encoder_mode_fixup,
+	.mode_set = drm_i2c_encoder_mode_set,
+	.prepare = drm_i2c_encoder_prepare,
+	.commit = drm_i2c_encoder_commit,
+	.detect = drm_i2c_encoder_detect,
+};
+
+static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np)
+{
+	struct arcpgu_drm_connector *arcpgu_connector;
+	struct drm_i2c_encoder_driver *driver;
+	struct drm_encoder_slave *encoder;
+	struct drm_connector *connector;
+	struct i2c_client *i2c_slave;
+	int ret;
+
+	encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL);
+	if (encoder == NULL)
+		return -ENOMEM;
+
+	i2c_slave = of_find_i2c_device_by_node(np);
+	if (!i2c_slave || !i2c_get_clientdata(i2c_slave)) {
+		dev_err(drm->dev, "failed to find i2c slave encoder\n");
+		return -EPROBE_DEFER;
+	}
+
+	if (i2c_slave->dev.driver == NULL) {
+		dev_err(drm->dev, "failed to find i2c slave driver\n");
+		return -EPROBE_DEFER;
+	}
+
+	driver =
+	    to_drm_i2c_encoder_driver(to_i2c_driver(i2c_slave->dev.driver));
+	ret = driver->encoder_init(i2c_slave, drm, encoder);
+	if (ret) {
+		dev_err(drm->dev, "failed to initialize i2c encoder slave\n");
+		return ret;
+	}
+
+	encoder->base.possible_crtcs = 1;
+	encoder->base.possible_clones = 0;
+	ret = drm_encoder_init(drm, &encoder->base, &arcpgu_drm_encoder_funcs,
+			       DRM_MODE_ENCODER_TMDS, NULL);
+	if (ret)
+		return ret;
+
+	drm_encoder_helper_add(&encoder->base,
+			       &arcpgu_drm_encoder_helper_funcs);
+
+	arcpgu_connector = devm_kzalloc(drm->dev, sizeof(*arcpgu_connector),
+					GFP_KERNEL);
+	if (!arcpgu_connector) {
+		ret = -ENOMEM;
+		goto error_encoder_cleanup;
+	}
+
+	connector = &arcpgu_connector->connector;
+	drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs);
+	ret = drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs,
+			DRM_MODE_CONNECTOR_HDMIA);
+	if (ret < 0) {
+		dev_err(drm->dev, "failed to initialize drm connector\n");
+		goto error_encoder_cleanup;
+	}
+
+	ret = drm_connector_register(connector);
+	if (ret < 0) {
+		dev_err(drm->dev, "failed to regiter DRM connector and helper funcs\n");
+		goto error_connector_cleanup;
+	}
+
+	ret = drm_mode_connector_attach_encoder(connector, &encoder->base);
+	if (ret < 0) {
+		dev_err(drm->dev, "could not attach connector to encoder\n");
+		drm_connector_unregister(connector);
+		goto error_connector_cleanup;
+	}
+
+	arcpgu_connector->encoder_slave = encoder;
+
+	return 0;
+
+error_connector_cleanup:
+	drm_connector_cleanup(connector);
+
+error_encoder_cleanup:
+	drm_encoder_cleanup(&encoder->base);
+	return ret;
+}
diff --git a/drivers/gpu/drm/arc/arcpgu_regs.h b/drivers/gpu/drm/arc/arcpgu_regs.h
new file mode 100644
index 0000000..f04165f
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_regs.h
@@ -0,0 +1,36 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ARC_PGU_REGS_H_
+#define _ARC_PGU_REGS_H_
+
+#define ARCPGU_REG_CTRL		0x00
+#define ARCPGU_REG_STAT		0x04
+#define ARCPGU_REG_FMT		0x10
+#define ARCPGU_REG_HSYNC	0x14
+#define ARCPGU_REG_VSYNC	0x18
+#define ARCPGU_REG_ACTIVE	0x1c
+#define ARCPGU_REG_BUF0_ADDR	0x40
+#define ARCPGU_REG_STRIDE	0x50
+#define ARCPGU_REG_START_SET	0x84
+
+#define ARCPGU_REG_ID		0x3FC
+
+#define ARCPGU_CTRL_ENABLE_MASK	0x02
+#define ARCPGU_MODE_RGB888_MASK	0x04
+#define ARCPGU_STAT_BUSY_MASK	0x02
+
+#endif
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Fri Mar 11 07:42:37 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Fri, 11 Mar 2016 18:42:37 +0300
Subject: [PATCH 2/4 v3] drm: Add DT bindings documentation for ARC PGU display
 controller
In-Reply-To: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1457710959-9562-3-git-send-email-abrodkin@synopsys.com>

This add DT bindings documentation for ARC PGU display controller.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: David Airlie <airlied at linux.ie>
Cc: dri-devel at lists.freedesktop.org
Cc: devicetree at vger.kernel.org
Cc: linux-snps-arc at lists.infradead.org
---

Changes v2 -> v3:
 * Reverted back to initial larger version of example
   with minor fixes (thanks Rob for spotting those).

Changes v1 -> v2:
 * Removed everything except PGU node itself.

 .../devicetree/bindings/display/snps,arcpgu.txt    | 72 ++++++++++++++++++++++
 1 file changed, 72 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt

diff --git a/Documentation/devicetree/bindings/display/snps,arcpgu.txt b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
new file mode 100644
index 0000000..b130924
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
@@ -0,0 +1,72 @@
+ARC PGU
+
+This is a display controller found on several development boards produced
+by Synopsys. The ARC PGU is an RGB streamer that reads the data from a
+framebuffer and sends it to a single digital encoder (usually HDMI).
+
+Required properties:
+  - compatible: "snps,arcpgu"
+  - reg: Physical base address and length of the controller's registers.
+  - clocks: A list of phandle + clock-specifier pairs, one for each
+    entry in 'clock-names'.
+  - clock-names: A list of clock names. For ARC PGU it should contain:
+      - "pxlclk" for the clock feeding the output PLL of the controller.
+  - encoder-slave: Phandle of encoder chip.
+
+Required sub-nodes:
+  - port: The PGU connection to an encoder chip.
+
+Example:
+
+/ {
+	...
+
+	pgu at XXXXXXXX {
+		compatible = "snps,arcpgu";
+		reg = <0xXXXXXXXX 0x400>;
+		clocks = <&clock_node>;
+		clock-names = "pxlclk";
+		encoder-slave = <&encoder_node>;
+
+		port {
+			pgu_output: endpoint {
+				remote-endpoint = <&hdmi_enc_input>;
+			};
+		};
+	};
+
+	/* HDMI encoder on I2C bus */
+	i2c at XXXXXXXX {
+		compatible = "...";
+
+		encoder_node:encoder_node at 0xXX{
+			compatible="...";
+
+			ports {
+				port at 0 {
+					reg = <0>;
+					hdmi_enc_input:endpoint {
+						remote-endpoint = <&pgu_output>;
+					};
+				};
+
+				port at 1 {
+					reg = <1>;
+					hdmi_enc_output:endpoint {
+						remote-endpoint = <&hdmi_connector_in>;
+					};
+				};
+			};
+		};
+	}
+
+	hdmi0: connector {
+		compatible = "hdmi-connector";
+
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&hdmi_enc_output>;
+			};
+		};
+	};
+};
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Fri Mar 11 07:42:39 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Fri, 11 Mar 2016 18:42:39 +0300
Subject: [PATCH 4/4 v3] MAINTAINERS: Add maintainer for ARC PGU display
 controller
In-Reply-To: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1457710959-9562-5-git-send-email-abrodkin@synopsys.com>

This updates MAINTEINERS file with information about maintainer of
ARC PGU display controller driver.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: linux-snps-arc at lists.infradead.org
Cc: dri-devel at lists.freedesktop.org
---

No changes v2 -> v3.

No changes v1 -> v2.

 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ea1d1de..0dcba67 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -827,6 +827,12 @@ S:	Maintained
 F:	drivers/net/arcnet/
 F:	include/uapi/linux/if_arcnet.h
 
+ARC PGU DRM DRIVER
+M:	Alexey Brodkin <abrodkin at synopsys.com>
+S:	Supported
+F:	drivers/gpu/drm/arc/
+F:	Documentation/devicetree/bindings/display/snps,arcpgu.txt
+
 ARM HDLCD DRM DRIVER
 M:	Liviu Dudau <liviu.dudau at arm.com>
 S:	Supported
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Fri Mar 11 07:42:38 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Fri, 11 Mar 2016 18:42:38 +0300
Subject: [PATCH 3/4 v3] arc: axs10x - add support of ARC PGU
In-Reply-To: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1457710959-9562-4-git-send-email-abrodkin@synopsys.com>

Synopsys DesignWare ARC SDP boards sport ARC SDP display
controller attached to ADV7511 HDMI encoder.

That change adds desctiption of both ARC PGU and ADV7511 in
ARC SDP'd base-board Device Tree.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: Vineet Gupta <vgupta at synopsys.com>
Cc: David Airlie <airlied at linux.ie>
Cc: dri-devel at lists.freedesktop.org
Cc: devicetree at vger.kernel.org
Cc: linux-snps-arc at lists.infradead.org
---

No changes v2 -> v3.

Changes v1 -> v2:
 * Added missing "pxlclk" clock in axs10x_mb.dtsi

 arch/arc/boot/dts/axs10x_mb.dtsi | 61 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
index 44a578c..6e639c9 100644
--- a/arch/arc/boot/dts/axs10x_mb.dtsi
+++ b/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -34,6 +34,12 @@
 				clock-frequency = <50000000>;
 				#clock-cells = <0>;
 			};
+
+			pguclk: pguclk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <74440000>;
+			};
 		};
 
 		ethernet at 0x18000 {
@@ -147,6 +153,37 @@
 			clocks = <&i2cclk>;
 			interrupts = <16>;
 
+			adv7511:adv7511 at 0x39{
+				compatible="adi,adv7511";
+				reg = <0x39>;
+				interrupts = <23>;
+				adi,input-depth = <8>;
+				adi,input-colorspace = "rgb";
+				adi,input-clock = "1x";
+				adi,clock-delay = <0x03>;
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					/* RGB/YUV input */
+					port at 0 {
+						reg = <0>;
+						adv7511_input:endpoint {
+						remote-endpoint = <&pgu_output>;
+						};
+					};
+
+					/* HDMI output */
+					port at 1 {
+						reg = <1>;
+						adv7511_output: endpoint {
+							remote-endpoint = <&hdmi_connector_in>;
+						};
+					};
+				};
+			};
+
 			eeprom at 0x54{
 				compatible = "24c01";
 				reg = <0x54>;
@@ -160,6 +197,16 @@
 			};
 		};
 
+		hdmi0: connector {
+			compatible = "hdmi-connector";
+			type = "a";
+			port {
+				hdmi_connector_in: endpoint {
+					remote-endpoint = <&adv7511_output>;
+				};
+			};
+		};
+
 		gpio0:gpio at 13000 {
 			compatible = "snps,dw-apb-gpio";
 			reg = <0x13000 0x1000>;
@@ -221,5 +268,19 @@
 				reg = <2>;
 			};
 		};
+
+		pgu at 0x17000 {
+			compatible = "snps,arcpgu";
+			reg = <0x17000 0x400>;
+			encoder-slave = <&adv7511>;
+			clocks = <&pguclk>;
+			clock-names = "pxlclk";
+
+			port {
+				pgu_output: endpoint {
+					remote-endpoint = <&adv7511_input>;
+				};
+			};
+		};
 	};
 };
-- 
2.5.0



From lkp at intel.com  Fri Mar 11 08:45:42 2016
From: lkp at intel.com (kbuild test robot)
Date: Sat, 12 Mar 2016 00:45:42 +0800
Subject: [PATCH 1/4 v3] drm: Add support of ARC PGU display controller
In-Reply-To: <1457710959-9562-2-git-send-email-abrodkin@synopsys.com>
Message-ID: <201603120053.Dr2iFD2z%fengguang.wu@intel.com>

Hi Alexey,

[auto build test WARNING on drm/drm-next]
[also build test WARNING on v4.5-rc7 next-20160311]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Alexey-Brodkin/drm-Add-support-of-ARC-PGU-display-controller/20160311-234824
base:   git://people.freedesktop.org/~airlied/linux.git drm-next


coccinelle warnings: (new ones prefixed by >>)

>> drivers/gpu/drm/arc/arcpgu_drv.c:243:6-11: No need to set .owner here. The core will do it.

Please review and possibly fold the followup patch.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation


From lkp at intel.com  Fri Mar 11 08:45:43 2016
From: lkp at intel.com (kbuild test robot)
Date: Sat, 12 Mar 2016 00:45:43 +0800
Subject: [PATCH] drm: fix platform_no_drv_owner.cocci warnings
In-Reply-To: <1457710959-9562-2-git-send-email-abrodkin@synopsys.com>
References: <201603120053.Dr2iFD2z%fengguang.wu@intel.com>
Message-ID: <20160311164542.GA94290@lkp-ib04>

drivers/gpu/drm/arc/arcpgu_drv.c:243:6-11: No need to set .owner here. The core will do it.

 Remove .owner field if calls are used which set it automatically

Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci

CC: Alexey Brodkin <Alexey.Brodkin at synopsys.com>
Signed-off-by: Fengguang Wu <fengguang.wu at intel.com>
---

 arcpgu_drv.c |    1 -
 1 file changed, 1 deletion(-)

--- a/drivers/gpu/drm/arc/arcpgu_drv.c
+++ b/drivers/gpu/drm/arc/arcpgu_drv.c
@@ -240,7 +240,6 @@ static struct platform_driver arcpgu_pla
 	.remove = arcpgu_remove,
 	.driver = {
 		   .name = "arcpgu",
-		   .owner = THIS_MODULE,
 		   .of_match_table = arcpgu_of_table,
 		   },
 };


From Vineet.Gupta1 at synopsys.com  Fri Mar 11 20:20:01 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Sat, 12 Mar 2016 09:50:01 +0530
Subject: [PATCH] arc: use little endian accesses
In-Reply-To: <C2D7FE5348E1B147BCA15975FBA23075F4E8F790@us01wembx1.internal.synopsys.com>
References: <1457544064-16167-1-git-send-email-ltrimas@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8F1A0@us01wembx1.internal.synopsys.com>
 <1457636268.457.34.camel@synopsys.com> <201603102023.59425.arnd@arndb.de>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8F790@us01wembx1.internal.synopsys.com>
Message-ID: <56E398F1.7090500@synopsys.com>

On Friday 11 March 2016 06:14 PM, Vineet Gupta wrote:
> @Lada I will fix up the changelog to add some of the background behind this
> change, and mark this for stable backport as well.

This is what I'm planning to add.
Noam please give this a spin - you might have to revert those native-endian DT
bindings from UART DT.

----->
>From f778cc65717687a3d3f26dd21bef62cd059f1b8b Mon Sep 17 00:00:00 2001
From: Lada Trimasova <ltrimas at synopsys.com>
Date: Wed, 9 Mar 2016 20:21:04 +0300
Subject: [PATCH] ARC: [BE] readl()/writel() to work in Big Endian CPU
 configuration

read{l,w}() write{l,w}() primitives should use le{16,32}_to_cpu() and
cpu_to_le{16,32}() respectively to ensure device registers are read
correctly in Big Endian CPU configuration.

Per Arnd Bergmann
| Most drivers using readl() or readl_relaxed() expect those to perform byte
| swaps on big-endian architectures, as the registers tend to be fixed endian

This was needed for getting UART to work correctly on a Big Endian ARC.

The ARC accessors originally were fine, and the bug got introduced
inadventently by commit b8a033023994 ("ARCv2: barriers")

Fixes: b8a033023994 ("ARCv2: barriers")
Link: http://lkml.kernel.org/r/201603100845.30602.arnd at arndb.de
Cc: Alexey Brodkin <abrodkin at synopsys.com>
Cc: stable at vger.kernel.org  [4.2+]
Cc: Arnd Bergmann <arnd at arndb.de>
Signed-off-by: Lada Trimasova <ltrimas at synopsys.com>
[vgupta: beefed up changelog, added Fixes/stable tags]
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/include/asm/io.h | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
index 694ece8a0243..27b17adea50d 100644
--- a/arch/arc/include/asm/io.h
+++ b/arch/arc/include/asm/io.h
@@ -129,15 +129,23 @@ static inline void __raw_writel(u32 w, volatile void __iomem
*addr)
 #define writel(v,c)		({ __iowmb(); writel_relaxed(v,c); })

 /*
- * Relaxed API for drivers which can handle any ordering themselves
+ * Relaxed API for drivers which can handle barrier ordering themselves
+ *
+ * Also these are defined to perform little endian accesses.
+ * To provide the typical device register semantics of fixed endian,
+ * swap the byte order for Big Endian
+ *
+ * http://lkml.kernel.org/r/201603100845.30602.arnd at arndb.de
  */
 #define readb_relaxed(c)	__raw_readb(c)
-#define readw_relaxed(c)	__raw_readw(c)
-#define readl_relaxed(c)	__raw_readl(c)
+#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
+					__raw_readw(c)); __r; })
+#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
+					__raw_readl(c)); __r; })

 #define writeb_relaxed(v,c)	__raw_writeb(v,c)
-#define writew_relaxed(v,c)	__raw_writew(v,c)
-#define writel_relaxed(v,c)	__raw_writel(v,c)
+#define writew_relaxed(v,c)	__raw_writew((__force u16) cpu_to_le16(v),c)
+#define writel_relaxed(v,c)	__raw_writel((__force u32) cpu_to_le32(v),c)

 #include <asm-generic/io.h>

-- 
2.5.0



From Vineet.Gupta1 at synopsys.com  Fri Mar 11 21:23:23 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Sat, 12 Mar 2016 10:53:23 +0530
Subject: [PATCH V3] net: ezchip: adapt driver to little endian architecture
In-Reply-To: <20160303.172043.676796529681577242.davem@davemloft.net>
References: <1457014066-27651-1-git-send-email-ltrimas@synopsys.com>
 <20160303.172043.676796529681577242.davem@davemloft.net>
Message-ID: <56E3A7CB.2020001@synopsys.com>

On Friday 04 March 2016 03:50 AM, David Miller wrote:
> From: Lada Trimasova <Lada.Trimasova at synopsys.com>
> Date: Thu,  3 Mar 2016 17:07:46 +0300
> 
>> Since ezchip network driver is written with big endian EZChip platform it
>> is necessary to add support for little endian architecture.
>>
>> The first issue is that the order of the bits in a bit field is
>> implementation specific. So all the bit fields are removed.
>> Named constants are used to access necessary fields.
>>
>> And the second one is that network byte order is big endian.
>> For example, data on ethernet is transmitted with most-significant
>> octet (byte) first. So in case of little endian architecture
>> it is important to swap data byte order when we read it from
>> register. In case of unaligned access we can use "get_unaligned_be32"
>> and in other case we can use function "ioread32_rep" which reads all
>> data from register and works either with little endian or big endian
>> architecture.
>>
>> And then when we are going to write data to register we need to restore
>> byte order using the function "put_unaligned_be32" in case of
>> unaligned access and in other case "iowrite32_rep".
>>
>> The last little fix is a space between type and pointer to observe
>> coding style.
>>
>> Signed-off-by: Lada Trimasova <ltrimas at synopsys.com>
> 
> Applied to net-next, thanks.
> 

@Lada, could you provide the corresponding arch/arc/{boot/dts,configs}/ updates so
we can switch over to this device-model/driver for OSCI platform for 4.6.

Thx,
-Vineet


From daniel at ffwll.ch  Mon Mar 14 00:00:09 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Mon, 14 Mar 2016 08:00:09 +0100
Subject: [PATCH 1/4 v3] drm: Add support of ARC PGU display controller
In-Reply-To: <1457710959-9562-2-git-send-email-abrodkin@synopsys.com>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
 <1457710959-9562-2-git-send-email-abrodkin@synopsys.com>
Message-ID: <20160314070009.GN14170@phenom.ffwll.local>

On Fri, Mar 11, 2016 at 06:42:36PM +0300, Alexey Brodkin wrote:
> ARC PGU could be found on some development boards from Synopsys.
> This is a simple byte streamer that reads data from a framebuffer
> and sends data to the single encoder.
> 
> Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
> Cc: David Airlie <airlied at linux.ie>
> Cc: dri-devel at lists.freedesktop.org
> Cc: linux-snps-arc at lists.infradead.org
> Cc: Jose Abreu <joabreu at synopsys.com>
> ---
> 
> Changes v2 -> v3:
>  * Improved failure path if arcpgu_connector wasn't allocated (thanks Jose).
>  * Fixed driver building as module (reported by 0-DAY kernel test infrastruct.)
>  * Implemented uncached mapping of user-space FB pages.
> 
> No changes v1 -> v2.
> 

Bunch of comments below to update your driver to latest styles and best
practices.

Cheers, Daniel

>  drivers/gpu/drm/Kconfig            |   2 +
>  drivers/gpu/drm/Makefile           |   1 +
>  drivers/gpu/drm/arc/Kconfig        |  10 ++
>  drivers/gpu/drm/arc/Makefile       |   2 +
>  drivers/gpu/drm/arc/arcpgu.h       |  50 +++++++
>  drivers/gpu/drm/arc/arcpgu_crtc.c  | 274 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/arc/arcpgu_drv.c   | 252 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/arc/arcpgu_fbdev.c | 245 +++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/arc/arcpgu_hdmi.c  | 207 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/arc/arcpgu_regs.h  |  36 +++++
>  10 files changed, 1079 insertions(+)
>  create mode 100644 drivers/gpu/drm/arc/Kconfig
>  create mode 100644 drivers/gpu/drm/arc/Makefile
>  create mode 100644 drivers/gpu/drm/arc/arcpgu.h
>  create mode 100644 drivers/gpu/drm/arc/arcpgu_crtc.c
>  create mode 100644 drivers/gpu/drm/arc/arcpgu_drv.c
>  create mode 100644 drivers/gpu/drm/arc/arcpgu_fbdev.c
>  create mode 100644 drivers/gpu/drm/arc/arcpgu_hdmi.c
>  create mode 100644 drivers/gpu/drm/arc/arcpgu_regs.h
> 
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index f2a74d0..9e4f2f1 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -281,3 +281,5 @@ source "drivers/gpu/drm/imx/Kconfig"
>  source "drivers/gpu/drm/vc4/Kconfig"
>  
>  source "drivers/gpu/drm/etnaviv/Kconfig"
> +
> +source "drivers/gpu/drm/arc/Kconfig"
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 6eb94fc..c338d04 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -78,3 +78,4 @@ obj-y			+= panel/
>  obj-y			+= bridge/
>  obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
>  obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
> +obj-$(CONFIG_DRM_ARCPGU)+= arc/
> diff --git a/drivers/gpu/drm/arc/Kconfig b/drivers/gpu/drm/arc/Kconfig
> new file mode 100644
> index 0000000..f9a13b6
> --- /dev/null
> +++ b/drivers/gpu/drm/arc/Kconfig
> @@ -0,0 +1,10 @@
> +config DRM_ARCPGU
> +	tristate "ARC PGU"
> +	depends on DRM && OF
> +	select DRM_KMS_CMA_HELPER
> +	select DRM_KMS_FB_HELPER
> +	select DRM_KMS_HELPER
> +	help
> +	  Choose this option if you have an ARC PGU controller.
> +
> +	  If M is selected the module will be called arcpgu.
> diff --git a/drivers/gpu/drm/arc/Makefile b/drivers/gpu/drm/arc/Makefile
> new file mode 100644
> index 0000000..736ee6f
> --- /dev/null
> +++ b/drivers/gpu/drm/arc/Makefile
> @@ -0,0 +1,2 @@
> +arcpgu-y := arcpgu_crtc.o arcpgu_hdmi.o arcpgu_fbdev.o arcpgu_drv.o
> +obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o
> diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h
> new file mode 100644
> index 0000000..86574b6
> --- /dev/null
> +++ b/drivers/gpu/drm/arc/arcpgu.h
> @@ -0,0 +1,50 @@
> +/*
> + * ARC PGU DRM driver.
> + *
> + * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#ifndef _ARCPGU_H_
> +#define _ARCPGU_H_
> +
> +struct arcpgu_drm_private {
> +	void __iomem		*regs;
> +	struct clk		*clk;
> +	struct drm_fbdev_cma	*fbdev;
> +	struct drm_framebuffer	*fb;
> +	struct list_head	event_list;
> +	struct drm_crtc		crtc;
> +	struct drm_plane	*plane;
> +};
> +
> +#define crtc_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, crtc)
> +
> +static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu,
> +				 unsigned int reg, u32 value)
> +{
> +	iowrite32(value, arcpgu->regs + reg);
> +}
> +
> +static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu,
> +			       unsigned int reg)
> +{
> +	return ioread32(arcpgu->regs + reg);
> +}
> +
> +int arc_pgu_setup_crtc(struct drm_device *dev);
> +int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np);
> +struct drm_fbdev_cma *arcpgu_fbdev_cma_init(struct drm_device *dev,
> +	unsigned int preferred_bpp, unsigned int num_crtc,
> +	unsigned int max_conn_count);
> +
> +#endif
> diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
> new file mode 100644
> index 0000000..0fe5c8a
> --- /dev/null
> +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
> @@ -0,0 +1,274 @@
> +/*
> + * ARC PGU DRM driver.
> + *
> + * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_plane_helper.h>
> +#include <linux/clk.h>
> +#include <linux/platform_data/simplefb.h>
> +
> +#include "arcpgu.h"
> +#include "arcpgu_regs.h"
> +
> +#define ENCODE_PGU_XY(x, y)	((((x) - 1) << 16) | ((y) - 1))
> +
> +static struct simplefb_format supported_formats[] = {
> +	{ "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0}, DRM_FORMAT_RGB565 },
> +	{ "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 },
> +};
> +
> +static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
> +{
> +	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> +	uint32_t pixel_format = crtc->primary->state->fb->pixel_format;
> +	struct simplefb_format *format = NULL;
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
> +		if (supported_formats[i].fourcc == pixel_format)
> +			format = &supported_formats[i];
> +	}
> +
> +	if (WARN_ON(!format))
> +		return;
> +
> +	if (format->fourcc == DRM_FORMAT_RGB888)
> +		arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
> +			      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) |
> +					   ARCPGU_MODE_RGB888_MASK);
> +
> +}
> +
> +static const struct drm_crtc_funcs arc_pgu_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 void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
> +	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> +	struct drm_display_mode *m = &crtc->state->adjusted_mode;
> +
> +	arc_pgu_write(arcpgu, ARCPGU_REG_FMT,
> +		      ENCODE_PGU_XY(m->crtc_htotal, m->crtc_vtotal));
> +
> +	arc_pgu_write(arcpgu, ARCPGU_REG_HSYNC,
> +		      ENCODE_PGU_XY(m->crtc_hsync_start - m->crtc_hdisplay,
> +				    m->crtc_hsync_end - m->crtc_hdisplay));
> +
> +	arc_pgu_write(arcpgu, ARCPGU_REG_VSYNC,
> +		      ENCODE_PGU_XY(m->crtc_vsync_start - m->crtc_vdisplay,
> +				    m->crtc_vsync_end - m->crtc_vdisplay));
> +
> +	arc_pgu_write(arcpgu, ARCPGU_REG_ACTIVE,
> +		      ENCODE_PGU_XY(m->crtc_hblank_end - m->crtc_hblank_start,
> +				    m->crtc_vblank_end - m->crtc_vblank_start));
> +
> +	arc_pgu_write(arcpgu, ARCPGU_REG_STRIDE, 0);
> +	arc_pgu_write(arcpgu, ARCPGU_REG_START_SET, 1);
> +
> +	arc_pgu_set_pxl_fmt(crtc);
> +
> +	clk_set_rate(arcpgu->clk, m->crtc_clock * 1000);
> +}
> +
> +static void arc_pgu_crtc_enable(struct drm_crtc *crtc)
> +{
> +	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> +
> +	clk_prepare_enable(arcpgu->clk);
> +	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
> +		      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) |
> +		      ARCPGU_CTRL_ENABLE_MASK);
> +}
> +
> +static void arc_pgu_crtc_disable(struct drm_crtc *crtc)
> +{
> +	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> +
> +	if (!crtc->primary->fb)
> +		return;
> +
> +	clk_disable_unprepare(arcpgu->clk);
> +	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
> +			      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) &
> +			      ~ARCPGU_CTRL_ENABLE_MASK);
> +}
> +
> +static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc,
> +				     struct drm_crtc_state *state)
> +{
> +	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> +	struct drm_display_mode *mode = &state->adjusted_mode;
> +	long rate, clk_rate = mode->clock * 1000;
> +
> +	rate = clk_round_rate(arcpgu->clk, clk_rate);
> +	if (rate != clk_rate)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
> +				      struct drm_crtc_state *state)
> +{
> +	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> +	unsigned long flags;
> +
> +	if (crtc->state->event) {
> +		struct drm_pending_vblank_event *event = crtc->state->event;
> +
> +		crtc->state->event = NULL;
> +		event->pipe = drm_crtc_index(crtc);
> +
> +		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
> +
> +		spin_lock_irqsave(&crtc->dev->event_lock, flags);
> +		list_add_tail(&event->base.link, &arcpgu->event_list);
> +		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
> +	}
> +}
> +
> +static void arc_pgu_crtc_atomic_flush(struct drm_crtc *crtc,
> +				      struct drm_crtc_state *state)
> +{
> +}
> +
> +static bool arc_pgu_crtc_mode_fixup(struct drm_crtc *crtc,
> +				    const struct drm_display_mode *mode,
> +				    struct drm_display_mode *adjusted_mode)
> +{
> +	return true;
> +}

You can drop the above 2 dummy functions.

> +
> +static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
> +	.mode_fixup	= arc_pgu_crtc_mode_fixup,
> +	.mode_set	= drm_helper_crtc_mode_set,
> +	.mode_set_base	= drm_helper_crtc_mode_set_base,
> +	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
> +	.enable		= arc_pgu_crtc_enable,
> +	.disable	= arc_pgu_crtc_disable,
> +	.prepare	= arc_pgu_crtc_disable,
> +	.commit		= arc_pgu_crtc_enable,
> +	.atomic_check	= arc_pgu_crtc_atomic_check,
> +	.atomic_begin	= arc_pgu_crtc_atomic_begin,
> +	.atomic_flush	= arc_pgu_crtc_atomic_flush,
> +};
> +
> +static int arc_pgu_plane_atomic_check(struct drm_plane *plane,
> +				      struct drm_plane_state *state)
> +{
> +	return 0;
> +}

You don't need dummy functions for this.

> +
> +static void arc_pgu_plane_atomic_update(struct drm_plane *plane,
> +					struct drm_plane_state *state)
> +{
> +	struct arcpgu_drm_private *arcpgu;
> +	struct drm_gem_cma_object *gem;
> +
> +	if (!plane->state->crtc || !plane->state->fb)
> +		return;
> +
> +	arcpgu = crtc_to_arcpgu_priv(plane->state->crtc);
> +	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
> +	arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr);
> +}
> +
> +static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = {
> +	.prepare_fb = NULL,
> +	.cleanup_fb = NULL,
> +	.atomic_check = arc_pgu_plane_atomic_check,
> +	.atomic_update = arc_pgu_plane_atomic_update,
> +};
> +
> +static void arc_pgu_plane_destroy(struct drm_plane *plane)
> +{
> +	drm_plane_helper_disable(plane);
> +	drm_plane_cleanup(plane);
> +}
> +
> +static const struct drm_plane_funcs arc_pgu_plane_funcs = {
> +	.update_plane		= drm_atomic_helper_update_plane,
> +	.disable_plane		= drm_atomic_helper_disable_plane,
> +	.destroy		= arc_pgu_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 struct drm_plane *arc_pgu_plane_init(struct drm_device *drm)
> +{
> +	struct arcpgu_drm_private *arcpgu = drm->dev_private;
> +	struct drm_plane *plane = NULL;
> +	u32 formats[ARRAY_SIZE(supported_formats)], i;
> +	int ret;
> +
> +	plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
> +	if (!plane)
> +		return ERR_PTR(-ENOMEM);
> +
> +	for (i = 0; i < ARRAY_SIZE(supported_formats); i++)
> +		formats[i] = supported_formats[i].fourcc;
> +
> +	ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs,
> +				       formats, ARRAY_SIZE(formats),
> +				       DRM_PLANE_TYPE_PRIMARY, NULL);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	drm_plane_helper_add(plane, &arc_pgu_plane_helper_funcs);
> +	arcpgu->plane = plane;
> +
> +	return plane;
> +}
> +
> +void arc_pgu_crtc_suspend(struct drm_crtc *crtc)
> +{
> +	arc_pgu_crtc_disable(crtc);
> +}
> +
> +void arc_pgu_crtc_resume(struct drm_crtc *crtc)
> +{
> +	arc_pgu_crtc_enable(crtc);
> +}

Please use the atomic suspend/resume helper that Thierry recently merged.
See the kerneldoc of drm_atomic_helper_suspend as a starting point for how
it works and how it's supposed to be used.

> +
> +int arc_pgu_setup_crtc(struct drm_device *drm)
> +{
> +	struct arcpgu_drm_private *arcpgu = drm->dev_private;
> +	struct drm_plane *primary;
> +	int ret;
> +
> +	primary = arc_pgu_plane_init(drm);
> +	if (IS_ERR(primary))
> +		return PTR_ERR(primary);
> +
> +	ret = drm_crtc_init_with_planes(drm, &arcpgu->crtc, primary, NULL,
> +					&arc_pgu_crtc_funcs, NULL);
> +	if (ret) {
> +		arc_pgu_plane_destroy(primary);
> +		return ret;
> +	}
> +
> +	drm_crtc_helper_add(&arcpgu->crtc, &arc_pgu_crtc_helper_funcs);
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c
> new file mode 100644
> index 0000000..d47481d
> --- /dev/null
> +++ b/drivers/gpu/drm/arc/arcpgu_drv.c
> @@ -0,0 +1,252 @@
> +/*
> + * ARC PGU DRM driver.
> + *
> + * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "arcpgu.h"
> +#include "arcpgu_regs.h"
> +
> +static void arcpgu_fb_output_poll_changed(struct drm_device *dev)
> +{
> +	struct arcpgu_drm_private *arcpgu = dev->dev_private;
> +
> +	if (arcpgu->fbdev)
> +		drm_fbdev_cma_hotplug_event(arcpgu->fbdev);
> +}
> +
> +static int arcpgu_atomic_commit(struct drm_device *dev,
> +				    struct drm_atomic_state *state, bool async)
> +{
> +	return drm_atomic_helper_commit(dev, state, false);

Note that this isn't really async if you ever get around to implement
fence support or vblank support. Just fyi.

> +}
> +
> +static struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = {
> +	.fb_create  = drm_fb_cma_create,
> +	.output_poll_changed = arcpgu_fb_output_poll_changed,
> +	.atomic_check = drm_atomic_helper_check,
> +	.atomic_commit = arcpgu_atomic_commit,
> +};
> +
> +static void arcpgu_setup_mode_config(struct drm_device *drm)
> +{
> +	drm_mode_config_init(drm);
> +	drm->mode_config.min_width = 0;
> +	drm->mode_config.min_height = 0;
> +	drm->mode_config.max_width = 1920;
> +	drm->mode_config.max_height = 1080;
> +	drm->mode_config.funcs = &arcpgu_drm_modecfg_funcs;
> +}
> +
> +int arcpgu_gem_mmap(struct file *filp, struct vm_area_struct *vma)
> +{
> +	int ret;
> +
> +	ret = drm_gem_mmap(filp, vma);
> +	if (ret)
> +		return ret;
> +
> +	vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags));
> +	return 0;
> +}
> +
> +static const struct file_operations arcpgu_drm_ops = {
> +	.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 = no_llseek,
> +	.mmap = arcpgu_gem_mmap,
> +};
> +
> +static void arcpgu_preclose(struct drm_device *drm, struct drm_file *file)
> +{
> +	struct arcpgu_drm_private *arcpgu = drm->dev_private;
> +	struct drm_pending_vblank_event *e, *t;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&drm->event_lock, flags);
> +	list_for_each_entry_safe(e, t, &arcpgu->event_list, base.link) {
> +		if (e->base.file_priv != file)
> +			continue;
> +		list_del(&e->base.link);
> +		e->base.destroy(&e->base);
> +	}
> +	spin_unlock_irqrestore(&drm->event_lock, flags);
> +}
> +
> +static void arcpgu_lastclose(struct drm_device *drm)
> +{
> +	struct arcpgu_drm_private *arcpgu = drm->dev_private;
> +
> +	drm_fbdev_cma_restore_mode(arcpgu->fbdev);
> +}
> +
> +static int arcpgu_load(struct drm_device *drm, unsigned long flags)
> +{
> +	struct platform_device *pdev = drm->platformdev;
> +	struct arcpgu_drm_private *arcpgu;
> +	struct device_node *encoder_node;
> +	struct resource *res;
> +	int ret;
> +
> +	arcpgu = devm_kzalloc(&pdev->dev, sizeof(*arcpgu), GFP_KERNEL);
> +	if (arcpgu == NULL)
> +		return -ENOMEM;
> +
> +	drm->dev_private = arcpgu;
> +
> +	arcpgu->clk = devm_clk_get(drm->dev, "pxlclk");
> +	if (IS_ERR(arcpgu->clk))
> +		return PTR_ERR(arcpgu->clk);
> +
> +	INIT_LIST_HEAD(&arcpgu->event_list);
> +
> +	arcpgu_setup_mode_config(drm);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	arcpgu->regs = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(arcpgu->regs)) {
> +		dev_err(drm->dev, "Could not remap IO mem\n");
> +		return PTR_ERR(arcpgu->regs);
> +	}
> +
> +	dev_info(drm->dev, "arc_pgu ID: 0x%x\n",
> +		 arc_pgu_read(arcpgu, ARCPGU_REG_ID));
> +
> +	if (dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32)))
> +		return -ENODEV;
> +
> +	if (arc_pgu_setup_crtc(drm) < 0)
> +		return -ENODEV;
> +
> +	/* find the encoder node and initialize it */
> +	encoder_node = of_parse_phandle(drm->dev->of_node, "encoder-slave", 0);
> +	if (!encoder_node) {
> +		dev_err(drm->dev, "failed to get an encoder slave node\n");
> +		return -ENODEV;
> +	}
> +
> +	ret = arcpgu_drm_hdmi_init(drm, encoder_node);
> +	if (ret < 0)
> +		return ret;
> +
> +	drm_mode_config_reset(drm);
> +	drm_kms_helper_poll_init(drm);
> +
> +	arcpgu->fbdev = arcpgu_fbdev_cma_init(drm, 16,
> +					      drm->mode_config.num_crtc,
> +					      drm->mode_config.num_connector);
> +	if (IS_ERR(arcpgu->fbdev)) {
> +		ret = PTR_ERR(arcpgu->fbdev);
> +		arcpgu->fbdev = NULL;
> +		return -ENODEV;
> +	}
> +
> +	platform_set_drvdata(pdev, arcpgu);
> +	return 0;
> +}
> +
> +int arcpgu_unload(struct drm_device *drm)
> +{
> +	struct arcpgu_drm_private *arcpgu = drm->dev_private;
> +
> +	if (arcpgu->fbdev) {
> +		drm_fbdev_cma_fini(arcpgu->fbdev);
> +		arcpgu->fbdev = NULL;
> +	}
> +	drm_kms_helper_poll_fini(drm);
> +	drm_vblank_cleanup(drm);
> +	drm_mode_config_cleanup(drm);
> +
> +	return 0;
> +}
> +
> +static struct drm_driver arcpgu_drm_driver = {
> +	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
> +			   DRIVER_ATOMIC,
> +	.preclose = arcpgu_preclose,
> +	.lastclose = arcpgu_lastclose,
> +	.name = "drm-arcpgu",
> +	.desc = "ARC PGU Controller",
> +	.date = "20160219",
> +	.major = 1,
> +	.minor = 0,
> +	.patchlevel = 0,
> +	.fops = &arcpgu_drm_ops,
> +	.load = arcpgu_load,
> +	.unload = arcpgu_unload,

Load and unload hooks are deprecated (it's a classic midlayer mistake).
Please use drm_dev_alloc/register pairs directly instead, and put your
device setup code in-between. Similar for unloading. There's a bunch of
example drivers converted already.

> +	.dumb_create = drm_gem_cma_dumb_create,
> +	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
> +	.dumb_destroy = drm_gem_dumb_destroy,
> +	.get_vblank_counter = drm_vblank_no_hw_counter,
> +	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> +	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> +	.gem_free_object = drm_gem_cma_free_object,
> +	.gem_vm_ops = &drm_gem_cma_vm_ops,
> +	.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,
> +};
> +
> +static int arcpgu_probe(struct platform_device *pdev)
> +{
> +	return drm_platform_init(&arcpgu_drm_driver, pdev);

... or read the kerneldoc of this function, which also explains what you
should do ;-)

> +}
> +
> +static int arcpgu_remove(struct platform_device *pdev)
> +{
> +	struct drm_device *drm = dev_get_drvdata(&pdev->dev);
> +
> +	drm_put_dev(drm);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id arcpgu_of_table[] = {
> +	{.compatible = "snps,arcpgu"},
> +	{}
> +};
> +
> +MODULE_DEVICE_TABLE(of, arcpgu_of_table);
> +
> +static struct platform_driver arcpgu_platform_driver = {
> +	.probe = arcpgu_probe,
> +	.remove = arcpgu_remove,
> +	.driver = {
> +		   .name = "arcpgu",
> +		   .owner = THIS_MODULE,
> +		   .of_match_table = arcpgu_of_table,
> +		   },
> +};
> +
> +module_platform_driver(arcpgu_platform_driver);
> +
> +MODULE_AUTHOR("Carlos Palminha <palminha at synopsys.com");
> +MODULE_DESCRIPTION("ARC PGU DRM driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/arc/arcpgu_fbdev.c b/drivers/gpu/drm/arc/arcpgu_fbdev.c
> new file mode 100644
> index 0000000..6f67706
> --- /dev/null
> +++ b/drivers/gpu/drm/arc/arcpgu_fbdev.c
> @@ -0,0 +1,245 @@
> +/*
> + * ARC PGU DRM driver.
> + *
> + * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <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>
> +
> +struct drm_fb_cma {
> +	struct drm_framebuffer		fb;
> +	struct drm_gem_cma_object	*obj[4];
> +};
> +
> +struct drm_fbdev_cma {
> +	struct drm_fb_helper	fb_helper;
> +	struct drm_fb_cma	*fb;
> +};
> +
> +static inline struct drm_fbdev_cma *to_fbdev_cma(struct drm_fb_helper *helper)
> +{
> +	return container_of(helper, struct drm_fbdev_cma, fb_helper);
> +}
> +
> +static inline struct drm_fb_cma *to_fb_cma(struct drm_framebuffer *fb)
> +{
> +	return container_of(fb, struct drm_fb_cma, fb);
> +}
> +
> +static void drm_fb_cma_destroy(struct drm_framebuffer *fb)
> +{
> +	struct drm_fb_cma *fb_cma = to_fb_cma(fb);
> +	int i;
> +
> +	for (i = 0; i < 4; i++) {
> +		if (fb_cma->obj[i])
> +			drm_gem_object_unreference_unlocked(&fb_cma->obj[i]->base);
> +	}
> +
> +	drm_framebuffer_cleanup(fb);
> +	kfree(fb_cma);
> +}
> +
> +static int drm_fb_cma_create_handle(struct drm_framebuffer *fb,
> +	struct drm_file *file_priv, unsigned int *handle)
> +{
> +	struct drm_fb_cma *fb_cma = to_fb_cma(fb);
> +
> +	return drm_gem_handle_create(file_priv,
> +			&fb_cma->obj[0]->base, handle);
> +}
> +
> +static struct drm_framebuffer_funcs drm_fb_cma_funcs = {
> +	.destroy	= drm_fb_cma_destroy,
> +	.create_handle	= drm_fb_cma_create_handle,
> +};
> +
> +static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev,
> +	const struct drm_mode_fb_cmd2 *mode_cmd,
> +	struct drm_gem_cma_object **obj,
> +	unsigned int num_planes)
> +{
> +	struct drm_fb_cma *fb_cma;
> +	int ret;
> +	int i;
> +
> +	fb_cma = kzalloc(sizeof(*fb_cma), GFP_KERNEL);
> +	if (!fb_cma)
> +		return ERR_PTR(-ENOMEM);
> +
> +	drm_helper_mode_fill_fb_struct(&fb_cma->fb, mode_cmd);
> +
> +	for (i = 0; i < num_planes; i++)
> +		fb_cma->obj[i] = obj[i];
> +
> +	ret = drm_framebuffer_init(dev, &fb_cma->fb, &drm_fb_cma_funcs);
> +	if (ret) {
> +		dev_err(dev->dev, "Failed to initialize framebuffer: %d\n", ret);
> +		kfree(fb_cma);
> +		return ERR_PTR(ret);
> +	}
> +
> +	return fb_cma;
> +}
> +
> +/*
> + * This function is the only reason to have a copy of drm_fbdev_cma_init()
> + * here in this driver.
> + *
> + * In its turn this mmap() is required to mark user-space page as non-cached
> + * because it is just a mirror or real hardware frame-buffer.
> + */
> +static int arcpgu_mmap(struct fb_info *info, struct vm_area_struct *vma)
> +{
> +	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> +	return vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
> +}

This looks very fishy, no other drm driver even bothers with providing an
fb_mmap hook. What exactly do you need this for? Assuming you've mmapped
your fbcon drm_framebuffer correctly for kernel access things should just
work ...

> +
> +static struct fb_ops drm_fbdev_cma_ops = {
> +	.owner		= THIS_MODULE,
> +	.fb_mmap	= arcpgu_mmap,
> +	.fb_fillrect	= drm_fb_helper_sys_fillrect,
> +	.fb_copyarea	= drm_fb_helper_sys_copyarea,
> +	.fb_imageblit	= drm_fb_helper_sys_imageblit,
> +	.fb_check_var	= drm_fb_helper_check_var,
> +	.fb_set_par	= drm_fb_helper_set_par,
> +	.fb_blank	= drm_fb_helper_blank,
> +	.fb_pan_display	= drm_fb_helper_pan_display,
> +	.fb_setcmap	= drm_fb_helper_setcmap,
> +};
> +
> +static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
> +	struct drm_fb_helper_surface_size *sizes)
> +{
> +	struct drm_fbdev_cma *fbdev_cma = to_fbdev_cma(helper);
> +	struct drm_mode_fb_cmd2 mode_cmd = { 0 };
> +	struct drm_device *dev = helper->dev;
> +	struct drm_gem_cma_object *obj;
> +	struct drm_framebuffer *fb;
> +	unsigned int bytes_per_pixel;
> +	unsigned long offset;
> +	struct fb_info *fbi;
> +	size_t size;
> +	int ret;
> +
> +	DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
> +			sizes->surface_width, sizes->surface_height,
> +			sizes->surface_bpp);
> +
> +	bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
> +
> +	mode_cmd.width = sizes->surface_width;
> +	mode_cmd.height = sizes->surface_height;
> +	mode_cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
> +	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
> +		sizes->surface_depth);
> +
> +	size = mode_cmd.pitches[0] * mode_cmd.height;
> +	obj = drm_gem_cma_create(dev, size);
> +	if (IS_ERR(obj))
> +		return -ENOMEM;
> +
> +	fbi = drm_fb_helper_alloc_fbi(helper);
> +	if (IS_ERR(fbi)) {
> +		ret = PTR_ERR(fbi);
> +		goto err_gem_free_object;
> +	}
> +
> +	fbdev_cma->fb = drm_fb_cma_alloc(dev, &mode_cmd, &obj, 1);
> +	if (IS_ERR(fbdev_cma->fb)) {
> +		dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
> +		ret = PTR_ERR(fbdev_cma->fb);
> +		goto err_fb_info_destroy;
> +	}
> +
> +	fb = &fbdev_cma->fb->fb;
> +	helper->fb = fb;
> +
> +	fbi->par = helper;
> +	fbi->flags = FBINFO_FLAG_DEFAULT;
> +	fbi->fbops = &drm_fbdev_cma_ops;
> +
> +	drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
> +	drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
> +
> +	offset = fbi->var.xoffset * bytes_per_pixel;
> +	offset += fbi->var.yoffset * fb->pitches[0];
> +
> +	dev->mode_config.fb_base = (resource_size_t)obj->paddr;
> +	fbi->screen_base = obj->vaddr + offset;
> +	fbi->fix.smem_start = (unsigned long)(obj->paddr + offset);
> +	fbi->screen_size = size;
> +	fbi->fix.smem_len = size;
> +
> +	return 0;
> +
> +err_fb_info_destroy:
> +	drm_fb_helper_release_fbi(helper);
> +err_gem_free_object:
> +	dev->driver->gem_free_object(&obj->base);
> +	return ret;
> +}
> +
> +static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
> +	.fb_probe = drm_fbdev_cma_create,
> +};
> +
> +struct drm_fbdev_cma *arcpgu_fbdev_cma_init(struct drm_device *dev,
> +	unsigned int preferred_bpp, unsigned int num_crtc,
> +	unsigned int max_conn_count)
> +{
> +	struct drm_fbdev_cma *fbdev_cma;
> +	struct drm_fb_helper *helper;
> +	int ret;
> +
> +	fbdev_cma = kzalloc(sizeof(*fbdev_cma), GFP_KERNEL);
> +	if (!fbdev_cma) {
> +		dev_err(dev->dev, "Failed to allocate drm fbdev.\n");
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	helper = &fbdev_cma->fb_helper;
> +
> +	drm_fb_helper_prepare(dev, helper, &drm_fb_cma_helper_funcs);
> +
> +	ret = drm_fb_helper_init(dev, helper, num_crtc, max_conn_count);
> +	if (ret < 0) {
> +		dev_err(dev->dev, "Failed to initialize drm fb helper.\n");
> +		goto err_free;
> +	}
> +
> +	ret = drm_fb_helper_single_add_all_connectors(helper);
> +	if (ret < 0) {
> +		dev_err(dev->dev, "Failed to add connectors.\n");
> +		goto err_drm_fb_helper_fini;
> +
> +	}
> +
> +	ret = drm_fb_helper_initial_config(helper, preferred_bpp);
> +	if (ret < 0) {
> +		dev_err(dev->dev, "Failed to set initial hw configuration.\n");
> +		goto err_drm_fb_helper_fini;
> +	}
> +
> +	return fbdev_cma;
> +
> +err_drm_fb_helper_fini:
> +	drm_fb_helper_fini(helper);
> +err_free:
> +	kfree(fbdev_cma);
> +
> +	return ERR_PTR(ret);
> +}
> diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c
> new file mode 100644
> index 0000000..7adafa3
> --- /dev/null
> +++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c
> @@ -0,0 +1,207 @@
> +/*
> + * ARC PGU DRM driver.
> + *
> + * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder_slave.h>
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "arcpgu.h"
> +
> +struct arcpgu_drm_connector {
> +	struct drm_connector connector;
> +	struct drm_encoder_slave *encoder_slave;
> +};
> +
> +static int arcpgu_drm_connector_get_modes(struct drm_connector *connector)
> +{
> +	const struct drm_encoder_slave_funcs *sfuncs;
> +	struct drm_encoder_slave *slave;
> +	struct arcpgu_drm_connector *con =
> +		container_of(connector, struct arcpgu_drm_connector, connector);
> +
> +	slave = con->encoder_slave;
> +	if (slave == NULL) {
> +		dev_err(connector->dev->dev,
> +			"connector_get_modes: cannot find slave encoder for connector\n");
> +		return 0;
> +	}
> +
> +	sfuncs = slave->slave_funcs;
> +	if (sfuncs->get_modes == NULL)
> +		return 0;
> +
> +	return sfuncs->get_modes(&slave->base, connector);
> +}
> +
> +struct drm_encoder *
> +arcpgu_drm_connector_best_encoder(struct drm_connector *connector)
> +{
> +	struct drm_encoder_slave *slave;
> +	struct arcpgu_drm_connector *con =
> +		container_of(connector, struct arcpgu_drm_connector, connector);
> +
> +	slave = con->encoder_slave;
> +	if (slave == NULL) {
> +		dev_err(connector->dev->dev,
> +			"connector_best_encoder: cannot find slave encoder for connector\n");
> +		return NULL;
> +	}
> +
> +	return &slave->base;
> +}
> +
> +static enum drm_connector_status
> +arcpgu_drm_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	enum drm_connector_status status = connector_status_unknown;
> +	const struct drm_encoder_slave_funcs *sfuncs;
> +	struct drm_encoder_slave *slave;
> +
> +	struct arcpgu_drm_connector *con =
> +		container_of(connector, struct arcpgu_drm_connector, connector);
> +
> +	slave = con->encoder_slave;
> +	if (slave == NULL) {
> +		dev_err(connector->dev->dev,
> +			"connector_detect: cannot find slave encoder for connector\n");
> +		return status;
> +	}
> +
> +	sfuncs = slave->slave_funcs;
> +	if (sfuncs && sfuncs->detect)
> +		return sfuncs->detect(&slave->base, connector);
> +
> +	dev_err(connector->dev->dev, "connector_detect: could not detect slave funcs\n");
> +	return status;
> +}
> +
> +static void arcpgu_drm_connector_destroy(struct drm_connector *connector)
> +{
> +	drm_connector_unregister(connector);
> +	drm_connector_cleanup(connector);
> +}
> +
> +static const struct drm_connector_helper_funcs
> +arcpgu_drm_connector_helper_funcs = {
> +	.get_modes = arcpgu_drm_connector_get_modes,
> +	.best_encoder = arcpgu_drm_connector_best_encoder,
> +};
> +
> +static const struct drm_connector_funcs arcpgu_drm_connector_funcs = {
> +	.dpms = drm_helper_connector_dpms,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.detect = arcpgu_drm_connector_detect,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.destroy = arcpgu_drm_connector_destroy,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static struct drm_encoder_helper_funcs arcpgu_drm_encoder_helper_funcs = {
> +	.dpms = drm_i2c_encoder_dpms,
> +	.mode_fixup = drm_i2c_encoder_mode_fixup,
> +	.mode_set = drm_i2c_encoder_mode_set,
> +	.prepare = drm_i2c_encoder_prepare,
> +	.commit = drm_i2c_encoder_commit,
> +	.detect = drm_i2c_encoder_detect,
> +};
> +
> +static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = {
> +	.destroy = drm_encoder_cleanup,
> +};
> +
> +int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np)
> +{
> +	struct arcpgu_drm_connector *arcpgu_connector;
> +	struct drm_i2c_encoder_driver *driver;
> +	struct drm_encoder_slave *encoder;
> +	struct drm_connector *connector;
> +	struct i2c_client *i2c_slave;
> +	int ret;
> +
> +	encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL);
> +	if (encoder == NULL)
> +		return -ENOMEM;
> +
> +	i2c_slave = of_find_i2c_device_by_node(np);
> +	if (!i2c_slave || !i2c_get_clientdata(i2c_slave)) {
> +		dev_err(drm->dev, "failed to find i2c slave encoder\n");
> +		return -EPROBE_DEFER;
> +	}
> +
> +	if (i2c_slave->dev.driver == NULL) {
> +		dev_err(drm->dev, "failed to find i2c slave driver\n");
> +		return -EPROBE_DEFER;
> +	}
> +
> +	driver =
> +	    to_drm_i2c_encoder_driver(to_i2c_driver(i2c_slave->dev.driver));
> +	ret = driver->encoder_init(i2c_slave, drm, encoder);
> +	if (ret) {
> +		dev_err(drm->dev, "failed to initialize i2c encoder slave\n");
> +		return ret;
> +	}
> +
> +	encoder->base.possible_crtcs = 1;
> +	encoder->base.possible_clones = 0;
> +	ret = drm_encoder_init(drm, &encoder->base, &arcpgu_drm_encoder_funcs,
> +			       DRM_MODE_ENCODER_TMDS, NULL);
> +	if (ret)
> +		return ret;
> +
> +	drm_encoder_helper_add(&encoder->base,
> +			       &arcpgu_drm_encoder_helper_funcs);
> +
> +	arcpgu_connector = devm_kzalloc(drm->dev, sizeof(*arcpgu_connector),
> +					GFP_KERNEL);
> +	if (!arcpgu_connector) {
> +		ret = -ENOMEM;
> +		goto error_encoder_cleanup;
> +	}
> +
> +	connector = &arcpgu_connector->connector;
> +	drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs);
> +	ret = drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs,
> +			DRM_MODE_CONNECTOR_HDMIA);
> +	if (ret < 0) {
> +		dev_err(drm->dev, "failed to initialize drm connector\n");
> +		goto error_encoder_cleanup;
> +	}
> +
> +	ret = drm_connector_register(connector);
> +	if (ret < 0) {
> +		dev_err(drm->dev, "failed to regiter DRM connector and helper funcs\n");
> +		goto error_connector_cleanup;
> +	}
> +
> +	ret = drm_mode_connector_attach_encoder(connector, &encoder->base);
> +	if (ret < 0) {
> +		dev_err(drm->dev, "could not attach connector to encoder\n");
> +		drm_connector_unregister(connector);
> +		goto error_connector_cleanup;
> +	}
> +
> +	arcpgu_connector->encoder_slave = encoder;
> +
> +	return 0;
> +
> +error_connector_cleanup:
> +	drm_connector_cleanup(connector);
> +
> +error_encoder_cleanup:
> +	drm_encoder_cleanup(&encoder->base);
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/arc/arcpgu_regs.h b/drivers/gpu/drm/arc/arcpgu_regs.h
> new file mode 100644
> index 0000000..f04165f
> --- /dev/null
> +++ b/drivers/gpu/drm/arc/arcpgu_regs.h
> @@ -0,0 +1,36 @@
> +/*
> + * ARC PGU DRM driver.
> + *
> + * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#ifndef _ARC_PGU_REGS_H_
> +#define _ARC_PGU_REGS_H_
> +
> +#define ARCPGU_REG_CTRL		0x00
> +#define ARCPGU_REG_STAT		0x04
> +#define ARCPGU_REG_FMT		0x10
> +#define ARCPGU_REG_HSYNC	0x14
> +#define ARCPGU_REG_VSYNC	0x18
> +#define ARCPGU_REG_ACTIVE	0x1c
> +#define ARCPGU_REG_BUF0_ADDR	0x40
> +#define ARCPGU_REG_STRIDE	0x50
> +#define ARCPGU_REG_START_SET	0x84
> +
> +#define ARCPGU_REG_ID		0x3FC
> +
> +#define ARCPGU_CTRL_ENABLE_MASK	0x02
> +#define ARCPGU_MODE_RGB888_MASK	0x04
> +#define ARCPGU_STAT_BUSY_MASK	0x02
> +
> +#endif
> -- 
> 2.5.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From Vineet.Gupta1 at synopsys.com  Mon Mar 14 01:05:20 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Mon, 14 Mar 2016 13:35:20 +0530
Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic
In-Reply-To: <20160309114054.GJ6356@twins.programming.kicks-ass.net>
References: <1457447457-25878-1-git-send-email-vgupta@synopsys.com>
 <alpine.DEB.2.20.1603080857360.4047@east.gentwo.org>
 <56DEF3D3.6080008@synopsys.com>
 <alpine.DEB.2.20.1603081438020.4268@east.gentwo.org>
 <56DFC604.6070407@synopsys.com>
 <20160309101349.GJ6344@twins.programming.kicks-ass.net>
 <56E0024F.4070401@synopsys.com>
 <20160309114054.GJ6356@twins.programming.kicks-ass.net>
Message-ID: <56E670C0.7080901@synopsys.com>

On Wednesday 09 March 2016 05:10 PM, Peter Zijlstra wrote:

> ---
> Subject: bitops: Do not default to __clear_bit() for __clear_bit_unlock()
> 
> __clear_bit_unlock() is a special little snowflake. While it carries the
> non-atomic '__' prefix, it is specifically documented to pair with
> test_and_set_bit() and therefore should be 'somewhat' atomic.
> 
> Therefore the generic implementation of __clear_bit_unlock() cannot use
> the fully non-atomic __clear_bit() as a default.
> 
> If an arch is able to do better; is must provide an implementation of
> __clear_bit_unlock() itself.
> 
> Specifically, this came up as a result of hackbench livelock'ing in
> slab_lock() on ARC with SMP + SLUB + !LLSC.
> 
> The issue was incorrect pairing of atomic ops.
> 
> slab_lock() -> bit_spin_lock() -> test_and_set_bit()
> slab_unlock() -> __bit_spin_unlock() -> __clear_bit()
> 
> The non serializing __clear_bit() was getting "lost"
> 
> 80543b8e:	ld_s       r2,[r13,0] <--- (A) Finds PG_locked is set
> 80543b90:	or         r3,r2,1    <--- (B) other core unlocks right here
> 80543b94:	st_s       r3,[r13,0] <--- (C) sets PG_locked (overwrites unlock)
> 
> Fixes ARC STAR 9000817404 (and probably more).
> 
> Cc: stable at vger.kernel.org
> Reported-by: Vineet Gupta <Vineet.Gupta1 at synopsys.com>
> Tested-by: Vineet Gupta <Vineet.Gupta1 at synopsys.com>
> Signed-off-by: Peter Zijlstra (Intel) <peterz at infradead.org>

Peter, I don't see this in linux-next yet. I'm hoping you will send it Linus' way
for 4.6-rc1.

Thx,
-Vineet




From noreply at ellerman.id.au  Mon Mar 14 01:27:27 2016
From: noreply at ellerman.id.au (noreply at ellerman.id.au)
Date: Mon, 14 Mar 2016 08:27:27 -0000
Subject: kisskb: FAILED linux-next/axs101_defconfig/arcompact Mon Mar 14, 19:26
Message-ID: <20160314082727.1.35694@820dd7c2bc0c>

FAILED linux-next/axs101_defconfig/arcompact Mon Mar 14, 19:26

http://kisskb.ellerman.id.au/kisskb/buildresult/12633624/

Commit:   Add linux-next specific files for 20160314
          4342eec3c5a2402ca5de3d6e56f541fe1c5171e2
Compiler: arc-buildroot-linux-uclibc-gcc (Buildroot 2015.08.1) 4.8.4

Possible errors
---------------

arch/arc/include/asm/pci.h:13:40: fatal error: asm-generic/pci-dma-compat.h: No such file or directory
make[3]: *** [net/ethernet/eth.o] Error 1
make[2]: *** [net/ethernet] Error 2
arch/arc/include/asm/pci.h:13:40: fatal error: asm-generic/pci-dma-compat.h: No such file or directory
make[3]: *** [drivers/of/device.o] Error 1
arch/arc/include/asm/pci.h:13:40: fatal error: asm-generic/pci-dma-compat.h: No such file or directory
make[2]: *** [lib/pci_iomap.o] Error 1
arch/arc/include/asm/pci.h:13:40: fatal error: asm-generic/pci-dma-compat.h: No such file or directory
make[2]: *** [lib/devres.o] Error 1
make[1]: *** [lib] Error 2
arch/arc/include/asm/pci.h:13:40: fatal error: asm-generic/pci-dma-compat.h: No such file or directory
make[3]: *** [net/core/dev.o] Error 1
arch/arc/include/asm/pci.h:13:40: fatal error: asm-generic/pci-dma-compat.h: No such file or directory
make[5]: *** [drivers/video/fbdev/core/fbmon.o] Error 1
arch/arc/include/asm/pci.h:13:40: fatal error: asm-generic/pci-dma-compat.h: No such file or directory
make[6]: *** [drivers/net/ethernet/stmicro/stmmac/stmmac_main.o] Error 1
make[5]: *** [drivers/net/ethernet/stmicro/stmmac] Error 2
make[4]: *** [drivers/net/ethernet/stmicro] Error 2
make[3]: *** [drivers/net/ethernet] Error 2
make[2]: *** [drivers/of] Error 2
make[4]: *** [drivers/video/fbdev/core] Error 2
make[3]: *** [drivers/video/fbdev] Error 2
arch/arc/include/asm/pci.h:13:40: fatal error: asm-generic/pci-dma-compat.h: No such file or directory
make[3]: *** [drivers/scsi/scsi_lib.o] Error 1
make[2]: *** [net/core] Error 2
make[1]: *** [net] Error 2
arch/arc/include/asm/pci.h:13:40: fatal error: asm-generic/pci-dma-compat.h: No such file or directory
make[4]: *** [drivers/usb/host/ehci-hcd.o] Error 1
make[3]: *** [drivers/usb/host] Error 2
arch/arc/include/asm/pci.h:13:40: fatal error: asm-generic/pci-dma-compat.h: No such file or directory
make[4]: *** [drivers/usb/core/message.o] Error 1
make[2]: *** [drivers/net] Error 2
make[2]: *** [drivers/scsi] Error 2
make[2]: *** [drivers/video] Error 2
make[3]: *** [drivers/usb/core] Error 2
make[2]: *** [drivers/usb] Error 2
make[1]: *** [drivers] Error 2
make: *** [sub-make] Error 2

Possible warnings (91)
----------------------

drivers/pci/pcie/Kconfig:61:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:67:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:74:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:61:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:67:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:74:warning: choice value used outside its choice group
<stdin>:1310:2: warning: #warning syscall preadv2 not implemented [-Wcpp]
<stdin>:1313:2: warning: #warning syscall pwritev2 not implemented [-Wcpp]
Warning (unit_address_vs_reg): Node /timer at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /timer at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
Warning (unit_address_vs_reg): Node /cpu_card has a reg or ranges property, but no unit name
Warning (unit_address_vs_reg): Node /cpu_card/arc700-intc at cpu has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /axs10x_mb has a reg or ranges property, but no unit name
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
kernel/sysctl.c:1958:12: warning: 'p' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/sched/core.c:3080:1: warning: control reaches end of non-void function [-Wreturn-type]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
kernel/sysctl.c:1958:12: warning: 'p' may be used uninitialized in this function [-Wmaybe-uninitialized]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
kernel/time/posix-cpu-timers.c:787:21: warning: 'now' may be used uninitialized in this function [-Wmaybe-uninitialized]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
kernel/time/posix-cpu-timers.c:95:8: warning: 'now' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:665:17: warning: 'val' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:1238:13: warning: 'now' may be used uninitialized in this function [-Wmaybe-uninitialized]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
ipc/shm.c:1252:2: warning: 'ret' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/namei.c:1712:2: warning: 'seq' may be used uninitialized in this function [-Wmaybe-uninitialized]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
fs/namei.c:1712:2: warning: 'seq' may be used uninitialized in this function [-Wmaybe-uninitialized]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
include/linux/rbtree.h:83:28: warning: 'rb_parent' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/linux/rbtree.h:86:11: warning: 'rb_link' may be used uninitialized in this function [-Wmaybe-uninitialized]
mm/mmap.c:558:17: warning: 'prev' may be used uninitialized in this function [-Wmaybe-uninitialized]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
include/linux/kernel.h:735:17: warning: comparison of distinct pointer types lacks a cast [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/elf.h:58:29: warning: integer overflow in expression [-Woverflow]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
net/core/datagram.c:99:5: warning: 'last' may be used uninitialized in this function [-Wmaybe-uninitialized]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
net/core/datagram.c:99:5: warning: 'last' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/asm-generic/bug.h:74:48: warning: 'fn' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
block/cfq-iosched.c:3793:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/linux/buffer_head.h:363:2: warning: 'blocknr' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/core/ethtool.c:295:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/linux/buffer_head.h:370:2: warning: 'blocknr' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:315:21: warning: 'handle' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
drivers/usb/core/hub.c:2767:16: warning: 'portchange' may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/usb/core/hub.c:2740:20: warning: 'portstatus' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_extents.h:224:8: warning: '*((void *)&zero_ex+8)' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_extents.h:225:12: warning: '*((void *)&zero_ex+6)' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/extents.c:3119:2: warning: 'zero_ex.ee_block' may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/tty/serial/8250/8250_core.c:250:10: warning: 'i' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/extents.c:2312:14: warning: 'lblock' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/extents.c:2311:14: warning: 'len' may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/usb/storage/transport.c:499:15: warning: 'partial' may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/usb/storage/transport.c:473:40: warning: 'partial' may be used uninitialized in this function [-Wmaybe-uninitialized]



From Alexey.Brodkin at synopsys.com  Mon Mar 14 04:15:59 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Mon, 14 Mar 2016 11:15:59 +0000
Subject: [PATCH 1/4 v3] drm: Add support of ARC PGU display controller
In-Reply-To: <20160314070009.GN14170@phenom.ffwll.local>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
 <1457710959-9562-2-git-send-email-abrodkin@synopsys.com>
 <20160314070009.GN14170@phenom.ffwll.local>
Message-ID: <1457954159.3306.24.camel@synopsys.com>

Hi Daniel,

On Mon, 2016-03-14 at 08:00 +0100, Daniel Vetter wrote:
> On Fri, Mar 11, 2016 at 06:42:36PM +0300, Alexey Brodkin wrote:
> > 
> > ARC PGU could be found on some development boards from Synopsys.
> > This is a simple byte streamer that reads data from a framebuffer
> > and sends data to the single encoder.
> > 
> > Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
> > Cc: David Airlie <airlied at linux.ie>
> > Cc: dri-devel at lists.freedesktop.org
> > Cc: linux-snps-arc at lists.infradead.org
> > Cc: Jose Abreu <joabreu at synopsys.com>
> > ---
> > 
> > Changes v2 -> v3:
> > ?* Improved failure path if arcpgu_connector wasn't allocated (thanks Jose).
> > ?* Fixed driver building as module (reported by 0-DAY kernel test infrastruct.)
> > ?* Implemented uncached mapping of user-space FB pages.
> > 
> > No changes v1 -> v2.
> > 
> Bunch of comments below to update your driver to latest styles and best
> practices.
> 
> Cheers, Daniel

Thanks for doing that review!

> > +
> > +static void arc_pgu_crtc_atomic_flush(struct drm_crtc *crtc,
> > +				??????struct drm_crtc_state *state)
> > +{
> > +}
> > +
> > +static bool arc_pgu_crtc_mode_fixup(struct drm_crtc *crtc,
> > +				????const struct drm_display_mode *mode,
> > +				????struct drm_display_mode *adjusted_mode)
> > +{
> > +	return true;
> > +}
> You can drop the above 2 dummy functions.

Ok will do.

> > 
> > +
> > +static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
> > +	.mode_fixup	= arc_pgu_crtc_mode_fixup,
> > +	.mode_set	= drm_helper_crtc_mode_set,
> > +	.mode_set_base	= drm_helper_crtc_mode_set_base,
> > +	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
> > +	.enable		= arc_pgu_crtc_enable,
> > +	.disable	= arc_pgu_crtc_disable,
> > +	.prepare	= arc_pgu_crtc_disable,
> > +	.commit		= arc_pgu_crtc_enable,
> > +	.atomic_check	= arc_pgu_crtc_atomic_check,
> > +	.atomic_begin	= arc_pgu_crtc_atomic_begin,
> > +	.atomic_flush	= arc_pgu_crtc_atomic_flush,
> > +};
> > +
> > +static int arc_pgu_plane_atomic_check(struct drm_plane *plane,
> > +				??????struct drm_plane_state *state)
> > +{
> > +	return 0;
> > +}
> You don't need dummy functions for this.

Ditto.

> > +
> > +void arc_pgu_crtc_suspend(struct drm_crtc *crtc)
> > +{
> > +	arc_pgu_crtc_disable(crtc);
> > +}
> > +
> > +void arc_pgu_crtc_resume(struct drm_crtc *crtc)
> > +{
> > +	arc_pgu_crtc_enable(crtc);
> > +}
> Please use the atomic suspend/resume helper that Thierry recently merged.
> See the kerneldoc of drm_atomic_helper_suspend as a starting point for how
> it works and how it's supposed to be used.

Well looks like this is a reminder if dummy copy-paste.
We don't support PM in that driver yet, so I'll remove both functions
for now.

> > +static int arcpgu_atomic_commit(struct drm_device *dev,
> > +				????struct drm_atomic_state *state, bool async)
> > +{
> > +	return drm_atomic_helper_commit(dev, state, false);
> Note that this isn't really async if you ever get around to implement
> fence support or vblank support. Just fyi.

Ok but for now should I leave it as it is?

> > +static struct drm_driver arcpgu_drm_driver = {
> > +	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
> > +			???DRIVER_ATOMIC,
> > +	.preclose = arcpgu_preclose,
> > +	.lastclose = arcpgu_lastclose,
> > +	.name = "drm-arcpgu",
> > +	.desc = "ARC PGU Controller",
> > +	.date = "20160219",
> > +	.major = 1,
> > +	.minor = 0,
> > +	.patchlevel = 0,
> > +	.fops = &arcpgu_drm_ops,
> > +	.load = arcpgu_load,
> > +	.unload = arcpgu_unload,
> Load and unload hooks are deprecated (it's a classic midlayer mistake).
> Please use drm_dev_alloc/register pairs directly instead, and put your
> device setup code in-between. Similar for unloading. There's a bunch of
> example drivers converted already.

Ok I took "atmel-hlcdc" as example.
And that's interesting.

If I put my?arcpgu_load() in between?drm_dev_alloc() and
drm_dev_register() then I'm getting this on the driver probe:
---------------------------------->8-------------------------------
[drm] Initialized drm 1.1.0 20060810
arcpgu e0017000.pgu: arc_pgu ID: 0xabbabaab
------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at lib/kobject.c:244 kobject_add_internal+0x17c/0x498()
kobject_add_internal failed for card0-HDMI-A-1 (error: -2 parent: card0)
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 4.5.0-rc3-01062-ga447822-dirty #17

Stack Trace:
? arc_unwind_core.constprop.1+0xa4/0x110
? warn_slowpath_fmt+0x6e/0xfc
? kobject_add_internal+0x17c/0x498
? kobject_add+0x98/0xe4
? device_add+0xc6/0x734
? device_create_with_groups+0x12a/0x144
? drm_sysfs_connector_add+0x54/0xe8
? arcpgu_drm_hdmi_init+0xd4/0x17c
? arcpgu_probe+0x138/0x24c
? platform_drv_probe+0x2e/0x6c
? really_probe+0x212/0x35c
? __driver_attach+0x90/0x94
? bus_for_each_dev+0x46/0x80
? bus_add_driver+0x14e/0x1b4
? driver_register+0x64/0x108
? do_one_initcall+0x86/0x194
? kernel_init_freeable+0xf0/0x188
---[ end trace c67166ad43ddcce2 ]---
[drm:drm_sysfs_connector_add] adding "HDMI-A-1" to sysfs
[drm:drm_sysfs_connector_add] *ERROR* failed to register connector device: -2
arcpgu e0017000.pgu: failed to regiter DRM connector and helper funcs
arcpgu: probe of e0017000.pgu failed with error -2
---------------------------------->8-------------------------------

But if I move arcpgu_load() after drm_dev_register() then everything
starts properly and I may see HDMI screen works perfectly fine.

Any thoughts?


> > 
> > +	.dumb_create = drm_gem_cma_dumb_create,
> > +	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
> > +	.dumb_destroy = drm_gem_dumb_destroy,
> > +	.get_vblank_counter = drm_vblank_no_hw_counter,
> > +	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> > +	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> > +	.gem_free_object = drm_gem_cma_free_object,
> > +	.gem_vm_ops = &drm_gem_cma_vm_ops,
> > +	.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,
> > +};
> > +
> > +static int arcpgu_probe(struct platform_device *pdev)
> > +{
> > +	return drm_platform_init(&arcpgu_drm_driver, pdev);
> ... or read the kerneldoc of this function, which also explains what you
> should do ;-)

Could you please point me to the relevant document?
I wasn't able to find anything related from the first glance :(

> > +
> > +/*
> > + * This function is the only reason to have a copy of drm_fbdev_cma_init()
> > + * here in this driver.
> > + *
> > + * In its turn this mmap() is required to mark user-space page as non-cached
> > + * because it is just a mirror or real hardware frame-buffer.
> > + */
> > +static int arcpgu_mmap(struct fb_info *info, struct vm_area_struct *vma)
> > +{
> > +	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> > +	return vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
> > +}
> This looks very fishy, no other drm driver even bothers with providing an
> fb_mmap hook. What exactly do you need this for? Assuming you've mmapped
> your fbcon drm_framebuffer correctly for kernel access things should just
> work ...

Indeed for kernel there's non need to that hack. Kernel deals directly with HW
frame-buffer area (that address we get from gem->paddr). And so every byte written gets
picked up by PGU and is then rendered on the display.

But when user-space opens /dev/fb0 and mmaps() it deals with memory pages which
are by default (at least on ARC) marked as "cached". I.e. user-space application
(I use that nice demo app?https://github.com/qtproject/qt/blob/4.8/examples/qws/framebuffer/main.c)
deals with frame-buffer via data cache. And that has 2 problems:
?[1] Since no explicit cache flush gets executed some data is left in data cache,
? ? ?i.e. some parts of the picture never reaches real PGU.
? ? ?See what happens on display -?http://imgur.com/iAbnnx3
? ? ?Those missing lines are exactly those 32-byte missing cache lines.
?[2] Even if we manage to flush data somehow massive amount of data that goes
? ? ?through data cache (let's sat 1080p at 30Hz) will thrash it and as a result
? ? ?there will be no benefit for other cache users to use cache.

So we fix it simply marking pages mapped to user-space apps as uncached
that effectively routes all FB data directly to memry instead of polluting cache.

Hopefully that explanation makes sense.

-Alexey


From Lada.Trimasova at synopsys.com  Mon Mar 14 07:11:57 2016
From: Lada.Trimasova at synopsys.com (Lada Trimasova)
Date: Mon, 14 Mar 2016 17:11:57 +0300
Subject: [PATCH] arc: use ezchip network driver
Message-ID: <1457964717-7167-1-git-send-email-ltrimas@synopsys.com>

Since ezchip network driver was adapted to little endian architecture
this patch provides the corresponding arch/arc/{boot/dts,configs}/ updates so
we can switch over to this device-model/driver for OSCI platform.

Signed-off-by: Lada Trimasova <ltrimas at synopsys.com>
Cc: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Vineet Gupta <vgupta at synopsys.com>:
---
 arch/arc/boot/dts/nsimosci.dts             | 5 ++---
 arch/arc/boot/dts/nsimosci_hs.dts          | 5 ++---
 arch/arc/boot/dts/nsimosci_hs_idu.dts      | 5 ++---
 arch/arc/configs/nsimosci_defconfig        | 1 +
 arch/arc/configs/nsimosci_hs_defconfig     | 1 +
 arch/arc/configs/nsimosci_hs_smp_defconfig | 1 +
 6 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/arc/boot/dts/nsimosci.dts b/arch/arc/boot/dts/nsimosci.dts
index 1c169dc..d94b4ce 100644
--- a/arch/arc/boot/dts/nsimosci.dts
+++ b/arch/arc/boot/dts/nsimosci.dts
@@ -65,10 +65,9 @@
 		};
 
 		eth0: ethernet at f0003000 {
-			compatible = "snps,oscilan";
+			compatible = "ezchip,nps-mgt-enet";
 			reg = <0xf0003000 0x44>;
-			interrupts = <7>, <8>;
-			interrupt-names = "rx", "tx";
+			interrupts = <7>;
 		};
 	};
 };
diff --git a/arch/arc/boot/dts/nsimosci_hs.dts b/arch/arc/boot/dts/nsimosci_hs.dts
index d64a96f..034a313 100644
--- a/arch/arc/boot/dts/nsimosci_hs.dts
+++ b/arch/arc/boot/dts/nsimosci_hs.dts
@@ -65,10 +65,9 @@
 		};
 
 		eth0: ethernet at f0003000 {
-			compatible = "snps,oscilan";
+			compatible = "ezchip,nps-mgt-enet";
 			reg = <0xf0003000 0x44>;
-			interrupts = <25>, <26>;
-			interrupt-names = "rx", "tx";
+			interrupts = <25>;
 		};
 
 		arcpct0: pct {
diff --git a/arch/arc/boot/dts/nsimosci_hs_idu.dts b/arch/arc/boot/dts/nsimosci_hs_idu.dts
index f6bf0ca..8a1297e 100644
--- a/arch/arc/boot/dts/nsimosci_hs_idu.dts
+++ b/arch/arc/boot/dts/nsimosci_hs_idu.dts
@@ -85,11 +85,10 @@
 		};
 
 		eth0: ethernet at f0003000 {
-			compatible = "snps,oscilan";
+			compatible = "ezchip,nps-mgt-enet";
 			reg = <0xf0003000 0x44>;
 			interrupt-parent = <&idu_intc>;
-			interrupts = <1 2>, <2 2>;
-			interrupt-names = "rx", "tx";
+			interrupts = <1 2>;
 		};
 
 		arcpct0: pct {
diff --git a/arch/arc/configs/nsimosci_defconfig b/arch/arc/configs/nsimosci_defconfig
index 646182e..97dfc30 100644
--- a/arch/arc/configs/nsimosci_defconfig
+++ b/arch/arc/configs/nsimosci_defconfig
@@ -27,6 +27,7 @@ CONFIG_ARC_PLAT_SIM=y
 CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci"
 # CONFIG_COMPACTION is not set
 CONFIG_NET=y
+CONFIG_EZCHIP_NPS_MANAGEMENT_ENET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_UNIX_DIAG=y
diff --git a/arch/arc/configs/nsimosci_hs_defconfig b/arch/arc/configs/nsimosci_hs_defconfig
index ceca254..55e2892 100644
--- a/arch/arc/configs/nsimosci_hs_defconfig
+++ b/arch/arc/configs/nsimosci_hs_defconfig
@@ -28,6 +28,7 @@ CONFIG_ISA_ARCV2=y
 CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci_hs"
 # CONFIG_COMPACTION is not set
 CONFIG_NET=y
+CONFIG_EZCHIP_NPS_MANAGEMENT_ENET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_UNIX_DIAG=y
diff --git a/arch/arc/configs/nsimosci_hs_smp_defconfig b/arch/arc/configs/nsimosci_hs_smp_defconfig
index 4b6da90..74a3e48 100644
--- a/arch/arc/configs/nsimosci_hs_smp_defconfig
+++ b/arch/arc/configs/nsimosci_hs_smp_defconfig
@@ -25,6 +25,7 @@ CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci_hs_idu"
 CONFIG_PREEMPT=y
 # CONFIG_COMPACTION is not set
 CONFIG_NET=y
+CONFIG_EZCHIP_NPS_MANAGEMENT_ENET=y
 CONFIG_PACKET=y
 CONFIG_PACKET_DIAG=y
 CONFIG_UNIX=y
-- 
2.5.0



From daniel at ffwll.ch  Tue Mar 15 01:10:57 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Tue, 15 Mar 2016 09:10:57 +0100
Subject: [PATCH 1/4 v3] drm: Add support of ARC PGU display controller
In-Reply-To: <1457954159.3306.24.camel@synopsys.com>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
 <1457710959-9562-2-git-send-email-abrodkin@synopsys.com>
 <20160314070009.GN14170@phenom.ffwll.local>
 <1457954159.3306.24.camel@synopsys.com>
Message-ID: <20160315081056.GS14170@phenom.ffwll.local>

On Mon, Mar 14, 2016 at 11:15:59AM +0000, Alexey Brodkin wrote:
> On Mon, 2016-03-14 at 08:00 +0100, Daniel Vetter wrote:
> > On Fri, Mar 11, 2016 at 06:42:36PM +0300, Alexey Brodkin wrote:
> > > +static int arcpgu_atomic_commit(struct drm_device *dev,
> > > +				????struct drm_atomic_state *state, bool async)
> > > +{
> > > +	return drm_atomic_helper_commit(dev, state, false);
> > Note that this isn't really async if you ever get around to implement
> > fence support or vblank support. Just fyi.
> 
> Ok but for now should I leave it as it is?

Yeah ok as-is, hence just fyi.

> > > +static struct drm_driver arcpgu_drm_driver = {
> > > +	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
> > > +			???DRIVER_ATOMIC,
> > > +	.preclose = arcpgu_preclose,
> > > +	.lastclose = arcpgu_lastclose,
> > > +	.name = "drm-arcpgu",
> > > +	.desc = "ARC PGU Controller",
> > > +	.date = "20160219",
> > > +	.major = 1,
> > > +	.minor = 0,
> > > +	.patchlevel = 0,
> > > +	.fops = &arcpgu_drm_ops,
> > > +	.load = arcpgu_load,
> > > +	.unload = arcpgu_unload,
> > Load and unload hooks are deprecated (it's a classic midlayer mistake).
> > Please use drm_dev_alloc/register pairs directly instead, and put your
> > device setup code in-between. Similar for unloading. There's a bunch of
> > example drivers converted already.
> 
> Ok I took "atmel-hlcdc" as example.
> And that's interesting.
> 
> If I put my?arcpgu_load() in between?drm_dev_alloc() and
> drm_dev_register() then I'm getting this on the driver probe:
> ---------------------------------->8-------------------------------
> [drm] Initialized drm 1.1.0 20060810
> arcpgu e0017000.pgu: arc_pgu ID: 0xabbabaab
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 1 at lib/kobject.c:244 kobject_add_internal+0x17c/0x498()
> kobject_add_internal failed for card0-HDMI-A-1 (error: -2 parent: card0)
> Modules linked in:
> CPU: 0 PID: 1 Comm: swapper Not tainted 4.5.0-rc3-01062-ga447822-dirty #17
> 
> Stack Trace:
> ? arc_unwind_core.constprop.1+0xa4/0x110
> ? warn_slowpath_fmt+0x6e/0xfc
> ? kobject_add_internal+0x17c/0x498
> ? kobject_add+0x98/0xe4
> ? device_add+0xc6/0x734
> ? device_create_with_groups+0x12a/0x144
> ? drm_sysfs_connector_add+0x54/0xe8
> ? arcpgu_drm_hdmi_init+0xd4/0x17c
> ? arcpgu_probe+0x138/0x24c
> ? platform_drv_probe+0x2e/0x6c
> ? really_probe+0x212/0x35c
> ? __driver_attach+0x90/0x94
> ? bus_for_each_dev+0x46/0x80
> ? bus_add_driver+0x14e/0x1b4
> ? driver_register+0x64/0x108
> ? do_one_initcall+0x86/0x194
> ? kernel_init_freeable+0xf0/0x188
> ---[ end trace c67166ad43ddcce2 ]---
> [drm:drm_sysfs_connector_add] adding "HDMI-A-1" to sysfs
> [drm:drm_sysfs_connector_add] *ERROR* failed to register connector device: -2
> arcpgu e0017000.pgu: failed to regiter DRM connector and helper funcs
> arcpgu: probe of e0017000.pgu failed with error -2
> ---------------------------------->8-------------------------------
> 
> But if I move arcpgu_load() after drm_dev_register() then everything
> starts properly and I may see HDMI screen works perfectly fine.
> 
> Any thoughts?

Oops, yeah missed that detail. If you look at atmel it has a loop to
register all the drm connectors _after_ calling drm_dev_register().
Totally forgot about that. Can you pls
- Extract a new drm_connector_register_all() function
  (atmel_hlcdc_dc_connector_plug_all seems to be the best template),
  including kerneldoc.
- Adjust kerneldoc of drm_dev_register() to mention
  drm_connector_register_all() and that ordering constraint.
- Roll that helper out to all the drivers that currently hand-roll it (one
  patch per driver).

I know a bit of work but imo not too much, and by doing some small
refactoring every time someone stumbles over a drm pitfall we keep the
subsystem clean&easy to understand. You're up for this? Would be a prep
series, I'll happily review it to get it merged fast. Just a few weeks ago
I merged 20+ patches to make ->mode_fixup hooks optional and remove dummy
ones all over the subsystem, in other words: You'll have my full attention
;-)

> > > +	.dumb_create = drm_gem_cma_dumb_create,
> > > +	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
> > > +	.dumb_destroy = drm_gem_dumb_destroy,
> > > +	.get_vblank_counter = drm_vblank_no_hw_counter,
> > > +	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> > > +	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> > > +	.gem_free_object = drm_gem_cma_free_object,
> > > +	.gem_vm_ops = &drm_gem_cma_vm_ops,
> > > +	.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,
> > > +};
> > > +
> > > +static int arcpgu_probe(struct platform_device *pdev)
> > > +{
> > > +	return drm_platform_init(&arcpgu_drm_driver, pdev);
> > ... or read the kerneldoc of this function, which also explains what you
> > should do ;-)
> 
> Could you please point me to the relevant document?
> I wasn't able to find anything related from the first glance :(

The kerneldoc comment for drm_platform_init says it's deprecated, please
use drm_dev_alloc/register instead.
> 
> > > +
> > > +/*
> > > + * This function is the only reason to have a copy of drm_fbdev_cma_init()
> > > + * here in this driver.
> > > + *
> > > + * In its turn this mmap() is required to mark user-space page as non-cached
> > > + * because it is just a mirror or real hardware frame-buffer.
> > > + */
> > > +static int arcpgu_mmap(struct fb_info *info, struct vm_area_struct *vma)
> > > +{
> > > +	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> > > +	return vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
> > > +}
> > This looks very fishy, no other drm driver even bothers with providing an
> > fb_mmap hook. What exactly do you need this for? Assuming you've mmapped
> > your fbcon drm_framebuffer correctly for kernel access things should just
> > work ...
> 
> Indeed for kernel there's non need to that hack. Kernel deals directly with HW
> frame-buffer area (that address we get from gem->paddr). And so every byte written gets
> picked up by PGU and is then rendered on the display.
> 
> But when user-space opens /dev/fb0 and mmaps() it deals with memory pages which
> are by default (at least on ARC) marked as "cached". I.e. user-space application
> (I use that nice demo app?https://github.com/qtproject/qt/blob/4.8/examples/qws/framebuffer/main.c)
> deals with frame-buffer via data cache. And that has 2 problems:
> ?[1] Since no explicit cache flush gets executed some data is left in data cache,
> ? ? ?i.e. some parts of the picture never reaches real PGU.
> ? ? ?See what happens on display -?http://imgur.com/iAbnnx3
> ? ? ?Those missing lines are exactly those 32-byte missing cache lines.
> ?[2] Even if we manage to flush data somehow massive amount of data that goes
> ? ? ?through data cache (let's sat 1080p at 30Hz) will thrash it and as a result
> ? ? ?there will be no benefit for other cache users to use cache.
> 
> So we fix it simply marking pages mapped to user-space apps as uncached
> that effectively routes all FB data directly to memry instead of polluting cache.
> 
> Hopefully that explanation makes sense.

Still strange that you're the only one who needs this. I think best case
would be to provide some mmap helpers for fbdev which remap to dumb buffer
helpers or something similar. That way other drivers don't need to

Another piece is that right now fbdev emulation hasn't wired up the manual
update mode to the drm ->dirtyfb call. Drivers that need to manual flush
stuff to the screen currently all have to hand-roll those calls one way or
the other (udl, qxl, i915).

But just an observation really, nothing to fix up for this driver imo.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From Alexey.Brodkin at synopsys.com  Tue Mar 15 02:29:10 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Tue, 15 Mar 2016 12:29:10 +0300
Subject: [PATCH] ARC: axs10x - add Ethernet PHY description in .dts
Message-ID: <1458034150-10766-1-git-send-email-abrodkin@synopsys.com>

Following commit broke DW GMAC functionality on AXS10x boards:
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763

That's what happens on eth0 up:
--------------------------->8------------------------
libphy: PHY stmmac-0:ffffffff not found
eth0: Could not attach to PHY
stmmac_open: Cannot attach to PHY (error: -19)
--------------------------->8------------------------

Simplest solution is to add PHY description in board's .dts.
And so we do here.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Rob Herring <robh at kernel.org>
Cc: Phil Reid <preid at electromag.com.au>
Cc: David S. Miller <davem at davemloft.net>
Cc: linux-kernel at vger.kernel.org
Cc: netdev at vger.kernel.org
Cc: stable at vger.kernel.org # 4.5.x
---
 arch/arc/boot/dts/axs10x_mb.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
index 44a578c..04b999e 100644
--- a/arch/arc/boot/dts/axs10x_mb.dtsi
+++ b/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -47,6 +47,14 @@
 			clocks = <&apbclk>;
 			clock-names = "stmmaceth";
 			max-speed = <100>;
+			mdio0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "snps,dwmac-mdio";
+				phy0: ethernet-phy at 0 {
+					reg = <1>;
+				};
+			};
 		};
 
 		ehci at 0x40000 {
-- 
2.5.0



From Joao.Pinto at synopsys.com  Tue Mar 15 04:06:02 2016
From: Joao.Pinto at synopsys.com (Joao Pinto)
Date: Tue, 15 Mar 2016 11:06:02 +0000
Subject: [PATCH] Remove the inclusion of pci-bridge.h and pci-dma-compat.h
Message-ID: <d3ed7b3e4f746831a5d0469da5361b4cd176f5c6.1457978659.git.jpinto@synopsys.com>

While building linux-next the test robot detected that the pci.h was including
two removed header files (pci-dma-compat.h and pci-bridge.h) causing the
process to fail:
http://lists.infradead.org/pipermail/linux-snps-arc/2016-March/000711.html

This patch has the goal to fix the build problem.

Signed-off-by: Joao Pinto <jpinto at synopsys.com>
---
 arch/arc/include/asm/pci.h | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/arch/arc/include/asm/pci.h b/arch/arc/include/asm/pci.h
index 2f2011c..ba56c23 100644
--- a/arch/arc/include/asm/pci.h
+++ b/arch/arc/include/asm/pci.h
@@ -10,9 +10,6 @@
 #define _ASM_ARC_PCI_H
 
 #ifdef __KERNEL__
-#include <asm-generic/pci-dma-compat.h>
-#include <asm-generic/pci-bridge.h>
-
 #include <linux/ioport.h>
 
 #define PCIBIOS_MIN_IO 0x100
-- 
1.8.1.5



From Vineet.Gupta1 at synopsys.com  Tue Mar 15 04:13:47 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 15 Mar 2016 11:13:47 +0000
Subject: [PATCH] Remove the inclusion of pci-bridge.h and pci-dma-compat.h
References: <d3ed7b3e4f746831a5d0469da5361b4cd176f5c6.1457978659.git.jpinto@synopsys.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E8FE6E@us01wembx1.internal.synopsys.com>

On Tuesday 15 March 2016 04:36 PM, Joao Pinto wrote:
> While building linux-next the test robot detected that the pci.h was including
> two removed header files (pci-dma-compat.h and pci-bridge.h) causing the
> process to fail:
> http://lists.infradead.org/pipermail/linux-snps-arc/2016-March/000711.html
>
> This patch has the goal to fix the build problem.
>
> Signed-off-by: Joao Pinto <jpinto at synopsys.com>

Acked-by: Vineet Gupta <vgupta at synopsys.com>

@Bjorn since the ARC PCI support is still not upstream, and was slated to go via
you, please pick this one up as well.

Thx,
-Vineet

> ---
>  arch/arc/include/asm/pci.h | 3 ---
>  1 file changed, 3 deletions(-)
>
> diff --git a/arch/arc/include/asm/pci.h b/arch/arc/include/asm/pci.h
> index 2f2011c..ba56c23 100644
> --- a/arch/arc/include/asm/pci.h
> +++ b/arch/arc/include/asm/pci.h
> @@ -10,9 +10,6 @@
>  #define _ASM_ARC_PCI_H
>  
>  #ifdef __KERNEL__
> -#include <asm-generic/pci-dma-compat.h>
> -#include <asm-generic/pci-bridge.h>
> -
>  #include <linux/ioport.h>
>  
>  #define PCIBIOS_MIN_IO 0x100



From andreas.ziegler at fau.de  Tue Mar 15 04:16:55 2016
From: andreas.ziegler at fau.de (Andreas Ziegler)
Date: Tue, 15 Mar 2016 12:16:55 +0100
Subject: [PATCH] ARC: Don't source drivers/pci/pcie/Kconfig ourselves
Message-ID: <1458040615-10697-1-git-send-email-andreas.ziegler@fau.de>

Commit 5f8fc43217a0 ("PCI: Include pci/pcie/Kconfig directly from
pci/Kconfig") in linux-next changed drivers/pci/Kconfig to include
drivers/pci/pcie/Kconfig itself, so that architectures do not need
to source both files themselves. ARC just recently gained PCI support
through commit 6b3fb77998dd ("ARC: Add PCI support"), but this change
was based on the old behaviour of the Kconfig files. This makes
Kconfig now spit out the following warnings:

drivers/pci/pcie/Kconfig:61:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:67:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:74:warning: choice value used outside its choice group

This change updates the Kconfig file for ARC, dropping the now
unnecessary 'source' statement, which makes the warning disappear.

Signed-off-by: Andreas Ziegler <andreas.ziegler at fau.de>
---
 arch/arc/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 69d05f5..282efec 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -592,7 +592,6 @@ config PCI_SYSCALL
 	def_bool PCI
 
 source "drivers/pci/Kconfig"
-source "drivers/pci/pcie/Kconfig"
 
 endmenu
 
-- 
1.9.1



From Vineet.Gupta1 at synopsys.com  Tue Mar 15 04:38:34 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 15 Mar 2016 11:38:34 +0000
Subject: [PATCH] ARC: Don't source drivers/pci/pcie/Kconfig ourselves
References: <1458040615-10697-1-git-send-email-andreas.ziegler@fau.de>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E8FE8F@us01wembx1.internal.synopsys.com>

On Tuesday 15 March 2016 04:47 PM, Andreas Ziegler wrote:
> Commit 5f8fc43217a0 ("PCI: Include pci/pcie/Kconfig directly from
> pci/Kconfig") in linux-next changed drivers/pci/Kconfig to include
> drivers/pci/pcie/Kconfig itself, so that architectures do not need
> to source both files themselves. ARC just recently gained PCI support
> through commit 6b3fb77998dd ("ARC: Add PCI support"), but this change
> was based on the old behaviour of the Kconfig files. This makes
> Kconfig now spit out the following warnings:
>
> drivers/pci/pcie/Kconfig:61:warning: choice value used outside its choice group
> drivers/pci/pcie/Kconfig:67:warning: choice value used outside its choice group
> drivers/pci/pcie/Kconfig:74:warning: choice value used outside its choice group
>
> This change updates the Kconfig file for ARC, dropping the now
> unnecessary 'source' statement, which makes the warning disappear.
>
> Signed-off-by: Andreas Ziegler <andreas.ziegler at fau.de>

Thx for the fix Andreas.

@Bjorn sorry you might to have to pick this one up as well.
If not, that's fine too - I'll queue it up once ARC PCI hits upstream.

Thx,
-Vineet

> ---
>  arch/arc/Kconfig | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
> index 69d05f5..282efec 100644
> --- a/arch/arc/Kconfig
> +++ b/arch/arc/Kconfig
> @@ -592,7 +592,6 @@ config PCI_SYSCALL
>  	def_bool PCI
>  
>  source "drivers/pci/Kconfig"
> -source "drivers/pci/pcie/Kconfig"
>  
>  endmenu
>  



From Joao.Pinto at synopsys.com  Tue Mar 15 05:06:31 2016
From: Joao.Pinto at synopsys.com (Joao Pinto)
Date: Tue, 15 Mar 2016 12:06:31 +0000
Subject: [PATCH] ARC: Don't source drivers/pci/pcie/Kconfig ourselves
In-Reply-To: <C2D7FE5348E1B147BCA15975FBA23075F4E8FE8F@us01wembx1.internal.synopsys.com>
References: <1458040615-10697-1-git-send-email-andreas.ziegler@fau.de>
 <C2D7FE5348E1B147BCA15975FBA23075F4E8FE8F@us01wembx1.internal.synopsys.com>
Message-ID: <56E7FAC7.7030001@synopsys.com>

On 3/15/2016 11:38 AM, Vineet Gupta wrote:
> On Tuesday 15 March 2016 04:47 PM, Andreas Ziegler wrote:
>> Commit 5f8fc43217a0 ("PCI: Include pci/pcie/Kconfig directly from
>> pci/Kconfig") in linux-next changed drivers/pci/Kconfig to include
>> drivers/pci/pcie/Kconfig itself, so that architectures do not need
>> to source both files themselves. ARC just recently gained PCI support
>> through commit 6b3fb77998dd ("ARC: Add PCI support"), but this change
>> was based on the old behaviour of the Kconfig files. This makes
>> Kconfig now spit out the following warnings:
>>
>> drivers/pci/pcie/Kconfig:61:warning: choice value used outside its choice group
>> drivers/pci/pcie/Kconfig:67:warning: choice value used outside its choice group
>> drivers/pci/pcie/Kconfig:74:warning: choice value used outside its choice group
>>
>> This change updates the Kconfig file for ARC, dropping the now
>> unnecessary 'source' statement, which makes the warning disappear.
>>
>> Signed-off-by: Andreas Ziegler <andreas.ziegler at fau.de>
> 
> Thx for the fix Andreas.
> 
> @Bjorn sorry you might to have to pick this one up as well.
> If not, that's fine too - I'll queue it up once ARC PCI hits upstream.
> 
> Thx,
> -Vineet
> 
>> ---
>>  arch/arc/Kconfig | 1 -
>>  1 file changed, 1 deletion(-)
>>
>> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
>> index 69d05f5..282efec 100644
>> --- a/arch/arc/Kconfig
>> +++ b/arch/arc/Kconfig
>> @@ -592,7 +592,6 @@ config PCI_SYSCALL
>>  	def_bool PCI
>>  
>>  source "drivers/pci/Kconfig"
>> -source "drivers/pci/pcie/Kconfig"
>>  
>>  endmenu
>>  
> 

Acked-by: Joao Pinto <jpinto at synopsys.com>


From helgaas at kernel.org  Tue Mar 15 06:51:28 2016
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Tue, 15 Mar 2016 08:51:28 -0500
Subject: [PATCH] Remove the inclusion of pci-bridge.h and pci-dma-compat.h
In-Reply-To: <d3ed7b3e4f746831a5d0469da5361b4cd176f5c6.1457978659.git.jpinto@synopsys.com>
References: <d3ed7b3e4f746831a5d0469da5361b4cd176f5c6.1457978659.git.jpinto@synopsys.com>
Message-ID: <20160315135127.GC19974@localhost>

On Tue, Mar 15, 2016 at 11:06:02AM +0000, Joao Pinto wrote:
> While building linux-next the test robot detected that the pci.h was including
> two removed header files (pci-dma-compat.h and pci-bridge.h) causing the
> process to fail:
> http://lists.infradead.org/pipermail/linux-snps-arc/2016-March/000711.html
> 
> This patch has the goal to fix the build problem.
> 
> Signed-off-by: Joao Pinto <jpinto at synopsys.com>

Thanks, Joao, I folded this fix into the original commit.  I should have
caught this myself, since I'm the one who removed pci-bridge.h.

> ---
>  arch/arc/include/asm/pci.h | 3 ---
>  1 file changed, 3 deletions(-)
> 
> diff --git a/arch/arc/include/asm/pci.h b/arch/arc/include/asm/pci.h
> index 2f2011c..ba56c23 100644
> --- a/arch/arc/include/asm/pci.h
> +++ b/arch/arc/include/asm/pci.h
> @@ -10,9 +10,6 @@
>  #define _ASM_ARC_PCI_H
>  
>  #ifdef __KERNEL__
> -#include <asm-generic/pci-dma-compat.h>
> -#include <asm-generic/pci-bridge.h>
> -
>  #include <linux/ioport.h>
>  
>  #define PCIBIOS_MIN_IO 0x100
> -- 
> 1.8.1.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From Joao.Pinto at synopsys.com  Tue Mar 15 07:24:01 2016
From: Joao.Pinto at synopsys.com (Joao Pinto)
Date: Tue, 15 Mar 2016 14:24:01 +0000
Subject: [PATCH] Remove the inclusion of pci-bridge.h and pci-dma-compat.h
In-Reply-To: <20160315135127.GC19974@localhost>
References: <d3ed7b3e4f746831a5d0469da5361b4cd176f5c6.1457978659.git.jpinto@synopsys.com>
 <20160315135127.GC19974@localhost>
Message-ID: <56E81B01.3010400@synopsys.com>


No problem! Thanks!

On 3/15/2016 1:51 PM, Bjorn Helgaas wrote:
> On Tue, Mar 15, 2016 at 11:06:02AM +0000, Joao Pinto wrote:
>> While building linux-next the test robot detected that the pci.h was including
>> two removed header files (pci-dma-compat.h and pci-bridge.h) causing the
>> process to fail:
>> http://lists.infradead.org/pipermail/linux-snps-arc/2016-March/000711.html
>>
>> This patch has the goal to fix the build problem.
>>
>> Signed-off-by: Joao Pinto <jpinto at synopsys.com>
> 
> Thanks, Joao, I folded this fix into the original commit.  I should have
> caught this myself, since I'm the one who removed pci-bridge.h.
> 
>> ---
>>  arch/arc/include/asm/pci.h | 3 ---
>>  1 file changed, 3 deletions(-)
>>
>> diff --git a/arch/arc/include/asm/pci.h b/arch/arc/include/asm/pci.h
>> index 2f2011c..ba56c23 100644
>> --- a/arch/arc/include/asm/pci.h
>> +++ b/arch/arc/include/asm/pci.h
>> @@ -10,9 +10,6 @@
>>  #define _ASM_ARC_PCI_H
>>  
>>  #ifdef __KERNEL__
>> -#include <asm-generic/pci-dma-compat.h>
>> -#include <asm-generic/pci-bridge.h>
>> -
>>  #include <linux/ioport.h>
>>  
>>  #define PCIBIOS_MIN_IO 0x100
>> -- 
>> 1.8.1.5
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html



From sergei.shtylyov at cogentembedded.com  Tue Mar 15 07:38:30 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Tue, 15 Mar 2016 17:38:30 +0300
Subject: [PATCH] ARC: axs10x - add Ethernet PHY description in .dts
In-Reply-To: <1458034150-10766-1-git-send-email-abrodkin@synopsys.com>
References: <1458034150-10766-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <56E81E66.6080706@cogentembedded.com>

Hello.

On 3/15/2016 12:29 PM, Alexey Brodkin wrote:

> Following commit broke DW GMAC functionality on AXS10x boards:
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763
>
> That's what happens on eth0 up:
> --------------------------->8------------------------
> libphy: PHY stmmac-0:ffffffff not found
> eth0: Could not attach to PHY
> stmmac_open: Cannot attach to PHY (error: -19)
> --------------------------->8------------------------
>
> Simplest solution is to add PHY description in board's .dts.
> And so we do here.
>
> Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
> Cc: Rob Herring <robh at kernel.org>
> Cc: Phil Reid <preid at electromag.com.au>
> Cc: David S. Miller <davem at davemloft.net>
> Cc: linux-kernel at vger.kernel.org
> Cc: netdev at vger.kernel.org
> Cc: stable at vger.kernel.org # 4.5.x
> ---
>   arch/arc/boot/dts/axs10x_mb.dtsi | 8 ++++++++
>   1 file changed, 8 insertions(+)
>
> diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
> index 44a578c..04b999e 100644
> --- a/arch/arc/boot/dts/axs10x_mb.dtsi
> +++ b/arch/arc/boot/dts/axs10x_mb.dtsi
> @@ -47,6 +47,14 @@
>   			clocks = <&apbclk>;
>   			clock-names = "stmmaceth";
>   			max-speed = <100>;
> +			mdio0 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				compatible = "snps,dwmac-mdio";
> +				phy0: ethernet-phy at 0 {

    The naming is inconsistent with the "reg" prop specified, should be @1.

MBR, Sergei



From Alexey.Brodkin at synopsys.com  Tue Mar 15 07:50:02 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Tue, 15 Mar 2016 14:50:02 +0000
Subject: [PATCH] ARC: axs10x - add Ethernet PHY description in .dts
In-Reply-To: <56E81E66.6080706@cogentembedded.com>
References: <1458034150-10766-1-git-send-email-abrodkin@synopsys.com>
 <56E81E66.6080706@cogentembedded.com>
Message-ID: <1458053402.4174.12.camel@synopsys.com>

Hi Sergei,

On Tue, 2016-03-15 at 17:38 +0300, Sergei Shtylyov wrote:
> Hello.
> 
> On 3/15/2016 12:29 PM, Alexey Brodkin wrote:
> 
> > 
> > Following commit broke DW GMAC functionality on AXS10x boards:
> > http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763
> > 
> > That's what happens on eth0 up:
> > --------------------------->8------------------------
> > libphy: PHY stmmac-0:ffffffff not found
> > eth0: Could not attach to PHY
> > stmmac_open: Cannot attach to PHY (error: -19)
> > --------------------------->8------------------------
> > 
> > Simplest solution is to add PHY description in board's .dts.
> > And so we do here.
> > 
> > Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
> > Cc: Rob Herring <robh at kernel.org>
> > Cc: Phil Reid <preid at electromag.com.au>
> > Cc: David S. Miller <davem at davemloft.net>
> > Cc: linux-kernel at vger.kernel.org
> > Cc: netdev at vger.kernel.org
> > Cc: stable at vger.kernel.org # 4.5.x
> > ---
> > ? arch/arc/boot/dts/axs10x_mb.dtsi | 8 ++++++++
> > ? 1 file changed, 8 insertions(+)
> > 
> > diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
> > index 44a578c..04b999e 100644
> > --- a/arch/arc/boot/dts/axs10x_mb.dtsi
> > +++ b/arch/arc/boot/dts/axs10x_mb.dtsi
> > @@ -47,6 +47,14 @@
> > ??			clocks = <&apbclk>;
> > ??			clock-names = "stmmaceth";
> > ??			max-speed = <100>;
> > +			mdio0 {
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				compatible = "snps,dwmac-mdio";
> > +				phy0: ethernet-phy at 0 {
> ????The naming is inconsistent with the "reg" prop specified, should be @1.

Makes sense.
Will re-send it with mentioned fix.

-Alexey

From Alexey.Brodkin at synopsys.com  Tue Mar 15 08:24:46 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Tue, 15 Mar 2016 15:24:46 +0000
Subject: [PATCH 1/4 v3] drm: Add support of ARC PGU display controller
In-Reply-To: <20160315081056.GS14170@phenom.ffwll.local>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
 <1457710959-9562-2-git-send-email-abrodkin@synopsys.com>
 <20160314070009.GN14170@phenom.ffwll.local>
 <1457954159.3306.24.camel@synopsys.com>
 <20160315081056.GS14170@phenom.ffwll.local>
Message-ID: <1458055486.4174.16.camel@synopsys.com>

Hi Daniel,

On Tue, 2016-03-15 at 09:10 +0100, Daniel Vetter wrote:
> On Mon, Mar 14, 2016 at 11:15:59AM +0000, Alexey Brodkin wrote:
> > 
> > On Mon, 2016-03-14 at 08:00 +0100, Daniel Vetter wrote:
> > > 
> > > On Fri, Mar 11, 2016 at 06:42:36PM +0300, Alexey Brodkin wrote:
> > > > 
> > > > +static int arcpgu_atomic_commit(struct drm_device *dev,
> > > > +				????struct drm_atomic_state *state, bool async)
> > > > +{
> > > > +	return drm_atomic_helper_commit(dev, state, false);
> > > Note that this isn't really async if you ever get around to implement
> > > fence support or vblank support. Just fyi.
> > Ok but for now should I leave it as it is?
> Yeah ok as-is, hence just fyi.

Thanks. Just wanted to make sure we're on the same page :)

> > 
> > > 
> > > > 
> > > > +static struct drm_driver arcpgu_drm_driver = {
> > > > +	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
> > > > +			???DRIVER_ATOMIC,
> > > > +	.preclose = arcpgu_preclose,
> > > > +	.lastclose = arcpgu_lastclose,
> > > > +	.name = "drm-arcpgu",
> > > > +	.desc = "ARC PGU Controller",
> > > > +	.date = "20160219",
> > > > +	.major = 1,
> > > > +	.minor = 0,
> > > > +	.patchlevel = 0,
> > > > +	.fops = &arcpgu_drm_ops,
> > > > +	.load = arcpgu_load,
> > > > +	.unload = arcpgu_unload,
> > > Load and unload hooks are deprecated (it's a classic midlayer mistake).
> > > Please use drm_dev_alloc/register pairs directly instead, and put your
> > > device setup code in-between. Similar for unloading. There's a bunch of
> > > example drivers converted already.
> > Ok I took "atmel-hlcdc" as example.
> > And that's interesting.
> > 
> > If I put my?arcpgu_load() in between?drm_dev_alloc() and
> > drm_dev_register() then I'm getting this on the driver probe:
> > ---------------------------------->8-------------------------------
> > [drm] Initialized drm 1.1.0 20060810
> > arcpgu e0017000.pgu: arc_pgu ID: 0xabbabaab
> > ------------[ cut here ]------------
> > WARNING: CPU: 0 PID: 1 at lib/kobject.c:244 kobject_add_internal+0x17c/0x498()
> > kobject_add_internal failed for card0-HDMI-A-1 (error: -2 parent: card0)
> > Modules linked in:
> > CPU: 0 PID: 1 Comm: swapper Not tainted 4.5.0-rc3-01062-ga447822-dirty #17
> > 
> > Stack Trace:
> > ? arc_unwind_core.constprop.1+0xa4/0x110
> > ? warn_slowpath_fmt+0x6e/0xfc
> > ? kobject_add_internal+0x17c/0x498
> > ? kobject_add+0x98/0xe4
> > ? device_add+0xc6/0x734
> > ? device_create_with_groups+0x12a/0x144
> > ? drm_sysfs_connector_add+0x54/0xe8
> > ? arcpgu_drm_hdmi_init+0xd4/0x17c
> > ? arcpgu_probe+0x138/0x24c
> > ? platform_drv_probe+0x2e/0x6c
> > ? really_probe+0x212/0x35c
> > ? __driver_attach+0x90/0x94
> > ? bus_for_each_dev+0x46/0x80
> > ? bus_add_driver+0x14e/0x1b4
> > ? driver_register+0x64/0x108
> > ? do_one_initcall+0x86/0x194
> > ? kernel_init_freeable+0xf0/0x188
> > ---[ end trace c67166ad43ddcce2 ]---
> > [drm:drm_sysfs_connector_add] adding "HDMI-A-1" to sysfs
> > [drm:drm_sysfs_connector_add] *ERROR* failed to register connector device: -2
> > arcpgu e0017000.pgu: failed to regiter DRM connector and helper funcs
> > arcpgu: probe of e0017000.pgu failed with error -2
> > ---------------------------------->8-------------------------------
> > 
> > But if I move arcpgu_load() after drm_dev_register() then everything
> > starts properly and I may see HDMI screen works perfectly fine.
> > 
> > Any thoughts?
> Oops, yeah missed that detail. If you look at atmel it has a loop to
> register all the drm connectors _after_ calling drm_dev_register().
> Totally forgot about that. Can you pls
> - Extract a new drm_connector_register_all() function
> ? (atmel_hlcdc_dc_connector_plug_all seems to be the best template),
> ? including kerneldoc.
> - Adjust kerneldoc of drm_dev_register() to mention
> ? drm_connector_register_all() and that ordering constraint.
> - Roll that helper out to all the drivers that currently hand-roll it (one
> ? patch per driver).
> 
> I know a bit of work but imo not too much, and by doing some small
> refactoring every time someone stumbles over a drm pitfall we keep the
> subsystem clean&easy to understand. You're up for this? Would be a prep
> series, I'll happily review it to get it merged fast. Just a few weeks ago
> I merged 20+ patches to make ->mode_fixup hooks optional and remove dummy
> ones all over the subsystem, in other words: You'll have my full attention
> ;-)

Sure, I'm ready to pay that price :)
Stay tuned and patches will follow.

> > 
> > > 
> > > > 
> > > > +	.dumb_create = drm_gem_cma_dumb_create,
> > > > +	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
> > > > +	.dumb_destroy = drm_gem_dumb_destroy,
> > > > +	.get_vblank_counter = drm_vblank_no_hw_counter,
> > > > +	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> > > > +	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> > > > +	.gem_free_object = drm_gem_cma_free_object,
> > > > +	.gem_vm_ops = &drm_gem_cma_vm_ops,
> > > > +	.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,
> > > > +};
> > > > +
> > > > +static int arcpgu_probe(struct platform_device *pdev)
> > > > +{
> > > > +	return drm_platform_init(&arcpgu_drm_driver, pdev);
> > > ... or read the kerneldoc of this function, which also explains what you
> > > should do ;-)
> > Could you please point me to the relevant document?
> > I wasn't able to find anything related from the first glance :(
> The kerneldoc comment for drm_platform_init says it's deprecated, please
> use drm_dev_alloc/register instead.

Yeah I saw this. I was a bit confused with word "kerneldoc" thinking about
.txt files in Documentation folder.

> > 
> > > 
> > > > 
> > > > +
> > > > +/*
> > > > + * This function is the only reason to have a copy of drm_fbdev_cma_init()
> > > > + * here in this driver.
> > > > + *
> > > > + * In its turn this mmap() is required to mark user-space page as non-cached
> > > > + * because it is just a mirror or real hardware frame-buffer.
> > > > + */
> > > > +static int arcpgu_mmap(struct fb_info *info, struct vm_area_struct *vma)
> > > > +{
> > > > +	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> > > > +	return vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
> > > > +}
> > > This looks very fishy, no other drm driver even bothers with providing an
> > > fb_mmap hook. What exactly do you need this for? Assuming you've mmapped
> > > your fbcon drm_framebuffer correctly for kernel access things should just
> > > work ...
> > Indeed for kernel there's non need to that hack. Kernel deals directly with HW
> > frame-buffer area (that address we get from gem->paddr). And so every byte written gets
> > picked up by PGU and is then rendered on the display.
> > 
> > But when user-space opens /dev/fb0 and mmaps() it deals with memory pages which
> > are by default (at least on ARC) marked as "cached". I.e. user-space application
> > (I use that nice demo app?https://github.com/qtproject/qt/blob/4.8/examples/qws/framebuffer/main.c)
> > deals with frame-buffer via data cache. And that has 2 problems:
> > ?[1] Since no explicit cache flush gets executed some data is left in data cache,
> > ? ? ?i.e. some parts of the picture never reaches real PGU.
> > ? ? ?See what happens on display -?http://imgur.com/iAbnnx3
> > ? ? ?Those missing lines are exactly those 32-byte missing cache lines.
> > ?[2] Even if we manage to flush data somehow massive amount of data that goes
> > ? ? ?through data cache (let's sat 1080p at 30Hz) will thrash it and as a result
> > ? ? ?there will be no benefit for other cache users to use cache.
> > 
> > So we fix it simply marking pages mapped to user-space apps as uncached
> > that effectively routes all FB data directly to memry instead of polluting cache.
> > 
> > Hopefully that explanation makes sense.
> Still strange that you're the only one who needs this. I think best case
> would be to provide some mmap helpers for fbdev which remap to dumb buffer
> helpers or something similar. That way other drivers don't need to.

Ok I took another look and now see what's missing.
All other arches implement their own?fb_pgprotect() in arch/X/include/asm/fb.h
which does exactly what I need. So entire arcpgu_fbdev.c will be dumped in v4 :)

-Alexey

From daniel at ffwll.ch  Tue Mar 15 08:59:40 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Tue, 15 Mar 2016 16:59:40 +0100
Subject: [PATCH 1/4 v3] drm: Add support of ARC PGU display controller
In-Reply-To: <1458055486.4174.16.camel@synopsys.com>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
 <1457710959-9562-2-git-send-email-abrodkin@synopsys.com>
 <20160314070009.GN14170@phenom.ffwll.local>
 <1457954159.3306.24.camel@synopsys.com>
 <20160315081056.GS14170@phenom.ffwll.local>
 <1458055486.4174.16.camel@synopsys.com>
Message-ID: <20160315155940.GL14170@phenom.ffwll.local>

On Tue, Mar 15, 2016 at 03:24:46PM +0000, Alexey Brodkin wrote:
> Hi Daniel,
> 
> On Tue, 2016-03-15 at 09:10 +0100, Daniel Vetter wrote:
> > On Mon, Mar 14, 2016 at 11:15:59AM +0000, Alexey Brodkin wrote:
> > > 
> > > On Mon, 2016-03-14 at 08:00 +0100, Daniel Vetter wrote:
> > > > 
> > > > On Fri, Mar 11, 2016 at 06:42:36PM +0300, Alexey Brodkin wrote:
> > > > > 
> > > > > +static int arcpgu_atomic_commit(struct drm_device *dev,
> > > > > +				????struct drm_atomic_state *state, bool async)
> > > > > +{
> > > > > +	return drm_atomic_helper_commit(dev, state, false);
> > > > Note that this isn't really async if you ever get around to implement
> > > > fence support or vblank support. Just fyi.
> > > Ok but for now should I leave it as it is?
> > Yeah ok as-is, hence just fyi.
> 
> Thanks. Just wanted to make sure we're on the same page :)
> 
> > > 
> > > > 
> > > > > 
> > > > > +static struct drm_driver arcpgu_drm_driver = {
> > > > > +	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
> > > > > +			???DRIVER_ATOMIC,
> > > > > +	.preclose = arcpgu_preclose,
> > > > > +	.lastclose = arcpgu_lastclose,
> > > > > +	.name = "drm-arcpgu",
> > > > > +	.desc = "ARC PGU Controller",
> > > > > +	.date = "20160219",
> > > > > +	.major = 1,
> > > > > +	.minor = 0,
> > > > > +	.patchlevel = 0,
> > > > > +	.fops = &arcpgu_drm_ops,
> > > > > +	.load = arcpgu_load,
> > > > > +	.unload = arcpgu_unload,
> > > > Load and unload hooks are deprecated (it's a classic midlayer mistake).
> > > > Please use drm_dev_alloc/register pairs directly instead, and put your
> > > > device setup code in-between. Similar for unloading. There's a bunch of
> > > > example drivers converted already.
> > > Ok I took "atmel-hlcdc" as example.
> > > And that's interesting.
> > > 
> > > If I put my?arcpgu_load() in between?drm_dev_alloc() and
> > > drm_dev_register() then I'm getting this on the driver probe:
> > > ---------------------------------->8-------------------------------
> > > [drm] Initialized drm 1.1.0 20060810
> > > arcpgu e0017000.pgu: arc_pgu ID: 0xabbabaab
> > > ------------[ cut here ]------------
> > > WARNING: CPU: 0 PID: 1 at lib/kobject.c:244 kobject_add_internal+0x17c/0x498()
> > > kobject_add_internal failed for card0-HDMI-A-1 (error: -2 parent: card0)
> > > Modules linked in:
> > > CPU: 0 PID: 1 Comm: swapper Not tainted 4.5.0-rc3-01062-ga447822-dirty #17
> > > 
> > > Stack Trace:
> > > ? arc_unwind_core.constprop.1+0xa4/0x110
> > > ? warn_slowpath_fmt+0x6e/0xfc
> > > ? kobject_add_internal+0x17c/0x498
> > > ? kobject_add+0x98/0xe4
> > > ? device_add+0xc6/0x734
> > > ? device_create_with_groups+0x12a/0x144
> > > ? drm_sysfs_connector_add+0x54/0xe8
> > > ? arcpgu_drm_hdmi_init+0xd4/0x17c
> > > ? arcpgu_probe+0x138/0x24c
> > > ? platform_drv_probe+0x2e/0x6c
> > > ? really_probe+0x212/0x35c
> > > ? __driver_attach+0x90/0x94
> > > ? bus_for_each_dev+0x46/0x80
> > > ? bus_add_driver+0x14e/0x1b4
> > > ? driver_register+0x64/0x108
> > > ? do_one_initcall+0x86/0x194
> > > ? kernel_init_freeable+0xf0/0x188
> > > ---[ end trace c67166ad43ddcce2 ]---
> > > [drm:drm_sysfs_connector_add] adding "HDMI-A-1" to sysfs
> > > [drm:drm_sysfs_connector_add] *ERROR* failed to register connector device: -2
> > > arcpgu e0017000.pgu: failed to regiter DRM connector and helper funcs
> > > arcpgu: probe of e0017000.pgu failed with error -2
> > > ---------------------------------->8-------------------------------
> > > 
> > > But if I move arcpgu_load() after drm_dev_register() then everything
> > > starts properly and I may see HDMI screen works perfectly fine.
> > > 
> > > Any thoughts?
> > Oops, yeah missed that detail. If you look at atmel it has a loop to
> > register all the drm connectors _after_ calling drm_dev_register().
> > Totally forgot about that. Can you pls
> > - Extract a new drm_connector_register_all() function
> > ? (atmel_hlcdc_dc_connector_plug_all seems to be the best template),
> > ? including kerneldoc.
> > - Adjust kerneldoc of drm_dev_register() to mention
> > ? drm_connector_register_all() and that ordering constraint.
> > - Roll that helper out to all the drivers that currently hand-roll it (one
> > ? patch per driver).
> > 
> > I know a bit of work but imo not too much, and by doing some small
> > refactoring every time someone stumbles over a drm pitfall we keep the
> > subsystem clean&easy to understand. You're up for this? Would be a prep
> > series, I'll happily review it to get it merged fast. Just a few weeks ago
> > I merged 20+ patches to make ->mode_fixup hooks optional and remove dummy
> > ones all over the subsystem, in other words: You'll have my full attention
> > ;-)
> 
> Sure, I'm ready to pay that price :)
> Stay tuned and patches will follow.

Awesome, looking forward to your patches.

> > > 
> > > > 
> > > > > 
> > > > > +	.dumb_create = drm_gem_cma_dumb_create,
> > > > > +	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
> > > > > +	.dumb_destroy = drm_gem_dumb_destroy,
> > > > > +	.get_vblank_counter = drm_vblank_no_hw_counter,
> > > > > +	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> > > > > +	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> > > > > +	.gem_free_object = drm_gem_cma_free_object,
> > > > > +	.gem_vm_ops = &drm_gem_cma_vm_ops,
> > > > > +	.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,
> > > > > +};
> > > > > +
> > > > > +static int arcpgu_probe(struct platform_device *pdev)
> > > > > +{
> > > > > +	return drm_platform_init(&arcpgu_drm_driver, pdev);
> > > > ... or read the kerneldoc of this function, which also explains what you
> > > > should do ;-)
> > > Could you please point me to the relevant document?
> > > I wasn't able to find anything related from the first glance :(
> > The kerneldoc comment for drm_platform_init says it's deprecated, please
> > use drm_dev_alloc/register instead.
> 
> Yeah I saw this. I was a bit confused with word "kerneldoc" thinking about
> .txt files in Documentation folder.

kerneldoc is the kernel-specific tool to parse the specially formatted
in-source comments starting with /**. Run

$ make htmldocs

and you should have the generated gpu docs in Documentation/DocBook/gpu/
which pulls all those together into something somewhat coherent.

> 
> > > 
> > > > 
> > > > > 
> > > > > +
> > > > > +/*
> > > > > + * This function is the only reason to have a copy of drm_fbdev_cma_init()
> > > > > + * here in this driver.
> > > > > + *
> > > > > + * In its turn this mmap() is required to mark user-space page as non-cached
> > > > > + * because it is just a mirror or real hardware frame-buffer.
> > > > > + */
> > > > > +static int arcpgu_mmap(struct fb_info *info, struct vm_area_struct *vma)
> > > > > +{
> > > > > +	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> > > > > +	return vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
> > > > > +}
> > > > This looks very fishy, no other drm driver even bothers with providing an
> > > > fb_mmap hook. What exactly do you need this for? Assuming you've mmapped
> > > > your fbcon drm_framebuffer correctly for kernel access things should just
> > > > work ...
> > > Indeed for kernel there's non need to that hack. Kernel deals directly with HW
> > > frame-buffer area (that address we get from gem->paddr). And so every byte written gets
> > > picked up by PGU and is then rendered on the display.
> > > 
> > > But when user-space opens /dev/fb0 and mmaps() it deals with memory pages which
> > > are by default (at least on ARC) marked as "cached". I.e. user-space application
> > > (I use that nice demo app?https://github.com/qtproject/qt/blob/4.8/examples/qws/framebuffer/main.c)
> > > deals with frame-buffer via data cache. And that has 2 problems:
> > > ?[1] Since no explicit cache flush gets executed some data is left in data cache,
> > > ? ? ?i.e. some parts of the picture never reaches real PGU.
> > > ? ? ?See what happens on display -?http://imgur.com/iAbnnx3
> > > ? ? ?Those missing lines are exactly those 32-byte missing cache lines.
> > > ?[2] Even if we manage to flush data somehow massive amount of data that goes
> > > ? ? ?through data cache (let's sat 1080p at 30Hz) will thrash it and as a result
> > > ? ? ?there will be no benefit for other cache users to use cache.
> > > 
> > > So we fix it simply marking pages mapped to user-space apps as uncached
> > > that effectively routes all FB data directly to memry instead of polluting cache.
> > > 
> > > Hopefully that explanation makes sense.
> > Still strange that you're the only one who needs this. I think best case
> > would be to provide some mmap helpers for fbdev which remap to dumb buffer
> > helpers or something similar. That way other drivers don't need to.
> 
> Ok I took another look and now see what's missing.
> All other arches implement their own?fb_pgprotect() in arch/X/include/asm/fb.h
> which does exactly what I need. So entire arcpgu_fbdev.c will be dumped in v4 :)

Ah, excellent.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From noreply at ellerman.id.au  Wed Mar 16 07:01:37 2016
From: noreply at ellerman.id.au (noreply at ellerman.id.au)
Date: Wed, 16 Mar 2016 14:01:37 -0000
Subject: kisskb: OK linux-next/axs101_defconfig/arcompact Thu Mar 17, 01:00
Message-ID: <20160316140137.1.915@4cca3ee1040e>

OK linux-next/axs101_defconfig/arcompact Thu Mar 17, 01:00

http://kisskb.ellerman.id.au/kisskb/buildresult/12636410/

Commit:   Add linux-next specific files for 20160316
          8559bac87dcf580b62d5cc751f5ab62d01832744
Compiler: arc-buildroot-linux-uclibc-gcc (Buildroot 2015.08.1) 4.8.4

Possible errors
---------------

     harderr = icmp_err_convert[code].fatal;

Possible warnings (145)
----------------------

drivers/pci/pcie/Kconfig:62:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:68:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:75:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:62:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:68:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:75:warning: choice value used outside its choice group
<stdin>:1310:2: warning: #warning syscall preadv2 not implemented [-Wcpp]
<stdin>:1313:2: warning: #warning syscall pwritev2 not implemented [-Wcpp]
Warning (unit_address_vs_reg): Node /cpu_card has a reg or ranges property, but no unit name
Warning (unit_address_vs_reg): Node /cpu_card/arc700-intc at cpu has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
Warning (unit_address_vs_reg): Node /axs10x_mb has a reg or ranges property, but no unit name
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
kernel/sched/core.c:3080:1: warning: control reaches end of non-void function [-Wreturn-type]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
kernel/sysctl.c:1949:12: warning: 'p' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/sysctl.c:1949:12: warning: 'p' may be used uninitialized in this function [-Wmaybe-uninitialized]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
ipc/shm.c:1252:2: warning: 'ret' may be used uninitialized in this function [-Wmaybe-uninitialized]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
include/linux/kernel.h:735:17: warning: comparison of distinct pointer types lacks a cast [enabled by default]
include/linux/rbtree.h:83:28: warning: 'rb_parent' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/linux/rbtree.h:86:11: warning: 'rb_link' may be used uninitialized in this function [-Wmaybe-uninitialized]
mm/mmap.c:558:17: warning: 'prev' may be used uninitialized in this function [-Wmaybe-uninitialized]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
fs/namei.c:1713:2: warning: 'seq' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:787:21: warning: 'now' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:95:8: warning: 'now' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:665:17: warning: 'val' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/namei.c:1713:2: warning: 'seq' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:1238:13: warning: 'now' may be used uninitialized in this function [-Wmaybe-uninitialized]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
arch/arc/include/asm/elf.h:58:29: warning: integer overflow in expression [-Woverflow]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
arch/arc/include/asm/tlbflush.h:29:0: warning: "flush_pmd_tlb_range" redefined [enabled by default]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
include/asm-generic/bug.h:74:48: warning: 'fn' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/core/datagram.c:99:5: warning: 'last' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:315:21: warning: 'handle' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/core/datagram.c:99:5: warning: 'last' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:556:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/linux/buffer_head.h:363:2: warning: 'blocknr' may be used uninitialized in this function [-Wmaybe-uninitialized]
block/cfq-iosched.c:3793:1: warning: control reaches end of non-void function [-Wreturn-type]
include/linux/buffer_head.h:370:2: warning: 'blocknr' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/core/ethtool.c:295:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
net/core/neighbour.c:3180:10: warning: 'p_name' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/packet/af_packet.c:2159:33: warning: 'hdrlen' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/unix/af_unix.c:1036:20: warning: 'hash' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/unix/af_unix.c:1251:8: warning: 'hash' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/unix/af_unix.c:1130:9: warning: 'hash' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/unix/af_unix.c:1721:9: warning: 'hash' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_extents.h:224:8: warning: '*((void *)&zero_ex+8)' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_extents.h:225:12: warning: '*((void *)&zero_ex+6)' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/extents.c:3119:2: warning: 'zero_ex.ee_block' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/unix/af_unix.c:1721:9: warning: 'hash' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
net/xfrm/xfrm_policy.c:1599:7: warning: 'dst_ops' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/extents.c:2312:14: warning: 'lblock' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/extents.c:2311:14: warning: 'len' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/xfrm/xfrm_policy.c:1599:7: warning: 'dst_ops' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
include/linux/sunrpc/svc_xprt.h:175:1: warning: control reaches end of non-void function [-Wreturn-type]
net/sunrpc/svcsock.c:779:6: warning: 'optname' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/svcsock.c:779:6: warning: 'level' may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/usb/core/hub.c:2767:16: warning: 'portchange' may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/usb/core/hub.c:2740:20: warning: 'portstatus' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/svcauth_unix.c:282:12: warning: 'sin6' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1153:8: warning: 'subbuf.tail[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1149:17: warning: 'subbuf.page_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1149:17: warning: 'subbuf.pages' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1144:8: warning: 'subbuf.head[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1153:8: warning: 'subbuf.tail[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1149:17: warning: 'subbuf.page_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1149:17: warning: 'subbuf.pages' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1144:8: warning: 'subbuf.head[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1122:8: warning: 'subbuf.tail[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.page_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.pages' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1113:8: warning: 'subbuf.head[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1122:8: warning: 'subbuf.tail[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.page_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.pages' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1113:8: warning: 'subbuf.head[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1122:8: warning: 'subbuf.tail[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.page_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.pages' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1207:12: warning: 'subbuf.head[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1122:8: warning: 'subbuf.tail[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.page_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.pages' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1113:8: warning: 'subbuf.head[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'saddr.<U2980>.key[3]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'saddr.<U2980>.key[2]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:26: warning: 'saddr.<U2980>.a4.vif' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'saddr.<U2980>.a4.addr' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'daddr.in6_u.u6_addr32[3]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'daddr.in6_u.u6_addr32[2]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'daddr.<U2980>.a4.addr' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/ipv4/tcp_metrics.c:1080:7: warning: 'hash' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'saddr.<U2980>.key[3]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'saddr.<U2980>.key[2]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'daddr.in6_u.u6_addr32[3]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'daddr.in6_u.u6_addr32[2]' may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/usb/storage/transport.c:499:15: warning: 'partial' may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/usb/storage/transport.c:473:40: warning: 'partial' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/ipv4/tcp_input.c:4273:49: warning: array subscript is above array bounds [-Warray-bounds]
net/ipv4/ping.c:561:37: warning: 'code' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/ipv4/ping.c:534:3: warning: 'type' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/ipv4/ping.c:515:48: warning: 'icmph' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/ipv4/ping.c:692:21: warning: 'type' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/ipv4/ping.c:478:63: warning: 'code' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/ipv4/fib_trie.c:909:11: warning: 'local_tp' may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/tty/serial/8250/8250_core.c:250:10: warning: 'i' may be used uninitialized in this function [-Wmaybe-uninitialized]



From Alexey.Brodkin at synopsys.com  Thu Mar 17 02:41:52 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 17 Mar 2016 12:41:52 +0300
Subject: [PATCH v2] ARC: axs10x - add Ethernet PHY description in .dts
Message-ID: <1458207712-29435-1-git-send-email-abrodkin@synopsys.com>

Following commit broke DW GMAC functionality on AXS10x boards:
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763

That's what happens on eth0 up:
--------------------------->8------------------------
libphy: PHY stmmac-0:ffffffff not found
eth0: Could not attach to PHY
stmmac_open: Cannot attach to PHY (error: -19)
--------------------------->8------------------------

Simplest solution is to add PHY description in board's .dts.
And so we do here.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Rob Herring <robh at kernel.org>
Cc: Phil Reid <preid at electromag.com.au>
Cc: David S. Miller <davem at davemloft.net>
Cc: linux-kernel at vger.kernel.org
Cc: netdev at vger.kernel.org
Cc: stable at vger.kernel.org # 4.5.x
Cc: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>
---

Changes v1 -> v2:
 * PHY node name changed to match real PHY number being used (Sergei)

 arch/arc/boot/dts/axs10x_mb.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
index 44a578c..ab5d570 100644
--- a/arch/arc/boot/dts/axs10x_mb.dtsi
+++ b/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -47,6 +47,14 @@
 			clocks = <&apbclk>;
 			clock-names = "stmmaceth";
 			max-speed = <100>;
+			mdio0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "snps,dwmac-mdio";
+				phy1: ethernet-phy at 1 {
+					reg = <1>;
+				};
+			};
 		};
 
 		ehci at 0x40000 {
-- 
2.5.0



From sergei.shtylyov at cogentembedded.com  Thu Mar 17 03:58:20 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 17 Mar 2016 13:58:20 +0300
Subject: [PATCH v2] ARC: axs10x - add Ethernet PHY description in .dts
In-Reply-To: <1458207712-29435-1-git-send-email-abrodkin@synopsys.com>
References: <1458207712-29435-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <56EA8DCC.8070308@cogentembedded.com>

On 3/17/2016 12:41 PM, Alexey Brodkin wrote:

> Following commit broke DW GMAC functionality on AXS10x boards:
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763

    Note that scripts/checkpatch.pl now enforces certain format for citing 
commits: commit <12-digit SHA1> ("<commit summary>").

[...]

MBR, Sergei



From Vineet.Gupta1 at synopsys.com  Thu Mar 17 04:13:50 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Thu, 17 Mar 2016 11:13:50 +0000
Subject: [PATCH v2] ARC: axs10x - add Ethernet PHY description in .dts
References: <1458207712-29435-1-git-send-email-abrodkin@synopsys.com>
 <56EA8DCC.8070308@cogentembedded.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E903A3@us01wembx1.internal.synopsys.com>

On Thursday 17 March 2016 04:28 PM, Sergei Shtylyov wrote:
> On 3/17/2016 12:41 PM, Alexey Brodkin wrote:
>
>> > Following commit broke DW GMAC functionality on AXS10x boards:
>> > http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763
>     Note that scripts/checkpatch.pl now enforces certain format for citing 
> commits: commit <12-digit SHA1> ("<commit summary>").
>
> [...]
>
> MBR, Sergei

Indeed - I've fixed this up and added to arc for-curr !

-Vineet


From Alexey.Brodkin at synopsys.com  Thu Mar 17 04:37:58 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 17 Mar 2016 11:37:58 +0000
Subject: [PATCH v2] ARC: axs10x - add Ethernet PHY description in .dts
In-Reply-To: <56EA8DCC.8070308@cogentembedded.com>
References: <1458207712-29435-1-git-send-email-abrodkin@synopsys.com>
 <56EA8DCC.8070308@cogentembedded.com>
Message-ID: <1458214678.14496.15.camel@synopsys.com>

Hi Sergei,

On Thu, 2016-03-17 at 13:58 +0300, Sergei Shtylyov wrote:
> On 3/17/2016 12:41 PM, Alexey Brodkin wrote:
> 
> > 
> > Following commit broke DW GMAC functionality on AXS10x boards:
> > http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763
> ????Note that scripts/checkpatch.pl now enforces certain format for citing?
> commits: commit <12-digit SHA1> ("<commit summary>").

Frankly I haven't run that patch through checkpatch due to patch
simplicity.

But I'll try to not do any assumptions from now on and will try to
use checkpatch for each and every thing I send :)

Thanks for spotting all his!

-Alexey

From Vineet.Gupta1 at synopsys.com  Thu Mar 17 04:41:30 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Thu, 17 Mar 2016 11:41:30 +0000
Subject: [PATCH v2] ARC: axs10x - add Ethernet PHY description in .dts
References: <1458207712-29435-1-git-send-email-abrodkin@synopsys.com>
 <56EA8DCC.8070308@cogentembedded.com>
 <1458214678.14496.15.camel@synopsys.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E903EF@us01wembx1.internal.synopsys.com>

On Thursday 17 March 2016 05:08 PM, Alexey Brodkin wrote:
> Hi Sergei,
>
> On Thu, 2016-03-17 at 13:58 +0300, Sergei Shtylyov wrote:
>> On 3/17/2016 12:41 PM, Alexey Brodkin wrote:
>>
>>> Following commit broke DW GMAC functionality on AXS10x boards:
>>> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763
>>     Note that scripts/checkpatch.pl now enforces certain format for citing 
>> commits: commit <12-digit SHA1> ("<commit summary>").
> Frankly I haven't run that patch through checkpatch due to patch
> simplicity.
>
> But I'll try to not do any assumptions from now on and will try to
> use checkpatch for each and every thing I send :)
>
> Thanks for spotting all his!
>
> -Alexey

Sergei, do you mind providing a Ack/Reviewed-by on the patch below

-------->
>From 67216d835d8c2a5748ba1631c8bfc19da4fb87fa Mon Sep 17 00:00:00 2001
From: Alexey Brodkin <Alexey.Brodkin at synopsys.com>
Date: Thu, 17 Mar 2016 12:41:52 +0300
Subject: [PATCH] ARC: axs10x - add Ethernet PHY description in .dts

Commit e34d65696d2e ("stmmac: create of compatible mdio bus for stmmac
driver") broke DW GMAC functionality on ARC AXS10x boards:

That's what happens on eth0 up:
  --------------------------->8------------------------
| libphy: PHY stmmac-0:ffffffff not found
| eth0: Could not attach to PHY
| stmmac_open: Cannot attach to PHY (error: -19)
  --------------------------->8------------------------

Simplest solution is to add PHY description in board's .dts.
And so we do here.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Rob Herring <robh at kernel.org>
Cc: Phil Reid <preid at electromag.com.au>
Cc: David S. Miller <davem at davemloft.net>
Cc: linux-kernel at vger.kernel.org
Cc: netdev at vger.kernel.org
Cc: stable at vger.kernel.org # 4.5
Cc: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/boot/dts/axs10x_mb.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
index 44a578c10732..ab5d5701e11d 100644
--- a/arch/arc/boot/dts/axs10x_mb.dtsi
+++ b/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -47,6 +47,14 @@
             clocks = <&apbclk>;
             clock-names = "stmmaceth";
             max-speed = <100>;
+            mdio0 {
+                #address-cells = <1>;
+                #size-cells = <0>;
+                compatible = "snps,dwmac-mdio";
+                phy1: ethernet-phy at 1 {
+                    reg = <1>;
+                };
+            };
         };
 
         ehci at 0x40000 {
-- 
2.5.0



From sergei.shtylyov at cogentembedded.com  Thu Mar 17 04:59:09 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 17 Mar 2016 14:59:09 +0300
Subject: [PATCH v2] ARC: axs10x - add Ethernet PHY description in .dts
In-Reply-To: <C2D7FE5348E1B147BCA15975FBA23075F4E903EF@us01wembx1.internal.synopsys.com>
References: <1458207712-29435-1-git-send-email-abrodkin@synopsys.com>
 <56EA8DCC.8070308@cogentembedded.com>
 <1458214678.14496.15.camel@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E903EF@us01wembx1.internal.synopsys.com>
Message-ID: <56EA9C0D.1090000@cogentembedded.com>

Hello.

On 3/17/2016 2:41 PM, Vineet Gupta wrote:

>>>> Following commit broke DW GMAC functionality on AXS10x boards:
>>>> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763
>>>      Note that scripts/checkpatch.pl now enforces certain format for citing
>>> commits: commit <12-digit SHA1> ("<commit summary>").

>> Frankly I haven't run that patch through checkpatch due to patch
>> simplicity.
>>
>> But I'll try to not do any assumptions from now on and will try to
>> use checkpatch for each and every thing I send :)
>>
>> Thanks for spotting all his!
>>

    Sorry for not reporting everything on the 1st review.

>> -Alexey
>
> Sergei, do you mind providing a Ack/Reviewed-by on the patch below
 >

Reviewed-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

    The patch here is white space damaged however: tabs were converted to 
spaces. :-(

MBR, Sergei



From Alexey.Brodkin at synopsys.com  Thu Mar 17 05:10:37 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 17 Mar 2016 12:10:37 +0000
Subject: [PATCH v2] ARC: axs10x - add Ethernet PHY description in .dts
In-Reply-To: <56EA9C0D.1090000@cogentembedded.com>
References: <1458207712-29435-1-git-send-email-abrodkin@synopsys.com>
 <56EA8DCC.8070308@cogentembedded.com>
 <1458214678.14496.15.camel@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E903EF@us01wembx1.internal.synopsys.com>
 <56EA9C0D.1090000@cogentembedded.com>
Message-ID: <1458216636.14496.19.camel@synopsys.com>

Hi Sergei,

On Thu, 2016-03-17 at 14:59 +0300, Sergei Shtylyov wrote:
> Hello.
> 
> On 3/17/2016 2:41 PM, Vineet Gupta wrote:
> 
> > 
> > > 
> > > > 
> > > > > 
> > > > > Following commit broke DW GMAC functionality on AXS10x boards:
> > > > > http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461e
> > > > > d763
> > > > ?????Note that scripts/checkpatch.pl now enforces certain format for citing
> > > > commits: commit <12-digit SHA1> ("<commit summary>").
> > 
> > > 
> > > Frankly I haven't run that patch through checkpatch due to patch
> > > simplicity.
> > > 
> > > But I'll try to not do any assumptions from now on and will try to
> > > use checkpatch for each and every thing I send :)
> > > 
> > > Thanks for spotting all his!
> > > 
> ????Sorry for not reporting everything on the 1st review.
> 
> > 
> > > 
> > > -Alexey
> > Sergei, do you mind providing a Ack/Reviewed-by on the patch below
> ?>
> 
> Reviewed-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>
> 
> ????The patch here is white space damaged however: tabs were converted to?
> spaces. :-(

Well, I'm not really sure why that substitution happened because my local patch
is indeed with tabs.

That's an output of checkpatch:
------------------------>8------------------------
./scripts/checkpatch.pl 0001-ARC-axs10x-add-Ethernet-PHY-description-in-.dts.patch?
[1]+??Done????????????????????gedit 0001-ARC-axs10x-add-Ethernet-PHY-description-in-.dts.patch
WARNING: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#7:?
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763

ERROR: Please use git commit description style 'commit <12+ chars of sha1> ("<title line>")' - ie: 'commit e34d65696d2e
("stmmac: create of compatible mdio bus for stmmac driver")'
#7:?
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763

total: 1 errors, 1 warnings, 14 lines checked

0001-ARC-axs10x-add-Ethernet-PHY-description-in-.dts.patch has style problems, please review.
------------------------>8------------------------

If there were spaces we would see tons of:
------------------------>8------------------------
ERROR: code indent should use tabs where possible
#43: FILE: arch/arc/boot/dts/axs10x_mb.dtsi:50:
+????????????????????????mdio0 {$
------------------------>8------------------------
which I didn't see.

-Alexey

From Vineet.Gupta1 at synopsys.com  Thu Mar 17 05:16:15 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Thu, 17 Mar 2016 12:16:15 +0000
Subject: [PATCH v2] ARC: axs10x - add Ethernet PHY description in .dts
References: <1458207712-29435-1-git-send-email-abrodkin@synopsys.com>
 <56EA8DCC.8070308@cogentembedded.com>
 <1458214678.14496.15.camel@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E903EF@us01wembx1.internal.synopsys.com>
 <56EA9C0D.1090000@cogentembedded.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E90440@us01wembx1.internal.synopsys.com>

On Thursday 17 March 2016 05:29 PM, Sergei Shtylyov wrote:
> Hello.
>
> On 3/17/2016 2:41 PM, Vineet Gupta wrote:
>
>>>>> >>>> Following commit broke DW GMAC functionality on AXS10x boards:
>>>>> >>>> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763
>>>> >>>      Note that scripts/checkpatch.pl now enforces certain format for citing
>>>> >>> commits: commit <12-digit SHA1> ("<commit summary>").
>>> >> Frankly I haven't run that patch through checkpatch due to patch
>>> >> simplicity.
>>> >>
>>> >> But I'll try to not do any assumptions from now on and will try to
>>> >> use checkpatch for each and every thing I send :)
>>> >>
>>> >> Thanks for spotting all his!
>>> >>
>     Sorry for not reporting everything on the 1st review.
>
>>> >> -Alexey
>> >
>> > Sergei, do you mind providing a Ack/Reviewed-by on the patch below
>  >
>
> Reviewed-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

Thx.

>     The patch here is white space damaged however: tabs were converted to 
> spaces. :-(
>
> MBR, Sergei


That was just because of copy-paste into mailer before switching to plain-text.
Don't ask - corporate email !
I added it just to give u an idea of what fixup i did.

Tx,
-Vineet


From robh at kernel.org  Thu Mar 17 09:24:21 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 17 Mar 2016 11:24:21 -0500
Subject: [PATCH v2 2/9] ARC: [dts] Introduce Timer bindings
In-Reply-To: <1457439972-20285-3-git-send-email-vgupta@synopsys.com>
References: <1457439972-20285-1-git-send-email-vgupta@synopsys.com>
 <1457439972-20285-3-git-send-email-vgupta@synopsys.com>
Message-ID: <20160317162421.GA21947@rob-hp-laptop>

On Tue, Mar 08, 2016 at 05:56:05PM +0530, Vineet Gupta wrote:
> ARC Timers have historically been probed directly.
> As precursor to start probing Timers thru DT introduce these bindings
> Note that to keep series bisectable, these bindings are not yet used in
> code.
> 
> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
> Cc: Rob Herring <robh at kernel.org>
> Cc: devicetree at vger.kernel.org
> Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
> ---
> Changes v1 -> v2
>  - snps,arc-timer[0-1] folded into single snps-arc-timer	[Rob]
>  - Node name in DT example fixed:				[Rob]
>      "timer1: timer_clksrc {" -> timer at 1 {
>  - Introduced 64bit RTC in skeleton_hs.dtsi			[Vineet]
> 
> v1:
>  - http://lists.infradead.org/pipermail/linux-snps-arc/2016-February/000447.html
> 
> Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
> ---
>  .../devicetree/bindings/timer/snps,arc-timer.txt   | 26 ++++++++++++++++++++++
>  .../devicetree/bindings/timer/snps,archs-gfrc.txt  | 14 ++++++++++++
>  .../devicetree/bindings/timer/snps,archs-rtc.txt   | 14 ++++++++++++
>  arch/arc/boot/dts/abilis_tb10x.dtsi                | 14 ++++++++++++
>  arch/arc/boot/dts/skeleton.dtsi                    | 14 ++++++++++++
>  arch/arc/boot/dts/skeleton_hs.dtsi                 | 20 +++++++++++++++++
>  arch/arc/boot/dts/skeleton_hs_idu.dtsi             | 14 ++++++++++++
>  7 files changed, 116 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/timer/snps,arc-timer.txt
>  create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
>  create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-rtc.txt
> 
> diff --git a/Documentation/devicetree/bindings/timer/snps,arc-timer.txt b/Documentation/devicetree/bindings/timer/snps,arc-timer.txt
> new file mode 100644
> index 000000000000..9e02be24e805
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/snps,arc-timer.txt
> @@ -0,0 +1,26 @@
> +Synopsys ARC Local Timer with Interrupt Capabilities
> +- Found on all ARC CPUs (ARC700/ARCHS)
> +- Can be optionally programmed to interrupt on Limit
> +- Two idential copies TIMER0 and TIMER1 exist in ARC cores and historically
> +  TIMER0 used as clockevent provider (true for all ARC cores)
> +  TIMER1 used for clocksource (mandatory for ARC700, optional for ARC HS)
> +
> +Required properties:
> +
> +- compatible : should be "snps,arc-timer"
> +- interrupts : single Interrupt going into parent intc
> +	       (16 for ARCHS cores, 3 for ARC700 cores)
> +- clocks     : phandle to the source clock
> +
> +Optional properties:
> +
> +- interrupt-parent : phandle to parent intc
> +
> +Example:
> +
> +	timer at 0 {

Use of unit addresses without reg property is going to start generating 
warnings. I would just use "timer0" in this case.

> +		compatible = "snps,arc-timer0";

s/timer0/timer/

> +		interrupts = <3>;
> +		interrupt-parent = <&core_intc>;
> +		clocks = <&core_clk>;
> +	};
> diff --git a/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt b/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
> new file mode 100644
> index 000000000000..aaab100f54e7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
> @@ -0,0 +1,14 @@
> +Synopsys ARC Free Running 64-bit Global Timer for ARC HS CPUs
> +- clocksource provider for SMP SoC
> +
> +Required properties:
> +
> +- compatible : should be "snps,archs-gfrc"
> +- clocks     : phandle to the source clock
> +
> +Example:
> +
> +	timer at 1 {
> +		compatible = "snps,archs-gfrc";
> +		clocks = <&core_clk>;
> +	};
> diff --git a/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt b/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt
> new file mode 100644
> index 000000000000..13f756fa1d6d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt
> @@ -0,0 +1,14 @@
> +Synopsys ARC Free Running 64-bit Local Timer for ARC HS CPUs
> +- clocksource provider for UP SoC
> +
> +Required properties:
> +
> +- compatible : should be "snps,archs-rtc"
> +- clocks     : phandle to the source clock
> +
> +Example:
> +
> +	timer at 1 {

rtc {

And then similar updates in the dts files.

> +		compatible = "snps,arc-rtc";
> +		clocks = <&core_clk>;
> +	};


From Alexey.Brodkin at synopsys.com  Thu Mar 17 13:27:10 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 17 Mar 2016 20:27:10 +0000
Subject: [PATCH 1/4 v3] drm: Add support of ARC PGU display controller
In-Reply-To: <20160315155940.GL14170@phenom.ffwll.local>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
 <1457710959-9562-2-git-send-email-abrodkin@synopsys.com>
 <20160314070009.GN14170@phenom.ffwll.local>
 <1457954159.3306.24.camel@synopsys.com>
 <20160315081056.GS14170@phenom.ffwll.local>
 <1458055486.4174.16.camel@synopsys.com>
 <20160315155940.GL14170@phenom.ffwll.local>
Message-ID: <1458246430.3134.14.camel@synopsys.com>

Hi Daniel,

On Tue, 2016-03-15 at 16:59 +0100, Daniel Vetter wrote:
> On Tue, Mar 15, 2016 at 03:24:46PM +0000, Alexey Brodkin wrote:
> > On Tue, 2016-03-15 at 09:10 +0100, Daniel Vetter wrote:
> > > On Mon, Mar 14, 2016 at 11:15:59AM +0000, Alexey Brodkin wrote:
> > > > On Mon, 2016-03-14 at 08:00 +0100, Daniel Vetter wrote:
> > > > > On Fri, Mar 11, 2016 at 06:42:36PM +0300, Alexey Brodkin wrote:
> > > > > >?
> > > > > > +static struct drm_driver arcpgu_drm_driver = {
> > > > > > +	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
> > > > > > +			???DRIVER_ATOMIC,
> > > > > > +	.preclose = arcpgu_preclose,
> > > > > > +	.lastclose = arcpgu_lastclose,
> > > > > > +	.name = "drm-arcpgu",
> > > > > > +	.desc = "ARC PGU Controller",
> > > > > > +	.date = "20160219",
> > > > > > +	.major = 1,
> > > > > > +	.minor = 0,
> > > > > > +	.patchlevel = 0,
> > > > > > +	.fops = &arcpgu_drm_ops,
> > > > > > +	.load = arcpgu_load,
> > > > > > +	.unload = arcpgu_unload,
> > > > > Load and unload hooks are deprecated (it's a classic midlayer mistake).
> > > > > Please use drm_dev_alloc/register pairs directly instead, and put your
> > > > > device setup code in-between. Similar for unloading. There's a bunch of
> > > > > example drivers converted already.
> > > > Ok I took "atmel-hlcdc" as example.
> > > > And that's interesting.
> > > > 
> > > > If I put my?arcpgu_load() in between?drm_dev_alloc() and
> > > > drm_dev_register() then I'm getting this on the driver probe:
> > > > ---------------------------------->8-------------------------------
> > > > [drm] Initialized drm 1.1.0 20060810
> > > > arcpgu e0017000.pgu: arc_pgu ID: 0xabbabaab
> > > > ------------[ cut here ]------------
> > > > WARNING: CPU: 0 PID: 1 at lib/kobject.c:244 kobject_add_internal+0x17c/0x498()
> > > > kobject_add_internal failed for card0-HDMI-A-1 (error: -2 parent: card0)
> > > > Modules linked in:
> > > > CPU: 0 PID: 1 Comm: swapper Not tainted 4.5.0-rc3-01062-ga447822-dirty #17
> > > > 
> > > > Stack Trace:
> > > > ? arc_unwind_core.constprop.1+0xa4/0x110
> > > > ? warn_slowpath_fmt+0x6e/0xfc
> > > > ? kobject_add_internal+0x17c/0x498
> > > > ? kobject_add+0x98/0xe4
> > > > ? device_add+0xc6/0x734
> > > > ? device_create_with_groups+0x12a/0x144
> > > > ? drm_sysfs_connector_add+0x54/0xe8
> > > > ? arcpgu_drm_hdmi_init+0xd4/0x17c
> > > > ? arcpgu_probe+0x138/0x24c
> > > > ? platform_drv_probe+0x2e/0x6c
> > > > ? really_probe+0x212/0x35c
> > > > ? __driver_attach+0x90/0x94
> > > > ? bus_for_each_dev+0x46/0x80
> > > > ? bus_add_driver+0x14e/0x1b4
> > > > ? driver_register+0x64/0x108
> > > > ? do_one_initcall+0x86/0x194
> > > > ? kernel_init_freeable+0xf0/0x188
> > > > ---[ end trace c67166ad43ddcce2 ]---
> > > > [drm:drm_sysfs_connector_add] adding "HDMI-A-1" to sysfs
> > > > [drm:drm_sysfs_connector_add] *ERROR* failed to register connector device: -2
> > > > arcpgu e0017000.pgu: failed to regiter DRM connector and helper funcs
> > > > arcpgu: probe of e0017000.pgu failed with error -2
> > > > ---------------------------------->8-------------------------------
> > > > 
> > > > But if I move arcpgu_load() after drm_dev_register() then everything
> > > > starts properly and I may see HDMI screen works perfectly fine.
> > > > 
> > > > Any thoughts?
> > > Oops, yeah missed that detail. If you look at atmel it has a loop to
> > > register all the drm connectors _after_ calling drm_dev_register().
> > > Totally forgot about that. Can you pls
> > > - Extract a new drm_connector_register_all() function
> > > ? (atmel_hlcdc_dc_connector_plug_all seems to be the best template),
> > > ? including kerneldoc.
> > > - Adjust kerneldoc of drm_dev_register() to mention
> > > ? drm_connector_register_all() and that ordering constraint.
> > > - Roll that helper out to all the drivers that currently hand-roll it (one
> > > ? patch per driver).
> > > 
> > > I know a bit of work but imo not too much, and by doing some small
> > > refactoring every time someone stumbles over a drm pitfall we keep the
> > > subsystem clean&easy to understand. You're up for this? Would be a prep
> > > series, I'll happily review it to get it merged fast. Just a few weeks ago
> > > I merged 20+ patches to make ->mode_fixup hooks optional and remove dummy
> > > ones all over the subsystem, in other words: You'll have my full attention
> > > ;-)
> > Sure, I'm ready to pay that price :)
> > Stay tuned and patches will follow.
> Awesome, looking forward to your patches.

Sorry it took longer for me to finally put my hands on that work but anyways.

I'm looking now at how drivers use existing?drm_connector_unplug_all() and
their implementation of what would be?drm_connector_plug_all() and see
in some implementations people wraps both helpers with
mutex_{lock|unlock}(&dev->mode_config.mutex). But not everybody does this.

So essentially my questions are:
?[1] If it's necessary to get hold of that mutex before execution of either helper?
?[2] If this is really necessary then IMHO it makes sense to move mutex_lock/unlock
? ? ?in helpers itself, right?

-Alexey

From Vineet.Gupta1 at synopsys.com  Thu Mar 17 22:26:29 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 18 Mar 2016 10:56:29 +0530
Subject: [PATCH v3] ARC: [dts] Introduce Timer bindings
In-Reply-To: <20160317162421.GA21947@rob-hp-laptop>
References: <20160317162421.GA21947@rob-hp-laptop>
Message-ID: <1458278789-18924-1-git-send-email-vgupta@synopsys.com>

ARC Timers have historically been probed directly.
As precursor to start probing Timers thru DT introduce these bindings
Note that to keep series bisectable, these bindings are not yet used in
code.

Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Cc: Rob Herring <robh at kernel.org>
Cc: devicetree at vger.kernel.org
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
v3:
 - Renamed Node name to avoid new warnings when unit address used w/o regs [Rob]
v2:
 - http://lists.infradead.org/pipermail/linux-snps-arc/2016-March/000653.html
 - snps,arc-timer[0-1] folded into single snps-arc-timer	[Rob]
 - Node name in DT example fixed:				[Rob]
     "timer1: timer_clksrc {" -> timer at 1 {
 - Introduced 64bit RTC in skeleton_hs.dtsi			[Vineet]
v1:
 - http://lists.infradead.org/pipermail/linux-snps-arc/2016-February/000447.html
---
 .../devicetree/bindings/timer/snps,arc-timer.txt   | 32 ++++++++++++++++++++++
 .../devicetree/bindings/timer/snps,archs-gfrc.txt  | 14 ++++++++++
 .../devicetree/bindings/timer/snps,archs-rtc.txt   | 14 ++++++++++
 arch/arc/boot/dts/abilis_tb10x.dtsi                | 14 ++++++++++
 arch/arc/boot/dts/skeleton.dtsi                    | 14 ++++++++++
 arch/arc/boot/dts/skeleton_hs.dtsi                 | 20 ++++++++++++++
 arch/arc/boot/dts/skeleton_hs_idu.dtsi             | 14 ++++++++++
 7 files changed, 122 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/snps,arc-timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
 create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-rtc.txt

diff --git a/Documentation/devicetree/bindings/timer/snps,arc-timer.txt b/Documentation/devicetree/bindings/timer/snps,arc-timer.txt
new file mode 100644
index 000000000000..29ba64432ad7
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/snps,arc-timer.txt
@@ -0,0 +1,32 @@
+Synopsys ARC Local Timer with Interrupt Capabilities
+- Found on all ARC CPUs (ARC700/ARCHS)
+- Can be optionally programmed to interrupt on Limit
+- Two idential copies TIMER0 and TIMER1 exist in ARC cores and historically
+  TIMER0 used as clockevent provider (true for all ARC cores)
+  TIMER1 used for clocksource (mandatory for ARC700, optional for ARC HS)
+
+Required properties:
+
+- compatible : should be "snps,arc-timer"
+- interrupts : single Interrupt going into parent intc
+	       (16 for ARCHS cores, 3 for ARC700 cores)
+- clocks     : phandle to the source clock
+
+Optional properties:
+
+- interrupt-parent : phandle to parent intc
+
+Example:
+
+	timer0 {
+		compatible = "snps,arc-timer";
+		interrupts = <3>;
+		interrupt-parent = <&core_intc>;
+		clocks = <&core_clk>;
+	};
+
+
+	timer1 {
+		compatible = "snps,arc-timer";
+		clocks = <&core_clk>;
+	};
diff --git a/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt b/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
new file mode 100644
index 000000000000..b6cd1b3922de
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
@@ -0,0 +1,14 @@
+Synopsys ARC Free Running 64-bit Global Timer for ARC HS CPUs
+- clocksource provider for SMP SoC
+
+Required properties:
+
+- compatible : should be "snps,archs-gfrc"
+- clocks     : phandle to the source clock
+
+Example:
+
+	gfrc {
+		compatible = "snps,archs-gfrc";
+		clocks = <&core_clk>;
+	};
diff --git a/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt b/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt
new file mode 100644
index 000000000000..47bd7a702f3f
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt
@@ -0,0 +1,14 @@
+Synopsys ARC Free Running 64-bit Local Timer for ARC HS CPUs
+- clocksource provider for UP SoC
+
+Required properties:
+
+- compatible : should be "snps,archs-rtc"
+- clocks     : phandle to the source clock
+
+Example:
+
+	rtc {
+		compatible = "snps,arc-rtc";
+		clocks = <&core_clk>;
+	};
diff --git a/arch/arc/boot/dts/abilis_tb10x.dtsi b/arch/arc/boot/dts/abilis_tb10x.dtsi
index cfb5052239a1..663671f22680 100644
--- a/arch/arc/boot/dts/abilis_tb10x.dtsi
+++ b/arch/arc/boot/dts/abilis_tb10x.dtsi
@@ -35,6 +35,20 @@
 		};
 	};
 
+	/* TIMER0 with interrupt for clockevent */
+	timer0 {
+		compatible = "snps,arc-timer";
+		interrupts = <3>;
+		interrupt-parent = <&intc>;
+		clocks = <&cpu_clk>;
+	};
+
+	/* TIMER1 for free running clocksource */
+	timer1 {
+		compatible = "snps,arc-timer";
+		clocks = <&cpu_clk>;
+	};
+
 	soc100 {
 		#address-cells	= <1>;
 		#size-cells	= <1>;
diff --git a/arch/arc/boot/dts/skeleton.dtsi b/arch/arc/boot/dts/skeleton.dtsi
index 296d371a335c..3a10cc633e2b 100644
--- a/arch/arc/boot/dts/skeleton.dtsi
+++ b/arch/arc/boot/dts/skeleton.dtsi
@@ -30,6 +30,20 @@
 		};
 	};
 
+	/* TIMER0 with interrupt for clockevent */
+	timer0 {
+		compatible = "snps,arc-timer";
+		interrupts = <3>;
+		interrupt-parent = <&core_intc>;
+		clocks = <&core_clk>;
+	};
+
+	/* TIMER1 for free running clocksource */
+	timer1 {
+		compatible = "snps,arc-timer";
+		clocks = <&core_clk>;
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x80000000 0x10000000>;	/* 256M */
diff --git a/arch/arc/boot/dts/skeleton_hs.dtsi b/arch/arc/boot/dts/skeleton_hs.dtsi
index a53876669030..71fd308a9298 100644
--- a/arch/arc/boot/dts/skeleton_hs.dtsi
+++ b/arch/arc/boot/dts/skeleton_hs.dtsi
@@ -25,6 +25,26 @@
 		};
 	};
 
+	/* TIMER0 with interrupt for clockevent */
+	timer0 {
+		compatible = "snps,arc-timer";
+		interrupts = <16>;
+		interrupt-parent = <&core_intc>;
+		clocks = <&core_clk>;
+	};
+
+	/* 64-bit Local RTC: preferred clocksource for UP */
+	rtc {
+		compatible = "snps,archs-timer-rtc";
+		clocks = <&core_clk>;
+	};
+
+	/* TIMER1 for free running clocksource: Fallback if rtc not found */
+	timer1 {
+		compatible = "snps,arc-timer";
+		clocks = <&core_clk>;
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x80000000 0x10000000>;	/* 256M */
diff --git a/arch/arc/boot/dts/skeleton_hs_idu.dtsi b/arch/arc/boot/dts/skeleton_hs_idu.dtsi
index 74898d017f7a..d1cb25a66989 100644
--- a/arch/arc/boot/dts/skeleton_hs_idu.dtsi
+++ b/arch/arc/boot/dts/skeleton_hs_idu.dtsi
@@ -25,6 +25,20 @@
 		};
 	};
 
+	/* TIMER0 with interrupt for clockevent */
+	timer0 {
+		compatible = "snps,arc-timer";
+		interrupts = <16>;
+		interrupt-parent = <&core_intc>;
+		clocks = <&core_clk>;
+	};
+
+	/* 64-bit Global Free Running Counter */
+	gfrc {
+		compatible = "snps,archs-timer-gfrc";
+		clocks = <&core_clk>;
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x80000000 0x10000000>;	/* 256M */
-- 
2.5.0



From noreply at ellerman.id.au  Thu Mar 17 23:35:08 2016
From: noreply at ellerman.id.au (noreply at ellerman.id.au)
Date: Fri, 18 Mar 2016 06:35:08 -0000
Subject: kisskb: OK linux-next/axs103_smp_defconfig/arcv2 Fri Mar 18, 17:34
Message-ID: <20160318063508.1.67928@4cca3ee1040e>

OK linux-next/axs103_smp_defconfig/arcv2 Fri Mar 18, 17:34

http://kisskb.ellerman.id.au/kisskb/buildresult/12638735/

Commit:   Add linux-next specific files for 20160318
          5e3497cca281616e7930b74a0076b7324dcc2057
Compiler: arc-buildroot-linux-uclibc-gcc (Buildroot 2015.08.1) 4.8.4

Possible errors
---------------

     harderr = icmp_err_convert[code].fatal;

Possible warnings (119)
----------------------

drivers/pci/pcie/Kconfig:62:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:68:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:75:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:62:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:68:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:75:warning: choice value used outside its choice group
<stdin>:1310:2: warning: #warning syscall preadv2 not implemented [-Wcpp]
<stdin>:1313:2: warning: #warning syscall pwritev2 not implemented [-Wcpp]
Warning (unit_address_vs_reg): Node /cpu_card has a reg or ranges property, but no unit name
Warning (unit_address_vs_reg): Node /cpu_card/archs-intc at cpu has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
Warning (unit_address_vs_reg): Node /axs10x_mb has a reg or ranges property, but no unit name
kernel/sched/core.c:3080:1: warning: control reaches end of non-void function [-Wreturn-type]
kernel/sysctl.c:1949:12: warning: 'p' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/sysctl.c:1949:12: warning: 'p' may be used uninitialized in this function [-Wmaybe-uninitialized]
ipc/shm.c:1252:2: warning: 'ret' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:787:21: warning: 'now' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:95:8: warning: 'now' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:665:17: warning: 'val' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:1238:13: warning: 'now' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/namei.c:1713:2: warning: 'seq' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/namei.c:1713:2: warning: 'seq' may be used uninitialized in this function [-Wmaybe-uninitialized]
arch/arc/include/asm/elf.h:58:29: warning: integer overflow in expression [-Woverflow]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
include/linux/rbtree.h:83:28: warning: 'rb_parent' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/linux/rbtree.h:86:11: warning: 'rb_link' may be used uninitialized in this function [-Wmaybe-uninitialized]
mm/mmap.c:558:17: warning: 'prev' may be used uninitialized in this function [-Wmaybe-uninitialized]
lib/cpumask.c:179:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
include/linux/kernel.h:735:17: warning: comparison of distinct pointer types lacks a cast [enabled by default]
net/core/datagram.c:99:5: warning: 'last' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/core/datagram.c:99:5: warning: 'last' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
drivers/usb/core/hub.c:2767:16: warning: 'portchange' may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/usb/core/hub.c:2740:20: warning: 'portstatus' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/core/ethtool.c:295:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/inode.c:561:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/linux/buffer_head.h:363:2: warning: 'blocknr' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:561:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/usb/storage/transport.c:473:40: warning: 'partial' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:561:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
drivers/usb/storage/transport.c:499:15: warning: 'partial' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:561:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/linux/buffer_head.h:370:2: warning: 'blocknr' may be used uninitialized in this function [-Wmaybe-uninitialized]
block/cfq-iosched.c:3793:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/inode.c:561:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:561:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:561:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:315:21: warning: 'handle' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:561:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/inode.c:561:5: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/core/neighbour.c:3180:10: warning: 'p_name' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/inode.c:5638:6: warning: 'retval' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
drivers/tty/serial/8250/8250_core.c:163:19: warning: 'i' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
include/net/inetpeer.h:141:6: warning: 'saddr.<Ue850>.key[3]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'saddr.<Ue850>.key[2]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:26: warning: 'saddr.<Ue850>.a4.vif' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'saddr.<Ue850>.a4.addr' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'daddr.in6_u.u6_addr32[3]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'daddr.in6_u.u6_addr32[2]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'daddr.<Ue850>.a4.addr' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/ipv4/tcp_metrics.c:1080:7: warning: 'hash' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'saddr.<Ue850>.key[3]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'saddr.<Ue850>.key[2]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'daddr.in6_u.u6_addr32[3]' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/net/inetpeer.h:141:6: warning: 'daddr.in6_u.u6_addr32[2]' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_extents.h:224:8: warning: '*((void *)&zero_ex+8)' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_extents.h:225:12: warning: '*((void *)&zero_ex+6)' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/extents.c:3129:2: warning: 'zero_ex.ee_block' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
net/ipv4/tcp_input.c:4273:49: warning: array subscript is above array bounds [-Warray-bounds]
net/ipv4/ping.c:561:37: warning: 'code' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/ipv4/ping.c:534:3: warning: 'type' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/ipv4/ping.c:515:48: warning: 'icmph' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/unix/af_unix.c:1721:9: warning: 'hash' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/packet/af_packet.c:2159:33: warning: 'hdrlen' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/ipv4/ping.c:692:21: warning: 'type' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/ipv4/ping.c:478:63: warning: 'code' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/xfrm/xfrm_policy.c:1599:7: warning: 'dst_ops' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/unix/af_unix.c:1036:20: warning: 'hash' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/ext4/extents.c:2320:14: warning: 'len' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/unix/af_unix.c:1251:8: warning: 'hash' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/unix/af_unix.c:1130:9: warning: 'hash' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/unix/af_unix.c:1721:9: warning: 'hash' may be used uninitialized in this function [-Wmaybe-uninitialized]
include/linux/sunrpc/svc_xprt.h:175:1: warning: control reaches end of non-void function [-Wreturn-type]
net/ipv4/fib_trie.c:909:11: warning: 'local_tp' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/xfrm/xfrm_policy.c:1599:7: warning: 'dst_ops' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/svcsock.c:779:6: warning: 'optname' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/svcsock.c:779:6: warning: 'level' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/svcauth_unix.c:282:12: warning: 'sin6' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1153:8: warning: 'subbuf.tail[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1149:17: warning: 'subbuf.page_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1149:17: warning: 'subbuf.pages' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1144:8: warning: 'subbuf.head[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1153:8: warning: 'subbuf.tail[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1149:17: warning: 'subbuf.page_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1149:17: warning: 'subbuf.pages' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1144:8: warning: 'subbuf.head[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1122:8: warning: 'subbuf.tail[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.page_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.pages' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1113:8: warning: 'subbuf.head[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1122:8: warning: 'subbuf.tail[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.page_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.pages' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1113:8: warning: 'subbuf.head[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1122:8: warning: 'subbuf.tail[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.page_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.pages' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1207:12: warning: 'subbuf.head[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1122:8: warning: 'subbuf.tail[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.page_base' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1118:19: warning: 'subbuf.pages' may be used uninitialized in this function [-Wmaybe-uninitialized]
net/sunrpc/xdr.c:1113:8: warning: 'subbuf.head[0].iov_base' may be used uninitialized in this function [-Wmaybe-uninitialized]



From daniel at ffwll.ch  Fri Mar 18 01:02:57 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Fri, 18 Mar 2016 09:02:57 +0100
Subject: [PATCH 1/4 v3] drm: Add support of ARC PGU display controller
In-Reply-To: <1458246430.3134.14.camel@synopsys.com>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
 <1457710959-9562-2-git-send-email-abrodkin@synopsys.com>
 <20160314070009.GN14170@phenom.ffwll.local>
 <1457954159.3306.24.camel@synopsys.com>
 <20160315081056.GS14170@phenom.ffwll.local>
 <1458055486.4174.16.camel@synopsys.com>
 <20160315155940.GL14170@phenom.ffwll.local>
 <1458246430.3134.14.camel@synopsys.com>
Message-ID: <20160318080257.GD14170@phenom.ffwll.local>

On Thu, Mar 17, 2016 at 08:27:10PM +0000, Alexey Brodkin wrote:
> Hi Daniel,
> 
> On Tue, 2016-03-15 at 16:59 +0100, Daniel Vetter wrote:
> > On Tue, Mar 15, 2016 at 03:24:46PM +0000, Alexey Brodkin wrote:
> > > On Tue, 2016-03-15 at 09:10 +0100, Daniel Vetter wrote:
> > > > On Mon, Mar 14, 2016 at 11:15:59AM +0000, Alexey Brodkin wrote:
> > > > > On Mon, 2016-03-14 at 08:00 +0100, Daniel Vetter wrote:
> > > > > > On Fri, Mar 11, 2016 at 06:42:36PM +0300, Alexey Brodkin wrote:
> > > > > > >?
> > > > > > > +static struct drm_driver arcpgu_drm_driver = {
> > > > > > > +	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
> > > > > > > +			???DRIVER_ATOMIC,
> > > > > > > +	.preclose = arcpgu_preclose,
> > > > > > > +	.lastclose = arcpgu_lastclose,
> > > > > > > +	.name = "drm-arcpgu",
> > > > > > > +	.desc = "ARC PGU Controller",
> > > > > > > +	.date = "20160219",
> > > > > > > +	.major = 1,
> > > > > > > +	.minor = 0,
> > > > > > > +	.patchlevel = 0,
> > > > > > > +	.fops = &arcpgu_drm_ops,
> > > > > > > +	.load = arcpgu_load,
> > > > > > > +	.unload = arcpgu_unload,
> > > > > > Load and unload hooks are deprecated (it's a classic midlayer mistake).
> > > > > > Please use drm_dev_alloc/register pairs directly instead, and put your
> > > > > > device setup code in-between. Similar for unloading. There's a bunch of
> > > > > > example drivers converted already.
> > > > > Ok I took "atmel-hlcdc" as example.
> > > > > And that's interesting.
> > > > > 
> > > > > If I put my?arcpgu_load() in between?drm_dev_alloc() and
> > > > > drm_dev_register() then I'm getting this on the driver probe:
> > > > > ---------------------------------->8-------------------------------
> > > > > [drm] Initialized drm 1.1.0 20060810
> > > > > arcpgu e0017000.pgu: arc_pgu ID: 0xabbabaab
> > > > > ------------[ cut here ]------------
> > > > > WARNING: CPU: 0 PID: 1 at lib/kobject.c:244 kobject_add_internal+0x17c/0x498()
> > > > > kobject_add_internal failed for card0-HDMI-A-1 (error: -2 parent: card0)
> > > > > Modules linked in:
> > > > > CPU: 0 PID: 1 Comm: swapper Not tainted 4.5.0-rc3-01062-ga447822-dirty #17
> > > > > 
> > > > > Stack Trace:
> > > > > ? arc_unwind_core.constprop.1+0xa4/0x110
> > > > > ? warn_slowpath_fmt+0x6e/0xfc
> > > > > ? kobject_add_internal+0x17c/0x498
> > > > > ? kobject_add+0x98/0xe4
> > > > > ? device_add+0xc6/0x734
> > > > > ? device_create_with_groups+0x12a/0x144
> > > > > ? drm_sysfs_connector_add+0x54/0xe8
> > > > > ? arcpgu_drm_hdmi_init+0xd4/0x17c
> > > > > ? arcpgu_probe+0x138/0x24c
> > > > > ? platform_drv_probe+0x2e/0x6c
> > > > > ? really_probe+0x212/0x35c
> > > > > ? __driver_attach+0x90/0x94
> > > > > ? bus_for_each_dev+0x46/0x80
> > > > > ? bus_add_driver+0x14e/0x1b4
> > > > > ? driver_register+0x64/0x108
> > > > > ? do_one_initcall+0x86/0x194
> > > > > ? kernel_init_freeable+0xf0/0x188
> > > > > ---[ end trace c67166ad43ddcce2 ]---
> > > > > [drm:drm_sysfs_connector_add] adding "HDMI-A-1" to sysfs
> > > > > [drm:drm_sysfs_connector_add] *ERROR* failed to register connector device: -2
> > > > > arcpgu e0017000.pgu: failed to regiter DRM connector and helper funcs
> > > > > arcpgu: probe of e0017000.pgu failed with error -2
> > > > > ---------------------------------->8-------------------------------
> > > > > 
> > > > > But if I move arcpgu_load() after drm_dev_register() then everything
> > > > > starts properly and I may see HDMI screen works perfectly fine.
> > > > > 
> > > > > Any thoughts?
> > > > Oops, yeah missed that detail. If you look at atmel it has a loop to
> > > > register all the drm connectors _after_ calling drm_dev_register().
> > > > Totally forgot about that. Can you pls
> > > > - Extract a new drm_connector_register_all() function
> > > > ? (atmel_hlcdc_dc_connector_plug_all seems to be the best template),
> > > > ? including kerneldoc.
> > > > - Adjust kerneldoc of drm_dev_register() to mention
> > > > ? drm_connector_register_all() and that ordering constraint.
> > > > - Roll that helper out to all the drivers that currently hand-roll it (one
> > > > ? patch per driver).
> > > > 
> > > > I know a bit of work but imo not too much, and by doing some small
> > > > refactoring every time someone stumbles over a drm pitfall we keep the
> > > > subsystem clean&easy to understand. You're up for this? Would be a prep
> > > > series, I'll happily review it to get it merged fast. Just a few weeks ago
> > > > I merged 20+ patches to make ->mode_fixup hooks optional and remove dummy
> > > > ones all over the subsystem, in other words: You'll have my full attention
> > > > ;-)
> > > Sure, I'm ready to pay that price :)
> > > Stay tuned and patches will follow.
> > Awesome, looking forward to your patches.
> 
> Sorry it took longer for me to finally put my hands on that work but anyways.
> 
> I'm looking now at how drivers use existing?drm_connector_unplug_all() and
> their implementation of what would be?drm_connector_plug_all() and see
> in some implementations people wraps both helpers with
> mutex_{lock|unlock}(&dev->mode_config.mutex). But not everybody does this.
> 
> So essentially my questions are:
> ?[1] If it's necessary to get hold of that mutex before execution of either helper?

In plug_all I think so, unplug_all has a FIXME comment about how locking
against sysfs is horrible and it's all going to blow up. But we did
recently change the connector sysfs files, so maybe that's fixed now. Not
sure.

> ?[2] If this is really necessary then IMHO it makes sense to move mutex_lock/unlock
> ? ? ?in helpers itself, right?

Yeah, locking in the helper makes imo sense. Aside: I'd vote for
register_all/unregister_all for consistency with drm_connector_register.
register/unregister has a very clear meaning of "publish the object to
userspace/other kernel subsystems". plug/unplug is confusing in DRM
because of hotplug.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From Alexey.Brodkin at synopsys.com  Fri Mar 18 01:11:49 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Fri, 18 Mar 2016 08:11:49 +0000
Subject: [PATCH 1/4 v3] drm: Add support of ARC PGU display controller
In-Reply-To: <20160318080257.GD14170@phenom.ffwll.local>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
 <1457710959-9562-2-git-send-email-abrodkin@synopsys.com>
 <20160314070009.GN14170@phenom.ffwll.local>
 <1457954159.3306.24.camel@synopsys.com>
 <20160315081056.GS14170@phenom.ffwll.local>
 <1458055486.4174.16.camel@synopsys.com>
 <20160315155940.GL14170@phenom.ffwll.local>
 <1458246430.3134.14.camel@synopsys.com>
 <20160318080257.GD14170@phenom.ffwll.local>
Message-ID: <1458288709.12484.15.camel@synopsys.com>

Hi Daniel,

On Fri, 2016-03-18 at 09:02 +0100, Daniel Vetter wrote:
> On Thu, Mar 17, 2016 at 08:27:10PM +0000, Alexey Brodkin wrote:
> > 
> > Hi Daniel,
> > 
> > On Tue, 2016-03-15 at 16:59 +0100, Daniel Vetter wrote:
> > > 
> > > On Tue, Mar 15, 2016 at 03:24:46PM +0000, Alexey Brodkin wrote:
> > > > 
> > > > On Tue, 2016-03-15 at 09:10 +0100, Daniel Vetter wrote:
> > > > > 
> > > > > On Mon, Mar 14, 2016 at 11:15:59AM +0000, Alexey Brodkin wrote:
> > > > > > 
> > > > > > On Mon, 2016-03-14 at 08:00 +0100, Daniel Vetter wrote:
> > > > > > > 
> > > > > > > On Fri, Mar 11, 2016 at 06:42:36PM +0300, Alexey Brodkin wrote:
> > > > > > > > 
> > > > > > > > ?
> > > > > > > > +static struct drm_driver arcpgu_drm_driver = {
> > > > > > > > +	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
> > > > > > > > +			???DRIVER_ATOMIC,
> > > > > > > > +	.preclose = arcpgu_preclose,
> > > > > > > > +	.lastclose = arcpgu_lastclose,
> > > > > > > > +	.name = "drm-arcpgu",
> > > > > > > > +	.desc = "ARC PGU Controller",
> > > > > > > > +	.date = "20160219",
> > > > > > > > +	.major = 1,
> > > > > > > > +	.minor = 0,
> > > > > > > > +	.patchlevel = 0,
> > > > > > > > +	.fops = &arcpgu_drm_ops,
> > > > > > > > +	.load = arcpgu_load,
> > > > > > > > +	.unload = arcpgu_unload,
> > > > > > > Load and unload hooks are deprecated (it's a classic midlayer mistake).
> > > > > > > Please use drm_dev_alloc/register pairs directly instead, and put your
> > > > > > > device setup code in-between. Similar for unloading. There's a bunch of
> > > > > > > example drivers converted already.
> > > > > > Ok I took "atmel-hlcdc" as example.
> > > > > > And that's interesting.
> > > > > > 
> > > > > > If I put my?arcpgu_load() in between?drm_dev_alloc() and
> > > > > > drm_dev_register() then I'm getting this on the driver probe:
> > > > > > ---------------------------------->8-------------------------------
> > > > > > [drm] Initialized drm 1.1.0 20060810
> > > > > > arcpgu e0017000.pgu: arc_pgu ID: 0xabbabaab
> > > > > > ------------[ cut here ]------------
> > > > > > WARNING: CPU: 0 PID: 1 at lib/kobject.c:244 kobject_add_internal+0x17c/0x498()
> > > > > > kobject_add_internal failed for card0-HDMI-A-1 (error: -2 parent: card0)
> > > > > > Modules linked in:
> > > > > > CPU: 0 PID: 1 Comm: swapper Not tainted 4.5.0-rc3-01062-ga447822-dirty #17
> > > > > > 
> > > > > > Stack Trace:
> > > > > > ? arc_unwind_core.constprop.1+0xa4/0x110
> > > > > > ? warn_slowpath_fmt+0x6e/0xfc
> > > > > > ? kobject_add_internal+0x17c/0x498
> > > > > > ? kobject_add+0x98/0xe4
> > > > > > ? device_add+0xc6/0x734
> > > > > > ? device_create_with_groups+0x12a/0x144
> > > > > > ? drm_sysfs_connector_add+0x54/0xe8
> > > > > > ? arcpgu_drm_hdmi_init+0xd4/0x17c
> > > > > > ? arcpgu_probe+0x138/0x24c
> > > > > > ? platform_drv_probe+0x2e/0x6c
> > > > > > ? really_probe+0x212/0x35c
> > > > > > ? __driver_attach+0x90/0x94
> > > > > > ? bus_for_each_dev+0x46/0x80
> > > > > > ? bus_add_driver+0x14e/0x1b4
> > > > > > ? driver_register+0x64/0x108
> > > > > > ? do_one_initcall+0x86/0x194
> > > > > > ? kernel_init_freeable+0xf0/0x188
> > > > > > ---[ end trace c67166ad43ddcce2 ]---
> > > > > > [drm:drm_sysfs_connector_add] adding "HDMI-A-1" to sysfs
> > > > > > [drm:drm_sysfs_connector_add] *ERROR* failed to register connector device: -2
> > > > > > arcpgu e0017000.pgu: failed to regiter DRM connector and helper funcs
> > > > > > arcpgu: probe of e0017000.pgu failed with error -2
> > > > > > ---------------------------------->8-------------------------------
> > > > > > 
> > > > > > But if I move arcpgu_load() after drm_dev_register() then everything
> > > > > > starts properly and I may see HDMI screen works perfectly fine.
> > > > > > 
> > > > > > Any thoughts?
> > > > > Oops, yeah missed that detail. If you look at atmel it has a loop to
> > > > > register all the drm connectors _after_ calling drm_dev_register().
> > > > > Totally forgot about that. Can you pls
> > > > > - Extract a new drm_connector_register_all() function
> > > > > ? (atmel_hlcdc_dc_connector_plug_all seems to be the best template),
> > > > > ? including kerneldoc.
> > > > > - Adjust kerneldoc of drm_dev_register() to mention
> > > > > ? drm_connector_register_all() and that ordering constraint.
> > > > > - Roll that helper out to all the drivers that currently hand-roll it (one
> > > > > ? patch per driver).
> > > > > 
> > > > > I know a bit of work but imo not too much, and by doing some small
> > > > > refactoring every time someone stumbles over a drm pitfall we keep the
> > > > > subsystem clean&easy to understand. You're up for this? Would be a prep
> > > > > series, I'll happily review it to get it merged fast. Just a few weeks ago
> > > > > I merged 20+ patches to make ->mode_fixup hooks optional and remove dummy
> > > > > ones all over the subsystem, in other words: You'll have my full attention
> > > > > ;-)
> > > > Sure, I'm ready to pay that price :)
> > > > Stay tuned and patches will follow.
> > > Awesome, looking forward to your patches.
> > Sorry it took longer for me to finally put my hands on that work but anyways.
> > 
> > I'm looking now at how drivers use existing?drm_connector_unplug_all() and
> > their implementation of what would be?drm_connector_plug_all() and see
> > in some implementations people wraps both helpers with
> > mutex_{lock|unlock}(&dev->mode_config.mutex). But not everybody does this.
> > 
> > So essentially my questions are:
> > ?[1] If it's necessary to get hold of that mutex before execution of either helper?
> In plug_all I think so, unplug_all has a FIXME comment about how locking
> against sysfs is horrible and it's all going to blow up. But we did
> recently change the connector sysfs files, so maybe that's fixed now. Not
> sure.
>
> > ?[2] If this is really necessary then IMHO it makes sense to move mutex_lock/unlock
> > ? ? ?in helpers itself, right?
> Yeah, locking in the helper makes imo sense.

Hm, now I'm even more confused :)
Above you're not sure if this locking is safe (at least on unplug) but here you say
it makes sense (not mentioning the case - both helpers or only on "plugging").

I may indeed try to embed mutex locks in both helpers but what if it works for me but
others will get broken stuff?

> Aside: I'd vote for
> register_all/unregister_all for consistency with drm_connector_register.
> register/unregister has a very clear meaning of "publish the object to
> userspace/other kernel subsystems". plug/unplug is confusing in DRM
> because of hotplug.

Well but what should happen to existing unplug() then?
Should I rename it to unregister_all() in the same change?

-Alexey


From Vineet.Gupta1 at synopsys.com  Fri Mar 18 01:46:23 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 18 Mar 2016 14:16:23 +0530
Subject: [PATCH] ARC: build: Turn off -Wmaybe-uninitialized for ARC gcc 4.8
Message-ID: <1458290783-31491-1-git-send-email-vgupta@synopsys.com>

linux-next has been reporting gazillion warnings for ARC build and
I finally decided to take a bite:

http://kisskb.ellerman.id.au/kisskb/buildresult/12638735/

Most of the them are due to -Wmaybe-uninitialized

| ../kernel/sysctl.c: In function '__do_proc_doulongvec_minmax':
| ../kernel/sysctl.c:1928:12: warning: 'p' may be used uninitialized in this function [-Wmaybe-uninitialized]
|   ret = tmp - *buf;
|            ^
| ../kernel/sysctl.c:2342:29: note: 'p' was declared here
|  char *kbuf = NULL, *p;
|                     ^
| ...
| ...

Cursory look at code seemed fine and a definite gcc false positive in say
kernel/sysctl.c

Mystery was why only for ARC (and not with ARM linaro toolchain based
off same gcc 4.8). Turns out that -O3 (default for ARC) triggers these
and if I enable -O3 for ARM kernel build, I see the same splat.

I doubt if gcc folks are going to fix warnings in gcc 4.8 (specially when this
was the much advertised front page feature @
https://gcc.gnu.org/gcc-4.8/porting_to.html

Better to to silent these for ARC, atleast for gcc 4.8 when we know that
these warnings are likely benign.

When we switch to later gcc, these will come back on and at that time we
could fixing gcc and/or relevant kernel code.

Cc: Claudiu Zissulescu <Claudiu.Zissulescu at synopsys.com>
Cc: Arnd Bergmann <arnd at arndb.de>
Cc: Michal Marek <mmarek at suse.cz>
Cc: Geert Uytterhoeven <geert at linux-m68k.org>
Cc: linux-kbuild at vger.kernel.org
Cc: linux-kernel at vger.kernel.org
Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/Makefile | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index fed12f39d8ce..aeb101e8e674 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -48,9 +48,14 @@ endif
 upto_gcc44    :=  $(call cc-ifversion, -le, 0404, y)
 atleast_gcc44 :=  $(call cc-ifversion, -ge, 0404, y)
 atleast_gcc48 :=  $(call cc-ifversion, -ge, 0408, y)
+is_gcc48      :=  $(call cc-ifversion, -eq, 0408, y)
 
 cflags-$(atleast_gcc44)			+= -fsection-anchors
 
+# gcc 4.8 spits out false positives for default -O3
+# disable these for 4.8 and revisit when we upgrade to newer ver
+cflags-$(is_gcc48)			+= $(call cc-disable-warning,maybe-uninitialized,)
+
 cflags-$(CONFIG_ARC_HAS_LLSC)		+= -mlock
 cflags-$(CONFIG_ARC_HAS_SWAPE)		+= -mswape
 
-- 
2.5.0



From arnd at arndb.de  Fri Mar 18 02:52:12 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 18 Mar 2016 10:52:12 +0100
Subject: [PATCH] ARC: build: Turn off -Wmaybe-uninitialized for ARC gcc 4.8
In-Reply-To: <1458290783-31491-1-git-send-email-vgupta@synopsys.com>
References: <1458290783-31491-1-git-send-email-vgupta@synopsys.com>
Message-ID: <23667289.mNa1Q2STbY@wuerfel>

On Friday 18 March 2016 14:16:23 Vineet Gupta wrote:
> diff --git a/arch/arc/Makefile b/arch/arc/Makefile
> index fed12f39d8ce..aeb101e8e674 100644
> --- a/arch/arc/Makefile
> +++ b/arch/arc/Makefile
> @@ -48,9 +48,14 @@ endif
>  upto_gcc44    :=  $(call cc-ifversion, -le, 0404, y)
>  atleast_gcc44 :=  $(call cc-ifversion, -ge, 0404, y)
>  atleast_gcc48 :=  $(call cc-ifversion, -ge, 0408, y)
> +is_gcc48      :=  $(call cc-ifversion, -eq, 0408, y)
>  
>  cflags-$(atleast_gcc44)                        += -fsection-anchors
>  
> +# gcc 4.8 spits out false positives for default -O3
> +# disable these for 4.8 and revisit when we upgrade to newer ver
> +cflags-$(is_gcc48)                     += $(call cc-disable-warning,maybe-uninitialized,)
> +
>  cflags-$(CONFIG_ARC_HAS_LLSC)          += -mlock
>  cflags-$(CONFIG_ARC_HAS_SWAPE)         += -mswape

Is this any better with gcc-4.9 or gcc-5? Maybe it's better to add the flag to
the line that adds -O3 for consistency. We do the same thing for -Os in the
global Makefile, as that triggers a similar load of warnings.

	Arnd


From Vineet.Gupta1 at synopsys.com  Fri Mar 18 03:20:11 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 18 Mar 2016 15:50:11 +0530
Subject: [PATCH] ARC: build: Turn off -Wmaybe-uninitialized for ARC gcc 4.8
In-Reply-To: <23667289.mNa1Q2STbY@wuerfel>
References: <1458290783-31491-1-git-send-email-vgupta@synopsys.com>
 <23667289.mNa1Q2STbY@wuerfel>
Message-ID: <56EBD65B.10109@synopsys.com>

On Friday 18 March 2016 03:22 PM, Arnd Bergmann wrote:
> On Friday 18 March 2016 14:16:23 Vineet Gupta wrote:
>> diff --git a/arch/arc/Makefile b/arch/arc/Makefile
>> index fed12f39d8ce..aeb101e8e674 100644
>> --- a/arch/arc/Makefile
>> +++ b/arch/arc/Makefile
>> @@ -48,9 +48,14 @@ endif
>>  upto_gcc44    :=  $(call cc-ifversion, -le, 0404, y)
>>  atleast_gcc44 :=  $(call cc-ifversion, -ge, 0404, y)
>>  atleast_gcc48 :=  $(call cc-ifversion, -ge, 0408, y)
>> +is_gcc48      :=  $(call cc-ifversion, -eq, 0408, y)
>>  
>>  cflags-$(atleast_gcc44)                        += -fsection-anchors
>>  
>> +# gcc 4.8 spits out false positives for default -O3
>> +# disable these for 4.8 and revisit when we upgrade to newer ver
>> +cflags-$(is_gcc48)                     += $(call cc-disable-warning,maybe-uninitialized,)
>> +
>>  cflags-$(CONFIG_ARC_HAS_LLSC)          += -mlock
>>  cflags-$(CONFIG_ARC_HAS_SWAPE)         += -mswape
> 
> Is this any better with gcc-4.9 or gcc-5? 

I don't think there's a production ARC toolchain with gcc 4.9 which we can use yet
- Claudiu is still in the the middle of upstreaming the new ARC HS port bits so
things are still in flight there. These tools are off of github !

Maybe it's better to add the flag to
> the line that adds -O3 for consistency. We do the same thing for -Os in the
> global Makefile, as that triggers a similar load of warnings.

Sure, but I prefer this to be only for gcc 4.8 as this warning seems to be
healthy in small doses :-) At least it keeps the door open for future discussion
with gcc guys !

The following nested construct actually works - does that look OK to you ?

ARCH_CFLAGS += -O3 $(call cc-ifversion, -lt, 0408, $(call
cc-disable-warning,maybe-uninitialized,))

Thx,
-Vineet
> 
> 	Arnd
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kbuild" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 



From arnd at arndb.de  Fri Mar 18 03:29:54 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 18 Mar 2016 11:29:54 +0100
Subject: [PATCH] ARC: build: Turn off -Wmaybe-uninitialized for ARC gcc 4.8
In-Reply-To: <56EBD65B.10109@synopsys.com>
References: <1458290783-31491-1-git-send-email-vgupta@synopsys.com>
 <23667289.mNa1Q2STbY@wuerfel> <56EBD65B.10109@synopsys.com>
Message-ID: <3287558.oO5rz13nxZ@wuerfel>

On Friday 18 March 2016 15:50:11 Vineet Gupta wrote:
> Sure, but I prefer this to be only for gcc 4.8 as this warning seems to be
> healthy in small doses  At least it keeps the door open for future discussion
> with gcc guys !

FWIW, testing on ARM with gcc-6.0 -O3, I also get tons of maybe-uninitialized
warnings. It's unlikely that this is architecture specific or fixed in newer
compiler versions.

> The following nested construct actually works - does that look OK to you ?
> 
> ARCH_CFLAGS += -O3 $(call cc-ifversion, -lt, 0408, $(call cc-disable-warning,maybe-uninitialized,))

Yes, that seems ok.

I don't really understand why -O3 is needed though, maybe it's better to
assume that it won't be needed in future gcc versions and do

ARCH_CFLAGS += $(call cc-ifversion, -lt, 0408, -O3 $(call cc-disable-warning,maybe-uninitialized,))

	Arnd


From Vineet.Gupta1 at synopsys.com  Fri Mar 18 03:43:28 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 18 Mar 2016 16:13:28 +0530
Subject: [PATCH] ARC: build: Turn off -Wmaybe-uninitialized for ARC gcc 4.8
In-Reply-To: <3287558.oO5rz13nxZ@wuerfel>
References: <1458290783-31491-1-git-send-email-vgupta@synopsys.com>
 <23667289.mNa1Q2STbY@wuerfel> <56EBD65B.10109@synopsys.com>
 <3287558.oO5rz13nxZ@wuerfel>
Message-ID: <56EBDBD0.6090001@synopsys.com>

On Friday 18 March 2016 03:59 PM, Arnd Bergmann wrote:
> On Friday 18 March 2016 15:50:11 Vineet Gupta wrote:
>> Sure, but I prefer this to be only for gcc 4.8 as this warning seems to be
>> healthy in small doses  At least it keeps the door open for future discussion
>> with gcc guys !
> 
> FWIW, testing on ARM with gcc-6.0 -O3, I also get tons of maybe-uninitialized
> warnings. It's unlikely that this is architecture specific or fixed in newer
> compiler versions.

So we disable this for good just like -Os.
What a shame - seemed like a reasonable safety net for programming errors.

>> The following nested construct actually works - does that look OK to you ?
>>
>> ARCH_CFLAGS += -O3 $(call cc-ifversion, -lt, 0408, $(call cc-disable-warning,maybe-uninitialized,))
> 
> Yes, that seems ok.

There was typo actually -lt needed to be -eq

> I don't really understand why -O3 is needed though, maybe it's better to
> assume that it won't be needed in future gcc versions and do

Not sure what you mean, -O3 for triggering the warnings or -O3 in ARC makefile at all.
Assuming it's latter, this is how its been forever and was added consciously as
performance seemed better with -O3 than the default -O2.


> 
> ARCH_CFLAGS += $(call cc-ifversion, -lt, 0408, -O3 $(call cc-disable-warning,maybe-uninitialized,))
> 
> 	Arnd
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kbuild" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 



From Vineet.Gupta1 at synopsys.com  Fri Mar 18 06:01:53 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 18 Mar 2016 18:31:53 +0530
Subject: [PATCH] ARC: build: Turn off -Wmaybe-uninitialized for ARC gcc 4.8
In-Reply-To: <4819806.6rjMriPpyK@wuerfel>
References: <1458290783-31491-1-git-send-email-vgupta@synopsys.com>
 <3287558.oO5rz13nxZ@wuerfel> <56EBDBD0.6090001@synopsys.com>
 <4819806.6rjMriPpyK@wuerfel>
Message-ID: <56EBFC41.7010803@synopsys.com>

On Friday 18 March 2016 05:43 PM, Arnd Bergmann wrote:
> I think it's dangerous to use -O3 in one architecture when nothing else
> uses it. If you don't have a strong reason to use -O3, maybe just drop that
> use the default -O2 -Wmaybe-uninitialized like everyone else does.

I know what u mean. In fact top level makefile change has bitten us atleast once.
However ARC gcc tends to generate better code (likely others do too) at -O3 and
increased inlining etc reflects in several benchmarks. Maybe its due to the
micro-architecture and smaller hardware call return stack - I'm not sure. So I'm
ready to pay that maintenance price. And it has been like this for 5+ years and I
fear that switching to -O2 might unravel something unwarranted for.

OTOH, I'd rather prefer -O3 for all arches but that ain't gonna happen for obvious
reasons :-)

> On a related note, I have submitted a patch that turns CONFIG_CC_OPTIMIZE_FOR_SIZE
> into a choice statement, so we actually get the -Wmaybe-uninitialized warnings
> in an allyesconfig or allmodconfig build. It would be trivial to extend that
> to give the choice between -Os, -O2 and -O3, and then pick -O3 in a defconfig,
> over the -O2 default.

Is it posted already. I couldn't find it with quick googling.

Thx,
-Vineet


From daniel at ffwll.ch  Fri Mar 18 10:23:28 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Fri, 18 Mar 2016 18:23:28 +0100
Subject: [PATCH 1/4 v3] drm: Add support of ARC PGU display controller
In-Reply-To: <1458288709.12484.15.camel@synopsys.com>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
 <1457710959-9562-2-git-send-email-abrodkin@synopsys.com>
 <20160314070009.GN14170@phenom.ffwll.local>
 <1457954159.3306.24.camel@synopsys.com>
 <20160315081056.GS14170@phenom.ffwll.local>
 <1458055486.4174.16.camel@synopsys.com>
 <20160315155940.GL14170@phenom.ffwll.local>
 <1458246430.3134.14.camel@synopsys.com>
 <20160318080257.GD14170@phenom.ffwll.local>
 <1458288709.12484.15.camel@synopsys.com>
Message-ID: <20160318172327.GH14170@phenom.ffwll.local>

On Fri, Mar 18, 2016 at 08:11:49AM +0000, Alexey Brodkin wrote:
> Hi Daniel,
> 
> On Fri, 2016-03-18 at 09:02 +0100, Daniel Vetter wrote:
> > On Thu, Mar 17, 2016 at 08:27:10PM +0000, Alexey Brodkin wrote:
> > > 
> > > Hi Daniel,
> > > 
> > > On Tue, 2016-03-15 at 16:59 +0100, Daniel Vetter wrote:
> > > > 
> > > > On Tue, Mar 15, 2016 at 03:24:46PM +0000, Alexey Brodkin wrote:
> > > > > 
> > > > > On Tue, 2016-03-15 at 09:10 +0100, Daniel Vetter wrote:
> > > > > > 
> > > > > > On Mon, Mar 14, 2016 at 11:15:59AM +0000, Alexey Brodkin wrote:
> > > > > > > 
> > > > > > > On Mon, 2016-03-14 at 08:00 +0100, Daniel Vetter wrote:
> > > > > > > > 
> > > > > > > > On Fri, Mar 11, 2016 at 06:42:36PM +0300, Alexey Brodkin wrote:
> > > > > > > > > 
> > > > > > > > > ?
> > > > > > > > > +static struct drm_driver arcpgu_drm_driver = {
> > > > > > > > > +	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
> > > > > > > > > +			???DRIVER_ATOMIC,
> > > > > > > > > +	.preclose = arcpgu_preclose,
> > > > > > > > > +	.lastclose = arcpgu_lastclose,
> > > > > > > > > +	.name = "drm-arcpgu",
> > > > > > > > > +	.desc = "ARC PGU Controller",
> > > > > > > > > +	.date = "20160219",
> > > > > > > > > +	.major = 1,
> > > > > > > > > +	.minor = 0,
> > > > > > > > > +	.patchlevel = 0,
> > > > > > > > > +	.fops = &arcpgu_drm_ops,
> > > > > > > > > +	.load = arcpgu_load,
> > > > > > > > > +	.unload = arcpgu_unload,
> > > > > > > > Load and unload hooks are deprecated (it's a classic midlayer mistake).
> > > > > > > > Please use drm_dev_alloc/register pairs directly instead, and put your
> > > > > > > > device setup code in-between. Similar for unloading. There's a bunch of
> > > > > > > > example drivers converted already.
> > > > > > > Ok I took "atmel-hlcdc" as example.
> > > > > > > And that's interesting.
> > > > > > > 
> > > > > > > If I put my?arcpgu_load() in between?drm_dev_alloc() and
> > > > > > > drm_dev_register() then I'm getting this on the driver probe:
> > > > > > > ---------------------------------->8-------------------------------
> > > > > > > [drm] Initialized drm 1.1.0 20060810
> > > > > > > arcpgu e0017000.pgu: arc_pgu ID: 0xabbabaab
> > > > > > > ------------[ cut here ]------------
> > > > > > > WARNING: CPU: 0 PID: 1 at lib/kobject.c:244 kobject_add_internal+0x17c/0x498()
> > > > > > > kobject_add_internal failed for card0-HDMI-A-1 (error: -2 parent: card0)
> > > > > > > Modules linked in:
> > > > > > > CPU: 0 PID: 1 Comm: swapper Not tainted 4.5.0-rc3-01062-ga447822-dirty #17
> > > > > > > 
> > > > > > > Stack Trace:
> > > > > > > ? arc_unwind_core.constprop.1+0xa4/0x110
> > > > > > > ? warn_slowpath_fmt+0x6e/0xfc
> > > > > > > ? kobject_add_internal+0x17c/0x498
> > > > > > > ? kobject_add+0x98/0xe4
> > > > > > > ? device_add+0xc6/0x734
> > > > > > > ? device_create_with_groups+0x12a/0x144
> > > > > > > ? drm_sysfs_connector_add+0x54/0xe8
> > > > > > > ? arcpgu_drm_hdmi_init+0xd4/0x17c
> > > > > > > ? arcpgu_probe+0x138/0x24c
> > > > > > > ? platform_drv_probe+0x2e/0x6c
> > > > > > > ? really_probe+0x212/0x35c
> > > > > > > ? __driver_attach+0x90/0x94
> > > > > > > ? bus_for_each_dev+0x46/0x80
> > > > > > > ? bus_add_driver+0x14e/0x1b4
> > > > > > > ? driver_register+0x64/0x108
> > > > > > > ? do_one_initcall+0x86/0x194
> > > > > > > ? kernel_init_freeable+0xf0/0x188
> > > > > > > ---[ end trace c67166ad43ddcce2 ]---
> > > > > > > [drm:drm_sysfs_connector_add] adding "HDMI-A-1" to sysfs
> > > > > > > [drm:drm_sysfs_connector_add] *ERROR* failed to register connector device: -2
> > > > > > > arcpgu e0017000.pgu: failed to regiter DRM connector and helper funcs
> > > > > > > arcpgu: probe of e0017000.pgu failed with error -2
> > > > > > > ---------------------------------->8-------------------------------
> > > > > > > 
> > > > > > > But if I move arcpgu_load() after drm_dev_register() then everything
> > > > > > > starts properly and I may see HDMI screen works perfectly fine.
> > > > > > > 
> > > > > > > Any thoughts?
> > > > > > Oops, yeah missed that detail. If you look at atmel it has a loop to
> > > > > > register all the drm connectors _after_ calling drm_dev_register().
> > > > > > Totally forgot about that. Can you pls
> > > > > > - Extract a new drm_connector_register_all() function
> > > > > > ? (atmel_hlcdc_dc_connector_plug_all seems to be the best template),
> > > > > > ? including kerneldoc.
> > > > > > - Adjust kerneldoc of drm_dev_register() to mention
> > > > > > ? drm_connector_register_all() and that ordering constraint.
> > > > > > - Roll that helper out to all the drivers that currently hand-roll it (one
> > > > > > ? patch per driver).
> > > > > > 
> > > > > > I know a bit of work but imo not too much, and by doing some small
> > > > > > refactoring every time someone stumbles over a drm pitfall we keep the
> > > > > > subsystem clean&easy to understand. You're up for this? Would be a prep
> > > > > > series, I'll happily review it to get it merged fast. Just a few weeks ago
> > > > > > I merged 20+ patches to make ->mode_fixup hooks optional and remove dummy
> > > > > > ones all over the subsystem, in other words: You'll have my full attention
> > > > > > ;-)
> > > > > Sure, I'm ready to pay that price :)
> > > > > Stay tuned and patches will follow.
> > > > Awesome, looking forward to your patches.
> > > Sorry it took longer for me to finally put my hands on that work but anyways.
> > > 
> > > I'm looking now at how drivers use existing?drm_connector_unplug_all() and
> > > their implementation of what would be?drm_connector_plug_all() and see
> > > in some implementations people wraps both helpers with
> > > mutex_{lock|unlock}(&dev->mode_config.mutex). But not everybody does this.
> > > 
> > > So essentially my questions are:
> > > ?[1] If it's necessary to get hold of that mutex before execution of either helper?
> > In plug_all I think so, unplug_all has a FIXME comment about how locking
> > against sysfs is horrible and it's all going to blow up. But we did
> > recently change the connector sysfs files, so maybe that's fixed now. Not
> > sure.
> >
> > > ?[2] If this is really necessary then IMHO it makes sense to move mutex_lock/unlock
> > > ? ? ?in helpers itself, right?
> > Yeah, locking in the helper makes imo sense.
> 
> Hm, now I'm even more confused :)
> Above you're not sure if this locking is safe (at least on unplug) but here you say
> it makes sense (not mentioning the case - both helpers or only on "plugging").
> 
> I may indeed try to embed mutex locks in both helpers but what if it works for me but
> others will get broken stuff?

Sorry, I meant only embed it it for register_all. And keep the FIXME
comment for unregister_all (well unplug_all as it's called still). Fixing
up sysfs vs. mode_config.mutex is a lot more work than just this.

> > Aside: I'd vote for
> > register_all/unregister_all for consistency with drm_connector_register.
> > register/unregister has a very clear meaning of "publish the object to
> > userspace/other kernel subsystems". plug/unplug is confusing in DRM
> > because of hotplug.
> 
> Well but what should happen to existing unplug() then?
> Should I rename it to unregister_all() in the same change?

Yes, that's what I'd do. I think that's clearer, if we go with a strict
distinction between register/unregister and hotplug handling.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From robh at kernel.org  Fri Mar 18 12:55:50 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 18 Mar 2016 14:55:50 -0500
Subject: [PATCH 2/4] drm: Add DT bindings documentation for ARC PGU
 display controller
In-Reply-To: <1457013497.3005.99.camel@synopsys.com>
References: <1455887034-7739-1-git-send-email-abrodkin@synopsys.com>
 <1455887034-7739-3-git-send-email-abrodkin@synopsys.com>
 <20160223203841.GA15744@rob-hp-laptop>
 <1457013497.3005.99.camel@synopsys.com>
Message-ID: <CAL_JsqLvhHGjYV2DaCL8nxQuzx2ox0EOfynt5PvHcBik6+aPpw@mail.gmail.com>

On Thu, Mar 3, 2016 at 7:58 AM, Alexey Brodkin
<Alexey.Brodkin at synopsys.com> wrote:
> Hi Rob,
>
> On Tue, 2016-02-23 at 14:38 -0600, Rob Herring wrote:
>> On Fri, Feb 19, 2016 at 04:03:52PM +0300, Alexey Brodkin wrote:
>> >
>> > This add DT bindings documentation for ARC PGU display controller.
>> >
>> > Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
>> > Cc: Rob Herring <robh+dt at kernel.org>
>> > Cc: Pawel Moll <pawel.moll at arm.com>
>> > Cc: Mark Rutland <mark.rutland at arm.com>
>> > Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
>> > Cc: Kumar Gala <galak at codeaurora.org>
>> > Cc: devicetree at vger.kernel.org
>> > Cc: linux-snps-arc at lists.infradead.org
>> > ---
>> >  .../devicetree/bindings/display/snps,arcpgu.txt    | 74 ++++++++++++++++++++++
>> >  1 file changed, 74 insertions(+)
>> >  create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt
>> >
>> > diff --git a/Documentation/devicetree/bindings/display/snps,arcpgu.txt
>> > b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
>> > new file mode 100644
>> > index 0000000..c8382fb
>> > --- /dev/null
>> > +++ b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
>> > @@ -0,0 +1,74 @@
>> > +ARC PGU
>> > +
>> > +This is a display controller found on several development boards produced
>> > +by Synopsys. The ARC PGU is an RGB streamer that reads the data from a
>> > +framebuffer and sends it to a single digital encoder (usually HDMI).
>> > +
>> > +Required properties:
>> > +  - compatible: "snps,arcpgu"
>> Seems like this should be more specific. Is there some sort or
>> versioning with ARC blocks?
>
> Well as of today there's only one and only version of PGU.
> So is there a real need for "snps,arcpgu-1.0"?
>
>> >
>> > +  - reg: Physical base address and length of the controller's registers.
>> > +  - clocks: A list of phandle + clock-specifier pairs, one for each
>> > +    entry in 'clock-names'.
>> > +  - clock-names: A list of clock names. For ARC PGU it should contain:
>> > +      - "pxlclk" for the clock feeding the output PLL of the controller.
>> > +  - encoder-slave: Phandle of encoder chip.
>> This is unnecessary with the OF graph.
>
> Do you mean I may drop "encoder-slave" from bindings description?

Yes, you should drop it.

> I actually thought about that because in case of simulation platform where
> this device is also used there's no encoder as well as no connector - we're
> dealing with memory area which is read by host and then displayed on host's
> display.
>


From noreply at ellerman.id.au  Sat Mar 19 01:22:49 2016
From: noreply at ellerman.id.au (noreply at ellerman.id.au)
Date: Sat, 19 Mar 2016 08:22:49 -0000
Subject: kisskb: FAILED linus/axs103_smp_defconfig/arcv2 Sat Mar 19, 19:22
Message-ID: <20160319082249.1.32265@4cca3ee1040e>

FAILED linus/axs103_smp_defconfig/arcv2 Sat Mar 19, 19:22

http://kisskb.ellerman.id.au/kisskb/buildresult/12640067/

Commit:   Merge branch 'for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
          6b5f04b6cf8ebab9a65d9c0026c650bb2538fd0f
Compiler: arc-buildroot-linux-uclibc-gcc (Buildroot 2015.08.1) 4.8.4

Possible errors
---------------

include/linux/compiler.h:485:2: error: expected identifier or '(' before 'do'
include/linux/compiler.h:491:4: error: expected identifier or '(' before 'while'
make[3]: *** [arch/arc/mm/tlb.o] Error 1
include/linux/compiler.h:485:2: error: expected identifier or '(' before 'do'
include/linux/compiler.h:491:4: error: expected identifier or '(' before 'while'
make[3]: *** [arch/arc/kernel/setup.o] Error 1
make[2]: *** [arch/arc/mm] Error 2
include/linux/compiler.h:485:2: error: expected identifier or '(' before 'do'
include/linux/compiler.h:491:4: error: expected identifier or '(' before 'while'
include/linux/compiler.h:485:2: error: expected identifier or '(' before 'do'
include/linux/compiler.h:491:4: error: expected identifier or '(' before 'while'
make[2]: *** [kernel/exit.o] Error 1
make[2]: *** [kernel/fork.o] Error 1
include/linux/compiler.h:485:2: error: expected identifier or '(' before 'do'
include/linux/compiler.h:491:4: error: expected identifier or '(' before 'while'
include/linux/compiler.h:485:2: error: expected identifier or '(' before 'do'
include/linux/compiler.h:491:4: error: expected identifier or '(' before 'while'
make[2]: *** [kernel/module.o] Error 1
make[3]: *** [kernel/sched/core.o] Error 1
include/linux/compiler.h:485:2: error: expected identifier or '(' before 'do'
include/linux/compiler.h:491:4: error: expected identifier or '(' before 'while'
make[2]: *** [mm/page_alloc.o] Error 1
make[2]: *** [arch/arc/kernel] Error 2
make[1]: *** [arch/arc] Error 2
include/linux/compiler.h:485:2: error: expected identifier or '(' before 'do'
include/linux/compiler.h:491:4: error: expected identifier or '(' before 'while'
make[2]: *** [mm/vmscan.o] Error 1
include/linux/compiler.h:485:2: error: expected identifier or '(' before 'do'
include/linux/compiler.h:491:4: error: expected identifier or '(' before 'while'
make[2]: *** [fs/exec.o] Error 1
make[1]: *** [mm] Error 2
make[2]: *** [kernel/sched] Error 2
make[1]: *** [fs] Error 2
make[1]: *** [kernel] Error 2
make: *** [sub-make] Error 2

Possible warnings (16)
----------------------

drivers/pci/pcie/Kconfig:62:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:68:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:75:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:62:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:68:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:75:warning: choice value used outside its choice group
kernel/sched/core.c:3079:1: warning: control reaches end of non-void function [-Wreturn-type]
kernel/sysctl.c:1949:12: warning: 'p' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/sysctl.c:1949:12: warning: 'p' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:787:21: warning: 'now' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:95:8: warning: 'now' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:665:17: warning: 'val' may be used uninitialized in this function [-Wmaybe-uninitialized]
kernel/time/posix-cpu-timers.c:1238:13: warning: 'now' may be used uninitialized in this function [-Wmaybe-uninitialized]
ipc/shm.c:1252:2: warning: 'ret' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/namei.c:1720:2: warning: 'seq' may be used uninitialized in this function [-Wmaybe-uninitialized]
fs/namei.c:1720:2: warning: 'seq' may be used uninitialized in this function [-Wmaybe-uninitialized]



From robh at kernel.org  Sat Mar 19 17:42:12 2016
From: robh at kernel.org (Rob Herring)
Date: Sat, 19 Mar 2016 19:42:12 -0500
Subject: [PATCH v3] ARC: [dts] Introduce Timer bindings
In-Reply-To: <1458278789-18924-1-git-send-email-vgupta@synopsys.com>
References: <20160317162421.GA21947@rob-hp-laptop>
 <1458278789-18924-1-git-send-email-vgupta@synopsys.com>
Message-ID: <20160320004212.GA8061@rob-hp-laptop>

On Fri, Mar 18, 2016 at 10:56:29AM +0530, Vineet Gupta wrote:
> ARC Timers have historically been probed directly.
> As precursor to start probing Timers thru DT introduce these bindings
> Note that to keep series bisectable, these bindings are not yet used in
> code.
> 
> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
> Cc: Rob Herring <robh at kernel.org>
> Cc: devicetree at vger.kernel.org
> Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
> ---
> v3:
>  - Renamed Node name to avoid new warnings when unit address used w/o regs [Rob]
> v2:
>  - http://lists.infradead.org/pipermail/linux-snps-arc/2016-March/000653.html
>  - snps,arc-timer[0-1] folded into single snps-arc-timer	[Rob]
>  - Node name in DT example fixed:				[Rob]
>      "timer1: timer_clksrc {" -> timer at 1 {
>  - Introduced 64bit RTC in skeleton_hs.dtsi			[Vineet]
> v1:
>  - http://lists.infradead.org/pipermail/linux-snps-arc/2016-February/000447.html
> ---
>  .../devicetree/bindings/timer/snps,arc-timer.txt   | 32 ++++++++++++++++++++++
>  .../devicetree/bindings/timer/snps,archs-gfrc.txt  | 14 ++++++++++
>  .../devicetree/bindings/timer/snps,archs-rtc.txt   | 14 ++++++++++
>  arch/arc/boot/dts/abilis_tb10x.dtsi                | 14 ++++++++++
>  arch/arc/boot/dts/skeleton.dtsi                    | 14 ++++++++++
>  arch/arc/boot/dts/skeleton_hs.dtsi                 | 20 ++++++++++++++
>  arch/arc/boot/dts/skeleton_hs_idu.dtsi             | 14 ++++++++++
>  7 files changed, 122 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/timer/snps,arc-timer.txt
>  create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
>  create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-rtc.txt

Acked-by: Rob Herring <robh at kernel.org>


From Vineet.Gupta1 at synopsys.com  Sun Mar 20 22:00:29 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Mon, 21 Mar 2016 10:30:29 +0530
Subject: [GIT PULL] ARC changes for 4.6-rc1
Message-ID: <56EF7FED.6050601@synopsys.com>

Hi Linus,

ARC changes for 4.6-rc1. Nothing too exciting here although diffstat hows more
files touched than usual due to some sweeping defconfig / DT updates.

Please pull !

Thx,
-Vineet
------------->
The following changes since commit fc77dbd34c5c99bce46d40a2491937c3bcbd10af:

  Linux 4.5-rc6 (2016-02-28 08:41:20 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git/ tags/arc-4.6-rc1

for you to fetch changes up to deaf7565eb618a80534844300aeacffa14125182:

  ARCv2: ioremap: Support dynamic peripheral address space (2016-03-19 14:34:10 +0530)

----------------------------------------------------------------
ARC updates for 4.6-rc1
- Big Endian io accessors fix [Lada]
- Spellos fixes [Adam]
- Fix for DW GMAC breakage [Alexey]
- Making DMA API 64-bit ready
- Shutting up -Wmaybe-uninitialized noise for ARC
- Other minor fixes here and there, comments update

----------------------------------------------------------------
Adam Buchbinder (1):
      ARC: Fix misspellings in comments.

Alexey Brodkin (1):
      ARC: [plat-axs10x] add Ethernet PHY description in .dts

Kefeng Wang (1):
      arc: use of_platform_default_populate() to populate default bus

Lada Trimasova (2):
      ARC: [BE] readl()/writel() to work in Big Endian CPU configuration
      arc: [plat-nsimosci*] use ezchip network driver

Vineet Gupta (16):
      ARC: bitops: Remove non relevant comments
      ARC: [BE] Select correct CROSS_COMPILE prefix
      ARC: [*defconfig] No need to specify CONFIG_CROSS_COMPILE
      ARCv2: Allow enabling PAE40 w/o HIGHMEM
      ARC: build: Better way to detect ISA compatible toolchain
      ARC: [plat-nsim] document ranges
      ARC: mm: Use virt_to_pfn() for addr >> PAGE_SHIFT pattern
      ARCv2: LLSC: software backoff is NOT needed starting HS2.1c
      ARC: thp: unbork !CONFIG_TRANSPARENT_HUGEPAGE build
      ARC: build: Turn off -Wmaybe-uninitialized for ARC gcc 4.8
      ARC: dma: Use struct page based page allocator helpers
      ARC: dma: non-coherent pages need V-P mapping if in HIGHMEM
      ARC: dma: pass_phys() not sg_virt() to cache ops
      ARC: dma: ioremap: use phys_addr_t consistenctly in code paths
      ARC: dma: reintroduce platform specific dma<->phys
      ARCv2: ioremap: Support dynamic peripheral address space

 arch/arc/Kconfig                           |  6 ++-
 arch/arc/Makefile                          | 22 ++++++++-
 arch/arc/boot/dts/axs10x_mb.dtsi           |  8 ++++
 arch/arc/boot/dts/nsim_hs.dts              |  3 +-
 arch/arc/boot/dts/nsimosci.dts             |  5 +-
 arch/arc/boot/dts/nsimosci_hs.dts          |  5 +-
 arch/arc/boot/dts/nsimosci_hs_idu.dts      |  5 +-
 arch/arc/configs/axs101_defconfig          |  1 -
 arch/arc/configs/axs103_defconfig          |  1 -
 arch/arc/configs/axs103_smp_defconfig      |  1 -
 arch/arc/configs/nsim_700_defconfig        |  1 -
 arch/arc/configs/nsim_hs_defconfig         |  1 -
 arch/arc/configs/nsim_hs_smp_defconfig     |  1 -
 arch/arc/configs/nsimosci_defconfig        |  2 +-
 arch/arc/configs/nsimosci_hs_defconfig     |  2 +-
 arch/arc/configs/nsimosci_hs_smp_defconfig |  3 +-
 arch/arc/configs/tb10x_defconfig           |  1 -
 arch/arc/configs/vdk_hs38_defconfig        |  1 -
 arch/arc/configs/vdk_hs38_smp_defconfig    |  1 -
 arch/arc/include/asm/arcregs.h             |  6 ---
 arch/arc/include/asm/bitops.h              | 15 ------
 arch/arc/include/asm/cache.h               |  1 +
 arch/arc/include/asm/cacheflush.h          |  6 +--
 arch/arc/include/asm/cmpxchg.h             |  2 +-
 arch/arc/include/asm/dma-mapping.h         |  7 +++
 arch/arc/include/asm/entry-compact.h       |  2 +-
 arch/arc/include/asm/io.h                  | 22 ++++++---
 arch/arc/include/asm/page.h                | 19 +++-----
 arch/arc/include/asm/pgtable.h             | 11 ++---
 arch/arc/include/asm/tlbflush.h            |  7 ++-
 arch/arc/kernel/setup.c                    | 21 ++-------
 arch/arc/kernel/stacktrace.c               |  2 +-
 arch/arc/kernel/time.c                     |  4 +-
 arch/arc/mm/cache.c                        | 39 +++++++++-------
 arch/arc/mm/dma.c                          | 75 ++++++++++++++++++++----------
 arch/arc/mm/highmem.c                      |  2 +-
 arch/arc/mm/ioremap.c                      | 37 ++++++++++-----
 arch/arc/mm/tlb.c                          |  8 ++--
 38 files changed, 201 insertions(+), 155 deletions(-)


From Vineet.Gupta1 at synopsys.com  Sun Mar 20 22:02:36 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Mon, 21 Mar 2016 05:02:36 +0000
Subject: [PATCH v3] ARC: [dts] Introduce Timer bindings
References: <20160317162421.GA21947@rob-hp-laptop>
 <1458278789-18924-1-git-send-email-vgupta@synopsys.com>
 <20160320004212.GA8061@rob-hp-laptop>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E90A92@us01wembx1.internal.synopsys.com>

On Sunday 20 March 2016 06:12 AM, Rob Herring wrote:
> On Fri, Mar 18, 2016 at 10:56:29AM +0530, Vineet Gupta wrote:
>> ARC Timers have historically been probed directly.
>> As precursor to start probing Timers thru DT introduce these bindings
>> Note that to keep series bisectable, these bindings are not yet used in
>> code.
>>
>> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
>> Cc: Rob Herring <robh at kernel.org>
>> Cc: devicetree at vger.kernel.org
>> Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
>> ---
>> v3:
>>  - Renamed Node name to avoid new warnings when unit address used w/o regs [Rob]
>> v2:
>>  - http://lists.infradead.org/pipermail/linux-snps-arc/2016-March/000653.html
>>  - snps,arc-timer[0-1] folded into single snps-arc-timer	[Rob]
>>  - Node name in DT example fixed:				[Rob]
>>      "timer1: timer_clksrc {" -> timer at 1 {
>>  - Introduced 64bit RTC in skeleton_hs.dtsi			[Vineet]
>> v1:
>>  - http://lists.infradead.org/pipermail/linux-snps-arc/2016-February/000447.html
>> ---
>>  .../devicetree/bindings/timer/snps,arc-timer.txt   | 32 ++++++++++++++++++++++
>>  .../devicetree/bindings/timer/snps,archs-gfrc.txt  | 14 ++++++++++
>>  .../devicetree/bindings/timer/snps,archs-rtc.txt   | 14 ++++++++++
>>  arch/arc/boot/dts/abilis_tb10x.dtsi                | 14 ++++++++++
>>  arch/arc/boot/dts/skeleton.dtsi                    | 14 ++++++++++
>>  arch/arc/boot/dts/skeleton_hs.dtsi                 | 20 ++++++++++++++
>>  arch/arc/boot/dts/skeleton_hs_idu.dtsi             | 14 ++++++++++
>>  7 files changed, 122 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/timer/snps,arc-timer.txt
>>  create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
>>  create mode 100644 Documentation/devicetree/bindings/timer/snps,archs-rtc.txt
> Acked-by: Rob Herring <robh at kernel.org>

Thx a bunch Rob !

-Vineet


From arnd at arndb.de  Fri Mar 18 05:13:32 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 18 Mar 2016 13:13:32 +0100
Subject: [PATCH] ARC: build: Turn off -Wmaybe-uninitialized for ARC gcc 4.8
In-Reply-To: <56EBDBD0.6090001@synopsys.com>
References: <1458290783-31491-1-git-send-email-vgupta@synopsys.com>
 <3287558.oO5rz13nxZ@wuerfel> <56EBDBD0.6090001@synopsys.com>
Message-ID: <4819806.6rjMriPpyK@wuerfel>

On Friday 18 March 2016 16:13:28 Vineet Gupta wrote:
> On Friday 18 March 2016 03:59 PM, Arnd Bergmann wrote:
> > On Friday 18 March 2016 15:50:11 Vineet Gupta wrote:
> >> Sure, but I prefer this to be only for gcc 4.8 as this warning seems to be
> >> healthy in small doses  At least it keeps the door open for future discussion
> >> with gcc guys !
> > 
> > FWIW, testing on ARM with gcc-6.0 -O3, I also get tons of maybe-uninitialized
> > warnings. It's unlikely that this is architecture specific or fixed in newer
> > compiler versions.
> 
> So we disable this for good just like -Os.
> What a shame - seemed like a reasonable safety net for programming errors.

Yes, it's an immensely useful warning, if you manage to avoid the
false positives.

> >> The following nested construct actually works - does that look OK to you ?
> >>
> >> ARCH_CFLAGS += -O3 $(call cc-ifversion, -lt, 0408, $(call cc-disable-warning,maybe-uninitialized,))
> > 
> > Yes, that seems ok.
> 
> There was typo actually -lt needed to be -eq
> 
> > I don't really understand why -O3 is needed though, maybe it's better to
> > assume that it won't be needed in future gcc versions and do
> 
> Not sure what you mean, -O3 for triggering the warnings or -O3 in ARC makefile at all.
> Assuming it's latter, this is how its been forever and was added consciously as
> performance seemed better with -O3 than the default -O2.

I think it's dangerous to use -O3 in one architecture when nothing else
uses it. If you don't have a strong reason to use -O3, maybe just drop that
use the default -O2 -Wmaybe-uninitialized like everyone else does.

On a related note, I have submitted a patch that turns CONFIG_CC_OPTIMIZE_FOR_SIZE
into a choice statement, so we actually get the -Wmaybe-uninitialized warnings
in an allyesconfig or allmodconfig build. It would be trivial to extend that
to give the choice between -Os, -O2 and -O3, and then pick -O3 in a defconfig,
over the -O2 default.

	Arnd


From arnd at arndb.de  Fri Mar 18 06:41:03 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 18 Mar 2016 14:41:03 +0100
Subject: [PATCH] ARC: build: Turn off -Wmaybe-uninitialized for ARC gcc 4.8
In-Reply-To: <56EBFC41.7010803@synopsys.com>
References: <1458290783-31491-1-git-send-email-vgupta@synopsys.com>
 <4819806.6rjMriPpyK@wuerfel> <56EBFC41.7010803@synopsys.com>
Message-ID: <12216502.1fD0EQ8zlH@wuerfel>

On Friday 18 March 2016 18:31:53 Vineet Gupta wrote:
> 
> > On a related note, I have submitted a patch that turns CONFIG_CC_OPTIMIZE_FOR_SIZE
> > into a choice statement, so we actually get the -Wmaybe-uninitialized warnings
> > in an allyesconfig or allmodconfig build. It would be trivial to extend that
> > to give the choice between -Os, -O2 and -O3, and then pick -O3 in a defconfig,
> > over the -O2 default.
> 
> Is it posted already. I couldn't find it with quick googling.
> 
> 
https://lkml.org/lkml/2016/2/12/315

	Arnd


From robh at kernel.org  Mon Mar 21 06:04:19 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 21 Mar 2016 08:04:19 -0500
Subject: [PATCH 2/4 v3] drm: Add DT bindings documentation for ARC PGU
 display controller
In-Reply-To: <1457710959-9562-3-git-send-email-abrodkin@synopsys.com>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
 <1457710959-9562-3-git-send-email-abrodkin@synopsys.com>
Message-ID: <20160321130419.GA23913@rob-hp-laptop>

On Fri, Mar 11, 2016 at 06:42:37PM +0300, Alexey Brodkin wrote:
> This add DT bindings documentation for ARC PGU display controller.
> 
> Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
> Cc: Rob Herring <robh+dt at kernel.org>
> Cc: Pawel Moll <pawel.moll at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
> Cc: Kumar Gala <galak at codeaurora.org>
> Cc: David Airlie <airlied at linux.ie>
> Cc: dri-devel at lists.freedesktop.org
> Cc: devicetree at vger.kernel.org
> Cc: linux-snps-arc at lists.infradead.org
> ---
> 
> Changes v2 -> v3:
>  * Reverted back to initial larger version of example
>    with minor fixes (thanks Rob for spotting those).
> 
> Changes v1 -> v2:
>  * Removed everything except PGU node itself.
> 
>  .../devicetree/bindings/display/snps,arcpgu.txt    | 72 ++++++++++++++++++++++
>  1 file changed, 72 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt
> 
> diff --git a/Documentation/devicetree/bindings/display/snps,arcpgu.txt b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> new file mode 100644
> index 0000000..b130924
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> @@ -0,0 +1,72 @@
> +ARC PGU
> +
> +This is a display controller found on several development boards produced
> +by Synopsys. The ARC PGU is an RGB streamer that reads the data from a
> +framebuffer and sends it to a single digital encoder (usually HDMI).
> +
> +Required properties:
> +  - compatible: "snps,arcpgu"
> +  - reg: Physical base address and length of the controller's registers.
> +  - clocks: A list of phandle + clock-specifier pairs, one for each
> +    entry in 'clock-names'.
> +  - clock-names: A list of clock names. For ARC PGU it should contain:
> +      - "pxlclk" for the clock feeding the output PLL of the controller.
> +  - encoder-slave: Phandle of encoder chip.

Drop this as discussed.

> +
> +Required sub-nodes:
> +  - port: The PGU connection to an encoder chip.
> +
> +Example:
> +
> +/ {
> +	...
> +
> +	pgu at XXXXXXXX {
> +		compatible = "snps,arcpgu";
> +		reg = <0xXXXXXXXX 0x400>;
> +		clocks = <&clock_node>;
> +		clock-names = "pxlclk";
> +		encoder-slave = <&encoder_node>;
> +
> +		port {
> +			pgu_output: endpoint {
> +				remote-endpoint = <&hdmi_enc_input>;
> +			};
> +		};
> +	};
> +
> +	/* HDMI encoder on I2C bus */
> +	i2c at XXXXXXXX {
> +		compatible = "...";
> +
> +		encoder_node:encoder_node at 0xXX{

Don't use underscores in node names. Just "hdmi at xx"

> +			compatible="...";
> +
> +			ports {
> +				port at 0 {
> +					reg = <0>;
> +					hdmi_enc_input:endpoint {
> +						remote-endpoint = <&pgu_output>;
> +					};
> +				};
> +
> +				port at 1 {
> +					reg = <1>;
> +					hdmi_enc_output:endpoint {
> +						remote-endpoint = <&hdmi_connector_in>;
> +					};
> +				};
> +			};
> +		};
> +	}
> +
> +	hdmi0: connector {
> +		compatible = "hdmi-connector";
> +
> +		port {
> +			hdmi_connector_in: endpoint {
> +				remote-endpoint = <&hdmi_enc_output>;
> +			};
> +		};
> +	};
> +};
> -- 
> 2.5.0
> 


From noamca at mellanox.com  Mon Mar 21 07:24:29 2016
From: noamca at mellanox.com (Noam Camus)
Date: Mon, 21 Mar 2016 16:24:29 +0200
Subject: [PATCH v6 0/3] Adding NPS400 drivers
Message-ID: <1458570272-23037-1-git-send-email-noamca@mellanox.com>

From: Noam Camus <noamc at ezchip.com>

Change Log--
v6:
Files headers changed to start with:
Copyright (c) 2016, Mellanox Technologies
...

This is due to the acquisition of EZchip made by Mellanox.
One can still find "EZchip" used in tree, and this is ok.

This patch set is a requierement before I can insert new platform to ARC,
one that supports the NPS400 SoC.

v5:
Clocksource, irqchip - Fix gracefull return.
				replace call to panic() with pr_err() and proper return value.

v4:
clocksource -- Apply all Daniel comments (Thanks)
				Handle gracefull return and also using clocksoure mmio driver at init

v3:
irqchip - Fix ARM build failure by adding missing include of linux/irq.h
clocksource -- Avoid 64bit arch's to build driver by adding new dependency !PHYS_ADDR_T_64BIT
				This is since we use explicit io access of 32 bit. So for test coverage we allow
				not only build for ARC, but restrict it to 32 bit arch's.
irqchip - Apply all Thomas comments (Thank you)

v2:
Add header file include/soc/nps/common.h.
Now to build we do not depend on ARC subtree.

General summay:
Both drivers are now apart of previous basic patch set of new platform for ARC.
The rest is now can be seen at ARC srctree:
https://git.kernel.org/cgit/linux/kernel/git/vgupta/arc.git/

Now ARC is supporting DT for clockevents and the interrupt controller ARC
uses irq domain handling.

Compare to last version now clocksource driver do not include clockevent registration
since NPS400 can use ARC generic driver.

Compare to last version now irqchip driver sets domain as default since it is the root domain.
Also mapping of IPI is done in this driver.

Last thing is that drivers can be build cleanly for i386 (still runs only for ARC)
Note: in order to build we need to merge drivers into srctree which includes new header:
soc/nps/common.h
This header is part of patch set applied to ARC srctree.

Regards,
Noam Camus

Noam Camus (3):
  soc: Support for EZchip SoC
  clocksource: Add NPS400 timers driver
  irqchip: add nps Internal and external irqchips

 .../interrupt-controller/ezchip,nps400-ic.txt      |   17 ++
 .../bindings/timer/ezchip,nps400-timer.txt         |   15 ++
 drivers/clocksource/Kconfig                        |   10 ++
 drivers/clocksource/Makefile                       |    1 +
 drivers/clocksource/timer-nps.c                    |   98 ++++++++++++
 drivers/irqchip/Kconfig                            |    6 +
 drivers/irqchip/Makefile                           |    1 +
 drivers/irqchip/irq-eznps.c                        |  165 +++++++++++++++++++
 include/soc/nps/common.h                           |  166 ++++++++++++++++++++
 9 files changed, 479 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 drivers/clocksource/timer-nps.c
 create mode 100644 drivers/irqchip/irq-eznps.c
 create mode 100644 include/soc/nps/common.h



From noamca at mellanox.com  Mon Mar 21 07:24:30 2016
From: noamca at mellanox.com (Noam Camus)
Date: Mon, 21 Mar 2016 16:24:30 +0200
Subject: [PATCH v6 1/3] soc: Support for EZchip SoC
In-Reply-To: <1458570272-23037-1-git-send-email-noamca@mellanox.com>
References: <1458570272-23037-1-git-send-email-noamca@mellanox.com>
Message-ID: <1458570272-23037-2-git-send-email-noamca@mellanox.com>

From: Noam Camus <noamc at ezchip.com>

This header file is for NPS400 SoC.
It includes macros for accessing memory mapped registers.
These are functional registers that core can use to configure SoC.

Signed-off-by: Noam Camus <noamc at ezchip.com>
---
 include/soc/nps/common.h |  166 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 166 insertions(+), 0 deletions(-)
 create mode 100644 include/soc/nps/common.h

diff --git a/include/soc/nps/common.h b/include/soc/nps/common.h
new file mode 100644
index 0000000..e959176
--- /dev/null
+++ b/include/soc/nps/common.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef SOC_NPS_COMMON_H
+#define SOC_NPS_COMMON_H
+
+#ifdef CONFIG_SMP
+#define IPI_IRQ					5
+#endif
+
+#define NPS_HOST_REG_BASE			0xF6000000
+
+#define NPS_MSU_BLKID				0x018
+
+#define CTOP_INST_RSPI_GIC_0_R12		0x3C56117E
+#define CTOP_INST_MOV2B_FLIP_R3_B1_B2_INST	0x5B60
+#define CTOP_INST_MOV2B_FLIP_R3_B1_B2_LIMM	0x00010422
+
+#ifndef __ASSEMBLY__
+
+/* In order to increase compilation test coverage */
+#ifdef CONFIG_ARC
+static inline void nps_ack_gic(void)
+{
+	__asm__ __volatile__ (
+	"       .word %0\n"
+	:
+	: "i"(CTOP_INST_RSPI_GIC_0_R12)
+	: "memory");
+}
+#else
+static inline void nps_ack_gic(void) { }
+#define write_aux_reg(r, v)
+#define read_aux_reg(r) 0
+#endif
+
+/* CPU global ID */
+struct global_id {
+	union {
+		struct {
+#ifdef CONFIG_EZNPS_MTM_EXT
+			u32 __reserved:20, cluster:4, core:4, thread:4;
+#else
+			u32 __reserved:24, cluster:4, core:4;
+#endif
+		};
+		u32 value;
+	};
+};
+
+/*
+ * Convert logical to physical CPU IDs
+ *
+ * The conversion swap bits 1 and 2 of cluster id (out of 4 bits)
+ * Now quad of logical clusters id's are adjacent physically,
+ * and not like the id's physically came with each cluster.
+ * Below table is 4x4 mesh of core clusters as it layout on chip.
+ * Cluster ids are in format: logical (physical)
+ *
+ *    -----------------   ------------------
+ * 3 |  5 (3)   7 (7)  | | 13 (11)   15 (15)|
+ *
+ * 2 |  4 (2)   6 (6)  | | 12 (10)   14 (14)|
+ *    -----------------   ------------------
+ * 1 |  1 (1)   3 (5)  | |  9  (9)   11 (13)|
+ *
+ * 0 |  0 (0)   2 (4)  | |  8  (8)   10 (12)|
+ *    -----------------   ------------------
+ *       0       1            2        3
+ */
+static inline int nps_cluster_logic_to_phys(int cluster)
+{
+#ifdef __arc__
+	 __asm__ __volatile__(
+	"       mov r3,%0\n"
+	"       .short %1\n"
+	"       .word %2\n"
+	"       mov %0,r3\n"
+	: "+r"(cluster)
+	: "i"(CTOP_INST_MOV2B_FLIP_R3_B1_B2_INST),
+	  "i"(CTOP_INST_MOV2B_FLIP_R3_B1_B2_LIMM)
+	: "r3");
+#endif
+
+	return cluster;
+}
+
+#define NPS_CPU_TO_CLUSTER_NUM(cpu) \
+	({ struct global_id gid; gid.value = cpu; \
+		nps_cluster_logic_to_phys(gid.cluster); })
+
+struct nps_host_reg_address {
+	union {
+		struct {
+			u32 base:8, cl_x:4, cl_y:4,
+			blkid:6, reg:8, __reserved:2;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_address_non_cl {
+	union {
+		struct {
+			u32 base:7, blkid:11, reg:12, __reserved:2;
+		};
+		u32 value;
+	};
+};
+
+static inline void *nps_host_reg_non_cl(u32 blkid, u32 reg)
+{
+	struct nps_host_reg_address_non_cl reg_address;
+
+	reg_address.value = NPS_HOST_REG_BASE;
+	reg_address.blkid = blkid;
+	reg_address.reg = reg;
+
+	return (void *)reg_address.value;
+}
+
+static inline void *nps_host_reg(u32 cpu, u32 blkid, u32 reg)
+{
+	struct nps_host_reg_address reg_address;
+	u32 cl = NPS_CPU_TO_CLUSTER_NUM(cpu);
+
+	reg_address.value = NPS_HOST_REG_BASE;
+	reg_address.cl_x  = (cl >> 2) & 0x3;
+	reg_address.cl_y  = cl & 0x3;
+	reg_address.blkid = blkid;
+	reg_address.reg   = reg;
+
+	return (void *)reg_address.value;
+}
+#endif /* __ASSEMBLY__ */
+
+#endif /* SOC_NPS_COMMON_H */
-- 
1.7.1



From noamca at mellanox.com  Mon Mar 21 07:24:31 2016
From: noamca at mellanox.com (Noam Camus)
Date: Mon, 21 Mar 2016 16:24:31 +0200
Subject: [PATCH v6 2/3] clocksource: Add NPS400 timers driver
In-Reply-To: <1458570272-23037-1-git-send-email-noamca@mellanox.com>
References: <1458570272-23037-1-git-send-email-noamca@mellanox.com>
Message-ID: <1458570272-23037-3-git-send-email-noamca@mellanox.com>

From: Noam Camus <noamc at ezchip.com>

Add internal tick generator which is shared by all cores.
Each cluster of cores view it through dedicated address.
This is used for SMP system where all CPUs synced by same
clock source.

Signed-off-by: Noam Camus <noamc at ezchip.com>
Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: John Stultz <john.stultz at linaro.org>
Acked-by: Vineet Gupta <vgupta at synopsys.com>
---
 .../bindings/timer/ezchip,nps400-timer.txt         |   15 +++
 drivers/clocksource/Kconfig                        |   10 ++
 drivers/clocksource/Makefile                       |    1 +
 drivers/clocksource/timer-nps.c                    |   98 ++++++++++++++++++++
 4 files changed, 124 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 drivers/clocksource/timer-nps.c

diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
new file mode 100644
index 0000000..c8c03d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
@@ -0,0 +1,15 @@
+NPS Network Processor
+
+Required properties:
+
+- compatible :	should be "ezchip,nps400-timer"
+
+Clocks required for compatible = "ezchip,nps400-timer":
+- clocks : Must contain a single entry describing the clock input
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer";
+	clocks = <&sysclk>;
+};
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 2eb5f0e..fa7be50 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -132,6 +132,16 @@ config CLKSRC_TI_32K
 	  This option enables support for Texas Instruments 32.768 Hz clocksource
 	  available on many OMAP-like platforms.
 
+config CLKSRC_NPS
+	bool "NPS400 clocksource driver" if COMPILE_TEST
+	depends on !PHYS_ADDR_T_64BIT
+	select CLKSRC_MMIO
+	select CLKSRC_OF if OF
+	help
+	  NPS400 clocksource support.
+	  Got 64 bit counter with update rate up to 1000MHz.
+	  This counter is accessed via couple of 32 bit memory mapped registers.
+
 config CLKSRC_STM32
 	bool "Clocksource for STM32 SoCs" if !ARCH_STM32
 	depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 56bd16e..056cffd 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o
 obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
 obj-$(CONFIG_CLKSRC_PISTACHIO)	+= time-pistachio.o
 obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-32k.o
+obj-$(CONFIG_CLKSRC_NPS)	+= timer-nps.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
new file mode 100644
index 0000000..d461089
--- /dev/null
+++ b/drivers/clocksource/timer-nps.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/cpu.h>
+#include <soc/nps/common.h>
+
+#define NPS_MSU_TICK_LOW	0xC8
+#define NPS_CLUSTER_OFFSET	8
+#define NPS_CLUSTER_NUM		16
+
+/* This array is per cluster of CPUs (Each NPS400 cluster got 256 CPUs) */
+static void *nps_msu_reg_low_addr[NPS_CLUSTER_NUM] __read_mostly;
+
+static unsigned long nps_timer_rate;
+
+static cycle_t nps_clksrc_read(struct clocksource *clksrc)
+{
+	int cluster = raw_smp_processor_id() >> NPS_CLUSTER_OFFSET;
+
+	return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]);
+}
+
+static void __init nps_setup_clocksource(struct device_node *node,
+					 struct clk *clk)
+{
+	int ret, cluster;
+
+	for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
+		nps_msu_reg_low_addr[cluster] =
+			nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
+				 NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
+
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		pr_err("Couldn't enable parent clock\n");
+		return;
+	}
+
+	nps_timer_rate = clk_get_rate(clk);
+
+	ret = clocksource_mmio_init(nps_msu_reg_low_addr, "EZnps-tick",
+				    nps_timer_rate, 301, 32, nps_clksrc_read);
+	if (ret) {
+		pr_err("Couldn't register clock source.\n");
+		clk_disable_unprepare(clk);
+	}
+}
+
+static void __init nps_timer_init(struct device_node *node)
+{
+	struct clk *clk;
+
+	clk = of_clk_get(node, 0);
+	if (IS_ERR(clk)) {
+		pr_err("Can't get timer clock.\n");
+		return;
+	}
+
+	nps_setup_clocksource(node, clk);
+}
+
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
+		       nps_timer_init);
-- 
1.7.1



From noamca at mellanox.com  Mon Mar 21 07:24:32 2016
From: noamca at mellanox.com (Noam Camus)
Date: Mon, 21 Mar 2016 16:24:32 +0200
Subject: [PATCH v6 3/3] irqchip: add nps Internal and external irqchips
In-Reply-To: <1458570272-23037-1-git-send-email-noamca@mellanox.com>
References: <1458570272-23037-1-git-send-email-noamca@mellanox.com>
Message-ID: <1458570272-23037-4-git-send-email-noamca@mellanox.com>

From: Noam Camus <noamc at ezchip.com>

Adding EZchip NPS400 support.
NPS internal interrupts are internally handled at
Multi Thread Manager (MTM) that is signaled for deactivating
an interrupt.
External interrupts is handled also at Global Interrupt
Controller (GIC) e.g. serial and network devices.

Signed-off-by: Noam Camus <noamc at ezchip.com>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Jason Cooper <jason at lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier at arm.com>
---
 .../interrupt-controller/ezchip,nps400-ic.txt      |   17 ++
 drivers/irqchip/Kconfig                            |    6 +
 drivers/irqchip/Makefile                           |    1 +
 drivers/irqchip/irq-eznps.c                        |  165 ++++++++++++++++++++
 4 files changed, 189 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
 create mode 100644 drivers/irqchip/irq-eznps.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt b/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
new file mode 100644
index 0000000..888b2b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
@@ -0,0 +1,17 @@
+EZchip NPS Interrupt Controller
+
+Required properties:
+
+- compatible : should be "ezchip,nps400-ic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 1.
+
+
+Example:
+
+intc: interrupt-controller {
+	compatible = "ezchip,nps400-ic";
+	interrupt-controller;
+	#interrupt-cells = <1>;
+};
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 4d7294e..bc5e775 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -193,3 +193,9 @@ config IRQ_MXS
 	def_bool y if MACH_ASM9260 || ARCH_MXS
 	select IRQ_DOMAIN
 	select STMP_DEVICE
+
+config EZNPS_GIC
+	bool "NPS400 Global Interrupt Manager (GIM)"
+	select IRQ_DOMAIN
+	help
+	  Support the EZchip NPS400 global interrupt controller
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 177f78f..1390142 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -55,3 +55,4 @@ obj-$(CONFIG_RENESAS_H8S_INTC)		+= irq-renesas-h8s.o
 obj-$(CONFIG_ARCH_SA1100)		+= irq-sa11x0.o
 obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
 obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
+obj-$(CONFIG_EZNPS_GIC)			+= irq-eznps.o
diff --git a/drivers/irqchip/irq-eznps.c b/drivers/irqchip/irq-eznps.c
new file mode 100644
index 0000000..97e4294
--- /dev/null
+++ b/drivers/irqchip/irq-eznps.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include <soc/nps/common.h>
+
+#define NPS_NR_CPU_IRQS 8  /* number of interrupt lines of NPS400 CPU */
+#define NPS_TIMER0_IRQ  3
+
+/*
+ * NPS400 core includes an Interrupt Controller (IC) support.
+ * All cores can deactivate level irqs at first level control
+ * at cores mesh layer called MTM.
+ * For devices out side chip e.g. uart, network there is another
+ * level called Global Interrupt Manager (GIM).
+ * This second level can control level and edge interrupt.
+ *
+ * NOTE: AUX_IENABLE and CTOP_AUX_IACK are auxiliary registers
+ * with private HW copy per CPU.
+ */
+
+static void nps400_irq_mask(struct irq_data *irqd)
+{
+	unsigned int ienb;
+	unsigned int irq = irqd_to_hwirq(irqd);
+
+	ienb = read_aux_reg(AUX_IENABLE);
+	ienb &= ~(1 << irq);
+	write_aux_reg(AUX_IENABLE, ienb);
+}
+
+static void nps400_irq_unmask(struct irq_data *irqd)
+{
+	unsigned int ienb;
+	unsigned int irq = irqd_to_hwirq(irqd);
+
+	ienb = read_aux_reg(AUX_IENABLE);
+	ienb |= (1 << irq);
+	write_aux_reg(AUX_IENABLE, ienb);
+}
+
+static void nps400_irq_eoi_global(struct irq_data *irqd)
+{
+	unsigned int __maybe_unused irq = irqd_to_hwirq(irqd);
+
+	write_aux_reg(CTOP_AUX_IACK, 1 << irq);
+
+	/* Don't ack GIC before all device access attempts are done */
+	mb();
+
+	nps_ack_gic();
+}
+
+static void nps400_irq_eoi(struct irq_data *irqd)
+{
+	unsigned int __maybe_unused irq = irqd_to_hwirq(irqd);
+
+	write_aux_reg(CTOP_AUX_IACK, 1 << irq);
+}
+
+static struct irq_chip nps400_irq_chip_fasteoi = {
+	.name		= "NPS400 IC Global",
+	.irq_mask	= nps400_irq_mask,
+	.irq_unmask	= nps400_irq_unmask,
+	.irq_eoi	= nps400_irq_eoi_global,
+};
+
+static struct irq_chip nps400_irq_chip_percpu = {
+	.name		= "NPS400 IC",
+	.irq_mask	= nps400_irq_mask,
+	.irq_unmask	= nps400_irq_unmask,
+	.irq_eoi	= nps400_irq_eoi,
+};
+
+static int nps400_irq_map(struct irq_domain *d, unsigned int virq,
+			  irq_hw_number_t hw)
+{
+	switch (hw) {
+	case NPS_TIMER0_IRQ:
+#ifdef CONFIG_SMP
+	case IPI_IRQ:
+#endif
+		irq_set_percpu_devid(virq);
+		irq_set_chip_and_handler(virq, &nps400_irq_chip_percpu,
+					 handle_percpu_devid_irq);
+		break;
+	default:
+		irq_set_chip_and_handler(virq, &nps400_irq_chip_fasteoi,
+					 handle_fasteoi_irq);
+		break;
+	}
+
+	return 0;
+}
+
+static const struct irq_domain_ops nps400_irq_ops = {
+	.xlate = irq_domain_xlate_onecell,
+	.map = nps400_irq_map,
+};
+
+static int __init nps400_of_init(struct device_node *node,
+				 struct device_node *parent)
+{
+	static struct irq_domain *nps400_root_domain;
+
+	if (parent) {
+		pr_err("DeviceTree incore ic not a root irq controller\n");
+		return -EINVAL;
+	}
+
+	nps400_root_domain = irq_domain_add_linear(node, NPS_NR_CPU_IRQS,
+						   &nps400_irq_ops, NULL);
+
+	if (!nps400_root_domain) {
+		pr_err("nps400 root irq domain not avail\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * Needed for primary domain lookup to succeed
+	 * This is a primary irqchip, and can never have a parent
+	 */
+	irq_set_default_host(nps400_root_domain);
+
+#ifdef CONFIG_SMP
+	irq_create_mapping(nps400_root_domain, IPI_IRQ);
+#endif
+
+	return 0;
+}
+IRQCHIP_DECLARE(ezchip_nps400_ic, "ezchip,nps400-ic", nps400_of_init);
-- 
1.7.1



From linux at roeck-us.net  Mon Mar 21 13:00:35 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Mon, 21 Mar 2016 13:00:35 -0700
Subject: Build error due to commit 458aa76d132dc ("mm/thp/migration: switch
 from flush_tlb_range to flush_pmd_tlb_range")
Message-ID: <20160321200035.GA31544@roeck-us.net>

Hi,

Your commit 458aa76d132dc1 ("mm/thp/migration: switch from flush_tlb_range
to flush_pmd_tlb_range") causes a build error when building
arcv2:vdk_hs38_smp_defconfig.

include/asm-generic/pgtable.h:799:45: note: in expansion of macro ?BUILD_BUG?
 #define flush_pmd_tlb_range(vma, addr, end) BUILD_BUG()
                                              ^
./arch/arc/include/asm/tlbflush.h:37:13: note:
	in expansion of macro ?flush_pmd_tlb_range?

The build triggers the newly introduced BUILD_BUG().

When building the image without the BUILD_BUG(), ie with no definition
of flush_pmd_tlb_range(), the problem is gone. This suggests that the
function is not needed for this build.

I could submit a patch to remove the BUILD_BUG(), but maybe you had a reason
for introducing it. Can you elaborate why you introduced the BUILD_BUG() ?

Thanks,
Guenter

---
Bisect log:

# bad: [ce69f4538ef366cdd8932097331549be902365f9] unicore32: mm: Add missing parameter to arch_vma_access_permitted
# good: [f7813ad5cbfd1fab2899914281b72a1ba0805c80] Merge tag 'for-linus-4.6' of git://git.code.sf.net/p/openipmi/linux-ipmi
git bisect start 'HEAD' 'f7813ad'
# good: [fb781c8e2a370d67acf7b8a8826e6f5e3ae1d7c6] clk: rockchip: add node-id for rk3036 emac hclk
git bisect good fb781c8e2a370d67acf7b8a8826e6f5e3ae1d7c6
# bad: [33b3d2e88c9efd701b6153ca4714d4aa6e9f5af0] Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
git bisect bad 33b3d2e88c9efd701b6153ca4714d4aa6e9f5af0
# bad: [d5e2d00898bdfed9586472679760fc81a2ca2d02] Merge tag 'powerpc-4.6-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
git bisect bad d5e2d00898bdfed9586472679760fc81a2ca2d02
# bad: [6b5f04b6cf8ebab9a65d9c0026c650bb2538fd0f] Merge branch 'for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
git bisect bad 6b5f04b6cf8ebab9a65d9c0026c650bb2538fd0f
# bad: [f9310b2f9a19b7f16c7b1c1558f8b649b9b933c1] sscanf: implement basic character sets
git bisect bad f9310b2f9a19b7f16c7b1c1558f8b649b9b933c1
# bad: [fec89c109f3a7737fe3a7bf0f40d1fb7709d353b] thp: rewrite freeze_page()/unfreeze_page() with generic rmap walkers
git bisect bad fec89c109f3a7737fe3a7bf0f40d1fb7709d353b
# good: [0a6b76dd23fa08c5fd7b68acdb55018a37afd4aa] mm: workingset: make shadow node shrinker memcg aware
git bisect good 0a6b76dd23fa08c5fd7b68acdb55018a37afd4aa
# bad: [fe896d1878949ea92ba547587bc3075cc688fb8f] mm: introduce page reference manipulation functions
git bisect bad fe896d1878949ea92ba547587bc3075cc688fb8f
# bad: [7eb50292d7f74ccb89155960d62b2697f2536b28] mm/Kconfig: remove redundant arch depend for memory hotplug
git bisect bad 7eb50292d7f74ccb89155960d62b2697f2536b28
# good: [39a1aa8e194ab67983de3b9d0b204ccee12e689a] mm: deduplicate memory overcommitment code
git bisect good 39a1aa8e194ab67983de3b9d0b204ccee12e689a
# bad: [458aa76d132dc1c3c60be0f0db99bcc0ce1767fc] mm/thp/migration: switch from flush_tlb_range to flush_pmd_tlb_range
git bisect bad 458aa76d132dc1c3c60be0f0db99bcc0ce1767fc
# good: [bcf6691797f425b301f629bb783b7ff2d0bcfa5a] mm, tracing: refresh __def_vmaflag_names
git bisect good bcf6691797f425b301f629bb783b7ff2d0bcfa5a
# first bad commit: [458aa76d132dc1c3c60be0f0db99bcc0ce1767fc] mm/thp/migration: switch from flush_tlb_range to flush_pmd_tlb_range


From noreply at ellerman.id.au  Mon Mar 21 18:37:01 2016
From: noreply at ellerman.id.au (noreply at ellerman.id.au)
Date: Tue, 22 Mar 2016 01:37:01 -0000
Subject: kisskb: OK linus/axs103_smp_defconfig/arcv2 Tue Mar 22, 12:35
Message-ID: <20160322013701.1.99541@37e79b8ac0a7>

OK linus/axs103_smp_defconfig/arcv2 Tue Mar 22, 12:35

http://kisskb.ellerman.id.au/kisskb/buildresult/12642460/

Commit:   Merge tag 'mmc-v4.6' of git://git.linaro.org/people/ulf.hansson/mmc
          e531cdf50a8a0fb7a4d51c06e52097bd01e9bf7c
Compiler: arc-buildroot-linux-uclibc-gcc (Buildroot 2015.08.1) 4.8.4

Possible errors
---------------

      mmc: mediatek: Change signal voltage error to dev_dbg()

Possible warnings (25)
----------------------

drivers/pci/pcie/Kconfig:62:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:68:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:75:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:62:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:68:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:75:warning: choice value used outside its choice group
<stdin>:1310:2: warning: #warning syscall preadv2 not implemented [-Wcpp]
<stdin>:1313:2: warning: #warning syscall pwritev2 not implemented [-Wcpp]
kernel/sched/core.c:3080:1: warning: control reaches end of non-void function [-Wreturn-type]
include/linux/kernel.h:754:17: warning: comparison of distinct pointer types lacks a cast [enabled by default]
block/cfq-iosched.c:3793:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
net/core/ethtool.c:295:1: warning: control reaches end of non-void function [-Wreturn-type]
net/ipv4/tcp_input.c:4273:49: warning: array subscript is above array bounds [-Warray-bounds]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
lib/cpumask.c:179:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
include/linux/sunrpc/svc_xprt.h:175:1: warning: control reaches end of non-void function [-Wreturn-type]
arch/arc/include/asm/elf.h:58:29: warning: integer overflow in expression [-Woverflow]



From aneesh.kumar at linux.vnet.ibm.com  Mon Mar 21 22:14:45 2016
From: aneesh.kumar at linux.vnet.ibm.com (Aneesh Kumar K.V)
Date: Tue, 22 Mar 2016 10:44:45 +0530
Subject: Build error due to commit 458aa76d132dc ("mm/thp/migration:
 switch from flush_tlb_range to flush_pmd_tlb_range")
In-Reply-To: <20160321200035.GA31544@roeck-us.net>
References: <20160321200035.GA31544@roeck-us.net>
Message-ID: <87k2kvt7p6.fsf@linux.vnet.ibm.com>

Guenter Roeck <linux at roeck-us.net> writes:

> [ text/plain ]
> Hi,
>
> Your commit 458aa76d132dc1 ("mm/thp/migration: switch from flush_tlb_range
> to flush_pmd_tlb_range") causes a build error when building
> arcv2:vdk_hs38_smp_defconfig.
>
> include/asm-generic/pgtable.h:799:45: note: in expansion of macro ?BUILD_BUG?
>  #define flush_pmd_tlb_range(vma, addr, end) BUILD_BUG()
>                                               ^
> ./arch/arc/include/asm/tlbflush.h:37:13: note:
> 	in expansion of macro ?flush_pmd_tlb_range?
>
> The build triggers the newly introduced BUILD_BUG().
>
> When building the image without the BUILD_BUG(), ie with no definition
> of flush_pmd_tlb_range(), the problem is gone. This suggests that the
> function is not needed for this build.
>
> I could submit a patch to remove the BUILD_BUG(), but maybe you had a reason
> for introducing it. Can you elaborate why you introduced the BUILD_BUG() ?
>

Isn't this going to be fixed by an update to ARC tree ?

http://article.gmane.org/gmane.linux.kernel.mm/148412

I also don't understand why we would hit that BUILD_BUG, if we are not
calling flush_pmd_tlb_range().

-aneesh



From evgeny.voevodin at intel.com  Mon Mar 21 23:50:35 2016
From: evgeny.voevodin at intel.com (Evgeny Voevodin)
Date: Tue, 22 Mar 2016 09:50:35 +0300
Subject: [PATCH] ARCv2: Additional trace IRQs to support locking correctness
 validator
Message-ID: <1458629435-33018-1-git-send-email-evgeny.voevodin@intel.com>

Flags should be saved in the same format in which clri instruction saves
them since they are passed directly to seti instruction over
arch_local_save_flags/arch_local_irq_restore calls.
Trace of all clri/seti assembly calls is added to support locking
correctness validator properly.
With this patch it is possible to use locking correctness framework which
did stop itself due to incomplete support. Locking tests are also became
available and work propely.

Signed-off-by: Evgeny Voevodin <evgeny.voevodin at intel.com>
---
 arch/arc/include/asm/irqflags-arcv2.h | 31 ++++++++++++++++++++++++++++++-
 arch/arc/kernel/entry-arcv2.S         | 14 +++++++++++++-
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/arch/arc/include/asm/irqflags-arcv2.h b/arch/arc/include/asm/irqflags-arcv2.h
index 37c2f75..bb17044 100644
--- a/arch/arc/include/asm/irqflags-arcv2.h
+++ b/arch/arc/include/asm/irqflags-arcv2.h
@@ -15,8 +15,13 @@
 #define STATUS_AD_BIT	19   /* Disable Align chk: core supports non-aligned */
 #define STATUS_IE_BIT	31
 
+/* status32 Bits stored on clri instruction */
+#define CLRI_STATUS_IE_BIT	4
+
 #define STATUS_AD_MASK		(1<<STATUS_AD_BIT)
 #define STATUS_IE_MASK		(1<<STATUS_IE_BIT)
+#define CLRI_STATUS_E_MASK	(0xF)
+#define CLRI_STATUS_IE_MASK	(1<<CLRI_STATUS_IE_BIT)
 
 #define AUX_USER_SP		0x00D
 #define AUX_IRQ_CTRL		0x00E
@@ -100,6 +105,9 @@ static inline long arch_local_save_flags(void)
 	:
 	: "memory");
 
+	temp = (1 << 5) |
+		((!!(temp & STATUS_IE_MASK)) << CLRI_STATUS_IE_BIT) |
+		(temp & CLRI_STATUS_E_MASK);
 	return temp;
 }
 
@@ -108,7 +116,7 @@ static inline long arch_local_save_flags(void)
  */
 static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
-	return !(flags & (STATUS_IE_MASK));
+	return !(flags & (CLRI_STATUS_IE_MASK));
 }
 
 static inline int arch_irqs_disabled(void)
@@ -128,11 +136,32 @@ static inline void arc_softirq_clear(int irq)
 
 #else
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+.macro TRACE_ASM_IRQ_DISABLE
+	bl	trace_hardirqs_off
+.endm
+
+.macro TRACE_ASM_IRQ_ENABLE
+	bl	trace_hardirqs_on
+.endm
+
+#else
+
+.macro TRACE_ASM_IRQ_DISABLE
+.endm
+
+.macro TRACE_ASM_IRQ_ENABLE
+.endm
+
+#endif
 .macro IRQ_DISABLE  scratch
 	clri
+	TRACE_ASM_IRQ_DISABLE
 .endm
 
 .macro IRQ_ENABLE  scratch
+	TRACE_ASM_IRQ_ENABLE
 	seti
 .endm
 
diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S
index c126460..24d9431 100644
--- a/arch/arc/kernel/entry-arcv2.S
+++ b/arch/arc/kernel/entry-arcv2.S
@@ -69,8 +69,11 @@ ENTRY(handle_interrupt)
 
 	clri		; To make status32.IE agree with CPU internal state
 
-	lr  r0, [ICAUSE]
+#ifdef CONFIG_TRACE_IRQFLAGS
+	TRACE_ASM_IRQ_DISABLE
+#endif
 
+	lr  r0, [ICAUSE]
 	mov   blink, ret_from_exception
 
 	b.d  arch_do_IRQ
@@ -173,6 +176,15 @@ END(EV_TLBProtV)
 	lr	r10, [AUX_IRQ_ACT]
 
 	bmsk	r11, r10, 15	; AUX_IRQ_ACT.ACTIVE
+#ifdef CONFIG_TRACE_IRQFLAGS
+	push r0
+	push r10
+	push r11
+	TRACE_ASM_IRQ_ENABLE
+	pop r11
+	pop r10
+	pop r0
+#endif
 	breq	r11, 0, .Lexcept_ret	; No intr active, ret from Exception
 
 ;####### Return from Intr #######
-- 
1.8.5.4



From linux at roeck-us.net  Tue Mar 22 04:19:57 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Tue, 22 Mar 2016 04:19:57 -0700
Subject: Build error due to commit 458aa76d132dc ("mm/thp/migration:
 switch from flush_tlb_range to flush_pmd_tlb_range")
In-Reply-To: <87k2kvt7p6.fsf@linux.vnet.ibm.com>
References: <20160321200035.GA31544@roeck-us.net>
 <87k2kvt7p6.fsf@linux.vnet.ibm.com>
Message-ID: <56F12A5D.7040904@roeck-us.net>

On 03/21/2016 10:14 PM, Aneesh Kumar K.V wrote:
> Guenter Roeck <linux at roeck-us.net> writes:
>
>> [ text/plain ]
>> Hi,
>>
>> Your commit 458aa76d132dc1 ("mm/thp/migration: switch from flush_tlb_range
>> to flush_pmd_tlb_range") causes a build error when building
>> arcv2:vdk_hs38_smp_defconfig.
>>
>> include/asm-generic/pgtable.h:799:45: note: in expansion of macro ?BUILD_BUG?
>>   #define flush_pmd_tlb_range(vma, addr, end) BUILD_BUG()
>>                                                ^
>> ./arch/arc/include/asm/tlbflush.h:37:13: note:
>> 	in expansion of macro ?flush_pmd_tlb_range?
>>
>> The build triggers the newly introduced BUILD_BUG().
>>
>> When building the image without the BUILD_BUG(), ie with no definition
>> of flush_pmd_tlb_range(), the problem is gone. This suggests that the
>> function is not needed for this build.
>>
>> I could submit a patch to remove the BUILD_BUG(), but maybe you had a reason
>> for introducing it. Can you elaborate why you introduced the BUILD_BUG() ?
>>
>
> Isn't this going to be fixed by an update to ARC tree ?
>
> http://article.gmane.org/gmane.linux.kernel.mm/148412
>

That wasn't a build error ?

> I also don't understand why we would hit that BUILD_BUG, if we are not
> calling flush_pmd_tlb_range().
>
Good question.

I'll wait for the commit window to close and report again if needed.

Guenter



From noreply at ellerman.id.au  Tue Mar 22 14:32:04 2016
From: noreply at ellerman.id.au (noreply at ellerman.id.au)
Date: Tue, 22 Mar 2016 21:32:04 -0000
Subject: kisskb: OK linus/axs103_smp_defconfig/arcv2 Wed Mar 23, 08:31
Message-ID: <20160322213204.1.39585@37e79b8ac0a7>

OK linus/axs103_smp_defconfig/arcv2 Wed Mar 23, 08:31

http://kisskb.ellerman.id.au/kisskb/buildresult/12643252/

Commit:   Merge tag 'nfs-for-4.6-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
          01cde1538e1dff4254e340f606177a870131a01f
Compiler: arc-buildroot-linux-uclibc-gcc (Buildroot 2015.08.1) 4.8.4

No errors found in log

Possible warnings (25)
----------------------

drivers/pci/pcie/Kconfig:62:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:68:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:75:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:62:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:68:warning: choice value used outside its choice group
drivers/pci/pcie/Kconfig:75:warning: choice value used outside its choice group
<stdin>:1310:2: warning: #warning syscall preadv2 not implemented [-Wcpp]
<stdin>:1313:2: warning: #warning syscall pwritev2 not implemented [-Wcpp]
kernel/sched/core.c:3080:1: warning: control reaches end of non-void function [-Wreturn-type]
include/linux/kernel.h:754:17: warning: comparison of distinct pointer types lacks a cast [enabled by default]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
arch/arc/include/asm/elf.h:58:29: warning: integer overflow in expression [-Woverflow]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
block/cfq-iosched.c:3793:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
lib/cpumask.c:179:1: warning: control reaches end of non-void function [-Wreturn-type]
net/core/ethtool.c:295:1: warning: control reaches end of non-void function [-Wreturn-type]
fs/ext4/ext4_jbd2.h:409:1: warning: control reaches end of non-void function [-Wreturn-type]
include/linux/sunrpc/svc_xprt.h:175:1: warning: control reaches end of non-void function [-Wreturn-type]
net/ipv4/tcp_input.c:4273:49: warning: array subscript is above array bounds [-Warray-bounds]



From evgeny.voevodin at intel.com  Wed Mar 23 02:26:52 2016
From: evgeny.voevodin at intel.com (Evgeny Voevodin)
Date: Wed, 23 Mar 2016 12:26:52 +0300
Subject: [PATCH] ARCv2: Additional trace IRQs to support locking correctness
 validator
Message-ID: <1458725212-21215-1-git-send-email-evgeny.voevodin@intel.com>

Flags should be saved in the same format in which clri instruction saves
them since they are passed directly to seti instruction over
arch_local_save_flags/arch_local_irq_restore calls.
Trace of all clri/seti assembly calls is added to support locking
correctness validator properly.
With this patch it is possible to use locking correctness framework which
did stop itself due to incomplete support. Locking tests are also became
available and work propely.

Signed-off-by: Evgeny Voevodin <evgeny.voevodin at intel.com>
---
 arch/arc/include/asm/irqflags-arcv2.h | 31 ++++++++++++++++++++++++++++++-
 arch/arc/kernel/entry-arcv2.S         | 14 +++++++++++++-
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/arch/arc/include/asm/irqflags-arcv2.h b/arch/arc/include/asm/irqflags-arcv2.h
index 37c2f75..bb17044 100644
--- a/arch/arc/include/asm/irqflags-arcv2.h
+++ b/arch/arc/include/asm/irqflags-arcv2.h
@@ -15,8 +15,13 @@
 #define STATUS_AD_BIT	19   /* Disable Align chk: core supports non-aligned */
 #define STATUS_IE_BIT	31
 
+/* status32 Bits stored on clri instruction */
+#define CLRI_STATUS_IE_BIT	4
+
 #define STATUS_AD_MASK		(1<<STATUS_AD_BIT)
 #define STATUS_IE_MASK		(1<<STATUS_IE_BIT)
+#define CLRI_STATUS_E_MASK	(0xF)
+#define CLRI_STATUS_IE_MASK	(1<<CLRI_STATUS_IE_BIT)
 
 #define AUX_USER_SP		0x00D
 #define AUX_IRQ_CTRL		0x00E
@@ -100,6 +105,9 @@ static inline long arch_local_save_flags(void)
 	:
 	: "memory");
 
+	temp = (1 << 5) |
+		((!!(temp & STATUS_IE_MASK)) << CLRI_STATUS_IE_BIT) |
+		(temp & CLRI_STATUS_E_MASK);
 	return temp;
 }
 
@@ -108,7 +116,7 @@ static inline long arch_local_save_flags(void)
  */
 static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
-	return !(flags & (STATUS_IE_MASK));
+	return !(flags & (CLRI_STATUS_IE_MASK));
 }
 
 static inline int arch_irqs_disabled(void)
@@ -128,11 +136,32 @@ static inline void arc_softirq_clear(int irq)
 
 #else
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+.macro TRACE_ASM_IRQ_DISABLE
+	bl	trace_hardirqs_off
+.endm
+
+.macro TRACE_ASM_IRQ_ENABLE
+	bl	trace_hardirqs_on
+.endm
+
+#else
+
+.macro TRACE_ASM_IRQ_DISABLE
+.endm
+
+.macro TRACE_ASM_IRQ_ENABLE
+.endm
+
+#endif
 .macro IRQ_DISABLE  scratch
 	clri
+	TRACE_ASM_IRQ_DISABLE
 .endm
 
 .macro IRQ_ENABLE  scratch
+	TRACE_ASM_IRQ_ENABLE
 	seti
 .endm
 
diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S
index c126460..24d9431 100644
--- a/arch/arc/kernel/entry-arcv2.S
+++ b/arch/arc/kernel/entry-arcv2.S
@@ -69,8 +69,11 @@ ENTRY(handle_interrupt)
 
 	clri		; To make status32.IE agree with CPU internal state
 
-	lr  r0, [ICAUSE]
+#ifdef CONFIG_TRACE_IRQFLAGS
+	TRACE_ASM_IRQ_DISABLE
+#endif
 
+	lr  r0, [ICAUSE]
 	mov   blink, ret_from_exception
 
 	b.d  arch_do_IRQ
@@ -173,6 +176,15 @@ END(EV_TLBProtV)
 	lr	r10, [AUX_IRQ_ACT]
 
 	bmsk	r11, r10, 15	; AUX_IRQ_ACT.ACTIVE
+#ifdef CONFIG_TRACE_IRQFLAGS
+	push r0
+	push r10
+	push r11
+	TRACE_ASM_IRQ_ENABLE
+	pop r11
+	pop r10
+	pop r0
+#endif
 	breq	r11, 0, .Lexcept_ret	; No intr active, ret from Exception
 
 ;####### Return from Intr #######
-- 
1.8.5.4


--------------------------------------------------------------------
Joint Stock Company Intel A/O
Registered legal address: Krylatsky Hills Business Park,
17 Krylatskaya Str., Bldg 4, Moscow 121614,
Russian Federation

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.



From Alexey.Brodkin at synopsys.com  Thu Mar 24 07:57:52 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 24 Mar 2016 14:57:52 +0000
Subject: [PATCH 2/4 v3] drm: Add DT bindings documentation for ARC PGU
 display controller
In-Reply-To: <20160321130419.GA23913@rob-hp-laptop>
References: <1457710959-9562-1-git-send-email-abrodkin@synopsys.com>
 <1457710959-9562-3-git-send-email-abrodkin@synopsys.com>
 <20160321130419.GA23913@rob-hp-laptop>
Message-ID: <1458831472.12765.8.camel@synopsys.com>

Hi Rob,

On Mon, 2016-03-21 at 08:04 -0500, Rob Herring wrote:
> On Fri, Mar 11, 2016 at 06:42:37PM +0300, Alexey Brodkin wrote:
> > 
> > This add DT bindings documentation for ARC PGU display controller.
> > 
> > Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
> > Cc: Rob Herring <robh+dt at kernel.org>
> > Cc: Pawel Moll <pawel.moll at arm.com>
> > Cc: Mark Rutland <mark.rutland at arm.com>
> > Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
> > Cc: Kumar Gala <galak at codeaurora.org>
> > Cc: David Airlie <airlied at linux.ie>
> > Cc: dri-devel at lists.freedesktop.org
> > Cc: devicetree at vger.kernel.org
> > Cc: linux-snps-arc at lists.infradead.org
> > ---
> > 
> > Changes v2 -> v3:
> > ?* Reverted back to initial larger version of example
> > ???with minor fixes (thanks Rob for spotting those).
> > 
> > Changes v1 -> v2:
> > ?* Removed everything except PGU node itself.
> > 
> > ?.../devicetree/bindings/display/snps,arcpgu.txt????| 72 ++++++++++++++++++++++
> > ?1 file changed, 72 insertions(+)
> > ?create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> > b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> > new file mode 100644
> > index 0000000..b130924
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> > @@ -0,0 +1,72 @@
> > +ARC PGU
> > +
> > +This is a display controller found on several development boards produced
> > +by Synopsys. The ARC PGU is an RGB streamer that reads the data from a
> > +framebuffer and sends it to a single digital encoder (usually HDMI).
> > +
> > +Required properties:
> > +??- compatible: "snps,arcpgu"
> > +??- reg: Physical base address and length of the controller's registers.
> > +??- clocks: A list of phandle + clock-specifier pairs, one for each
> > +????entry in 'clock-names'.
> > +??- clock-names: A list of clock names. For ARC PGU it should contain:
> > +??????- "pxlclk" for the clock feeding the output PLL of the controller.
> > +??- encoder-slave: Phandle of encoder chip.
> Drop this as discussed.

Ok I'll do that.
But what about my example below?
Do I need to remove encoder node from it as well?

> > 
> > +
> > +Required sub-nodes:
> > +??- port: The PGU connection to an encoder chip.
> > +
> > +Example:
> > +
> > +/ {
> > +	...
> > +
> > +	pgu at XXXXXXXX {
> > +		compatible = "snps,arcpgu";
> > +		reg = <0xXXXXXXXX 0x400>;
> > +		clocks = <&clock_node>;
> > +		clock-names = "pxlclk";
> > +		encoder-slave = <&encoder_node>;
> > +
> > +		port {
> > +			pgu_output: endpoint {
> > +				remote-endpoint = <&hdmi_enc_input>;
> > +			};
> > +		};
> > +	};
> > +
> > +	/* HDMI encoder on I2C bus */
> > +	i2c at XXXXXXXX {
> > +		compatible = "...";
> > +
> > +		encoder_node:encoder_node at 0xXX{
> Don't use underscores in node names. Just "hdmi at xx"

Ok still I may keep label "encoder_node" here, right?

-Alexey

From Alexey.Brodkin at synopsys.com  Thu Mar 24 09:48:31 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 24 Mar 2016 19:48:31 +0300
Subject: [PATCH 0/5 v4] drm: Add support of ARC PGU display controller
Message-ID: <1458838116-24954-1-git-send-email-abrodkin@synopsys.com>

This series add support of ARC PGU display controller.
ARC PGU is a quite simple byte streamer that gets data from the framebuffer
and pushes it to hte connected encoder (DP or HDMI).

It was tested on ARC SDP boards (axs101/103 in particular).

Note following series that introduces
drm_connector_register_all()/drm_connector_unregister_all() is a prerequisite
now: https://lkml.org/lkml/2016/3/23/61

Changes v3 -> v4:
 * Main driver author is now set properly (thanks Carlos for all your efforts)
 * Implemented correct hsync and vsync setup (thanks Jose)
 * Dummy call-backs were removed (as suggested by Daniel)
 * Obsolete load()/unload() call-backs were removed (as suggested by Daniel)
 * With above in mind we were able to adopt recently introduced
   drm_connector_register_all()/drm_connector_unregister_all()
 * Implemented setup of properties (uncached) for FB user-pages
 * Minor clean-up in DT binding docs and axs10x_mb.dtsi

Changes v2 -> v3:
 * Improved failure path if arcpgu_connector wasn't allocated.
 * Fixed driver building as module.
 * Implemented uncached mapping of user-space FB pages.
 * Again updated DT bindings docs.

Changes v1 -> v2:
 * Clean-up of DT bindings documentation.
 * Added missing "pxlclk" clock in axs10x_mb.dtsi.

Cc: David Airlie <airlied at linux.ie>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: linux-snps-arc at lists.infradead.org
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Vineet Gupta <vgupta at synopsys.com>
Cc: Jose Abreu <joabreu at synopsys.com>
Cc: Carlos Palminha <palminha at synopsys.com>

Alexey Brodkin (4):
  drm: Add DT bindings documentation for ARC PGU display controller
  MAINTAINERS: Add maintainer for ARC PGU display controller
  arc: Add our own implementation of fb_pgprotect()
  arc: axs10x - add support of ARC PGU

Carlos Palminha (1):
  drm: Add support of ARC PGU display controller

 .../devicetree/bindings/display/snps,arcpgu.txt    |  71 ++++++
 MAINTAINERS                                        |   6 +
 arch/arc/boot/dts/axs10x_mb.dtsi                   |  61 +++++
 arch/arc/include/asm/fb.h                          |  19 ++
 drivers/gpu/drm/Kconfig                            |   2 +
 drivers/gpu/drm/Makefile                           |   1 +
 drivers/gpu/drm/arc/Kconfig                        |  10 +
 drivers/gpu/drm/arc/Makefile                       |   2 +
 drivers/gpu/drm/arc/arcpgu.h                       |  50 ++++
 drivers/gpu/drm/arc/arcpgu_crtc.c                  | 257 +++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_drv.c                   | 282 +++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_hdmi.c                  | 201 +++++++++++++++
 drivers/gpu/drm/arc/arcpgu_regs.h                  |  40 +++
 13 files changed, 1002 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt
 create mode 100644 arch/arc/include/asm/fb.h
 create mode 100644 drivers/gpu/drm/arc/Kconfig
 create mode 100644 drivers/gpu/drm/arc/Makefile
 create mode 100644 drivers/gpu/drm/arc/arcpgu.h
 create mode 100644 drivers/gpu/drm/arc/arcpgu_crtc.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_drv.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_hdmi.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_regs.h

-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Thu Mar 24 09:48:35 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 24 Mar 2016 19:48:35 +0300
Subject: [PATCH 4/5 v4] arc: Add our own implementation of fb_pgprotect()
In-Reply-To: <1458838116-24954-1-git-send-email-abrodkin@synopsys.com>
References: <1458838116-24954-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1458838116-24954-5-git-send-email-abrodkin@synopsys.com>

During mmaping of frame-buffer pages to user-space
fb_protect() is called to set proper page settings.

In case of ARC we need to mark pages that are mmaped to
user as uncached because of 2 reasons:
 * Huge amount of data if passing through data cache will
   thrash cache a lot making cache almost useless for other
   less traffic hungry processes.
 * Data written by user in FB will be immediately available for
   hardware (such as PGU etc) without requirements to flush data
   cache regularly.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: linux-snps-arc at lists.infradead.org
---

Changes v3 -> v4:
 * This change was introduced only in v4.

 arch/arc/include/asm/fb.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 arch/arc/include/asm/fb.h

diff --git a/arch/arc/include/asm/fb.h b/arch/arc/include/asm/fb.h
new file mode 100644
index 0000000..bd3f68c
--- /dev/null
+++ b/arch/arc/include/asm/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Thu Mar 24 09:48:33 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 24 Mar 2016 19:48:33 +0300
Subject: [PATCH 2/5 v4] drm: Add DT bindings documentation for ARC PGU display
 controller
In-Reply-To: <1458838116-24954-1-git-send-email-abrodkin@synopsys.com>
References: <1458838116-24954-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1458838116-24954-3-git-send-email-abrodkin@synopsys.com>

This add DT bindings documentation for ARC PGU display controller.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: devicetree at vger.kernel.org
Cc: linux-snps-arc at lists.infradead.org
---

Changes v3 -> v4: (addressing Rob's comments)
 * Removed "encoder-slave" from required properties
 * Removed "0x" from node names

Changes v2 -> v3:
 * Reverted back to initial larger version of example
   with minor fixes (thanks Rob for spotting those).

Changes v1 -> v2:
 * Removed everything except PGU node itself.

 .../devicetree/bindings/display/snps,arcpgu.txt    | 71 ++++++++++++++++++++++
 1 file changed, 71 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt

diff --git a/Documentation/devicetree/bindings/display/snps,arcpgu.txt b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
new file mode 100644
index 0000000..b126577
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
@@ -0,0 +1,71 @@
+ARC PGU
+
+This is a display controller found on several development boards produced
+by Synopsys. The ARC PGU is an RGB streamer that reads the data from a
+framebuffer and sends it to a single digital encoder (usually HDMI).
+
+Required properties:
+  - compatible: "snps,arcpgu"
+  - reg: Physical base address and length of the controller's registers.
+  - clocks: A list of phandle + clock-specifier pairs, one for each
+    entry in 'clock-names'.
+  - clock-names: A list of clock names. For ARC PGU it should contain:
+      - "pxlclk" for the clock feeding the output PLL of the controller.
+
+Required sub-nodes:
+  - port: The PGU connection to an encoder chip.
+
+Example:
+
+/ {
+	...
+
+	pgu at XXXXXXXX {
+		compatible = "snps,arcpgu";
+		reg = <0xXXXXXXXX 0x400>;
+		clocks = <&clock_node>;
+		clock-names = "pxlclk";
+		encoder-slave = <&encoder_node>;
+
+		port {
+			pgu_output: endpoint {
+				remote-endpoint = <&hdmi_enc_input>;
+			};
+		};
+	};
+
+	/* HDMI encoder on I2C bus */
+	i2c at XXXXXXXX {
+		compatible = "...";
+
+		encoder_node:hdmi at XX{
+			compatible="...";
+
+			ports {
+				port at 0 {
+					reg = <0>;
+					hdmi_enc_input:endpoint {
+						remote-endpoint = <&pgu_output>;
+					};
+				};
+
+				port at 1 {
+					reg = <1>;
+					hdmi_enc_output:endpoint {
+						remote-endpoint = <&hdmi_connector_in>;
+					};
+				};
+			};
+		};
+	}
+
+	hdmi0: connector {
+		compatible = "hdmi-connector";
+
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&hdmi_enc_output>;
+			};
+		};
+	};
+};
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Thu Mar 24 09:48:34 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 24 Mar 2016 19:48:34 +0300
Subject: [PATCH 3/5 v4] MAINTAINERS: Add maintainer for ARC PGU display
 controller
In-Reply-To: <1458838116-24954-1-git-send-email-abrodkin@synopsys.com>
References: <1458838116-24954-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1458838116-24954-4-git-send-email-abrodkin@synopsys.com>

This updates MAINTEINERS file with information about maintainer of
ARC PGU display controller driver.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: linux-snps-arc at lists.infradead.org
---

No changes v3 -> v4.

No changes v2 -> v3.

No changes v1 -> v2.

 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ea1d1de..0dcba67 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -827,6 +827,12 @@ S:	Maintained
 F:	drivers/net/arcnet/
 F:	include/uapi/linux/if_arcnet.h
 
+ARC PGU DRM DRIVER
+M:	Alexey Brodkin <abrodkin at synopsys.com>
+S:	Supported
+F:	drivers/gpu/drm/arc/
+F:	Documentation/devicetree/bindings/display/snps,arcpgu.txt
+
 ARM HDLCD DRM DRIVER
 M:	Liviu Dudau <liviu.dudau at arm.com>
 S:	Supported
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Thu Mar 24 09:48:36 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 24 Mar 2016 19:48:36 +0300
Subject: [PATCH 5/5 v4] arc: axs10x - add support of ARC PGU
In-Reply-To: <1458838116-24954-1-git-send-email-abrodkin@synopsys.com>
References: <1458838116-24954-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1458838116-24954-6-git-send-email-abrodkin@synopsys.com>

Synopsys DesignWare ARC SDP boards sport ARC SDP display
controller attached to ADV7511 HDMI encoder.

That change adds desctiption of both ARC PGU and ADV7511 in
ARC SDP'd base-board Device Tree.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: Vineet Gupta <vgupta at synopsys.com>
Cc: devicetree at vger.kernel.org
Cc: linux-snps-arc at lists.infradead.org
---

Changes v3 -> v4:
 * Removed "0x" from node names (as suggested by Rob)

No changes v2 -> v3.

Changes v1 -> v2:
 * Added missing "pxlclk" clock in axs10x_mb.dtsi

 arch/arc/boot/dts/axs10x_mb.dtsi | 61 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
index 44a578c..8fee596 100644
--- a/arch/arc/boot/dts/axs10x_mb.dtsi
+++ b/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -34,6 +34,12 @@
 				clock-frequency = <50000000>;
 				#clock-cells = <0>;
 			};
+
+			pguclk: pguclk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <74440000>;
+			};
 		};
 
 		ethernet at 0x18000 {
@@ -147,6 +153,37 @@
 			clocks = <&i2cclk>;
 			interrupts = <16>;
 
+			adv7511:adv7511 at 39{
+				compatible="adi,adv7511";
+				reg = <0x39>;
+				interrupts = <23>;
+				adi,input-depth = <8>;
+				adi,input-colorspace = "rgb";
+				adi,input-clock = "1x";
+				adi,clock-delay = <0x03>;
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					/* RGB/YUV input */
+					port at 0 {
+						reg = <0>;
+						adv7511_input:endpoint {
+						remote-endpoint = <&pgu_output>;
+						};
+					};
+
+					/* HDMI output */
+					port at 1 {
+						reg = <1>;
+						adv7511_output: endpoint {
+							remote-endpoint = <&hdmi_connector_in>;
+						};
+					};
+				};
+			};
+
 			eeprom at 0x54{
 				compatible = "24c01";
 				reg = <0x54>;
@@ -160,6 +197,16 @@
 			};
 		};
 
+		hdmi0: connector {
+			compatible = "hdmi-connector";
+			type = "a";
+			port {
+				hdmi_connector_in: endpoint {
+					remote-endpoint = <&adv7511_output>;
+				};
+			};
+		};
+
 		gpio0:gpio at 13000 {
 			compatible = "snps,dw-apb-gpio";
 			reg = <0x13000 0x1000>;
@@ -221,5 +268,19 @@
 				reg = <2>;
 			};
 		};
+
+		pgu at 17000 {
+			compatible = "snps,arcpgu";
+			reg = <0x17000 0x400>;
+			encoder-slave = <&adv7511>;
+			clocks = <&pguclk>;
+			clock-names = "pxlclk";
+
+			port {
+				pgu_output: endpoint {
+					remote-endpoint = <&adv7511_input>;
+				};
+			};
+		};
 	};
 };
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Thu Mar 24 09:48:32 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 24 Mar 2016 19:48:32 +0300
Subject: [PATCH 1/5 v4] drm: Add support of ARC PGU display controller
In-Reply-To: <1458838116-24954-1-git-send-email-abrodkin@synopsys.com>
References: <1458838116-24954-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1458838116-24954-2-git-send-email-abrodkin@synopsys.com>

From: Carlos Palminha <palminha at synopsys.com>

ARC PGU could be found on some development boards from Synopsys.
This is a simple byte streamer that reads data from a framebuffer
and sends data to the single encoder.

Signed-off-by: Carlos Palminha <palminha at synopsys.com>
Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: David Airlie <airlied at linux.ie>
Cc: dri-devel at lists.freedesktop.org
Cc: linux-snps-arc at lists.infradead.org
---

Note following series that introduces
drm_connector_register_all()/drm_connector_unregister_all() is a prerequisite
now: https://lkml.org/lkml/2016/3/23/61

Changes v3 -> v4:
 * The driver author is now set properly (thanks Carlos for all your efforts)
 * Implemented correct hsync and vsync setup (thanks Jose)
 * Dummy call-backs were removed (as suggested by Daniel)
 * Obsolete load()/unload() call-backs were removed (as suggested by Daniel)
 * With above in mind we were able to adopt recently introduced
   drm_connector_register_all()/drm_connector_unregister_all()

Changes v2 -> v3:
 * Improved failure path if arcpgu_connector wasn't allocated (thanks Jose).
 * Fixed driver building as module (reported by 0-DAY kernel test infrastruct.)
 * Implemented uncached mapping of user-space FB pages.

No changes v1 -> v2.

 drivers/gpu/drm/Kconfig           |   2 +
 drivers/gpu/drm/Makefile          |   1 +
 drivers/gpu/drm/arc/Kconfig       |  10 ++
 drivers/gpu/drm/arc/Makefile      |   2 +
 drivers/gpu/drm/arc/arcpgu.h      |  50 +++++++
 drivers/gpu/drm/arc/arcpgu_crtc.c | 257 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_drv.c  | 282 ++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_hdmi.c | 201 +++++++++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_regs.h |  40 ++++++
 9 files changed, 845 insertions(+)
 create mode 100644 drivers/gpu/drm/arc/Kconfig
 create mode 100644 drivers/gpu/drm/arc/Makefile
 create mode 100644 drivers/gpu/drm/arc/arcpgu.h
 create mode 100644 drivers/gpu/drm/arc/arcpgu_crtc.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_drv.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_hdmi.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_regs.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index f2a74d0..9e4f2f1 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -281,3 +281,5 @@ source "drivers/gpu/drm/imx/Kconfig"
 source "drivers/gpu/drm/vc4/Kconfig"
 
 source "drivers/gpu/drm/etnaviv/Kconfig"
+
+source "drivers/gpu/drm/arc/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 6eb94fc..c338d04 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -78,3 +78,4 @@ obj-y			+= panel/
 obj-y			+= bridge/
 obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
 obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
+obj-$(CONFIG_DRM_ARCPGU)+= arc/
diff --git a/drivers/gpu/drm/arc/Kconfig b/drivers/gpu/drm/arc/Kconfig
new file mode 100644
index 0000000..f9a13b6
--- /dev/null
+++ b/drivers/gpu/drm/arc/Kconfig
@@ -0,0 +1,10 @@
+config DRM_ARCPGU
+	tristate "ARC PGU"
+	depends on DRM && OF
+	select DRM_KMS_CMA_HELPER
+	select DRM_KMS_FB_HELPER
+	select DRM_KMS_HELPER
+	help
+	  Choose this option if you have an ARC PGU controller.
+
+	  If M is selected the module will be called arcpgu.
diff --git a/drivers/gpu/drm/arc/Makefile b/drivers/gpu/drm/arc/Makefile
new file mode 100644
index 0000000..d48fda7
--- /dev/null
+++ b/drivers/gpu/drm/arc/Makefile
@@ -0,0 +1,2 @@
+arcpgu-y := arcpgu_crtc.o arcpgu_hdmi.o arcpgu_drv.o
+obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o
diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h
new file mode 100644
index 0000000..86574b6
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu.h
@@ -0,0 +1,50 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ARCPGU_H_
+#define _ARCPGU_H_
+
+struct arcpgu_drm_private {
+	void __iomem		*regs;
+	struct clk		*clk;
+	struct drm_fbdev_cma	*fbdev;
+	struct drm_framebuffer	*fb;
+	struct list_head	event_list;
+	struct drm_crtc		crtc;
+	struct drm_plane	*plane;
+};
+
+#define crtc_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, crtc)
+
+static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu,
+				 unsigned int reg, u32 value)
+{
+	iowrite32(value, arcpgu->regs + reg);
+}
+
+static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu,
+			       unsigned int reg)
+{
+	return ioread32(arcpgu->regs + reg);
+}
+
+int arc_pgu_setup_crtc(struct drm_device *dev);
+int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np);
+struct drm_fbdev_cma *arcpgu_fbdev_cma_init(struct drm_device *dev,
+	unsigned int preferred_bpp, unsigned int num_crtc,
+	unsigned int max_conn_count);
+
+#endif
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
new file mode 100644
index 0000000..92f8bef
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
@@ -0,0 +1,257 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <linux/clk.h>
+#include <linux/platform_data/simplefb.h>
+
+#include "arcpgu.h"
+#include "arcpgu_regs.h"
+
+#define ENCODE_PGU_XY(x, y)	((((x) - 1) << 16) | ((y) - 1))
+
+static struct simplefb_format supported_formats[] = {
+	{ "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0}, DRM_FORMAT_RGB565 },
+	{ "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 },
+};
+
+static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	uint32_t pixel_format = crtc->primary->state->fb->pixel_format;
+	struct simplefb_format *format = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
+		if (supported_formats[i].fourcc == pixel_format)
+			format = &supported_formats[i];
+	}
+
+	if (WARN_ON(!format))
+		return;
+
+	if (format->fourcc == DRM_FORMAT_RGB888)
+		arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+			      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) |
+					   ARCPGU_MODE_RGB888_MASK);
+
+}
+
+static const struct drm_crtc_funcs arc_pgu_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 void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	struct drm_display_mode *m = &crtc->state->adjusted_mode;
+	u32 val;
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_FMT,
+		      ENCODE_PGU_XY(m->crtc_htotal, m->crtc_vtotal));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_HSYNC,
+		      ENCODE_PGU_XY(m->crtc_hsync_start - m->crtc_hdisplay,
+				    m->crtc_hsync_end - m->crtc_hdisplay));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_VSYNC,
+		      ENCODE_PGU_XY(m->crtc_vsync_start - m->crtc_vdisplay,
+				    m->crtc_vsync_end - m->crtc_vdisplay));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_ACTIVE,
+		      ENCODE_PGU_XY(m->crtc_hblank_end - m->crtc_hblank_start,
+				    m->crtc_vblank_end - m->crtc_vblank_start));
+
+	val = arc_pgu_read(arcpgu, ARCPGU_REG_CTRL);
+
+	if (m->flags & DRM_MODE_FLAG_PVSYNC)
+		val |= ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST;
+	else
+		val &= ~(ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST);
+
+	if (m->flags & DRM_MODE_FLAG_PHSYNC)
+		val |= ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST;
+	else
+		val &= ~(ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST);
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, val);
+	arc_pgu_write(arcpgu, ARCPGU_REG_STRIDE, 0);
+	arc_pgu_write(arcpgu, ARCPGU_REG_START_SET, 1);
+
+	arc_pgu_set_pxl_fmt(crtc);
+
+	clk_set_rate(arcpgu->clk, m->crtc_clock * 1000);
+}
+
+static void arc_pgu_crtc_enable(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+
+	clk_prepare_enable(arcpgu->clk);
+	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+		      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) |
+		      ARCPGU_CTRL_ENABLE_MASK);
+}
+
+static void arc_pgu_crtc_disable(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+
+	if (!crtc->primary->fb)
+		return;
+
+	clk_disable_unprepare(arcpgu->clk);
+	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+			      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) &
+			      ~ARCPGU_CTRL_ENABLE_MASK);
+}
+
+static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc,
+				     struct drm_crtc_state *state)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	struct drm_display_mode *mode = &state->adjusted_mode;
+	long rate, clk_rate = mode->clock * 1000;
+
+	rate = clk_round_rate(arcpgu->clk, clk_rate);
+	if (rate != clk_rate)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
+				      struct drm_crtc_state *state)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	unsigned long flags;
+
+	if (crtc->state->event) {
+		struct drm_pending_vblank_event *event = crtc->state->event;
+
+		crtc->state->event = NULL;
+		event->pipe = drm_crtc_index(crtc);
+
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+		spin_lock_irqsave(&crtc->dev->event_lock, flags);
+		list_add_tail(&event->base.link, &arcpgu->event_list);
+		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+	}
+}
+
+static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
+	.mode_set	= drm_helper_crtc_mode_set,
+	.mode_set_base	= drm_helper_crtc_mode_set_base,
+	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
+	.enable		= arc_pgu_crtc_enable,
+	.disable	= arc_pgu_crtc_disable,
+	.prepare	= arc_pgu_crtc_disable,
+	.commit		= arc_pgu_crtc_enable,
+	.atomic_check	= arc_pgu_crtc_atomic_check,
+	.atomic_begin	= arc_pgu_crtc_atomic_begin,
+};
+
+static void arc_pgu_plane_atomic_update(struct drm_plane *plane,
+					struct drm_plane_state *state)
+{
+	struct arcpgu_drm_private *arcpgu;
+	struct drm_gem_cma_object *gem;
+
+	if (!plane->state->crtc || !plane->state->fb)
+		return;
+
+	arcpgu = crtc_to_arcpgu_priv(plane->state->crtc);
+	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
+	arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr);
+}
+
+static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = {
+	.prepare_fb = NULL,
+	.cleanup_fb = NULL,
+	.atomic_update = arc_pgu_plane_atomic_update,
+};
+
+static void arc_pgu_plane_destroy(struct drm_plane *plane)
+{
+	drm_plane_helper_disable(plane);
+	drm_plane_cleanup(plane);
+}
+
+static const struct drm_plane_funcs arc_pgu_plane_funcs = {
+	.update_plane		= drm_atomic_helper_update_plane,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.destroy		= arc_pgu_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 struct drm_plane *arc_pgu_plane_init(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_plane *plane = NULL;
+	u32 formats[ARRAY_SIZE(supported_formats)], i;
+	int ret;
+
+	plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
+	if (!plane)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(supported_formats); i++)
+		formats[i] = supported_formats[i].fourcc;
+
+	ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs,
+				       formats, ARRAY_SIZE(formats),
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_plane_helper_add(plane, &arc_pgu_plane_helper_funcs);
+	arcpgu->plane = plane;
+
+	return plane;
+}
+
+int arc_pgu_setup_crtc(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_plane *primary;
+	int ret;
+
+	primary = arc_pgu_plane_init(drm);
+	if (IS_ERR(primary))
+		return PTR_ERR(primary);
+
+	ret = drm_crtc_init_with_planes(drm, &arcpgu->crtc, primary, NULL,
+					&arc_pgu_crtc_funcs, NULL);
+	if (ret) {
+		arc_pgu_plane_destroy(primary);
+		return ret;
+	}
+
+	drm_crtc_helper_add(&arcpgu->crtc, &arc_pgu_crtc_helper_funcs);
+	return 0;
+}
diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c
new file mode 100644
index 0000000..5b35e5db
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_drv.c
@@ -0,0 +1,282 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "arcpgu.h"
+#include "arcpgu_regs.h"
+
+static void arcpgu_fb_output_poll_changed(struct drm_device *dev)
+{
+	struct arcpgu_drm_private *arcpgu = dev->dev_private;
+
+	if (arcpgu->fbdev)
+		drm_fbdev_cma_hotplug_event(arcpgu->fbdev);
+}
+
+static int arcpgu_atomic_commit(struct drm_device *dev,
+				    struct drm_atomic_state *state, bool async)
+{
+	return drm_atomic_helper_commit(dev, state, false);
+}
+
+static struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = {
+	.fb_create  = drm_fb_cma_create,
+	.output_poll_changed = arcpgu_fb_output_poll_changed,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = arcpgu_atomic_commit,
+};
+
+static void arcpgu_setup_mode_config(struct drm_device *drm)
+{
+	drm_mode_config_init(drm);
+	drm->mode_config.min_width = 0;
+	drm->mode_config.min_height = 0;
+	drm->mode_config.max_width = 1920;
+	drm->mode_config.max_height = 1080;
+	drm->mode_config.funcs = &arcpgu_drm_modecfg_funcs;
+}
+
+int arcpgu_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	int ret;
+
+	ret = drm_gem_mmap(filp, vma);
+	if (ret)
+		return ret;
+
+	vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags));
+	return 0;
+}
+
+static const struct file_operations arcpgu_drm_ops = {
+	.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 = no_llseek,
+	.mmap = arcpgu_gem_mmap,
+};
+
+static void arcpgu_preclose(struct drm_device *drm, struct drm_file *file)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_pending_vblank_event *e, *t;
+	unsigned long flags;
+
+	spin_lock_irqsave(&drm->event_lock, flags);
+	list_for_each_entry_safe(e, t, &arcpgu->event_list, base.link) {
+		if (e->base.file_priv != file)
+			continue;
+		list_del(&e->base.link);
+		e->base.destroy(&e->base);
+	}
+	spin_unlock_irqrestore(&drm->event_lock, flags);
+}
+
+static void arcpgu_lastclose(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+
+	drm_fbdev_cma_restore_mode(arcpgu->fbdev);
+}
+
+static int arcpgu_load(struct drm_device *drm)
+{
+	struct platform_device *pdev = to_platform_device(drm->dev);
+	struct arcpgu_drm_private *arcpgu;
+	struct device_node *encoder_node;
+	struct resource *res;
+	int ret;
+
+	arcpgu = devm_kzalloc(&pdev->dev, sizeof(*arcpgu), GFP_KERNEL);
+	if (arcpgu == NULL)
+		return -ENOMEM;
+
+	drm->dev_private = arcpgu;
+
+	arcpgu->clk = devm_clk_get(drm->dev, "pxlclk");
+	if (IS_ERR(arcpgu->clk))
+		return PTR_ERR(arcpgu->clk);
+
+	INIT_LIST_HEAD(&arcpgu->event_list);
+
+	arcpgu_setup_mode_config(drm);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	arcpgu->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(arcpgu->regs)) {
+		dev_err(drm->dev, "Could not remap IO mem\n");
+		return PTR_ERR(arcpgu->regs);
+	}
+
+	dev_info(drm->dev, "arc_pgu ID: 0x%x\n",
+		 arc_pgu_read(arcpgu, ARCPGU_REG_ID));
+
+	if (dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32)))
+		return -ENODEV;
+
+	if (arc_pgu_setup_crtc(drm) < 0)
+		return -ENODEV;
+
+	/* find the encoder node and initialize it */
+	encoder_node = of_parse_phandle(drm->dev->of_node, "encoder-slave", 0);
+	if (!encoder_node) {
+		dev_err(drm->dev, "failed to get an encoder slave node\n");
+		return -ENODEV;
+	}
+
+	ret = arcpgu_drm_hdmi_init(drm, encoder_node);
+	if (ret < 0)
+		return ret;
+
+	drm_mode_config_reset(drm);
+	drm_kms_helper_poll_init(drm);
+
+	arcpgu->fbdev = drm_fbdev_cma_init(drm, 16,
+					      drm->mode_config.num_crtc,
+					      drm->mode_config.num_connector);
+	if (IS_ERR(arcpgu->fbdev)) {
+		ret = PTR_ERR(arcpgu->fbdev);
+		arcpgu->fbdev = NULL;
+		return -ENODEV;
+	}
+
+	platform_set_drvdata(pdev, arcpgu);
+	return 0;
+}
+
+int arcpgu_unload(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+
+	if (arcpgu->fbdev) {
+		drm_fbdev_cma_fini(arcpgu->fbdev);
+		arcpgu->fbdev = NULL;
+	}
+	drm_kms_helper_poll_fini(drm);
+	drm_vblank_cleanup(drm);
+	drm_mode_config_cleanup(drm);
+
+	return 0;
+}
+
+static struct drm_driver arcpgu_drm_driver = {
+	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
+			   DRIVER_ATOMIC,
+	.preclose = arcpgu_preclose,
+	.lastclose = arcpgu_lastclose,
+	.name = "drm-arcpgu",
+	.desc = "ARC PGU Controller",
+	.date = "20160219",
+	.major = 1,
+	.minor = 0,
+	.patchlevel = 0,
+	.fops = &arcpgu_drm_ops,
+	.dumb_create = drm_gem_cma_dumb_create,
+	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
+	.dumb_destroy = drm_gem_dumb_destroy,
+	.get_vblank_counter = drm_vblank_no_hw_counter,
+	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+	.gem_free_object = drm_gem_cma_free_object,
+	.gem_vm_ops = &drm_gem_cma_vm_ops,
+	.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,
+};
+
+static int arcpgu_probe(struct platform_device *pdev)
+{
+	struct drm_device *drm;
+	int ret;
+
+	drm = drm_dev_alloc(&arcpgu_drm_driver, &pdev->dev);
+	if (!drm)
+		return -ENOMEM;
+
+	ret = arcpgu_load(drm);
+	if (ret)
+		goto err_unref;
+
+	ret = drm_dev_register(drm, 0);
+	if (ret)
+		goto err_unload;
+
+	ret = drm_connector_register_all(drm);
+	if (ret)
+		goto err_unregister;
+
+	return 0;
+
+err_unregister:
+	drm_dev_unregister(drm);
+
+err_unload:
+	arcpgu_unload(drm);
+
+err_unref:
+	drm_dev_unref(drm);
+
+	return ret;
+}
+
+static int arcpgu_remove(struct platform_device *pdev)
+{
+	struct drm_device *drm = platform_get_drvdata(pdev);
+
+	drm_connector_unregister_all(drm);
+	drm_dev_unregister(drm);
+	arcpgu_unload(drm);
+	drm_dev_unref(drm);
+
+	return 0;
+}
+
+static const struct of_device_id arcpgu_of_table[] = {
+	{.compatible = "snps,arcpgu"},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, arcpgu_of_table);
+
+static struct platform_driver arcpgu_platform_driver = {
+	.probe = arcpgu_probe,
+	.remove = arcpgu_remove,
+	.driver = {
+		   .name = "arcpgu",
+		   .of_match_table = arcpgu_of_table,
+		   },
+};
+
+module_platform_driver(arcpgu_platform_driver);
+
+MODULE_AUTHOR("Carlos Palminha <palminha at synopsys.com>");
+MODULE_DESCRIPTION("ARC PGU DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c
new file mode 100644
index 0000000..08b6bae
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c
@@ -0,0 +1,201 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "arcpgu.h"
+
+struct arcpgu_drm_connector {
+	struct drm_connector connector;
+	struct drm_encoder_slave *encoder_slave;
+};
+
+static int arcpgu_drm_connector_get_modes(struct drm_connector *connector)
+{
+	const struct drm_encoder_slave_funcs *sfuncs;
+	struct drm_encoder_slave *slave;
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_get_modes: cannot find slave encoder for connector\n");
+		return 0;
+	}
+
+	sfuncs = slave->slave_funcs;
+	if (sfuncs->get_modes == NULL)
+		return 0;
+
+	return sfuncs->get_modes(&slave->base, connector);
+}
+
+struct drm_encoder *
+arcpgu_drm_connector_best_encoder(struct drm_connector *connector)
+{
+	struct drm_encoder_slave *slave;
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_best_encoder: cannot find slave encoder for connector\n");
+		return NULL;
+	}
+
+	return &slave->base;
+}
+
+static enum drm_connector_status
+arcpgu_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	enum drm_connector_status status = connector_status_unknown;
+	const struct drm_encoder_slave_funcs *sfuncs;
+	struct drm_encoder_slave *slave;
+
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_detect: cannot find slave encoder for connector\n");
+		return status;
+	}
+
+	sfuncs = slave->slave_funcs;
+	if (sfuncs && sfuncs->detect)
+		return sfuncs->detect(&slave->base, connector);
+
+	dev_err(connector->dev->dev, "connector_detect: could not detect slave funcs\n");
+	return status;
+}
+
+static void arcpgu_drm_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_helper_funcs
+arcpgu_drm_connector_helper_funcs = {
+	.get_modes = arcpgu_drm_connector_get_modes,
+	.best_encoder = arcpgu_drm_connector_best_encoder,
+};
+
+static const struct drm_connector_funcs arcpgu_drm_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = arcpgu_drm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = arcpgu_drm_connector_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static struct drm_encoder_helper_funcs arcpgu_drm_encoder_helper_funcs = {
+	.dpms = drm_i2c_encoder_dpms,
+	.mode_fixup = drm_i2c_encoder_mode_fixup,
+	.mode_set = drm_i2c_encoder_mode_set,
+	.prepare = drm_i2c_encoder_prepare,
+	.commit = drm_i2c_encoder_commit,
+	.detect = drm_i2c_encoder_detect,
+};
+
+static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np)
+{
+	struct arcpgu_drm_connector *arcpgu_connector;
+	struct drm_i2c_encoder_driver *driver;
+	struct drm_encoder_slave *encoder;
+	struct drm_connector *connector;
+	struct i2c_client *i2c_slave;
+	int ret;
+
+	encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL);
+	if (encoder == NULL)
+		return -ENOMEM;
+
+	i2c_slave = of_find_i2c_device_by_node(np);
+	if (!i2c_slave || !i2c_get_clientdata(i2c_slave)) {
+		dev_err(drm->dev, "failed to find i2c slave encoder\n");
+		return -EPROBE_DEFER;
+	}
+
+	if (i2c_slave->dev.driver == NULL) {
+		dev_err(drm->dev, "failed to find i2c slave driver\n");
+		return -EPROBE_DEFER;
+	}
+
+	driver =
+	    to_drm_i2c_encoder_driver(to_i2c_driver(i2c_slave->dev.driver));
+	ret = driver->encoder_init(i2c_slave, drm, encoder);
+	if (ret) {
+		dev_err(drm->dev, "failed to initialize i2c encoder slave\n");
+		return ret;
+	}
+
+	encoder->base.possible_crtcs = 1;
+	encoder->base.possible_clones = 0;
+	ret = drm_encoder_init(drm, &encoder->base, &arcpgu_drm_encoder_funcs,
+			       DRM_MODE_ENCODER_TMDS, NULL);
+	if (ret)
+		return ret;
+
+	drm_encoder_helper_add(&encoder->base,
+			       &arcpgu_drm_encoder_helper_funcs);
+
+	arcpgu_connector = devm_kzalloc(drm->dev, sizeof(*arcpgu_connector),
+					GFP_KERNEL);
+	if (!arcpgu_connector) {
+		ret = -ENOMEM;
+		goto error_encoder_cleanup;
+	}
+
+	connector = &arcpgu_connector->connector;
+	drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs);
+	ret = drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs,
+			DRM_MODE_CONNECTOR_HDMIA);
+	if (ret < 0) {
+		dev_err(drm->dev, "failed to initialize drm connector\n");
+		goto error_encoder_cleanup;
+	}
+
+	ret = drm_mode_connector_attach_encoder(connector, &encoder->base);
+	if (ret < 0) {
+		dev_err(drm->dev, "could not attach connector to encoder\n");
+		drm_connector_unregister(connector);
+		goto error_connector_cleanup;
+	}
+
+	arcpgu_connector->encoder_slave = encoder;
+
+	return 0;
+
+error_connector_cleanup:
+	drm_connector_cleanup(connector);
+
+error_encoder_cleanup:
+	drm_encoder_cleanup(&encoder->base);
+	return ret;
+}
diff --git a/drivers/gpu/drm/arc/arcpgu_regs.h b/drivers/gpu/drm/arc/arcpgu_regs.h
new file mode 100644
index 0000000..95a13a8
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_regs.h
@@ -0,0 +1,40 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ARC_PGU_REGS_H_
+#define _ARC_PGU_REGS_H_
+
+#define ARCPGU_REG_CTRL		0x00
+#define ARCPGU_REG_STAT		0x04
+#define ARCPGU_REG_FMT		0x10
+#define ARCPGU_REG_HSYNC	0x14
+#define ARCPGU_REG_VSYNC	0x18
+#define ARCPGU_REG_ACTIVE	0x1c
+#define ARCPGU_REG_BUF0_ADDR	0x40
+#define ARCPGU_REG_STRIDE	0x50
+#define ARCPGU_REG_START_SET	0x84
+
+#define ARCPGU_REG_ID		0x3FC
+
+#define ARCPGU_CTRL_ENABLE_MASK	0x02
+#define ARCPGU_CTRL_VS_POL_MASK	0x1
+#define ARCPGU_CTRL_VS_POL_OFST	0x3
+#define ARCPGU_CTRL_HS_POL_MASK	0x1
+#define ARCPGU_CTRL_HS_POL_OFST	0x4
+#define ARCPGU_MODE_RGB888_MASK	0x04
+#define ARCPGU_STAT_BUSY_MASK	0x02
+
+#endif
-- 
2.5.0



From lkp at intel.com  Thu Mar 24 10:37:22 2016
From: lkp at intel.com (kbuild test robot)
Date: Fri, 25 Mar 2016 01:37:22 +0800
Subject: [PATCH 1/5 v4] drm: Add support of ARC PGU display controller
In-Reply-To: <1458838116-24954-2-git-send-email-abrodkin@synopsys.com>
Message-ID: <201603250131.aMZWaAoR%fengguang.wu@intel.com>

Hi Carlos,

[auto build test ERROR on drm/drm-next]
[also build test ERROR on v4.5 next-20160324]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Alexey-Brodkin/drm-Add-support-of-ARC-PGU-display-controller/20160325-005345
base:   git://people.freedesktop.org/~airlied/linux.git drm-next
config: i386-allmodconfig (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/gpu/drm/arc/arcpgu_drv.c: In function 'arcpgu_probe':
>> drivers/gpu/drm/arc/arcpgu_drv.c:232:8: error: implicit declaration of function 'drm_connector_register_all' [-Werror=implicit-function-declaration]
     ret = drm_connector_register_all(drm);
           ^
   drivers/gpu/drm/arc/arcpgu_drv.c: In function 'arcpgu_remove':
>> drivers/gpu/drm/arc/arcpgu_drv.c:254:2: error: implicit declaration of function 'drm_connector_unregister_all' [-Werror=implicit-function-declaration]
     drm_connector_unregister_all(drm);
     ^
   cc1: some warnings being treated as errors

vim +/drm_connector_register_all +232 drivers/gpu/drm/arc/arcpgu_drv.c

   226			goto err_unref;
   227	
   228		ret = drm_dev_register(drm, 0);
   229		if (ret)
   230			goto err_unload;
   231	
 > 232		ret = drm_connector_register_all(drm);
   233		if (ret)
   234			goto err_unregister;
   235	
   236		return 0;
   237	
   238	err_unregister:
   239		drm_dev_unregister(drm);
   240	
   241	err_unload:
   242		arcpgu_unload(drm);
   243	
   244	err_unref:
   245		drm_dev_unref(drm);
   246	
   247		return ret;
   248	}
   249	
   250	static int arcpgu_remove(struct platform_device *pdev)
   251	{
   252		struct drm_device *drm = platform_get_drvdata(pdev);
   253	
 > 254		drm_connector_unregister_all(drm);
   255		drm_dev_unregister(drm);
   256		arcpgu_unload(drm);
   257		drm_dev_unref(drm);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 53512 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-snps-arc/attachments/20160325/f1605ccf/attachment-0001.obj>

From Alexey.Brodkin at synopsys.com  Thu Mar 24 14:12:12 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Thu, 24 Mar 2016 21:12:12 +0000
Subject: [PATCH 1/5 v4] drm: Add support of ARC PGU display controller
In-Reply-To: <201603250131.aMZWaAoR%fengguang.wu@intel.com>
References: <201603250131.aMZWaAoR%fengguang.wu@intel.com>
Message-ID: <1458853932.3068.13.camel@synopsys.com>

Hello,

On Fri, 2016-03-25 at 01:37 +0800, kbuild test robot wrote:
> Hi Carlos,
> 
> [auto build test ERROR on drm/drm-next]
> [also build test ERROR on v4.5 next-20160324]
> [if your patch is applied to the wrong git tree, please drop us a note to help improving the system]
> 
> url:????https://github.com/0day-ci/linux/commits/Alexey-Brodkin/drm-Add-support-of-ARC-PGU-display-controller/20160325
> -005345
> base:???git://people.freedesktop.org/~airlied/linux.git drm-next
> config: i386-allmodconfig (attached as .config)
> reproduce:
> ????????# save the attached .config to linux build tree
> ????????make ARCH=i386?
> 
> All errors (new ones prefixed by >>):
> ? ?230			goto err_unload;
> ???231	
> ?> 232		ret = drm_connector_register_all(drm);

...

> ?> 254		drm_connector_unregister_all(drm);
> ???255		drm_dev_unregister(drm);

That problem happens because that change relies on another series that yet
to be accepted in DRM for 4.7 cycle, see?https://lkml.org/lkml/2016/3/23/128

Based on Daniel's comment I would assume soon after 4.6-rc1 will be cut
pending prerequisite will be applied to drm-next and that build failure will
go away.

-Alexey

From robh at kernel.org  Fri Mar 25 07:39:50 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 25 Mar 2016 09:39:50 -0500
Subject: [PATCH 2/5 v4] drm: Add DT bindings documentation for ARC PGU
 display controller
In-Reply-To: <1458838116-24954-3-git-send-email-abrodkin@synopsys.com>
References: <1458838116-24954-1-git-send-email-abrodkin@synopsys.com>
 <1458838116-24954-3-git-send-email-abrodkin@synopsys.com>
Message-ID: <20160325143950.GA25362@rob-hp-laptop>

On Thu, Mar 24, 2016 at 07:48:33PM +0300, Alexey Brodkin wrote:
> This add DT bindings documentation for ARC PGU display controller.
> 
> Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
> Cc: Rob Herring <robh+dt at kernel.org>
> Cc: Pawel Moll <pawel.moll at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
> Cc: Kumar Gala <galak at codeaurora.org>
> Cc: devicetree at vger.kernel.org
> Cc: linux-snps-arc at lists.infradead.org
> ---
> 
> Changes v3 -> v4: (addressing Rob's comments)
>  * Removed "encoder-slave" from required properties
>  * Removed "0x" from node names
> 
> Changes v2 -> v3:
>  * Reverted back to initial larger version of example
>    with minor fixes (thanks Rob for spotting those).
> 
> Changes v1 -> v2:
>  * Removed everything except PGU node itself.
> 
>  .../devicetree/bindings/display/snps,arcpgu.txt    | 71 ++++++++++++++++++++++
>  1 file changed, 71 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt
> 
> diff --git a/Documentation/devicetree/bindings/display/snps,arcpgu.txt b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> new file mode 100644
> index 0000000..b126577
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
> @@ -0,0 +1,71 @@
> +ARC PGU
> +
> +This is a display controller found on several development boards produced
> +by Synopsys. The ARC PGU is an RGB streamer that reads the data from a
> +framebuffer and sends it to a single digital encoder (usually HDMI).
> +
> +Required properties:
> +  - compatible: "snps,arcpgu"
> +  - reg: Physical base address and length of the controller's registers.
> +  - clocks: A list of phandle + clock-specifier pairs, one for each
> +    entry in 'clock-names'.
> +  - clock-names: A list of clock names. For ARC PGU it should contain:
> +      - "pxlclk" for the clock feeding the output PLL of the controller.
> +
> +Required sub-nodes:
> +  - port: The PGU connection to an encoder chip.
> +
> +Example:
> +
> +/ {
> +	...
> +
> +	pgu at XXXXXXXX {
> +		compatible = "snps,arcpgu";
> +		reg = <0xXXXXXXXX 0x400>;
> +		clocks = <&clock_node>;
> +		clock-names = "pxlclk";
> +		encoder-slave = <&encoder_node>;

Still in the example...

Otherwise,

Acked-by: Rob Herring <robh at kernel.org>


From zhaoxiu.zeng at gmail.com  Sat Mar 26 21:02:26 2016
From: zhaoxiu.zeng at gmail.com (zhaoxiu.zeng)
Date: Sun, 27 Mar 2016 12:02:26 +0800
Subject: [PATCH 02/31] Include generic parity.h in some architectures' bitops.h
In-Reply-To: <1458788612-4367-1-git-send-email-zhaoxiu.zeng@gmail.com>
References: <1458788612-4367-1-git-send-email-zhaoxiu.zeng@gmail.com>
Message-ID: <56F75B52.5070805@gmail.com>

From: Zeng Zhaoxiu <zhaoxiu.zeng at gmail.com>

Use the generic version.

Signed-off-by: Zeng Zhaoxiu <zhaoxiu.zeng at gmail.com>
---
 arch/arc/include/asm/bitops.h      | 1 +
 arch/arm/include/asm/bitops.h      | 1 +
 arch/arm64/include/asm/bitops.h    | 1 +
 arch/c6x/include/asm/bitops.h      | 1 +
 arch/cris/include/asm/bitops.h     | 1 +
 arch/frv/include/asm/bitops.h      | 1 +
 arch/h8300/include/asm/bitops.h    | 1 +
 arch/hexagon/include/asm/bitops.h  | 1 +
 arch/m32r/include/asm/bitops.h     | 1 +
 arch/m68k/include/asm/bitops.h     | 1 +
 arch/metag/include/asm/bitops.h    | 1 +
 arch/mn10300/include/asm/bitops.h  | 1 +
 arch/openrisc/include/asm/bitops.h | 1 +
 arch/parisc/include/asm/bitops.h   | 1 +
 arch/s390/include/asm/bitops.h     | 1 +
 arch/sh/include/asm/bitops.h       | 1 +
 arch/xtensa/include/asm/bitops.h   | 1 +
 17 files changed, 17 insertions(+)

diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h
index 0352fb8..7967e47 100644
--- a/arch/arc/include/asm/bitops.h
+++ b/arch/arc/include/asm/bitops.h
@@ -370,6 +370,7 @@ static inline __attribute__ ((const)) int __ffs(unsigned long x)
 #define ffz(x)	__ffs(~(x))
 
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/lock.h>
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index e943e6c..99f28a6 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -313,6 +313,7 @@ static inline unsigned long __ffs(unsigned long x)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #ifdef __ARMEB__
diff --git a/arch/arm64/include/asm/bitops.h b/arch/arm64/include/asm/bitops.h
index 9c19594..eac4965 100644
--- a/arch/arm64/include/asm/bitops.h
+++ b/arch/arm64/include/asm/bitops.h
@@ -44,6 +44,7 @@ extern int test_and_change_bit(int nr, volatile unsigned long *p);
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/non-atomic.h>
diff --git a/arch/c6x/include/asm/bitops.h b/arch/c6x/include/asm/bitops.h
index f0ab012..94eb0d1 100644
--- a/arch/c6x/include/asm/bitops.h
+++ b/arch/c6x/include/asm/bitops.h
@@ -87,6 +87,7 @@ static inline int ffs(int x)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/atomic.h>
diff --git a/arch/cris/include/asm/bitops.h b/arch/cris/include/asm/bitops.h
index 8062cb5..06bc246 100644
--- a/arch/cris/include/asm/bitops.h
+++ b/arch/cris/include/asm/bitops.h
@@ -36,6 +36,7 @@
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/lock.h>
 
diff --git a/arch/frv/include/asm/bitops.h b/arch/frv/include/asm/bitops.h
index 0df8e95..f2a7ee8 100644
--- a/arch/frv/include/asm/bitops.h
+++ b/arch/frv/include/asm/bitops.h
@@ -314,6 +314,7 @@ int __ilog2_u64(u64 n)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/le.h>
diff --git a/arch/h8300/include/asm/bitops.h b/arch/h8300/include/asm/bitops.h
index 05999ab..e392db2 100644
--- a/arch/h8300/include/asm/bitops.h
+++ b/arch/h8300/include/asm/bitops.h
@@ -172,6 +172,7 @@ static inline unsigned long __ffs(unsigned long word)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
diff --git a/arch/hexagon/include/asm/bitops.h b/arch/hexagon/include/asm/bitops.h
index 5e4a59b..2df614e 100644
--- a/arch/hexagon/include/asm/bitops.h
+++ b/arch/hexagon/include/asm/bitops.h
@@ -290,6 +290,7 @@ static inline unsigned long __fls(unsigned long word)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
diff --git a/arch/m32r/include/asm/bitops.h b/arch/m32r/include/asm/bitops.h
index 86ba2b4..e3cf46b 100644
--- a/arch/m32r/include/asm/bitops.h
+++ b/arch/m32r/include/asm/bitops.h
@@ -259,6 +259,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #endif /* __KERNEL__ */
diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h
index b4a9b0d..fd673ea 100644
--- a/arch/m68k/include/asm/bitops.h
+++ b/arch/m68k/include/asm/bitops.h
@@ -519,6 +519,7 @@ static inline int __fls(int x)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #endif /* __KERNEL__ */
 
diff --git a/arch/metag/include/asm/bitops.h b/arch/metag/include/asm/bitops.h
index 2671134..ad13087 100644
--- a/arch/metag/include/asm/bitops.h
+++ b/arch/metag/include/asm/bitops.h
@@ -118,6 +118,7 @@ static inline int test_and_change_bit(unsigned int bit,
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
diff --git a/arch/mn10300/include/asm/bitops.h b/arch/mn10300/include/asm/bitops.h
index fe6f8e2..60761b7 100644
--- a/arch/mn10300/include/asm/bitops.h
+++ b/arch/mn10300/include/asm/bitops.h
@@ -225,6 +225,7 @@ int ffs(int x)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
 #include <asm-generic/bitops/le.h>
 
diff --git a/arch/openrisc/include/asm/bitops.h b/arch/openrisc/include/asm/bitops.h
index 3003cda..8c97642 100644
--- a/arch/openrisc/include/asm/bitops.h
+++ b/arch/openrisc/include/asm/bitops.h
@@ -43,6 +43,7 @@
 #include <asm-generic/bitops/sched.h>
 #include <asm/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/atomic.h>
diff --git a/arch/parisc/include/asm/bitops.h b/arch/parisc/include/asm/bitops.h
index 3f9406d..867ba10 100644
--- a/arch/parisc/include/asm/bitops.h
+++ b/arch/parisc/include/asm/bitops.h
@@ -211,6 +211,7 @@ static __inline__ int fls(int x)
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 8043f10..198eead 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -460,6 +460,7 @@ static inline int fls(int word)
 #include <asm-generic/bitops/ffz.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
diff --git a/arch/sh/include/asm/bitops.h b/arch/sh/include/asm/bitops.h
index fc8e652..4bf0c35 100644
--- a/arch/sh/include/asm/bitops.h
+++ b/arch/sh/include/asm/bitops.h
@@ -86,6 +86,7 @@ static inline unsigned long ffz(unsigned long word)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
diff --git a/arch/xtensa/include/asm/bitops.h b/arch/xtensa/include/asm/bitops.h
index 3f44fa2..981fa83 100644
--- a/arch/xtensa/include/asm/bitops.h
+++ b/arch/xtensa/include/asm/bitops.h
@@ -229,6 +229,7 @@ test_and_change_bit(unsigned int bit, volatile unsigned long *p)
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 
-- 
2.5.5



From jslaby at suse.cz  Thu Mar 24 05:58:13 2016
From: jslaby at suse.cz (Jiri Slaby)
Date: Thu, 24 Mar 2016 13:58:13 +0100
Subject: [PATCH 3/4] exit_thread: accept a task parameter to be exited
Message-ID: <1458824294-29733-1-git-send-email-jslaby@suse.cz>

We need to call exit_thread from copy_process in a fail path.  So make
it accept task_struct as a parameter.

Signed-off-by: Jiri Slaby <jslaby at suse.cz>
Cc: Richard Henderson <rth at twiddle.net>
Cc: Ivan Kokshaysky <ink at jurassic.park.msu.ru>
Cc: Matt Turner <mattst88 at gmail.com>
Cc: Vineet Gupta <vgupta at synopsys.com>
Cc: Russell King <linux at arm.linux.org.uk>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
Cc: Haavard Skinnemoen <hskinnemoen at gmail.com>
Cc: Hans-Christian Egtvedt <egtvedt at samfundet.no>
Cc: Steven Miao <realmz6 at gmail.com>
Cc: Mark Salter <msalter at redhat.com>
Cc: Aurelien Jacquiot <a-jacquiot at ti.com>
Cc: Mikael Starvik <starvik at axis.com>
Cc: Jesper Nilsson <jesper.nilsson at axis.com>
Cc: Yoshinori Sato <ysato at users.sourceforge.jp>
Cc: Richard Kuo <rkuo at codeaurora.org>
Cc: Tony Luck <tony.luck at intel.com>
Cc: Fenghua Yu <fenghua.yu at intel.com>
Cc: Geert Uytterhoeven <geert at linux-m68k.org>
Cc: James Hogan <james.hogan at imgtec.com>
Cc: Michal Simek <monstr at monstr.eu>
Cc: Ralf Baechle <ralf at linux-mips.org>
Cc: David Howells <dhowells at redhat.com>
Cc: Koichi Yasutake <yasutake.koichi at jp.panasonic.com>
Cc: Ley Foon Tan <lftan at altera.com>
Cc: Jonas Bonn <jonas at southpole.se>
Cc: "James E.J. Bottomley" <jejb at parisc-linux.org>
Cc: Helge Deller <deller at gmx.de>
Cc: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Cc: Paul Mackerras <paulus at samba.org>
Cc: Michael Ellerman <mpe at ellerman.id.au>
Cc: Martin Schwidefsky <schwidefsky at de.ibm.com>
Cc: Heiko Carstens <heiko.carstens at de.ibm.com>
Cc: Chen Liqin <liqin.linux at gmail.com>
Cc: Lennox Wu <lennox.wu at gmail.com>
Cc: Rich Felker <dalias at libc.org>
Cc: "David S. Miller" <davem at davemloft.net>
Cc: Chris Metcalf <cmetcalf at mellanox.com>
Cc: Jeff Dike <jdike at addtoit.com>
Cc: Richard Weinberger <richard at nod.at>
Cc: Guan Xuetao <gxt at mprc.pku.edu.cn>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: "H. Peter Anvin" <hpa at zytor.com>
Cc: x86 at kernel.org
Cc: Chris Zankel <chris at zankel.net>
Cc: Max Filippov <jcmvbkbc at gmail.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: linux-alpha at vger.kernel.org
Cc: linux-kernel at vger.kernel.org
Cc: linux-snps-arc at lists.infradead.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: adi-buildroot-devel at lists.sourceforge.net
Cc: linux-c6x-dev at linux-c6x.org
Cc: linux-cris-kernel at axis.com
Cc: uclinux-h8-devel at lists.sourceforge.jp
Cc: linux-hexagon at vger.kernel.org
Cc: linux-ia64 at vger.kernel.org
Cc: linux-m68k at lists.linux-m68k.org
Cc: linux-metag at vger.kernel.org
Cc: linux-mips at linux-mips.org
Cc: linux-am33-list at redhat.com
Cc: nios2-dev at lists.rocketboards.org
Cc: linux-parisc at vger.kernel.org
Cc: linuxppc-dev at lists.ozlabs.org
Cc: linux-s390 at vger.kernel.org
Cc: linux-sh at vger.kernel.org
Cc: sparclinux at vger.kernel.org
Cc: user-mode-linux-devel at lists.sourceforge.net
Cc: user-mode-linux-user at lists.sourceforge.net
Cc: linux-xtensa at linux-xtensa.org
---
 arch/alpha/kernel/process.c             |  2 +-
 arch/arc/kernel/process.c               |  2 +-
 arch/arm/kernel/process.c               |  4 ++--
 arch/arm64/kernel/process.c             |  2 +-
 arch/avr32/kernel/process.c             |  4 ++--
 arch/blackfin/include/asm/processor.h   |  2 +-
 arch/c6x/kernel/process.c               |  2 +-
 arch/cris/arch-v10/kernel/process.c     |  2 +-
 arch/cris/arch-v32/kernel/process.c     |  4 ++--
 arch/frv/include/asm/processor.h        |  2 +-
 arch/h8300/include/asm/processor.h      |  2 +-
 arch/hexagon/kernel/process.c           |  2 +-
 arch/ia64/kernel/perfmon.c              |  4 ++--
 arch/ia64/kernel/process.c              | 14 +++++++-------
 arch/m32r/kernel/process.c              |  4 ++--
 arch/m68k/include/asm/processor.h       |  2 +-
 arch/metag/include/asm/processor.h      |  2 +-
 arch/metag/kernel/process.c             |  6 +++---
 arch/microblaze/include/asm/processor.h |  4 ++--
 arch/mips/kernel/process.c              |  2 +-
 arch/mn10300/kernel/process.c           |  4 ++--
 arch/nios2/include/asm/processor.h      |  2 +-
 arch/openrisc/include/asm/processor.h   |  2 +-
 arch/parisc/kernel/process.c            |  2 +-
 arch/powerpc/kernel/process.c           |  2 +-
 arch/s390/kernel/process.c              |  4 ++--
 arch/score/kernel/process.c             |  2 +-
 arch/sh/kernel/process_32.c             |  2 +-
 arch/sh/kernel/process_64.c             |  4 ++--
 arch/sparc/kernel/process_32.c          | 12 ++++++------
 arch/sparc/kernel/process_64.c          |  4 ++--
 arch/tile/kernel/process.c              |  4 ++--
 arch/um/kernel/process.c                |  2 +-
 arch/unicore32/kernel/process.c         |  2 +-
 arch/x86/kernel/process.c               |  3 +--
 arch/xtensa/kernel/process.c            |  4 ++--
 include/linux/sched.h                   |  2 +-
 kernel/exit.c                           |  2 +-
 38 files changed, 63 insertions(+), 64 deletions(-)

diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 84d13263ce46..1e044d1f7525 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -214,7 +214,7 @@ EXPORT_SYMBOL(start_thread);
  * Free current thread data structures etc..
  */
 void
-exit_thread(void)
+exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c
index a3f750e76b68..70944dfab6c6 100644
--- a/arch/arc/kernel/process.c
+++ b/arch/arc/kernel/process.c
@@ -186,7 +186,7 @@ void flush_thread(void)
 /*
  * Free any architecture-specific thread data structures, etc.
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 4adfb46e3ee9..e8ecd02bf7ea 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -193,9 +193,9 @@ EXPORT_SYMBOL_GPL(thread_notify_head);
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
-	thread_notify(THREAD_NOTIFY_EXIT, current_thread_info());
+	thread_notify(THREAD_NOTIFY_EXIT, task_thread_info(me));
 }
 
 void flush_thread(void)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 80624829db61..84b288c85e4a 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -203,7 +203,7 @@ void show_regs(struct pt_regs * regs)
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
index 42a53e740a7e..ea21d0e99b6b 100644
--- a/arch/avr32/kernel/process.c
+++ b/arch/avr32/kernel/process.c
@@ -62,9 +62,9 @@ void machine_restart(char *cmd)
 /*
  * Free current thread data structures etc
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
-	ocd_disable(current);
+	ocd_disable(me);
 }
 
 void flush_thread(void)
diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h
index 7acd46653df3..7aa6cd0ac8d9 100644
--- a/arch/blackfin/include/asm/processor.h
+++ b/arch/blackfin/include/asm/processor.h
@@ -78,7 +78,7 @@ static inline void release_thread(struct task_struct *dead_task)
 /*
  * Free current thread data structures etc..
  */
-static inline void exit_thread(void)
+static inline void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/c6x/kernel/process.c b/arch/c6x/kernel/process.c
index 3ae9f5a166a0..4b2dfb1d330d 100644
--- a/arch/c6x/kernel/process.c
+++ b/arch/c6x/kernel/process.c
@@ -82,7 +82,7 @@ void flush_thread(void)
 {
 }
 
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c
index 02b783457be0..2aaaccc3883c 100644
--- a/arch/cris/arch-v10/kernel/process.c
+++ b/arch/cris/arch-v10/kernel/process.c
@@ -39,7 +39,7 @@ void default_idle(void)
  * Free current thread data structures etc..
  */
 
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 	/* Nothing needs to be done.  */
 }
diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c
index c7ce784a393c..5f55d15366ea 100644
--- a/arch/cris/arch-v32/kernel/process.c
+++ b/arch/cris/arch-v32/kernel/process.c
@@ -33,9 +33,9 @@ void default_idle(void)
  */
 
 extern void deconfigure_bp(long pid);
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
-	deconfigure_bp(current->pid);
+	deconfigure_bp(me->pid);
 }
 
 /*
diff --git a/arch/frv/include/asm/processor.h b/arch/frv/include/asm/processor.h
index ae8d423e79d9..cff4440abcee 100644
--- a/arch/frv/include/asm/processor.h
+++ b/arch/frv/include/asm/processor.h
@@ -99,7 +99,7 @@ extern asmlinkage void *restore_user_regs(const struct user_context *target, ...
 /*
  * Free current thread data structures etc..
  */
-static inline void exit_thread(void)
+static inline void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h
index 54e3fd83c336..d79f99c645ad 100644
--- a/arch/h8300/include/asm/processor.h
+++ b/arch/h8300/include/asm/processor.h
@@ -113,7 +113,7 @@ static inline void release_thread(struct task_struct *dead_task)
 /*
  * Free current thread data structures etc..
  */
-static inline void exit_thread(void)
+static inline void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c
index a9ebd471823a..228b77433fe8 100644
--- a/arch/hexagon/kernel/process.c
+++ b/arch/hexagon/kernel/process.c
@@ -139,7 +139,7 @@ void release_thread(struct task_struct *dead_task)
 /*
  * Free any architecture-specific thread data structures, etc.
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 9cd607b06964..2436ad5f92c1 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -4542,8 +4542,8 @@ pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
 
 
 /*
- * called only from exit_thread(): task == current
- * we come here only if current has a context attached (loaded or masked)
+ * called only from exit_thread()
+ * we come here only if the task has a context attached (loaded or masked)
  */
 void
 pfm_exit_thread(struct task_struct *task)
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index b51514957620..445f09fb2820 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -570,22 +570,22 @@ flush_thread (void)
 }
 
 /*
- * Clean up state associated with current thread.  This is called when
+ * Clean up state associated with a thread.  This is called when
  * the thread calls exit().
  */
 void
-exit_thread (void)
+exit_thread (struct task_struct *me)
 {
 
-	ia64_drop_fpu(current);
+	ia64_drop_fpu(me);
 #ifdef CONFIG_PERFMON
        /* if needed, stop monitoring and flush state to perfmon context */
-	if (current->thread.pfm_context)
-		pfm_exit_thread(current);
+	if (me->thread.pfm_context)
+		pfm_exit_thread(me);
 
 	/* free debug register resources */
-	if (current->thread.flags & IA64_THREAD_DBG_VALID)
-		pfm_release_debug_registers(current);
+	if (me->thread.flags & IA64_THREAD_DBG_VALID)
+		pfm_release_debug_registers(me);
 #endif
 }
 
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index e69221d581d5..00a41866b05e 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -104,10 +104,10 @@ void show_regs(struct pt_regs * regs)
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 	/* Nothing to do. */
-	DPRINTK("pid = %d\n", current->pid);
+	DPRINTK("pid = %d\n", me->pid);
 }
 
 void flush_thread(void)
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index 20dda1d4b860..57ef5d420307 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -156,7 +156,7 @@ static inline void release_thread(struct task_struct *dead_task)
 /*
  * Free current thread data structures etc..
  */
-static inline void exit_thread(void)
+static inline void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/metag/include/asm/processor.h b/arch/metag/include/asm/processor.h
index 0838ca699764..daf7943168f0 100644
--- a/arch/metag/include/asm/processor.h
+++ b/arch/metag/include/asm/processor.h
@@ -134,7 +134,7 @@ static inline void release_thread(struct task_struct *dead_task)
 #define copy_segments(tsk, mm)		do { } while (0)
 #define release_segments(mm)		do { } while (0)
 
-extern void exit_thread(void);
+extern void exit_thread(struct task_struct *me);
 
 /*
  * Return saved PC of a blocked thread.
diff --git a/arch/metag/kernel/process.c b/arch/metag/kernel/process.c
index 7f546183a0f0..f5c507c3d804 100644
--- a/arch/metag/kernel/process.c
+++ b/arch/metag/kernel/process.c
@@ -345,10 +345,10 @@ void flush_thread(void)
 /*
  * Free current thread data structures etc.
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
-	clear_fpu(&current->thread);
-	clear_dsp(&current->thread);
+	clear_fpu(&me->thread);
+	clear_dsp(&me->thread);
 }
 
 /* TODO: figure out how to unwind the kernel stack here to figure out
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h
index 497a988d79c2..41300e76aac0 100644
--- a/arch/microblaze/include/asm/processor.h
+++ b/arch/microblaze/include/asm/processor.h
@@ -71,7 +71,7 @@ static inline void release_thread(struct task_struct *dead_task)
 }
 
 /* Free all resources held by a thread. */
-static inline void exit_thread(void)
+static inline void exit_thread(struct task_struct *me)
 {
 }
 
@@ -128,7 +128,7 @@ static inline void release_thread(struct task_struct *dead_task)
 }
 
 /* Free current thread data structures etc.  */
-static inline void exit_thread(void)
+static inline void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 92880cee449e..26f90e9ea288 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -73,7 +73,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
 	regs->regs[29] = sp;
 }
 
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c
index 74a96ccf7451..99d73b5c2d33 100644
--- a/arch/mn10300/kernel/process.c
+++ b/arch/mn10300/kernel/process.c
@@ -103,9 +103,9 @@ void show_regs(struct pt_regs *regs)
 /*
  * free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
-	exit_fpu(current);
+	exit_fpu(me);
 }
 
 void flush_thread(void)
diff --git a/arch/nios2/include/asm/processor.h b/arch/nios2/include/asm/processor.h
index c2ba45c159c7..a8443c158d65 100644
--- a/arch/nios2/include/asm/processor.h
+++ b/arch/nios2/include/asm/processor.h
@@ -76,7 +76,7 @@ static inline void release_thread(struct task_struct *dead_task)
 }
 
 /* Free current thread data structures etc.. */
-static inline void exit_thread(void)
+static inline void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h
index 4d235e3d2534..26a8f3760a71 100644
--- a/arch/openrisc/include/asm/processor.h
+++ b/arch/openrisc/include/asm/processor.h
@@ -88,7 +88,7 @@ unsigned long get_wchan(struct task_struct *p);
  * Free current thread data structures etc..
  */
 
-extern inline void exit_thread(void)
+extern inline void exit_thread(struct task_struct *me)
 {
 	/* Nothing needs to be done.  */
 }
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 809905a811ed..5750fe642202 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -147,7 +147,7 @@ EXPORT_SYMBOL(pm_power_off);
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 612df305886b..bb6da7f3c27b 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1326,7 +1326,7 @@ void show_regs(struct pt_regs * regs)
 		show_instructions(regs);
 }
 
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 7fabc985a7dd..b86625490090 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -70,9 +70,9 @@ extern void kernel_thread_starter(void);
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
-	exit_thread_runtime_instr(current);
+	exit_thread_runtime_instr(me);
 }
 
 void flush_thread(void)
diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c
index a1519ad3d49d..de22a45558d6 100644
--- a/arch/score/kernel/process.c
+++ b/arch/score/kernel/process.c
@@ -56,7 +56,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
 	regs->regs[0] = sp;
 }
 
-void exit_thread(void) {}
+void exit_thread(struct task_struct *me) {}
 
 /*
  * When a process does an "exec", machine state like FPU and debug
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index 2885fc9d9dcd..4e360f2be5fd 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -79,7 +79,7 @@ EXPORT_SYMBOL(start_thread);
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c
index e2062e643341..8bb717f5bfc9 100644
--- a/arch/sh/kernel/process_64.c
+++ b/arch/sh/kernel/process_64.c
@@ -288,7 +288,7 @@ void show_regs(struct pt_regs *regs)
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 	/*
 	 * See arch/sparc/kernel/process.c for the precedent for doing
@@ -307,7 +307,7 @@ void exit_thread(void)
 	 * which it would get safely nulled.
 	 */
 #ifdef CONFIG_SH_FPU
-	if (last_task_used_math == current) {
+	if (last_task_used_math == me) {
 		last_task_used_math = NULL;
 	}
 #endif
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
index c5113c7ce2fd..00ade5a2f5e8 100644
--- a/arch/sparc/kernel/process_32.c
+++ b/arch/sparc/kernel/process_32.c
@@ -184,21 +184,21 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 #ifndef CONFIG_SMP
-	if(last_task_used_math == current) {
+	if (last_task_used_math == me) {
 #else
-	if (test_thread_flag(TIF_USEDFPU)) {
+	if (test_ti_thread_flag(task_thread_info(me), TIF_USEDFPU)) {
 #endif
 		/* Keep process from leaving FPU in a bogon state. */
 		put_psr(get_psr() | PSR_EF);
-		fpsave(&current->thread.float_regs[0], &current->thread.fsr,
-		       &current->thread.fpqueue[0], &current->thread.fpqdepth);
+		fpsave(&me->thread.float_regs[0], &me->thread.fsr,
+		       &me->thread.fpqueue[0], &me->thread.fpqdepth);
 #ifndef CONFIG_SMP
 		last_task_used_math = NULL;
 #else
-		clear_thread_flag(TIF_USEDFPU);
+		clear_ti_thread_flag(task_thread_info(me), TIF_USEDFPU);
 #endif
 	}
 }
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
index 46a59643bb1c..5cb4077f5cb8 100644
--- a/arch/sparc/kernel/process_64.c
+++ b/arch/sparc/kernel/process_64.c
@@ -417,9 +417,9 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
 }
 
 /* Free current thread data structures etc.. */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
-	struct thread_info *t = current_thread_info();
+	struct thread_info *t = task_thread_info(me);
 
 	if (t->utraps) {
 		if (t->utraps[0] < 2)
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index b5f30d376ce1..94080d327efc 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -541,7 +541,7 @@ void flush_thread(void)
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 #ifdef CONFIG_HARDWALL
 	/*
@@ -550,7 +550,7 @@ void exit_thread(void)
 	 * the last reference to a hardwall fd, it would already have
 	 * been released and deactivated at this point.)
 	 */
-	hardwall_deactivate_all(current);
+	hardwall_deactivate_all(me);
 #endif
 }
 
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 48af59aae129..06eb532965d1 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -103,7 +103,7 @@ void interrupt_end(void)
 		tracehook_notify_resume(regs);
 }
 
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c
index b008e9961465..7c23697bc2ed 100644
--- a/arch/unicore32/kernel/process.c
+++ b/arch/unicore32/kernel/process.c
@@ -204,7 +204,7 @@ void show_regs(struct pt_regs *regs)
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 }
 
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 2915d54e9dd5..55c97e4ef71b 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -97,9 +97,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
-	struct task_struct *me = current;
 	struct thread_struct *t = &me->thread;
 	unsigned long *bp = t->io_bitmap_ptr;
 	struct fpu *fpu = &t->fpu;
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index 5bbfed81c97b..6f3b54eb346c 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -115,10 +115,10 @@ void arch_cpu_idle(void)
 /*
  * This is called when the thread calls exit().
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *me)
 {
 #if XTENSA_HAVE_COPROCESSORS
-	coprocessor_release_all(current_thread_info());
+	coprocessor_release_all(task_thread_info(me));
 #endif
 }
 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index af5cc4768026..db4daa3aa894 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2648,7 +2648,7 @@ static inline int copy_thread_tls(
 }
 #endif
 extern void flush_thread(void);
-extern void exit_thread(void);
+extern void exit_thread(struct task_struct *);
 
 extern void exit_files(struct task_struct *);
 extern void __cleanup_sighand(struct sighand_struct *);
diff --git a/kernel/exit.c b/kernel/exit.c
index fd90195667e1..75b34fe835b2 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -746,7 +746,7 @@ void do_exit(long code)
 		disassociate_ctty(1);
 	exit_task_namespaces(tsk);
 	exit_task_work(tsk);
-	exit_thread();
+	exit_thread(tsk);
 
 	/*
 	 * Flush inherited counters to the parent - before the parent
-- 
2.7.4



From peterz at infradead.org  Thu Mar 24 06:03:03 2016
From: peterz at infradead.org (Peter Zijlstra)
Date: Thu, 24 Mar 2016 14:03:03 +0100
Subject: [PATCH 3/4] exit_thread: accept a task parameter to be exited
In-Reply-To: <1458824294-29733-1-git-send-email-jslaby@suse.cz>
References: <1458824294-29733-1-git-send-email-jslaby@suse.cz>
Message-ID: <20160324130303.GS6356@twins.programming.kicks-ass.net>

On Thu, Mar 24, 2016 at 01:58:13PM +0100, Jiri Slaby wrote:
>  void
> -exit_thread(void)
> +exit_thread(struct task_struct *me)
>  {
>  }

task_struct arguments are called: tsk, task, p
'me' seems very wrong, as that could only mean 'current', and its
clearly not that.


From jslaby at suse.cz  Thu Mar 24 06:05:03 2016
From: jslaby at suse.cz (Jiri Slaby)
Date: Thu, 24 Mar 2016 14:05:03 +0100
Subject: [PATCH 3/4] exit_thread: accept a task parameter to be exited
In-Reply-To: <20160324130303.GS6356@twins.programming.kicks-ass.net>
References: <1458824294-29733-1-git-send-email-jslaby@suse.cz>
 <20160324130303.GS6356@twins.programming.kicks-ass.net>
Message-ID: <56F3E5FF.9030105@suse.cz>

On 03/24/2016, 02:03 PM, Peter Zijlstra wrote:
> On Thu, Mar 24, 2016 at 01:58:13PM +0100, Jiri Slaby wrote:
>>  void
>> -exit_thread(void)
>> +exit_thread(struct task_struct *me)
>>  {
>>  }
> 
> task_struct arguments are called: tsk, task, p
> 'me' seems very wrong, as that could only mean 'current', and its
> clearly not that.

Ah, OK. I will wait for more feedback and will fix this.

thanks,
-- 
js
suse labs


From linux at arm.linux.org.uk  Thu Mar 24 08:36:58 2016
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Thu, 24 Mar 2016 15:36:58 +0000
Subject: [PATCH 3/4] exit_thread: accept a task parameter to be exited
In-Reply-To: <1458824294-29733-1-git-send-email-jslaby@suse.cz>
References: <1458824294-29733-1-git-send-email-jslaby@suse.cz>
Message-ID: <20160324153658.GU19428@n2100.arm.linux.org.uk>

On Thu, Mar 24, 2016 at 01:58:13PM +0100, Jiri Slaby wrote:
> We need to call exit_thread from copy_process in a fail path.  So make
> it accept task_struct as a parameter.

Hmm, so what this means is that exit_thread() can now be called for
threads which are not running on the CPU.  So, I think the comment
in arch/arm/vfp/vfpmodule.c needs to be updated:

 *  THREAD_NOTIFY_EXIT
 *   - the thread (v) will be running on the local CPU, so
 *      v === current_thread_info()

along with this change, since that becomes false.

The code, however, looks like it'll cope just fine with that being
false, as will the other users of THREAD_NOTIFY_EXIT in ARM.

Thanks.

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From Vineet.Gupta1 at synopsys.com  Mon Mar 28 00:04:08 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Mon, 28 Mar 2016 07:04:08 +0000
Subject: Build error due to commit 458aa76d132dc ("mm/thp/migration:
 switch from flush_tlb_range to flush_pmd_tlb_range")
References: <20160321200035.GA31544@roeck-us.net>
 <87k2kvt7p6.fsf@linux.vnet.ibm.com> <56F12A5D.7040904@roeck-us.net>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E911A6@us01wembx1.internal.synopsys.com>

On Tuesday 22 March 2016 04:50 PM, Guenter Roeck wrote:
> On 03/21/2016 10:14 PM, Aneesh Kumar K.V wrote:
>> Guenter Roeck <linux at roeck-us.net> writes:
>>
>>> [ text/plain ]
>>> Hi,
>>>
>>> Your commit 458aa76d132dc1 ("mm/thp/migration: switch from flush_tlb_range
>>> to flush_pmd_tlb_range") causes a build error when building
>>> arcv2:vdk_hs38_smp_defconfig.
>>>
>>> include/asm-generic/pgtable.h:799:45: note: in expansion of macro ?BUILD_BUG?
>>>   #define flush_pmd_tlb_range(vma, addr, end) BUILD_BUG()
>>>                                                ^
>>> ./arch/arc/include/asm/tlbflush.h:37:13: note:
>>> 	in expansion of macro ?flush_pmd_tlb_range?
>>>
>>> The build triggers the newly introduced BUILD_BUG().
>>>
>>> When building the image without the BUILD_BUG(), ie with no definition
>>> of flush_pmd_tlb_range(), the problem is gone. This suggests that the
>>> function is not needed for this build.
>>>
>>> I could submit a patch to remove the BUILD_BUG(), but maybe you had a reason
>>> for introducing it. Can you elaborate why you introduced the BUILD_BUG() ?
>>>
>> Isn't this going to be fixed by an update to ARC tree ?
>>
>> http://article.gmane.org/gmane.linux.kernel.mm/148412
>>
> That wasn't a build error ?

It was an ARC build error for !THP - the issue was definition of
flush_pmd_tlb_range() w/o THP guard

 #define flush_pmd_tlb_range(vma, s, e) local_flush_pmd_tlb_range(vma, s, e)

And BUILD_BUG was nice as it caught this unwarranted code inclusion !

>
>> I also don't understand why we would hit that BUILD_BUG, if we are not
>> calling flush_pmd_tlb_range().
>>
> Good question.

It's not the call but the definition in ARC

-Vineet

>
> I'll wait for the commit window to close and report again if needed.
>
> Guenter
>
>



From Vineet.Gupta1 at synopsys.com  Mon Mar 28 00:21:09 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Mon, 28 Mar 2016 07:21:09 +0000
Subject: [LTP] [PATCH] sort the open posix tests before executing
References: <1457415124-5023-1-git-send-email-vgupta@synopsys.com>
 <20160309142302.GE28171@rei.lan>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E911E7@us01wembx1.internal.synopsys.com>

On Wednesday 09 March 2016 07:55 PM, Cyril Hrubis wrote:
> Hi!
>> Helps do a simple diff of output logs !
> Sounds reasonable to me.
>
> Has anyone an argument against this?
>

Ping !


From Alexey.Brodkin at synopsys.com  Mon Mar 28 04:36:36 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Mon, 28 Mar 2016 14:36:36 +0300
Subject: [PATCH 2/5 v5] drm: Add DT bindings documentation for ARC PGU display
 controller
In-Reply-To: <1459164999-11850-1-git-send-email-abrodkin@synopsys.com>
References: <1459164999-11850-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1459164999-11850-3-git-send-email-abrodkin@synopsys.com>

This add DT bindings documentation for ARC PGU display controller.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: devicetree at vger.kernel.org
Cc: linux-snps-arc at lists.infradead.org
Acked-by: Rob Herring <robh at kernel.org>
---

Changes v4 -> v5: (addressing Rob's comment)
 * Added Rob's acked-by
 * Remove "encoder-slave" from the example as well.
   Now only "pgu" node is mentioned in the example.

Changes v3 -> v4: (addressing Rob's comments)
 * Removed "encoder-slave" from required properties
 * Removed "0x" from node names

Changes v2 -> v3:
 * Reverted back to initial larger version of example
   with minor fixes (thanks Rob for spotting those).

Changes v1 -> v2:
 * Removed everything except PGU node itself.

 .../devicetree/bindings/display/snps,arcpgu.txt    | 35 ++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt

diff --git a/Documentation/devicetree/bindings/display/snps,arcpgu.txt b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
new file mode 100644
index 0000000..c5c7dfd
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/snps,arcpgu.txt
@@ -0,0 +1,35 @@
+ARC PGU
+
+This is a display controller found on several development boards produced
+by Synopsys. The ARC PGU is an RGB streamer that reads the data from a
+framebuffer and sends it to a single digital encoder (usually HDMI).
+
+Required properties:
+  - compatible: "snps,arcpgu"
+  - reg: Physical base address and length of the controller's registers.
+  - clocks: A list of phandle + clock-specifier pairs, one for each
+    entry in 'clock-names'.
+  - clock-names: A list of clock names. For ARC PGU it should contain:
+      - "pxlclk" for the clock feeding the output PLL of the controller.
+
+Required sub-nodes:
+  - port: The PGU connection to an encoder chip.
+
+Example:
+
+/ {
+	...
+
+	pgu at XXXXXXXX {
+		compatible = "snps,arcpgu";
+		reg = <0xXXXXXXXX 0x400>;
+		clocks = <&clock_node>;
+		clock-names = "pxlclk";
+
+		port {
+			pgu_output: endpoint {
+				remote-endpoint = <&hdmi_enc_input>;
+			};
+		};
+	};
+};
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Mon Mar 28 04:36:34 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Mon, 28 Mar 2016 14:36:34 +0300
Subject: [PATCH 0/5 v5] drm: Add support of ARC PGU display controller
Message-ID: <1459164999-11850-1-git-send-email-abrodkin@synopsys.com>

This series add support of ARC PGU display controller.
ARC PGU is a quite simple byte streamer that gets data from the framebuffer
and pushes it to hte connected encoder (DP or HDMI).

It was tested on ARC SDP boards (axs101/103 in particular).

Note following series that introduces
drm_connector_register_all()/drm_connector_unregister_all() is a prerequisite
now: https://lkml.org/lkml/2016/3/23/61

Changes v4 -> v5:
 * Removed encode node from DT bindings example (as suggested by Rob)

Changes v3 -> v4:
 * Main driver author is now set properly (thanks Carlos for all your efforts)
 * Implemented correct hsync and vsync setup (thanks Jose)
 * Dummy call-backs were removed (as suggested by Daniel)
 * Obsolete load()/unload() call-backs were removed (as suggested by Daniel)
 * With above in mind we were able to adopt recently introduced
   drm_connector_register_all()/drm_connector_unregister_all()
 * Implemented setup of properties (uncached) for FB user-pages
 * Minor clean-up in DT binding docs and axs10x_mb.dtsi

Changes v2 -> v3:
 * Improved failure path if arcpgu_connector wasn't allocated.
 * Fixed driver building as module.
 * Implemented uncached mapping of user-space FB pages.
 * Again updated DT bindings docs.

Changes v1 -> v2:
 * Clean-up of DT bindings documentation.
 * Added missing "pxlclk" clock in axs10x_mb.dtsi.

Cc: David Airlie <airlied at linux.ie>
Cc: devicetree at vger.kernel.org
Cc: dri-devel at lists.freedesktop.org
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: linux-snps-arc at lists.infradead.org
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Vineet Gupta <vgupta at synopsys.com>
Cc: Jose Abreu <joabreu at synopsys.com>
Cc: Carlos Palminha <palminha at synopsys.com>

Alexey Brodkin (4):
  drm: Add DT bindings documentation for ARC PGU display controller
  MAINTAINERS: Add maintainer for ARC PGU display controller
  arc: Add our own implementation of fb_pgprotect()
  arc: axs10x - add support of ARC PGU

Carlos Palminha (1):
  drm: Add support of ARC PGU display controller

 .../devicetree/bindings/display/snps,arcpgu.txt    |  35 +++
 MAINTAINERS                                        |   6 +
 arch/arc/boot/dts/axs10x_mb.dtsi                   |  61 +++++
 arch/arc/include/asm/fb.h                          |  19 ++
 drivers/gpu/drm/Kconfig                            |   2 +
 drivers/gpu/drm/Makefile                           |   1 +
 drivers/gpu/drm/arc/Kconfig                        |  10 +
 drivers/gpu/drm/arc/Makefile                       |   2 +
 drivers/gpu/drm/arc/arcpgu.h                       |  50 ++++
 drivers/gpu/drm/arc/arcpgu_crtc.c                  | 257 +++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_drv.c                   | 282 +++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_hdmi.c                  | 201 +++++++++++++++
 drivers/gpu/drm/arc/arcpgu_regs.h                  |  40 +++
 13 files changed, 966 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/snps,arcpgu.txt
 create mode 100644 arch/arc/include/asm/fb.h
 create mode 100644 drivers/gpu/drm/arc/Kconfig
 create mode 100644 drivers/gpu/drm/arc/Makefile
 create mode 100644 drivers/gpu/drm/arc/arcpgu.h
 create mode 100644 drivers/gpu/drm/arc/arcpgu_crtc.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_drv.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_hdmi.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_regs.h

-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Mon Mar 28 04:36:35 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Mon, 28 Mar 2016 14:36:35 +0300
Subject: [PATCH 1/5 v5] drm: Add support of ARC PGU display controller
In-Reply-To: <1459164999-11850-1-git-send-email-abrodkin@synopsys.com>
References: <1459164999-11850-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1459164999-11850-2-git-send-email-abrodkin@synopsys.com>

From: Carlos Palminha <palminha at synopsys.com>

ARC PGU could be found on some development boards from Synopsys.
This is a simple byte streamer that reads data from a framebuffer
and sends data to the single encoder.

Signed-off-by: Carlos Palminha <palminha at synopsys.com>
Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: David Airlie <airlied at linux.ie>
Cc: dri-devel at lists.freedesktop.org
Cc: linux-snps-arc at lists.infradead.org
---

Note following series that introduces
drm_connector_register_all()/drm_connector_unregister_all() is a prerequisite
now: https://lkml.org/lkml/2016/3/23/61

No changes v4 -> v5.

Changes v3 -> v4:
 * The driver author is now set properly (thanks Carlos for all your efforts)
 * Implemented correct hsync and vsync setup (thanks Jose)
 * Dummy call-backs were removed (as suggested by Daniel)
 * Obsolete load()/unload() call-backs were removed (as suggested by Daniel)
 * With above in mind we were able to adopt recently introduced
   drm_connector_register_all()/drm_connector_unregister_all()

Changes v2 -> v3:
 * Improved failure path if arcpgu_connector wasn't allocated (thanks Jose).
 * Fixed driver building as module (reported by 0-DAY kernel test infrastruct.)
 * Implemented uncached mapping of user-space FB pages.

No changes v1 -> v2.

 drivers/gpu/drm/Kconfig           |   2 +
 drivers/gpu/drm/Makefile          |   1 +
 drivers/gpu/drm/arc/Kconfig       |  10 ++
 drivers/gpu/drm/arc/Makefile      |   2 +
 drivers/gpu/drm/arc/arcpgu.h      |  50 +++++++
 drivers/gpu/drm/arc/arcpgu_crtc.c | 257 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_drv.c  | 282 ++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_hdmi.c | 201 +++++++++++++++++++++++++++
 drivers/gpu/drm/arc/arcpgu_regs.h |  40 ++++++
 9 files changed, 845 insertions(+)
 create mode 100644 drivers/gpu/drm/arc/Kconfig
 create mode 100644 drivers/gpu/drm/arc/Makefile
 create mode 100644 drivers/gpu/drm/arc/arcpgu.h
 create mode 100644 drivers/gpu/drm/arc/arcpgu_crtc.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_drv.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_hdmi.c
 create mode 100644 drivers/gpu/drm/arc/arcpgu_regs.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index f2a74d0..9e4f2f1 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -281,3 +281,5 @@ source "drivers/gpu/drm/imx/Kconfig"
 source "drivers/gpu/drm/vc4/Kconfig"
 
 source "drivers/gpu/drm/etnaviv/Kconfig"
+
+source "drivers/gpu/drm/arc/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 6eb94fc..c338d04 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -78,3 +78,4 @@ obj-y			+= panel/
 obj-y			+= bridge/
 obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
 obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
+obj-$(CONFIG_DRM_ARCPGU)+= arc/
diff --git a/drivers/gpu/drm/arc/Kconfig b/drivers/gpu/drm/arc/Kconfig
new file mode 100644
index 0000000..f9a13b6
--- /dev/null
+++ b/drivers/gpu/drm/arc/Kconfig
@@ -0,0 +1,10 @@
+config DRM_ARCPGU
+	tristate "ARC PGU"
+	depends on DRM && OF
+	select DRM_KMS_CMA_HELPER
+	select DRM_KMS_FB_HELPER
+	select DRM_KMS_HELPER
+	help
+	  Choose this option if you have an ARC PGU controller.
+
+	  If M is selected the module will be called arcpgu.
diff --git a/drivers/gpu/drm/arc/Makefile b/drivers/gpu/drm/arc/Makefile
new file mode 100644
index 0000000..d48fda7
--- /dev/null
+++ b/drivers/gpu/drm/arc/Makefile
@@ -0,0 +1,2 @@
+arcpgu-y := arcpgu_crtc.o arcpgu_hdmi.o arcpgu_drv.o
+obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o
diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h
new file mode 100644
index 0000000..86574b6
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu.h
@@ -0,0 +1,50 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ARCPGU_H_
+#define _ARCPGU_H_
+
+struct arcpgu_drm_private {
+	void __iomem		*regs;
+	struct clk		*clk;
+	struct drm_fbdev_cma	*fbdev;
+	struct drm_framebuffer	*fb;
+	struct list_head	event_list;
+	struct drm_crtc		crtc;
+	struct drm_plane	*plane;
+};
+
+#define crtc_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, crtc)
+
+static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu,
+				 unsigned int reg, u32 value)
+{
+	iowrite32(value, arcpgu->regs + reg);
+}
+
+static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu,
+			       unsigned int reg)
+{
+	return ioread32(arcpgu->regs + reg);
+}
+
+int arc_pgu_setup_crtc(struct drm_device *dev);
+int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np);
+struct drm_fbdev_cma *arcpgu_fbdev_cma_init(struct drm_device *dev,
+	unsigned int preferred_bpp, unsigned int num_crtc,
+	unsigned int max_conn_count);
+
+#endif
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
new file mode 100644
index 0000000..92f8bef
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
@@ -0,0 +1,257 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <linux/clk.h>
+#include <linux/platform_data/simplefb.h>
+
+#include "arcpgu.h"
+#include "arcpgu_regs.h"
+
+#define ENCODE_PGU_XY(x, y)	((((x) - 1) << 16) | ((y) - 1))
+
+static struct simplefb_format supported_formats[] = {
+	{ "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0}, DRM_FORMAT_RGB565 },
+	{ "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 },
+};
+
+static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	uint32_t pixel_format = crtc->primary->state->fb->pixel_format;
+	struct simplefb_format *format = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
+		if (supported_formats[i].fourcc == pixel_format)
+			format = &supported_formats[i];
+	}
+
+	if (WARN_ON(!format))
+		return;
+
+	if (format->fourcc == DRM_FORMAT_RGB888)
+		arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+			      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) |
+					   ARCPGU_MODE_RGB888_MASK);
+
+}
+
+static const struct drm_crtc_funcs arc_pgu_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 void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	struct drm_display_mode *m = &crtc->state->adjusted_mode;
+	u32 val;
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_FMT,
+		      ENCODE_PGU_XY(m->crtc_htotal, m->crtc_vtotal));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_HSYNC,
+		      ENCODE_PGU_XY(m->crtc_hsync_start - m->crtc_hdisplay,
+				    m->crtc_hsync_end - m->crtc_hdisplay));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_VSYNC,
+		      ENCODE_PGU_XY(m->crtc_vsync_start - m->crtc_vdisplay,
+				    m->crtc_vsync_end - m->crtc_vdisplay));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_ACTIVE,
+		      ENCODE_PGU_XY(m->crtc_hblank_end - m->crtc_hblank_start,
+				    m->crtc_vblank_end - m->crtc_vblank_start));
+
+	val = arc_pgu_read(arcpgu, ARCPGU_REG_CTRL);
+
+	if (m->flags & DRM_MODE_FLAG_PVSYNC)
+		val |= ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST;
+	else
+		val &= ~(ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST);
+
+	if (m->flags & DRM_MODE_FLAG_PHSYNC)
+		val |= ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST;
+	else
+		val &= ~(ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST);
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, val);
+	arc_pgu_write(arcpgu, ARCPGU_REG_STRIDE, 0);
+	arc_pgu_write(arcpgu, ARCPGU_REG_START_SET, 1);
+
+	arc_pgu_set_pxl_fmt(crtc);
+
+	clk_set_rate(arcpgu->clk, m->crtc_clock * 1000);
+}
+
+static void arc_pgu_crtc_enable(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+
+	clk_prepare_enable(arcpgu->clk);
+	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+		      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) |
+		      ARCPGU_CTRL_ENABLE_MASK);
+}
+
+static void arc_pgu_crtc_disable(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+
+	if (!crtc->primary->fb)
+		return;
+
+	clk_disable_unprepare(arcpgu->clk);
+	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+			      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) &
+			      ~ARCPGU_CTRL_ENABLE_MASK);
+}
+
+static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc,
+				     struct drm_crtc_state *state)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	struct drm_display_mode *mode = &state->adjusted_mode;
+	long rate, clk_rate = mode->clock * 1000;
+
+	rate = clk_round_rate(arcpgu->clk, clk_rate);
+	if (rate != clk_rate)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
+				      struct drm_crtc_state *state)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	unsigned long flags;
+
+	if (crtc->state->event) {
+		struct drm_pending_vblank_event *event = crtc->state->event;
+
+		crtc->state->event = NULL;
+		event->pipe = drm_crtc_index(crtc);
+
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+		spin_lock_irqsave(&crtc->dev->event_lock, flags);
+		list_add_tail(&event->base.link, &arcpgu->event_list);
+		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+	}
+}
+
+static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
+	.mode_set	= drm_helper_crtc_mode_set,
+	.mode_set_base	= drm_helper_crtc_mode_set_base,
+	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
+	.enable		= arc_pgu_crtc_enable,
+	.disable	= arc_pgu_crtc_disable,
+	.prepare	= arc_pgu_crtc_disable,
+	.commit		= arc_pgu_crtc_enable,
+	.atomic_check	= arc_pgu_crtc_atomic_check,
+	.atomic_begin	= arc_pgu_crtc_atomic_begin,
+};
+
+static void arc_pgu_plane_atomic_update(struct drm_plane *plane,
+					struct drm_plane_state *state)
+{
+	struct arcpgu_drm_private *arcpgu;
+	struct drm_gem_cma_object *gem;
+
+	if (!plane->state->crtc || !plane->state->fb)
+		return;
+
+	arcpgu = crtc_to_arcpgu_priv(plane->state->crtc);
+	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
+	arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr);
+}
+
+static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = {
+	.prepare_fb = NULL,
+	.cleanup_fb = NULL,
+	.atomic_update = arc_pgu_plane_atomic_update,
+};
+
+static void arc_pgu_plane_destroy(struct drm_plane *plane)
+{
+	drm_plane_helper_disable(plane);
+	drm_plane_cleanup(plane);
+}
+
+static const struct drm_plane_funcs arc_pgu_plane_funcs = {
+	.update_plane		= drm_atomic_helper_update_plane,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.destroy		= arc_pgu_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 struct drm_plane *arc_pgu_plane_init(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_plane *plane = NULL;
+	u32 formats[ARRAY_SIZE(supported_formats)], i;
+	int ret;
+
+	plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
+	if (!plane)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(supported_formats); i++)
+		formats[i] = supported_formats[i].fourcc;
+
+	ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs,
+				       formats, ARRAY_SIZE(formats),
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_plane_helper_add(plane, &arc_pgu_plane_helper_funcs);
+	arcpgu->plane = plane;
+
+	return plane;
+}
+
+int arc_pgu_setup_crtc(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_plane *primary;
+	int ret;
+
+	primary = arc_pgu_plane_init(drm);
+	if (IS_ERR(primary))
+		return PTR_ERR(primary);
+
+	ret = drm_crtc_init_with_planes(drm, &arcpgu->crtc, primary, NULL,
+					&arc_pgu_crtc_funcs, NULL);
+	if (ret) {
+		arc_pgu_plane_destroy(primary);
+		return ret;
+	}
+
+	drm_crtc_helper_add(&arcpgu->crtc, &arc_pgu_crtc_helper_funcs);
+	return 0;
+}
diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c
new file mode 100644
index 0000000..5b35e5db
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_drv.c
@@ -0,0 +1,282 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "arcpgu.h"
+#include "arcpgu_regs.h"
+
+static void arcpgu_fb_output_poll_changed(struct drm_device *dev)
+{
+	struct arcpgu_drm_private *arcpgu = dev->dev_private;
+
+	if (arcpgu->fbdev)
+		drm_fbdev_cma_hotplug_event(arcpgu->fbdev);
+}
+
+static int arcpgu_atomic_commit(struct drm_device *dev,
+				    struct drm_atomic_state *state, bool async)
+{
+	return drm_atomic_helper_commit(dev, state, false);
+}
+
+static struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = {
+	.fb_create  = drm_fb_cma_create,
+	.output_poll_changed = arcpgu_fb_output_poll_changed,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = arcpgu_atomic_commit,
+};
+
+static void arcpgu_setup_mode_config(struct drm_device *drm)
+{
+	drm_mode_config_init(drm);
+	drm->mode_config.min_width = 0;
+	drm->mode_config.min_height = 0;
+	drm->mode_config.max_width = 1920;
+	drm->mode_config.max_height = 1080;
+	drm->mode_config.funcs = &arcpgu_drm_modecfg_funcs;
+}
+
+int arcpgu_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	int ret;
+
+	ret = drm_gem_mmap(filp, vma);
+	if (ret)
+		return ret;
+
+	vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags));
+	return 0;
+}
+
+static const struct file_operations arcpgu_drm_ops = {
+	.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 = no_llseek,
+	.mmap = arcpgu_gem_mmap,
+};
+
+static void arcpgu_preclose(struct drm_device *drm, struct drm_file *file)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_pending_vblank_event *e, *t;
+	unsigned long flags;
+
+	spin_lock_irqsave(&drm->event_lock, flags);
+	list_for_each_entry_safe(e, t, &arcpgu->event_list, base.link) {
+		if (e->base.file_priv != file)
+			continue;
+		list_del(&e->base.link);
+		e->base.destroy(&e->base);
+	}
+	spin_unlock_irqrestore(&drm->event_lock, flags);
+}
+
+static void arcpgu_lastclose(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+
+	drm_fbdev_cma_restore_mode(arcpgu->fbdev);
+}
+
+static int arcpgu_load(struct drm_device *drm)
+{
+	struct platform_device *pdev = to_platform_device(drm->dev);
+	struct arcpgu_drm_private *arcpgu;
+	struct device_node *encoder_node;
+	struct resource *res;
+	int ret;
+
+	arcpgu = devm_kzalloc(&pdev->dev, sizeof(*arcpgu), GFP_KERNEL);
+	if (arcpgu == NULL)
+		return -ENOMEM;
+
+	drm->dev_private = arcpgu;
+
+	arcpgu->clk = devm_clk_get(drm->dev, "pxlclk");
+	if (IS_ERR(arcpgu->clk))
+		return PTR_ERR(arcpgu->clk);
+
+	INIT_LIST_HEAD(&arcpgu->event_list);
+
+	arcpgu_setup_mode_config(drm);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	arcpgu->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(arcpgu->regs)) {
+		dev_err(drm->dev, "Could not remap IO mem\n");
+		return PTR_ERR(arcpgu->regs);
+	}
+
+	dev_info(drm->dev, "arc_pgu ID: 0x%x\n",
+		 arc_pgu_read(arcpgu, ARCPGU_REG_ID));
+
+	if (dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32)))
+		return -ENODEV;
+
+	if (arc_pgu_setup_crtc(drm) < 0)
+		return -ENODEV;
+
+	/* find the encoder node and initialize it */
+	encoder_node = of_parse_phandle(drm->dev->of_node, "encoder-slave", 0);
+	if (!encoder_node) {
+		dev_err(drm->dev, "failed to get an encoder slave node\n");
+		return -ENODEV;
+	}
+
+	ret = arcpgu_drm_hdmi_init(drm, encoder_node);
+	if (ret < 0)
+		return ret;
+
+	drm_mode_config_reset(drm);
+	drm_kms_helper_poll_init(drm);
+
+	arcpgu->fbdev = drm_fbdev_cma_init(drm, 16,
+					      drm->mode_config.num_crtc,
+					      drm->mode_config.num_connector);
+	if (IS_ERR(arcpgu->fbdev)) {
+		ret = PTR_ERR(arcpgu->fbdev);
+		arcpgu->fbdev = NULL;
+		return -ENODEV;
+	}
+
+	platform_set_drvdata(pdev, arcpgu);
+	return 0;
+}
+
+int arcpgu_unload(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+
+	if (arcpgu->fbdev) {
+		drm_fbdev_cma_fini(arcpgu->fbdev);
+		arcpgu->fbdev = NULL;
+	}
+	drm_kms_helper_poll_fini(drm);
+	drm_vblank_cleanup(drm);
+	drm_mode_config_cleanup(drm);
+
+	return 0;
+}
+
+static struct drm_driver arcpgu_drm_driver = {
+	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
+			   DRIVER_ATOMIC,
+	.preclose = arcpgu_preclose,
+	.lastclose = arcpgu_lastclose,
+	.name = "drm-arcpgu",
+	.desc = "ARC PGU Controller",
+	.date = "20160219",
+	.major = 1,
+	.minor = 0,
+	.patchlevel = 0,
+	.fops = &arcpgu_drm_ops,
+	.dumb_create = drm_gem_cma_dumb_create,
+	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
+	.dumb_destroy = drm_gem_dumb_destroy,
+	.get_vblank_counter = drm_vblank_no_hw_counter,
+	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+	.gem_free_object = drm_gem_cma_free_object,
+	.gem_vm_ops = &drm_gem_cma_vm_ops,
+	.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,
+};
+
+static int arcpgu_probe(struct platform_device *pdev)
+{
+	struct drm_device *drm;
+	int ret;
+
+	drm = drm_dev_alloc(&arcpgu_drm_driver, &pdev->dev);
+	if (!drm)
+		return -ENOMEM;
+
+	ret = arcpgu_load(drm);
+	if (ret)
+		goto err_unref;
+
+	ret = drm_dev_register(drm, 0);
+	if (ret)
+		goto err_unload;
+
+	ret = drm_connector_register_all(drm);
+	if (ret)
+		goto err_unregister;
+
+	return 0;
+
+err_unregister:
+	drm_dev_unregister(drm);
+
+err_unload:
+	arcpgu_unload(drm);
+
+err_unref:
+	drm_dev_unref(drm);
+
+	return ret;
+}
+
+static int arcpgu_remove(struct platform_device *pdev)
+{
+	struct drm_device *drm = platform_get_drvdata(pdev);
+
+	drm_connector_unregister_all(drm);
+	drm_dev_unregister(drm);
+	arcpgu_unload(drm);
+	drm_dev_unref(drm);
+
+	return 0;
+}
+
+static const struct of_device_id arcpgu_of_table[] = {
+	{.compatible = "snps,arcpgu"},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, arcpgu_of_table);
+
+static struct platform_driver arcpgu_platform_driver = {
+	.probe = arcpgu_probe,
+	.remove = arcpgu_remove,
+	.driver = {
+		   .name = "arcpgu",
+		   .of_match_table = arcpgu_of_table,
+		   },
+};
+
+module_platform_driver(arcpgu_platform_driver);
+
+MODULE_AUTHOR("Carlos Palminha <palminha at synopsys.com>");
+MODULE_DESCRIPTION("ARC PGU DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c
new file mode 100644
index 0000000..08b6bae
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c
@@ -0,0 +1,201 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "arcpgu.h"
+
+struct arcpgu_drm_connector {
+	struct drm_connector connector;
+	struct drm_encoder_slave *encoder_slave;
+};
+
+static int arcpgu_drm_connector_get_modes(struct drm_connector *connector)
+{
+	const struct drm_encoder_slave_funcs *sfuncs;
+	struct drm_encoder_slave *slave;
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_get_modes: cannot find slave encoder for connector\n");
+		return 0;
+	}
+
+	sfuncs = slave->slave_funcs;
+	if (sfuncs->get_modes == NULL)
+		return 0;
+
+	return sfuncs->get_modes(&slave->base, connector);
+}
+
+struct drm_encoder *
+arcpgu_drm_connector_best_encoder(struct drm_connector *connector)
+{
+	struct drm_encoder_slave *slave;
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_best_encoder: cannot find slave encoder for connector\n");
+		return NULL;
+	}
+
+	return &slave->base;
+}
+
+static enum drm_connector_status
+arcpgu_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	enum drm_connector_status status = connector_status_unknown;
+	const struct drm_encoder_slave_funcs *sfuncs;
+	struct drm_encoder_slave *slave;
+
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_detect: cannot find slave encoder for connector\n");
+		return status;
+	}
+
+	sfuncs = slave->slave_funcs;
+	if (sfuncs && sfuncs->detect)
+		return sfuncs->detect(&slave->base, connector);
+
+	dev_err(connector->dev->dev, "connector_detect: could not detect slave funcs\n");
+	return status;
+}
+
+static void arcpgu_drm_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_helper_funcs
+arcpgu_drm_connector_helper_funcs = {
+	.get_modes = arcpgu_drm_connector_get_modes,
+	.best_encoder = arcpgu_drm_connector_best_encoder,
+};
+
+static const struct drm_connector_funcs arcpgu_drm_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = arcpgu_drm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = arcpgu_drm_connector_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static struct drm_encoder_helper_funcs arcpgu_drm_encoder_helper_funcs = {
+	.dpms = drm_i2c_encoder_dpms,
+	.mode_fixup = drm_i2c_encoder_mode_fixup,
+	.mode_set = drm_i2c_encoder_mode_set,
+	.prepare = drm_i2c_encoder_prepare,
+	.commit = drm_i2c_encoder_commit,
+	.detect = drm_i2c_encoder_detect,
+};
+
+static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np)
+{
+	struct arcpgu_drm_connector *arcpgu_connector;
+	struct drm_i2c_encoder_driver *driver;
+	struct drm_encoder_slave *encoder;
+	struct drm_connector *connector;
+	struct i2c_client *i2c_slave;
+	int ret;
+
+	encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL);
+	if (encoder == NULL)
+		return -ENOMEM;
+
+	i2c_slave = of_find_i2c_device_by_node(np);
+	if (!i2c_slave || !i2c_get_clientdata(i2c_slave)) {
+		dev_err(drm->dev, "failed to find i2c slave encoder\n");
+		return -EPROBE_DEFER;
+	}
+
+	if (i2c_slave->dev.driver == NULL) {
+		dev_err(drm->dev, "failed to find i2c slave driver\n");
+		return -EPROBE_DEFER;
+	}
+
+	driver =
+	    to_drm_i2c_encoder_driver(to_i2c_driver(i2c_slave->dev.driver));
+	ret = driver->encoder_init(i2c_slave, drm, encoder);
+	if (ret) {
+		dev_err(drm->dev, "failed to initialize i2c encoder slave\n");
+		return ret;
+	}
+
+	encoder->base.possible_crtcs = 1;
+	encoder->base.possible_clones = 0;
+	ret = drm_encoder_init(drm, &encoder->base, &arcpgu_drm_encoder_funcs,
+			       DRM_MODE_ENCODER_TMDS, NULL);
+	if (ret)
+		return ret;
+
+	drm_encoder_helper_add(&encoder->base,
+			       &arcpgu_drm_encoder_helper_funcs);
+
+	arcpgu_connector = devm_kzalloc(drm->dev, sizeof(*arcpgu_connector),
+					GFP_KERNEL);
+	if (!arcpgu_connector) {
+		ret = -ENOMEM;
+		goto error_encoder_cleanup;
+	}
+
+	connector = &arcpgu_connector->connector;
+	drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs);
+	ret = drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs,
+			DRM_MODE_CONNECTOR_HDMIA);
+	if (ret < 0) {
+		dev_err(drm->dev, "failed to initialize drm connector\n");
+		goto error_encoder_cleanup;
+	}
+
+	ret = drm_mode_connector_attach_encoder(connector, &encoder->base);
+	if (ret < 0) {
+		dev_err(drm->dev, "could not attach connector to encoder\n");
+		drm_connector_unregister(connector);
+		goto error_connector_cleanup;
+	}
+
+	arcpgu_connector->encoder_slave = encoder;
+
+	return 0;
+
+error_connector_cleanup:
+	drm_connector_cleanup(connector);
+
+error_encoder_cleanup:
+	drm_encoder_cleanup(&encoder->base);
+	return ret;
+}
diff --git a/drivers/gpu/drm/arc/arcpgu_regs.h b/drivers/gpu/drm/arc/arcpgu_regs.h
new file mode 100644
index 0000000..95a13a8
--- /dev/null
+++ b/drivers/gpu/drm/arc/arcpgu_regs.h
@@ -0,0 +1,40 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ARC_PGU_REGS_H_
+#define _ARC_PGU_REGS_H_
+
+#define ARCPGU_REG_CTRL		0x00
+#define ARCPGU_REG_STAT		0x04
+#define ARCPGU_REG_FMT		0x10
+#define ARCPGU_REG_HSYNC	0x14
+#define ARCPGU_REG_VSYNC	0x18
+#define ARCPGU_REG_ACTIVE	0x1c
+#define ARCPGU_REG_BUF0_ADDR	0x40
+#define ARCPGU_REG_STRIDE	0x50
+#define ARCPGU_REG_START_SET	0x84
+
+#define ARCPGU_REG_ID		0x3FC
+
+#define ARCPGU_CTRL_ENABLE_MASK	0x02
+#define ARCPGU_CTRL_VS_POL_MASK	0x1
+#define ARCPGU_CTRL_VS_POL_OFST	0x3
+#define ARCPGU_CTRL_HS_POL_MASK	0x1
+#define ARCPGU_CTRL_HS_POL_OFST	0x4
+#define ARCPGU_MODE_RGB888_MASK	0x04
+#define ARCPGU_STAT_BUSY_MASK	0x02
+
+#endif
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Mon Mar 28 04:36:38 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Mon, 28 Mar 2016 14:36:38 +0300
Subject: [PATCH 4/5 v5] arc: Add our own implementation of fb_pgprotect()
In-Reply-To: <1459164999-11850-1-git-send-email-abrodkin@synopsys.com>
References: <1459164999-11850-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1459164999-11850-5-git-send-email-abrodkin@synopsys.com>

During mmaping of frame-buffer pages to user-space
fb_protect() is called to set proper page settings.

In case of ARC we need to mark pages that are mmaped to
user as uncached because of 2 reasons:
 * Huge amount of data if passing through data cache will
   thrash cache a lot making cache almost useless for other
   less traffic hungry processes.
 * Data written by user in FB will be immediately available for
   hardware (such as PGU etc) without requirements to flush data
   cache regularly.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Vineet Gupta <vgupta at synopsys.com>
Cc: linux-snps-arc at lists.infradead.org
---

No changes v4 -> v5.

Changes v3 -> v4:
 * This change was introduced only in v4.

 arch/arc/include/asm/fb.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 arch/arc/include/asm/fb.h

diff --git a/arch/arc/include/asm/fb.h b/arch/arc/include/asm/fb.h
new file mode 100644
index 0000000..bd3f68c
--- /dev/null
+++ b/arch/arc/include/asm/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H_ */
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Mon Mar 28 04:36:37 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Mon, 28 Mar 2016 14:36:37 +0300
Subject: [PATCH 3/5 v5] MAINTAINERS: Add maintainer for ARC PGU display
 controller
In-Reply-To: <1459164999-11850-1-git-send-email-abrodkin@synopsys.com>
References: <1459164999-11850-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1459164999-11850-4-git-send-email-abrodkin@synopsys.com>

This updates MAINTEINERS file with information about maintainer of
ARC PGU display controller driver.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: linux-snps-arc at lists.infradead.org
---

No changes v4 -> v5.

No changes v3 -> v4.

No changes v2 -> v3.

No changes v1 -> v2.

 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ea1d1de..0dcba67 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -827,6 +827,12 @@ S:	Maintained
 F:	drivers/net/arcnet/
 F:	include/uapi/linux/if_arcnet.h
 
+ARC PGU DRM DRIVER
+M:	Alexey Brodkin <abrodkin at synopsys.com>
+S:	Supported
+F:	drivers/gpu/drm/arc/
+F:	Documentation/devicetree/bindings/display/snps,arcpgu.txt
+
 ARM HDLCD DRM DRIVER
 M:	Liviu Dudau <liviu.dudau at arm.com>
 S:	Supported
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Mon Mar 28 04:36:39 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Mon, 28 Mar 2016 14:36:39 +0300
Subject: [PATCH 5/5 v5] arc: axs10x - add support of ARC PGU
In-Reply-To: <1459164999-11850-1-git-send-email-abrodkin@synopsys.com>
References: <1459164999-11850-1-git-send-email-abrodkin@synopsys.com>
Message-ID: <1459164999-11850-6-git-send-email-abrodkin@synopsys.com>

Synopsys DesignWare ARC SDP boards sport ARC SDP display
controller attached to ADV7511 HDMI encoder.

That change adds desctiption of both ARC PGU and ADV7511 in
ARC SDP'd base-board Device Tree.

Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: Vineet Gupta <vgupta at synopsys.com>
Cc: devicetree at vger.kernel.org
Cc: linux-snps-arc at lists.infradead.org
---

No changes v4 -> v5.

Changes v3 -> v4:
 * Removed "0x" from node names (as suggested by Rob)

No changes v2 -> v3.

Changes v1 -> v2:
 * Added missing "pxlclk" clock in axs10x_mb.dtsi

 arch/arc/boot/dts/axs10x_mb.dtsi | 61 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
index 44a578c..8fee596 100644
--- a/arch/arc/boot/dts/axs10x_mb.dtsi
+++ b/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -34,6 +34,12 @@
 				clock-frequency = <50000000>;
 				#clock-cells = <0>;
 			};
+
+			pguclk: pguclk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <74440000>;
+			};
 		};
 
 		ethernet at 0x18000 {
@@ -147,6 +153,37 @@
 			clocks = <&i2cclk>;
 			interrupts = <16>;
 
+			adv7511:adv7511 at 39{
+				compatible="adi,adv7511";
+				reg = <0x39>;
+				interrupts = <23>;
+				adi,input-depth = <8>;
+				adi,input-colorspace = "rgb";
+				adi,input-clock = "1x";
+				adi,clock-delay = <0x03>;
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					/* RGB/YUV input */
+					port at 0 {
+						reg = <0>;
+						adv7511_input:endpoint {
+						remote-endpoint = <&pgu_output>;
+						};
+					};
+
+					/* HDMI output */
+					port at 1 {
+						reg = <1>;
+						adv7511_output: endpoint {
+							remote-endpoint = <&hdmi_connector_in>;
+						};
+					};
+				};
+			};
+
 			eeprom at 0x54{
 				compatible = "24c01";
 				reg = <0x54>;
@@ -160,6 +197,16 @@
 			};
 		};
 
+		hdmi0: connector {
+			compatible = "hdmi-connector";
+			type = "a";
+			port {
+				hdmi_connector_in: endpoint {
+					remote-endpoint = <&adv7511_output>;
+				};
+			};
+		};
+
 		gpio0:gpio at 13000 {
 			compatible = "snps,dw-apb-gpio";
 			reg = <0x13000 0x1000>;
@@ -221,5 +268,19 @@
 				reg = <2>;
 			};
 		};
+
+		pgu at 17000 {
+			compatible = "snps,arcpgu";
+			reg = <0x17000 0x400>;
+			encoder-slave = <&adv7511>;
+			clocks = <&pguclk>;
+			clock-names = "pxlclk";
+
+			port {
+				pgu_output: endpoint {
+					remote-endpoint = <&adv7511_input>;
+				};
+			};
+		};
 	};
 };
-- 
2.5.0



From Alexey.Brodkin at synopsys.com  Mon Mar 28 04:48:35 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Mon, 28 Mar 2016 11:48:35 +0000
Subject: [PATCH 2/4] ARC: axs10x: Update defconfigs so that audio is
 enabled
In-Reply-To: <88015401488eed4f253f49d5831be13e0007339f.1458839710.git.joabreu@synopsys.com>
References: <cover.1458839710.git.joabreu@synopsys.com>
 <88015401488eed4f253f49d5831be13e0007339f.1458839710.git.joabreu@synopsys.com>
Message-ID: <1459165715.4785.71.camel@synopsys.com>

Hi Jose,

On Mon, 2016-03-28 at 10:41 +0100, Jose Abreu wrote:
> The defconfigs for the AXS boards were updated so that
> ALSA SoC is enabled and also the audio for the ADV7511
> HDMI transmitter.
> 
> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
> ---
> ?arch/arc/configs/axs101_defconfig?????| 3 +++
> ?arch/arc/configs/axs103_defconfig?????| 5 +++++
> ?arch/arc/configs/axs103_smp_defconfig | 5 +++++
> ?3 files changed, 13 insertions(+)

As Vineet suggested here?http://lists.infradead.org/pipermail/linux-snps-arc/2016-February/000595.html
let's not pollute axs10x_defconfigs with new stuff but instead add all new
options to new configs that will cover everything available on ARC SDP boards.

Since those defconfigs for full SDP doesn't exist as of today please drop that change
as well as "[PATCH 4/4] ARC: axs10x: Update defconfigs so that I2S is enabled" from that
series.

I'll try to come up with mentioed new configs ASAP and then if your series is
already in upstream I'll add bits for audio through HDMI otherwise you'll add it
in some follow-up series.

-Alexey

From Alexey.Brodkin at synopsys.com  Mon Mar 28 04:55:45 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Mon, 28 Mar 2016 11:55:45 +0000
Subject: [PATCH 3/4] ASoC: dwc: Add I2S HDMI audio support using custom
 platform driver
In-Reply-To: <7aaad0b57652fc724be7b447790c194645321173.1458839710.git.joabreu@synopsys.com>
References: <cover.1458839710.git.joabreu@synopsys.com>
 <7aaad0b57652fc724be7b447790c194645321173.1458839710.git.joabreu@synopsys.com>
Message-ID: <1459166144.4785.77.camel@synopsys.com>

Hi Jose,

On Mon, 2016-03-28 at 10:41 +0100, Jose Abreu wrote:
> HDMI audio support was added to the AXS board using an
> I2S cpu driver and a custom platform driver.
> 
> The platform driver supports two channels @ 16 bits with
> rates 32k, 44.1k and 48k. ALSA Simple audio card is used to
> glue the cpu, platform and codec driver (adv7511).
> 
> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
> ---
> ?arch/arc/boot/dts/axs10x_mb.dtsi |??20 +-

You should not mix DT bindings for a particular board with generic driver
fixes or improvements.

I think it makes sense to split this patch in 2:
?1) Driver improvements
?2) .dts update for boards that use this driver

> ?sound/soc/dwc/Kconfig????????????|???1 +
> ?sound/soc/dwc/designware_i2s.c???| 384 +++++++++++++++++++++++++++++++++++++--
> ?3 files changed, 388 insertions(+), 17 deletions(-)

-Alexey

From Jose.Abreu at synopsys.com  Mon Mar 28 07:36:08 2016
From: Jose.Abreu at synopsys.com (Jose Abreu)
Date: Mon, 28 Mar 2016 15:36:08 +0100
Subject: [PATCH 0/3 v2] Add I2S/ADV7511 audio support for ARC AXS10x boards
Message-ID: <cover.1459174494.git.joabreu@synopsys.com>

ARC AXS10x platforms consist of a mainboard with several peripherals.
One of those peripherals is an HDMI output port controlled by the ADV7511
transmitter.

This patch set adds audio for the ADV7511 transmitter and I2S audio for
the AXS10x platform.

Changes v1 -> v2:
* DT bindings moved to separate patch (as suggested by Alexey Brodkin)
* Removed defconfigs entries (as suggested by Alexey Brodkin)

Jose Abreu (3):
  drm/i2c/adv7511: Add audio support
  ASoC: dwc: Add I2S HDMI audio support
  arc: axs10x: Add support for Designware I2S on DT

 arch/arc/boot/dts/axs10x_mb.dtsi    |   49 +-
 drivers/gpu/drm/i2c/Kconfig         |   11 +
 drivers/gpu/drm/i2c/Makefile        |    2 +
 drivers/gpu/drm/i2c/adv7511.c       | 1024 -----------------------------------
 drivers/gpu/drm/i2c/adv7511.h       |   41 ++
 drivers/gpu/drm/i2c/adv7511_audio.c |  310 +++++++++++
 drivers/gpu/drm/i2c/adv7511_core.c  | 1005 ++++++++++++++++++++++++++++++++++
 include/sound/soc-dai.h             |    1 +
 sound/soc/dwc/Kconfig               |    1 +
 sound/soc/dwc/designware_i2s.c      |  385 ++++++++++++-
 10 files changed, 1788 insertions(+), 1041 deletions(-)
 delete mode 100644 drivers/gpu/drm/i2c/adv7511.c
 create mode 100644 drivers/gpu/drm/i2c/adv7511_audio.c
 create mode 100644 drivers/gpu/drm/i2c/adv7511_core.c

-- 
1.9.1




From Jose.Abreu at synopsys.com  Mon Mar 28 07:36:10 2016
From: Jose.Abreu at synopsys.com (Jose Abreu)
Date: Mon, 28 Mar 2016 15:36:10 +0100
Subject: [PATCH 2/3 v2] ASoC: dwc: Add I2S HDMI audio support
In-Reply-To: <cover.1459174494.git.joabreu@synopsys.com>
References: <cover.1459174494.git.joabreu@synopsys.com>
Message-ID: <538be366488bf0d7633d702f2d0bab16707b7a47.1459174494.git.joabreu@synopsys.com>

HDMI audio support was added to the AXS board using an
I2S cpu driver and a custom platform driver.

The platform driver supports two channels @ 16 bits with
rates 32k, 44.1k and 48k. ALSA Simple audio card is used to
glue the cpu, platform and codec driver (adv7511).

Signed-off-by: Jose Abreu <joabreu at synopsys.com>
---

No changes v1 -> v2.

 sound/soc/dwc/Kconfig          |   1 +
 sound/soc/dwc/designware_i2s.c | 385 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 373 insertions(+), 13 deletions(-)

diff --git a/sound/soc/dwc/Kconfig b/sound/soc/dwc/Kconfig
index d50e085..bc3fae7 100644
--- a/sound/soc/dwc/Kconfig
+++ b/sound/soc/dwc/Kconfig
@@ -2,6 +2,7 @@ config SND_DESIGNWARE_I2S
 	tristate "Synopsys I2S Device Driver"
 	depends on CLKDEV_LOOKUP
 	select SND_SOC_GENERIC_DMAENGINE_PCM
+	select SND_SIMPLE_CARD
 	help
 	 Say Y or M if you want to add support for I2S driver for
 	 Synopsys desigwnware I2S device. The device supports upto
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
index bff258d..0f2f588 100644
--- a/sound/soc/dwc/designware_i2s.c
+++ b/sound/soc/dwc/designware_i2s.c
@@ -84,11 +84,37 @@
 #define MAX_CHANNEL_NUM		8
 #define MIN_CHANNEL_NUM		2
 
+/* FPGA Version Info */
+#define FPGA_VER_INFO	0xE0011230
+#define FPGA_VER_27M	0x000FBED9
+
+/* PLL registers addresses */
+#define PLL_IDIV_ADDR	0xE00100A0
+#define PLL_FBDIV_ADDR	0xE00100A4
+#define PLL_ODIV0_ADDR	0xE00100A8
+#define PLL_ODIV1_ADDR	0xE00100AC
+
+/* PCM definitions */
+#define BUFFER_BYTES_MAX	384000
+#define PERIOD_BYTES_MIN	2048
+#define PERIODS_MIN		8
+
 union dw_i2s_snd_dma_data {
 	struct i2s_dma_data pd;
 	struct snd_dmaengine_dai_dma_data dt;
 };
 
+struct dw_pcm_binfo {
+	struct snd_pcm_substream *stream;
+	unsigned char *dma_base;
+	unsigned char *dma_pointer;
+	unsigned int period_size_frames;
+	unsigned int size;
+	snd_pcm_uframes_t period_pointer;
+	unsigned int total_periods;
+	unsigned int current_period;
+};
+
 struct dw_i2s_dev {
 	void __iomem *i2s_base;
 	struct clk *clk;
@@ -100,14 +126,103 @@ struct dw_i2s_dev {
 	struct device *dev;
 	u32 ccr;
 	u32 xfer_resolution;
+	u32 xfer_bytes;
+	u32 fifo_th;
 
 	/* data related to DMA transfers b/w i2s and DMAC */
 	union dw_i2s_snd_dma_data play_dma_data;
 	union dw_i2s_snd_dma_data capture_dma_data;
 	struct i2s_clk_config_data config;
 	int (*i2s_clk_cfg)(struct i2s_clk_config_data *config);
+	struct dw_pcm_binfo binfo;
+};
+
+struct dw_i2s_pll {
+	unsigned int rate;
+	unsigned int data_width;
+	unsigned int idiv;
+	unsigned int fbdiv;
+	unsigned int odiv0;
+	unsigned int odiv1;
+};
+
+static const struct dw_i2s_pll dw_i2s_pll_cfg_27m[] = {
+	/* 27Mhz */
+	{ 32000, 16, 0x104, 0x451, 0x10E38, 0x2000 },
+	{ 44100, 16, 0x104, 0x596, 0x10D35, 0x2000 },
+	{ 48000, 16, 0x208, 0xA28, 0x10B2C, 0x2000 },
+	{ 0, 0, 0, 0, 0, 0 },
 };
 
+static const struct dw_i2s_pll dw_i2s_pll_cfg_28m[] = {
+	/* 28.224Mhz */
+	{ 32000, 16, 0x82, 0x105, 0x107DF, 0x2000 },
+	{ 44100, 16, 0x28A, 0x1, 0x10001, 0x2000 },
+	{ 48000, 16, 0xA28, 0x187, 0x10042, 0x2000 },
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static const struct snd_pcm_hardware dw_pcm_hw = {
+	.info       = SNDRV_PCM_INFO_INTERLEAVED |
+			SNDRV_PCM_INFO_MMAP |
+			SNDRV_PCM_INFO_MMAP_VALID |
+			SNDRV_PCM_INFO_BLOCK_TRANSFER,
+	.rates      = SNDRV_PCM_RATE_32000 |
+			SNDRV_PCM_RATE_44100 |
+			SNDRV_PCM_RATE_48000,
+	.rate_min   = 32000,
+	.rate_max   = 48000,
+	.formats    = SNDRV_PCM_FMTBIT_S16_LE,
+	.channels_min = 2,
+	.channels_max = 2,
+	.buffer_bytes_max = BUFFER_BYTES_MAX,
+	.period_bytes_min = PERIOD_BYTES_MIN,
+	.period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN,
+	.periods_min      = PERIODS_MIN,
+	.periods_max      = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
+};
+
+static int dw_pcm_transfer(u32 *lsample, u32 *rsample, int bytes, int buf_size,
+		struct dw_pcm_binfo *bi)
+{
+	struct snd_pcm_runtime *rt = NULL;
+	int i;
+
+	if (!bi)
+		return -EINVAL;
+
+	rt = bi->stream->runtime;
+
+	for (i = 0; i < buf_size; i++) {
+		if (bi->stream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			memcpy(&lsample[i], bi->dma_pointer, bytes);
+			bi->dma_pointer += bytes;
+			memcpy(&rsample[i], bi->dma_pointer, bytes);
+			bi->dma_pointer += bytes;
+		} else {
+			memcpy(bi->dma_pointer, &lsample[i], bytes);
+			bi->dma_pointer += bytes;
+			memcpy(bi->dma_pointer, &rsample[i], bytes);
+			bi->dma_pointer += bytes;
+		}
+	}
+	bi->period_pointer += bytes_to_frames(rt, bytes * 2 * buf_size);
+
+	if (bi->period_pointer >=
+			(bi->period_size_frames * bi->current_period)) {
+		bi->current_period++;
+		if (bi->current_period > bi->total_periods) {
+			bi->dma_pointer = bi->dma_base;
+			bi->period_pointer = 0;
+			bi->current_period = 1;
+		}
+
+		snd_pcm_period_elapsed(bi->stream);
+	}
+
+	return 0;
+}
+
 static inline void i2s_write_reg(void __iomem *io_base, int reg, u32 val)
 {
 	writel(val, io_base + reg);
@@ -144,20 +259,94 @@ static inline void i2s_clear_irqs(struct dw_i2s_dev *dev, u32 stream)
 	}
 }
 
+static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
+{
+	struct dw_i2s_dev *dev = dev_id;
+	u32 isr[4], sleft[dev->fifo_th], sright[dev->fifo_th];
+	int i, j;
+
+	for (i = 0; i < 4; i++)
+		isr[i] = i2s_read_reg(dev->i2s_base, ISR(i));
+
+	for (i = 0; i < 4; i++) {
+		/* Copy only to/from first two channels.
+		 *  TODO: Remaining channels
+		 */
+		if ((isr[i] & 0x10) && (i == 0) && (dev->binfo.stream->stream ==
+					SNDRV_PCM_STREAM_PLAYBACK)) {
+			/* TXFE - TX FIFO is empty */
+			dw_pcm_transfer(sleft, sright, dev->xfer_bytes,
+					dev->fifo_th, &dev->binfo);
+
+			for (j = 0; j < dev->fifo_th; j++) {
+				i2s_write_reg(dev->i2s_base, LRBR_LTHR(i),
+						sleft[j]);
+				i2s_write_reg(dev->i2s_base, RRBR_RTHR(i),
+						sright[j]);
+			}
+		} else if ((isr[i] & 0x1) && (i == 0) &&
+					(dev->binfo.stream->stream ==
+					SNDRV_PCM_STREAM_CAPTURE)) {
+			/* RSFE - RX FIFO is full */
+			for (j = 0; j < dev->fifo_th; j++) {
+				sleft[j] = i2s_read_reg(dev->i2s_base,
+						LRBR_LTHR(i));
+				sright[j] = i2s_read_reg(dev->i2s_base,
+						RRBR_RTHR(i));
+			}
+
+			dw_pcm_transfer(sleft, sright, dev->xfer_bytes,
+					dev->fifo_th, &dev->binfo);
+		}
+	}
+
+	i2s_clear_irqs(dev, SNDRV_PCM_STREAM_PLAYBACK);
+	i2s_clear_irqs(dev, SNDRV_PCM_STREAM_CAPTURE);
+
+	return IRQ_HANDLED;
+}
+
+static int i2s_pll_cfg(struct i2s_clk_config_data *config)
+{
+	const struct dw_i2s_pll *pll_cfg;
+	u32 rate = config->sample_rate;
+	u32 data_width = config->data_width;
+	int i;
+
+	if (readl((void *)FPGA_VER_INFO) <= FPGA_VER_27M)
+		pll_cfg = dw_i2s_pll_cfg_27m;
+	else
+		pll_cfg = dw_i2s_pll_cfg_28m;
+
+	for (i = 0; pll_cfg[i].rate != 0; i++) {
+		if ((pll_cfg[i].rate == rate) &&
+				(pll_cfg[i].data_width == data_width)) {
+			writel(pll_cfg[i].idiv, (void *)PLL_IDIV_ADDR);
+			writel(pll_cfg[i].fbdiv, (void *)PLL_FBDIV_ADDR);
+			writel(pll_cfg[i].odiv0, (void *)PLL_ODIV0_ADDR);
+			writel(pll_cfg[i].odiv1, (void *)PLL_ODIV1_ADDR);
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
 static void i2s_start(struct dw_i2s_dev *dev,
 		      struct snd_pcm_substream *substream)
 {
+	struct i2s_clk_config_data *config = &dev->config;
 	u32 i, irq;
 	i2s_write_reg(dev->i2s_base, IER, 1);
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		for (i = 0; i < 4; i++) {
+		for (i = 0; i < (config->chan_nr / 2); i++) {
 			irq = i2s_read_reg(dev->i2s_base, IMR(i));
 			i2s_write_reg(dev->i2s_base, IMR(i), irq & ~0x30);
 		}
 		i2s_write_reg(dev->i2s_base, ITER, 1);
 	} else {
-		for (i = 0; i < 4; i++) {
+		for (i = 0; i < (config->chan_nr / 2); i++) {
 			irq = i2s_read_reg(dev->i2s_base, IMR(i));
 			i2s_write_reg(dev->i2s_base, IMR(i), irq & ~0x03);
 		}
@@ -195,6 +384,139 @@ static void i2s_stop(struct dw_i2s_dev *dev,
 	}
 }
 
+static int dw_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_pcm_runtime *rt = substream->runtime;
+	struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai);
+
+	snd_soc_set_runtime_hwparams(substream, &dw_pcm_hw);
+	snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
+
+	rt->hw.rate_min = 32000;
+	rt->hw.rate_max = 48000;
+
+	dev->binfo.stream = substream;
+	rt->private_data = &dev->binfo;
+	return 0;
+}
+
+static int dw_pcm_close(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+static int dw_pcm_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *hw_params)
+{
+	struct snd_pcm_runtime *rt = substream->runtime;
+	struct dw_pcm_binfo *bi = rt->private_data;
+	int ret;
+
+	ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
+			params_buffer_bytes(hw_params));
+	if (ret < 0)
+		return ret;
+
+	memset(rt->dma_area, 0, params_buffer_bytes(hw_params));
+	bi->dma_base = rt->dma_area;
+	bi->dma_pointer = bi->dma_base;
+
+	return 0;
+}
+
+static int dw_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	int ret;
+
+	ret = snd_pcm_lib_free_vmalloc_buffer(substream);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int dw_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *rt = substream->runtime;
+	struct dw_pcm_binfo *bi = rt->private_data;
+	u32 buffer_size_frames = 0;
+
+	bi->period_size_frames = bytes_to_frames(rt,
+			snd_pcm_lib_period_bytes(substream));
+	bi->size = snd_pcm_lib_buffer_bytes(substream);
+	buffer_size_frames = bytes_to_frames(rt, bi->size);
+	bi->total_periods = buffer_size_frames / bi->period_size_frames;
+	bi->current_period = 1;
+
+	if ((buffer_size_frames % bi->period_size_frames) != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int dw_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static snd_pcm_uframes_t dw_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *rt = substream->runtime;
+	struct dw_pcm_binfo *bi = rt->private_data;
+
+	return bi->period_pointer;
+}
+
+static struct snd_pcm_ops dw_pcm_ops = {
+	.open      = dw_pcm_open,
+	.close     = dw_pcm_close,
+	.ioctl     = snd_pcm_lib_ioctl,
+	.hw_params = dw_pcm_hw_params,
+	.hw_free   = dw_pcm_hw_free,
+	.prepare   = dw_pcm_prepare,
+	.trigger   = dw_pcm_trigger,
+	.pointer   = dw_pcm_pointer,
+	.page      = snd_pcm_lib_get_vmalloc_page,
+	.mmap      = snd_pcm_lib_mmap_vmalloc,
+};
+
+static int dw_pcm_new(struct snd_soc_pcm_runtime *runtime)
+{
+	struct snd_pcm *pcm = runtime->pcm;
+	int ret;
+
+	ret =  snd_pcm_lib_preallocate_pages_for_all(pcm,
+			SNDRV_DMA_TYPE_DEV,
+			snd_dma_continuous_data(GFP_KERNEL),
+			dw_pcm_hw.buffer_bytes_max,
+			dw_pcm_hw.buffer_bytes_max);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static void dw_pcm_free(struct snd_pcm *pcm)
+{
+	snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+static struct snd_soc_platform_driver dw_pcm_soc_platform = {
+	.pcm_new  = dw_pcm_new,
+	.pcm_free = dw_pcm_free,
+	.ops = &dw_pcm_ops,
+};
+
 static int dw_i2s_startup(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *cpu_dai)
 {
@@ -231,14 +553,16 @@ static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
 		if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
 			i2s_write_reg(dev->i2s_base, TCR(ch_reg),
 				      dev->xfer_resolution);
-			i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
+			i2s_write_reg(dev->i2s_base, TFCR(ch_reg),
+				      dev->fifo_th - 1);
 			irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
 			i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
 			i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
 		} else {
 			i2s_write_reg(dev->i2s_base, RCR(ch_reg),
 				      dev->xfer_resolution);
-			i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
+			i2s_write_reg(dev->i2s_base, RFCR(ch_reg),
+				      dev->fifo_th - 1);
 			irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
 			i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03);
 			i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
@@ -259,22 +583,25 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
 		config->data_width = 16;
 		dev->ccr = 0x00;
 		dev->xfer_resolution = 0x02;
+		dev->xfer_bytes = 0x02;
 		break;
 
 	case SNDRV_PCM_FORMAT_S24_LE:
 		config->data_width = 24;
 		dev->ccr = 0x08;
 		dev->xfer_resolution = 0x04;
+		dev->xfer_bytes = 0x03;
 		break;
 
 	case SNDRV_PCM_FORMAT_S32_LE:
 		config->data_width = 32;
 		dev->ccr = 0x10;
 		dev->xfer_resolution = 0x05;
+		dev->xfer_bytes = 0x04;
 		break;
 
 	default:
-		dev_err(dev->dev, "designware-i2s: unsuppted PCM fmt");
+		dev_err(dev->dev, "designware-i2s: unsupported PCM fmt");
 		return -EINVAL;
 	}
 
@@ -316,6 +643,7 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
 			}
 		}
 	}
+
 	return 0;
 }
 
@@ -498,6 +826,7 @@ static int dw_configure_dai(struct dw_i2s_dev *dev,
 	 */
 	u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1);
 	u32 comp2 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp2);
+	u32 fifo_depth = 1 << (1 + COMP1_FIFO_DEPTH_GLOBAL(comp1));
 	u32 idx;
 
 	if (dev->capability & DWC_I2S_RECORD &&
@@ -536,6 +865,7 @@ static int dw_configure_dai(struct dw_i2s_dev *dev,
 		dev->capability |= DW_I2S_SLAVE;
 	}
 
+	dev->fifo_th = fifo_depth / 2;
 	return 0;
 }
 
@@ -620,7 +950,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
 	const struct i2s_platform_data *pdata = pdev->dev.platform_data;
 	struct dw_i2s_dev *dev;
 	struct resource *res;
-	int ret;
+	int ret, irq_number;
 	struct snd_soc_dai_driver *dw_i2s_dai;
 	const char *clk_id;
 
@@ -643,6 +973,19 @@ static int dw_i2s_probe(struct platform_device *pdev)
 	if (IS_ERR(dev->i2s_base))
 		return PTR_ERR(dev->i2s_base);
 
+	irq_number = platform_get_irq(pdev, 0);
+	if (irq_number <= 0) {
+		dev_err(&pdev->dev, "get irq fail\n");
+		return -EINVAL;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq_number, i2s_irq_handler,
+			IRQF_SHARED, "dw_i2s_irq_handler", dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "request irq fail\n");
+		return ret;
+	}
+
 	dev->dev = &pdev->dev;
 
 	dev->i2s_reg_comp1 = I2S_COMP_PARAM_1;
@@ -671,14 +1014,22 @@ static int dw_i2s_probe(struct platform_device *pdev)
 				return -ENODEV;
 			}
 		}
-		dev->clk = devm_clk_get(&pdev->dev, clk_id);
 
-		if (IS_ERR(dev->clk))
-			return PTR_ERR(dev->clk);
+		if (dev->i2s_clk_cfg ||
+				of_get_property(pdev->dev.of_node, "clocks", NULL)) {
+			dev->clk = devm_clk_get(&pdev->dev, clk_id);
+
+			if (IS_ERR(dev->clk))
+				return PTR_ERR(dev->clk);
 
-		ret = clk_prepare_enable(dev->clk);
-		if (ret < 0)
-			return ret;
+			ret = clk_prepare_enable(dev->clk);
+			if (ret < 0)
+				return ret;
+		} else {
+			/* Use internal PLL config */
+			dev->i2s_clk_cfg = i2s_pll_cfg;
+			dev->clk = NULL;
+		}
 	}
 
 	dev_set_drvdata(&pdev->dev, dev);
@@ -690,7 +1041,14 @@ static int dw_i2s_probe(struct platform_device *pdev)
 	}
 
 	if (!pdata) {
-		ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+		if (of_get_property(pdev->dev.of_node, "dmas", NULL)) {
+			/* Using DMA */
+			ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+		} else {
+			ret = snd_soc_register_platform(&pdev->dev,
+					&dw_pcm_soc_platform);
+		}
+
 		if (ret) {
 			dev_err(&pdev->dev,
 				"Could not register PCM: %d\n", ret);
@@ -714,6 +1072,7 @@ static int dw_i2s_remove(struct platform_device *pdev)
 		clk_disable_unprepare(dev->clk);
 
 	pm_runtime_disable(&pdev->dev);
+	snd_soc_unregister_platform(&pdev->dev);
 	return 0;
 }
 
-- 
1.9.1




From Jose.Abreu at synopsys.com  Mon Mar 28 07:36:09 2016
From: Jose.Abreu at synopsys.com (Jose Abreu)
Date: Mon, 28 Mar 2016 15:36:09 +0100
Subject: [PATCH 1/3 v2] drm/i2c/adv7511: Add audio support
In-Reply-To: <cover.1459174494.git.joabreu@synopsys.com>
References: <cover.1459174494.git.joabreu@synopsys.com>
Message-ID: <15b1936d307912ba12df7fa09ec3a7a80ac5fcef.1459174494.git.joabreu@synopsys.com>

This patch adds audio support for the ADV7511 HDMI transmitter
using ALSA SoC.

The code was ported from Analog Devices linux tree from
commit 1770c4a1e32b ("Merge remote-tracking branch
'xilinx/master' into xcomm_zynq"), which is available at:
	- https://github.com/analogdevicesinc/linux/

The main core file was renamed from adv7511.c to adv7511_core.c
so that audio and video compile into a single adv7511.ko module
and to keep up with Analog Devices kernel tree.

The audio can be disabled using menu-config so it is possible
to use only video mode.

The HDMI mode is automatically started at boot and the audio
(when enabled) registers as a codec into ALSA.

SPDIF DAI format was also added to ASoC as it is required
by adv7511 audio.

Signed-off-by: Jose Abreu <joabreu at synopsys.com>
---

No changes v1 -> v2.

 drivers/gpu/drm/i2c/Kconfig         |   11 +
 drivers/gpu/drm/i2c/Makefile        |    2 +
 drivers/gpu/drm/i2c/adv7511.c       | 1024 -----------------------------------
 drivers/gpu/drm/i2c/adv7511.h       |   41 ++
 drivers/gpu/drm/i2c/adv7511_audio.c |  310 +++++++++++
 drivers/gpu/drm/i2c/adv7511_core.c  | 1005 ++++++++++++++++++++++++++++++++++
 include/sound/soc-dai.h             |    1 +
 7 files changed, 1370 insertions(+), 1024 deletions(-)
 delete mode 100644 drivers/gpu/drm/i2c/adv7511.c
 create mode 100644 drivers/gpu/drm/i2c/adv7511_audio.c
 create mode 100644 drivers/gpu/drm/i2c/adv7511_core.c

diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig
index 22c7ed6..baed409 100644
--- a/drivers/gpu/drm/i2c/Kconfig
+++ b/drivers/gpu/drm/i2c/Kconfig
@@ -7,6 +7,17 @@ config DRM_I2C_ADV7511
 	help
 	  Support for the Analog Device ADV7511(W) and ADV7513 HDMI encoders.
 
+config DRM_I2C_ADV7511_AUDIO
+	bool "ADV7511 audio"
+	depends on DRM_I2C_ADV7511 && SND_SOC
+	default y
+	help
+	  This adds support for audio on the ADV7511(W) and ADV7513 HDMI
+	  encoders.
+
+	  By selecting this option the ADV7511 will register a codec interface
+	  into ALSA.
+
 config DRM_I2C_CH7006
 	tristate "Chrontel ch7006 TV encoder"
 	default m if DRM_NOUVEAU
diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile
index 2c72eb5..7fae13b9 100644
--- a/drivers/gpu/drm/i2c/Makefile
+++ b/drivers/gpu/drm/i2c/Makefile
@@ -1,5 +1,7 @@
 ccflags-y := -Iinclude/drm
 
+adv7511-y := adv7511_core.o
+adv7511-$(CONFIG_DRM_I2C_ADV7511_AUDIO) += adv7511_audio.o
 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511.o
 
 ch7006-y := ch7006_drv.o ch7006_mode.o
diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c
deleted file mode 100644
index a02112b..0000000
--- a/drivers/gpu/drm/i2c/adv7511.c
+++ /dev/null
@@ -1,1024 +0,0 @@
-/*
- * Analog Devices ADV7511 HDMI transmitter driver
- *
- * Copyright 2012 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
- */
-
-#include <linux/device.h>
-#include <linux/gpio/consumer.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/regmap.h>
-#include <linux/slab.h>
-
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_edid.h>
-#include <drm/drm_encoder_slave.h>
-
-#include "adv7511.h"
-
-struct adv7511 {
-	struct i2c_client *i2c_main;
-	struct i2c_client *i2c_edid;
-
-	struct regmap *regmap;
-	struct regmap *packet_memory_regmap;
-	enum drm_connector_status status;
-	bool powered;
-
-	unsigned int f_tmds;
-
-	unsigned int current_edid_segment;
-	uint8_t edid_buf[256];
-	bool edid_read;
-
-	wait_queue_head_t wq;
-	struct drm_encoder *encoder;
-
-	bool embedded_sync;
-	enum adv7511_sync_polarity vsync_polarity;
-	enum adv7511_sync_polarity hsync_polarity;
-	bool rgb;
-
-	struct edid *edid;
-
-	struct gpio_desc *gpio_pd;
-};
-
-static struct adv7511 *encoder_to_adv7511(struct drm_encoder *encoder)
-{
-	return to_encoder_slave(encoder)->slave_priv;
-}
-
-/* ADI recommended values for proper operation. */
-static const struct reg_sequence adv7511_fixed_registers[] = {
-	{ 0x98, 0x03 },
-	{ 0x9a, 0xe0 },
-	{ 0x9c, 0x30 },
-	{ 0x9d, 0x61 },
-	{ 0xa2, 0xa4 },
-	{ 0xa3, 0xa4 },
-	{ 0xe0, 0xd0 },
-	{ 0xf9, 0x00 },
-	{ 0x55, 0x02 },
-};
-
-/* -----------------------------------------------------------------------------
- * Register access
- */
-
-static const uint8_t adv7511_register_defaults[] = {
-	0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00 */
-	0x00, 0x00, 0x01, 0x0e, 0xbc, 0x18, 0x01, 0x13,
-	0x25, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */
-	0x46, 0x62, 0x04, 0xa8, 0x00, 0x00, 0x1c, 0x84,
-	0x1c, 0xbf, 0x04, 0xa8, 0x1e, 0x70, 0x02, 0x1e, /* 20 */
-	0x00, 0x00, 0x04, 0xa8, 0x08, 0x12, 0x1b, 0xac,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 */
-	0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0,
-	0x00, 0x50, 0x90, 0x7e, 0x79, 0x70, 0x00, 0x00, /* 40 */
-	0x00, 0xa8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x00, /* 50 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 60 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 70 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 80 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 90 */
-	0x0b, 0x02, 0x00, 0x18, 0x5a, 0x60, 0x00, 0x00,
-	0x00, 0x00, 0x80, 0x80, 0x08, 0x04, 0x00, 0x00, /* a0 */
-	0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x14,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b0 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c0 */
-	0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0x04,
-	0x30, 0xff, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, /* d0 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01,
-	0x80, 0x75, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, /* e0 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x11, 0x00, /* f0 */
-	0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-static bool adv7511_register_volatile(struct device *dev, unsigned int reg)
-{
-	switch (reg) {
-	case ADV7511_REG_CHIP_REVISION:
-	case ADV7511_REG_SPDIF_FREQ:
-	case ADV7511_REG_CTS_AUTOMATIC1:
-	case ADV7511_REG_CTS_AUTOMATIC2:
-	case ADV7511_REG_VIC_DETECTED:
-	case ADV7511_REG_VIC_SEND:
-	case ADV7511_REG_AUX_VIC_DETECTED:
-	case ADV7511_REG_STATUS:
-	case ADV7511_REG_GC(1):
-	case ADV7511_REG_INT(0):
-	case ADV7511_REG_INT(1):
-	case ADV7511_REG_PLL_STATUS:
-	case ADV7511_REG_AN(0):
-	case ADV7511_REG_AN(1):
-	case ADV7511_REG_AN(2):
-	case ADV7511_REG_AN(3):
-	case ADV7511_REG_AN(4):
-	case ADV7511_REG_AN(5):
-	case ADV7511_REG_AN(6):
-	case ADV7511_REG_AN(7):
-	case ADV7511_REG_HDCP_STATUS:
-	case ADV7511_REG_BCAPS:
-	case ADV7511_REG_BKSV(0):
-	case ADV7511_REG_BKSV(1):
-	case ADV7511_REG_BKSV(2):
-	case ADV7511_REG_BKSV(3):
-	case ADV7511_REG_BKSV(4):
-	case ADV7511_REG_DDC_STATUS:
-	case ADV7511_REG_EDID_READ_CTRL:
-	case ADV7511_REG_BSTATUS(0):
-	case ADV7511_REG_BSTATUS(1):
-	case ADV7511_REG_CHIP_ID_HIGH:
-	case ADV7511_REG_CHIP_ID_LOW:
-		return true;
-	}
-
-	return false;
-}
-
-static const struct regmap_config adv7511_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-
-	.max_register = 0xff,
-	.cache_type = REGCACHE_RBTREE,
-	.reg_defaults_raw = adv7511_register_defaults,
-	.num_reg_defaults_raw = ARRAY_SIZE(adv7511_register_defaults),
-
-	.volatile_reg = adv7511_register_volatile,
-};
-
-/* -----------------------------------------------------------------------------
- * Hardware configuration
- */
-
-static void adv7511_set_colormap(struct adv7511 *adv7511, bool enable,
-				 const uint16_t *coeff,
-				 unsigned int scaling_factor)
-{
-	unsigned int i;
-
-	regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(1),
-			   ADV7511_CSC_UPDATE_MODE, ADV7511_CSC_UPDATE_MODE);
-
-	if (enable) {
-		for (i = 0; i < 12; ++i) {
-			regmap_update_bits(adv7511->regmap,
-					   ADV7511_REG_CSC_UPPER(i),
-					   0x1f, coeff[i] >> 8);
-			regmap_write(adv7511->regmap,
-				     ADV7511_REG_CSC_LOWER(i),
-				     coeff[i] & 0xff);
-		}
-	}
-
-	if (enable)
-		regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(0),
-				   0xe0, 0x80 | (scaling_factor << 5));
-	else
-		regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(0),
-				   0x80, 0x00);
-
-	regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(1),
-			   ADV7511_CSC_UPDATE_MODE, 0);
-}
-
-static int adv7511_packet_enable(struct adv7511 *adv7511, unsigned int packet)
-{
-	if (packet & 0xff)
-		regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE0,
-				   packet, 0xff);
-
-	if (packet & 0xff00) {
-		packet >>= 8;
-		regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
-				   packet, 0xff);
-	}
-
-	return 0;
-}
-
-static int adv7511_packet_disable(struct adv7511 *adv7511, unsigned int packet)
-{
-	if (packet & 0xff)
-		regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE0,
-				   packet, 0x00);
-
-	if (packet & 0xff00) {
-		packet >>= 8;
-		regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
-				   packet, 0x00);
-	}
-
-	return 0;
-}
-
-/* Coefficients for adv7511 color space conversion */
-static const uint16_t adv7511_csc_ycbcr_to_rgb[] = {
-	0x0734, 0x04ad, 0x0000, 0x1c1b,
-	0x1ddc, 0x04ad, 0x1f24, 0x0135,
-	0x0000, 0x04ad, 0x087c, 0x1b77,
-};
-
-static void adv7511_set_config_csc(struct adv7511 *adv7511,
-				   struct drm_connector *connector,
-				   bool rgb)
-{
-	struct adv7511_video_config config;
-	bool output_format_422, output_format_ycbcr;
-	unsigned int mode;
-	uint8_t infoframe[17];
-
-	if (adv7511->edid)
-		config.hdmi_mode = drm_detect_hdmi_monitor(adv7511->edid);
-	else
-		config.hdmi_mode = false;
-
-	hdmi_avi_infoframe_init(&config.avi_infoframe);
-
-	config.avi_infoframe.scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
-
-	if (rgb) {
-		config.csc_enable = false;
-		config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
-	} else {
-		config.csc_scaling_factor = ADV7511_CSC_SCALING_4;
-		config.csc_coefficents = adv7511_csc_ycbcr_to_rgb;
-
-		if ((connector->display_info.color_formats &
-		     DRM_COLOR_FORMAT_YCRCB422) &&
-		    config.hdmi_mode) {
-			config.csc_enable = false;
-			config.avi_infoframe.colorspace =
-				HDMI_COLORSPACE_YUV422;
-		} else {
-			config.csc_enable = true;
-			config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
-		}
-	}
-
-	if (config.hdmi_mode) {
-		mode = ADV7511_HDMI_CFG_MODE_HDMI;
-
-		switch (config.avi_infoframe.colorspace) {
-		case HDMI_COLORSPACE_YUV444:
-			output_format_422 = false;
-			output_format_ycbcr = true;
-			break;
-		case HDMI_COLORSPACE_YUV422:
-			output_format_422 = true;
-			output_format_ycbcr = true;
-			break;
-		default:
-			output_format_422 = false;
-			output_format_ycbcr = false;
-			break;
-		}
-	} else {
-		mode = ADV7511_HDMI_CFG_MODE_DVI;
-		output_format_422 = false;
-		output_format_ycbcr = false;
-	}
-
-	adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
-
-	adv7511_set_colormap(adv7511, config.csc_enable,
-			     config.csc_coefficents,
-			     config.csc_scaling_factor);
-
-	regmap_update_bits(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG1, 0x81,
-			   (output_format_422 << 7) | output_format_ycbcr);
-
-	regmap_update_bits(adv7511->regmap, ADV7511_REG_HDCP_HDMI_CFG,
-			   ADV7511_HDMI_CFG_MODE_MASK, mode);
-
-	hdmi_avi_infoframe_pack(&config.avi_infoframe, infoframe,
-				sizeof(infoframe));
-
-	/* The AVI infoframe id is not configurable */
-	regmap_bulk_write(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME_VERSION,
-			  infoframe + 1, sizeof(infoframe) - 1);
-
-	adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
-}
-
-static void adv7511_set_link_config(struct adv7511 *adv7511,
-				    const struct adv7511_link_config *config)
-{
-	/*
-	 * The input style values documented in the datasheet don't match the
-	 * hardware register field values :-(
-	 */
-	static const unsigned int input_styles[4] = { 0, 2, 1, 3 };
-
-	unsigned int clock_delay;
-	unsigned int color_depth;
-	unsigned int input_id;
-
-	clock_delay = (config->clock_delay + 1200) / 400;
-	color_depth = config->input_color_depth == 8 ? 3
-		    : (config->input_color_depth == 10 ? 1 : 2);
-
-	/* TODO Support input ID 6 */
-	if (config->input_colorspace != HDMI_COLORSPACE_YUV422)
-		input_id = config->input_clock == ADV7511_INPUT_CLOCK_DDR
-			 ? 5 : 0;
-	else if (config->input_clock == ADV7511_INPUT_CLOCK_DDR)
-		input_id = config->embedded_sync ? 8 : 7;
-	else if (config->input_clock == ADV7511_INPUT_CLOCK_2X)
-		input_id = config->embedded_sync ? 4 : 3;
-	else
-		input_id = config->embedded_sync ? 2 : 1;
-
-	regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG, 0xf,
-			   input_id);
-	regmap_update_bits(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG1, 0x7e,
-			   (color_depth << 4) |
-			   (input_styles[config->input_style] << 2));
-	regmap_write(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG2,
-		     config->input_justification << 3);
-	regmap_write(adv7511->regmap, ADV7511_REG_TIMING_GEN_SEQ,
-		     config->sync_pulse << 2);
-
-	regmap_write(adv7511->regmap, 0xba, clock_delay << 5);
-
-	adv7511->embedded_sync = config->embedded_sync;
-	adv7511->hsync_polarity = config->hsync_polarity;
-	adv7511->vsync_polarity = config->vsync_polarity;
-	adv7511->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB;
-}
-
-static void adv7511_power_on(struct adv7511 *adv7511)
-{
-	adv7511->current_edid_segment = -1;
-
-	regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
-			   ADV7511_POWER_POWER_DOWN, 0);
-	if (adv7511->i2c_main->irq) {
-		/*
-		 * Documentation says the INT_ENABLE registers are reset in
-		 * POWER_DOWN mode. My 7511w preserved the bits, however.
-		 * Still, let's be safe and stick to the documentation.
-		 */
-		regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0),
-			     ADV7511_INT0_EDID_READY);
-		regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1),
-			     ADV7511_INT1_DDC_ERROR);
-	}
-
-	/*
-	 * Per spec it is allowed to pulse the HPD signal to indicate that the
-	 * EDID information has changed. Some monitors do this when they wakeup
-	 * from standby or are enabled. When the HPD goes low the adv7511 is
-	 * reset and the outputs are disabled which might cause the monitor to
-	 * go to standby again. To avoid this we ignore the HPD pin for the
-	 * first few seconds after enabling the output.
-	 */
-	regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
-			   ADV7511_REG_POWER2_HPD_SRC_MASK,
-			   ADV7511_REG_POWER2_HPD_SRC_NONE);
-
-	/*
-	 * Most of the registers are reset during power down or when HPD is low.
-	 */
-	regcache_sync(adv7511->regmap);
-
-	adv7511->powered = true;
-}
-
-static void adv7511_power_off(struct adv7511 *adv7511)
-{
-	/* TODO: setup additional power down modes */
-	regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
-			   ADV7511_POWER_POWER_DOWN,
-			   ADV7511_POWER_POWER_DOWN);
-	regcache_mark_dirty(adv7511->regmap);
-
-	adv7511->powered = false;
-}
-
-/* -----------------------------------------------------------------------------
- * Interrupt and hotplug detection
- */
-
-static bool adv7511_hpd(struct adv7511 *adv7511)
-{
-	unsigned int irq0;
-	int ret;
-
-	ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
-	if (ret < 0)
-		return false;
-
-	if (irq0 & ADV7511_INT0_HPD) {
-		regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
-			     ADV7511_INT0_HPD);
-		return true;
-	}
-
-	return false;
-}
-
-static int adv7511_irq_process(struct adv7511 *adv7511)
-{
-	unsigned int irq0, irq1;
-	int ret;
-
-	ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
-	if (ret < 0)
-		return ret;
-
-	ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(1), &irq1);
-	if (ret < 0)
-		return ret;
-
-	regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0);
-	regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
-
-	if (irq0 & ADV7511_INT0_HPD && adv7511->encoder)
-		drm_helper_hpd_irq_event(adv7511->encoder->dev);
-
-	if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
-		adv7511->edid_read = true;
-
-		if (adv7511->i2c_main->irq)
-			wake_up_all(&adv7511->wq);
-	}
-
-	return 0;
-}
-
-static irqreturn_t adv7511_irq_handler(int irq, void *devid)
-{
-	struct adv7511 *adv7511 = devid;
-	int ret;
-
-	ret = adv7511_irq_process(adv7511);
-	return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
-}
-
-/* -----------------------------------------------------------------------------
- * EDID retrieval
- */
-
-static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout)
-{
-	int ret;
-
-	if (adv7511->i2c_main->irq) {
-		ret = wait_event_interruptible_timeout(adv7511->wq,
-				adv7511->edid_read, msecs_to_jiffies(timeout));
-	} else {
-		for (; timeout > 0; timeout -= 25) {
-			ret = adv7511_irq_process(adv7511);
-			if (ret < 0)
-				break;
-
-			if (adv7511->edid_read)
-				break;
-
-			msleep(25);
-		}
-	}
-
-	return adv7511->edid_read ? 0 : -EIO;
-}
-
-static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block,
-				  size_t len)
-{
-	struct adv7511 *adv7511 = data;
-	struct i2c_msg xfer[2];
-	uint8_t offset;
-	unsigned int i;
-	int ret;
-
-	if (len > 128)
-		return -EINVAL;
-
-	if (adv7511->current_edid_segment != block / 2) {
-		unsigned int status;
-
-		ret = regmap_read(adv7511->regmap, ADV7511_REG_DDC_STATUS,
-				  &status);
-		if (ret < 0)
-			return ret;
-
-		if (status != 2) {
-			adv7511->edid_read = false;
-			regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT,
-				     block);
-			ret = adv7511_wait_for_edid(adv7511, 200);
-			if (ret < 0)
-				return ret;
-		}
-
-		/* Break this apart, hopefully more I2C controllers will
-		 * support 64 byte transfers than 256 byte transfers
-		 */
-
-		xfer[0].addr = adv7511->i2c_edid->addr;
-		xfer[0].flags = 0;
-		xfer[0].len = 1;
-		xfer[0].buf = &offset;
-		xfer[1].addr = adv7511->i2c_edid->addr;
-		xfer[1].flags = I2C_M_RD;
-		xfer[1].len = 64;
-		xfer[1].buf = adv7511->edid_buf;
-
-		offset = 0;
-
-		for (i = 0; i < 4; ++i) {
-			ret = i2c_transfer(adv7511->i2c_edid->adapter, xfer,
-					   ARRAY_SIZE(xfer));
-			if (ret < 0)
-				return ret;
-			else if (ret != 2)
-				return -EIO;
-
-			xfer[1].buf += 64;
-			offset += 64;
-		}
-
-		adv7511->current_edid_segment = block / 2;
-	}
-
-	if (block % 2 == 0)
-		memcpy(buf, adv7511->edid_buf, len);
-	else
-		memcpy(buf, adv7511->edid_buf + 128, len);
-
-	return 0;
-}
-
-/* -----------------------------------------------------------------------------
- * Encoder operations
- */
-
-static int adv7511_get_modes(struct drm_encoder *encoder,
-			     struct drm_connector *connector)
-{
-	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
-	struct edid *edid;
-	unsigned int count;
-
-	/* Reading the EDID only works if the device is powered */
-	if (!adv7511->powered) {
-		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
-				   ADV7511_POWER_POWER_DOWN, 0);
-		if (adv7511->i2c_main->irq) {
-			regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0),
-				     ADV7511_INT0_EDID_READY);
-			regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1),
-				     ADV7511_INT1_DDC_ERROR);
-		}
-		adv7511->current_edid_segment = -1;
-	}
-
-	edid = drm_do_get_edid(connector, adv7511_get_edid_block, adv7511);
-
-	if (!adv7511->powered)
-		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
-				   ADV7511_POWER_POWER_DOWN,
-				   ADV7511_POWER_POWER_DOWN);
-
-	kfree(adv7511->edid);
-	adv7511->edid = edid;
-	if (!edid)
-		return 0;
-
-	drm_mode_connector_update_edid_property(connector, edid);
-	count = drm_add_edid_modes(connector, edid);
-
-	adv7511_set_config_csc(adv7511, connector, adv7511->rgb);
-
-	return count;
-}
-
-static void adv7511_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
-	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
-
-	if (mode == DRM_MODE_DPMS_ON)
-		adv7511_power_on(adv7511);
-	else
-		adv7511_power_off(adv7511);
-}
-
-static enum drm_connector_status
-adv7511_encoder_detect(struct drm_encoder *encoder,
-		       struct drm_connector *connector)
-{
-	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
-	enum drm_connector_status status;
-	unsigned int val;
-	bool hpd;
-	int ret;
-
-	ret = regmap_read(adv7511->regmap, ADV7511_REG_STATUS, &val);
-	if (ret < 0)
-		return connector_status_disconnected;
-
-	if (val & ADV7511_STATUS_HPD)
-		status = connector_status_connected;
-	else
-		status = connector_status_disconnected;
-
-	hpd = adv7511_hpd(adv7511);
-
-	/* The chip resets itself when the cable is disconnected, so in case
-	 * there is a pending HPD interrupt and the cable is connected there was
-	 * at least one transition from disconnected to connected and the chip
-	 * has to be reinitialized. */
-	if (status == connector_status_connected && hpd && adv7511->powered) {
-		regcache_mark_dirty(adv7511->regmap);
-		adv7511_power_on(adv7511);
-		adv7511_get_modes(encoder, connector);
-		if (adv7511->status == connector_status_connected)
-			status = connector_status_disconnected;
-	} else {
-		/* Renable HPD sensing */
-		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
-				   ADV7511_REG_POWER2_HPD_SRC_MASK,
-				   ADV7511_REG_POWER2_HPD_SRC_BOTH);
-	}
-
-	adv7511->status = status;
-	return status;
-}
-
-static int adv7511_encoder_mode_valid(struct drm_encoder *encoder,
-				      struct drm_display_mode *mode)
-{
-	if (mode->clock > 165000)
-		return MODE_CLOCK_HIGH;
-
-	return MODE_OK;
-}
-
-static void adv7511_encoder_mode_set(struct drm_encoder *encoder,
-				     struct drm_display_mode *mode,
-				     struct drm_display_mode *adj_mode)
-{
-	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
-	unsigned int low_refresh_rate;
-	unsigned int hsync_polarity = 0;
-	unsigned int vsync_polarity = 0;
-
-	if (adv7511->embedded_sync) {
-		unsigned int hsync_offset, hsync_len;
-		unsigned int vsync_offset, vsync_len;
-
-		hsync_offset = adj_mode->crtc_hsync_start -
-			       adj_mode->crtc_hdisplay;
-		vsync_offset = adj_mode->crtc_vsync_start -
-			       adj_mode->crtc_vdisplay;
-		hsync_len = adj_mode->crtc_hsync_end -
-			    adj_mode->crtc_hsync_start;
-		vsync_len = adj_mode->crtc_vsync_end -
-			    adj_mode->crtc_vsync_start;
-
-		/* The hardware vsync generator has a off-by-one bug */
-		vsync_offset += 1;
-
-		regmap_write(adv7511->regmap, ADV7511_REG_HSYNC_PLACEMENT_MSB,
-			     ((hsync_offset >> 10) & 0x7) << 5);
-		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(0),
-			     (hsync_offset >> 2) & 0xff);
-		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(1),
-			     ((hsync_offset & 0x3) << 6) |
-			     ((hsync_len >> 4) & 0x3f));
-		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(2),
-			     ((hsync_len & 0xf) << 4) |
-			     ((vsync_offset >> 6) & 0xf));
-		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(3),
-			     ((vsync_offset & 0x3f) << 2) |
-			     ((vsync_len >> 8) & 0x3));
-		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(4),
-			     vsync_len & 0xff);
-
-		hsync_polarity = !(adj_mode->flags & DRM_MODE_FLAG_PHSYNC);
-		vsync_polarity = !(adj_mode->flags & DRM_MODE_FLAG_PVSYNC);
-	} else {
-		enum adv7511_sync_polarity mode_hsync_polarity;
-		enum adv7511_sync_polarity mode_vsync_polarity;
-
-		/**
-		 * If the input signal is always low or always high we want to
-		 * invert or let it passthrough depending on the polarity of the
-		 * current mode.
-		 **/
-		if (adj_mode->flags & DRM_MODE_FLAG_NHSYNC)
-			mode_hsync_polarity = ADV7511_SYNC_POLARITY_LOW;
-		else
-			mode_hsync_polarity = ADV7511_SYNC_POLARITY_HIGH;
-
-		if (adj_mode->flags & DRM_MODE_FLAG_NVSYNC)
-			mode_vsync_polarity = ADV7511_SYNC_POLARITY_LOW;
-		else
-			mode_vsync_polarity = ADV7511_SYNC_POLARITY_HIGH;
-
-		if (adv7511->hsync_polarity != mode_hsync_polarity &&
-		    adv7511->hsync_polarity !=
-		    ADV7511_SYNC_POLARITY_PASSTHROUGH)
-			hsync_polarity = 1;
-
-		if (adv7511->vsync_polarity != mode_vsync_polarity &&
-		    adv7511->vsync_polarity !=
-		    ADV7511_SYNC_POLARITY_PASSTHROUGH)
-			vsync_polarity = 1;
-	}
-
-	if (mode->vrefresh <= 24000)
-		low_refresh_rate = ADV7511_LOW_REFRESH_RATE_24HZ;
-	else if (mode->vrefresh <= 25000)
-		low_refresh_rate = ADV7511_LOW_REFRESH_RATE_25HZ;
-	else if (mode->vrefresh <= 30000)
-		low_refresh_rate = ADV7511_LOW_REFRESH_RATE_30HZ;
-	else
-		low_refresh_rate = ADV7511_LOW_REFRESH_RATE_NONE;
-
-	regmap_update_bits(adv7511->regmap, 0xfb,
-		0x6, low_refresh_rate << 1);
-	regmap_update_bits(adv7511->regmap, 0x17,
-		0x60, (vsync_polarity << 6) | (hsync_polarity << 5));
-
-	/*
-	 * TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is
-	 * supposed to give better results.
-	 */
-
-	adv7511->f_tmds = mode->clock;
-}
-
-static const struct drm_encoder_slave_funcs adv7511_encoder_funcs = {
-	.dpms = adv7511_encoder_dpms,
-	.mode_valid = adv7511_encoder_mode_valid,
-	.mode_set = adv7511_encoder_mode_set,
-	.detect = adv7511_encoder_detect,
-	.get_modes = adv7511_get_modes,
-};
-
-/* -----------------------------------------------------------------------------
- * Probe & remove
- */
-
-static int adv7511_parse_dt(struct device_node *np,
-			    struct adv7511_link_config *config)
-{
-	const char *str;
-	int ret;
-
-	memset(config, 0, sizeof(*config));
-
-	of_property_read_u32(np, "adi,input-depth", &config->input_color_depth);
-	if (config->input_color_depth != 8 && config->input_color_depth != 10 &&
-	    config->input_color_depth != 12)
-		return -EINVAL;
-
-	ret = of_property_read_string(np, "adi,input-colorspace", &str);
-	if (ret < 0)
-		return ret;
-
-	if (!strcmp(str, "rgb"))
-		config->input_colorspace = HDMI_COLORSPACE_RGB;
-	else if (!strcmp(str, "yuv422"))
-		config->input_colorspace = HDMI_COLORSPACE_YUV422;
-	else if (!strcmp(str, "yuv444"))
-		config->input_colorspace = HDMI_COLORSPACE_YUV444;
-	else
-		return -EINVAL;
-
-	ret = of_property_read_string(np, "adi,input-clock", &str);
-	if (ret < 0)
-		return ret;
-
-	if (!strcmp(str, "1x"))
-		config->input_clock = ADV7511_INPUT_CLOCK_1X;
-	else if (!strcmp(str, "2x"))
-		config->input_clock = ADV7511_INPUT_CLOCK_2X;
-	else if (!strcmp(str, "ddr"))
-		config->input_clock = ADV7511_INPUT_CLOCK_DDR;
-	else
-		return -EINVAL;
-
-	if (config->input_colorspace == HDMI_COLORSPACE_YUV422 ||
-	    config->input_clock != ADV7511_INPUT_CLOCK_1X) {
-		ret = of_property_read_u32(np, "adi,input-style",
-					   &config->input_style);
-		if (ret)
-			return ret;
-
-		if (config->input_style < 1 || config->input_style > 3)
-			return -EINVAL;
-
-		ret = of_property_read_string(np, "adi,input-justification",
-					      &str);
-		if (ret < 0)
-			return ret;
-
-		if (!strcmp(str, "left"))
-			config->input_justification =
-				ADV7511_INPUT_JUSTIFICATION_LEFT;
-		else if (!strcmp(str, "evenly"))
-			config->input_justification =
-				ADV7511_INPUT_JUSTIFICATION_EVENLY;
-		else if (!strcmp(str, "right"))
-			config->input_justification =
-				ADV7511_INPUT_JUSTIFICATION_RIGHT;
-		else
-			return -EINVAL;
-
-	} else {
-		config->input_style = 1;
-		config->input_justification = ADV7511_INPUT_JUSTIFICATION_LEFT;
-	}
-
-	of_property_read_u32(np, "adi,clock-delay", &config->clock_delay);
-	if (config->clock_delay < -1200 || config->clock_delay > 1600)
-		return -EINVAL;
-
-	config->embedded_sync = of_property_read_bool(np, "adi,embedded-sync");
-
-	/* Hardcode the sync pulse configurations for now. */
-	config->sync_pulse = ADV7511_INPUT_SYNC_PULSE_NONE;
-	config->vsync_polarity = ADV7511_SYNC_POLARITY_PASSTHROUGH;
-	config->hsync_polarity = ADV7511_SYNC_POLARITY_PASSTHROUGH;
-
-	return 0;
-}
-
-static const int edid_i2c_addr = 0x7e;
-static const int packet_i2c_addr = 0x70;
-static const int cec_i2c_addr = 0x78;
-
-static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
-{
-	struct adv7511_link_config link_config;
-	struct adv7511 *adv7511;
-	struct device *dev = &i2c->dev;
-	unsigned int val;
-	int ret;
-
-	if (!dev->of_node)
-		return -EINVAL;
-
-	adv7511 = devm_kzalloc(dev, sizeof(*adv7511), GFP_KERNEL);
-	if (!adv7511)
-		return -ENOMEM;
-
-	adv7511->powered = false;
-	adv7511->status = connector_status_disconnected;
-
-	ret = adv7511_parse_dt(dev->of_node, &link_config);
-	if (ret)
-		return ret;
-
-	/*
-	 * The power down GPIO is optional. If present, toggle it from active to
-	 * inactive to wake up the encoder.
-	 */
-	adv7511->gpio_pd = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_HIGH);
-	if (IS_ERR(adv7511->gpio_pd))
-		return PTR_ERR(adv7511->gpio_pd);
-
-	if (adv7511->gpio_pd) {
-		mdelay(5);
-		gpiod_set_value_cansleep(adv7511->gpio_pd, 0);
-	}
-
-	adv7511->regmap = devm_regmap_init_i2c(i2c, &adv7511_regmap_config);
-	if (IS_ERR(adv7511->regmap))
-		return PTR_ERR(adv7511->regmap);
-
-	ret = regmap_read(adv7511->regmap, ADV7511_REG_CHIP_REVISION, &val);
-	if (ret)
-		return ret;
-	dev_dbg(dev, "Rev. %d\n", val);
-
-	ret = regmap_register_patch(adv7511->regmap, adv7511_fixed_registers,
-				    ARRAY_SIZE(adv7511_fixed_registers));
-	if (ret)
-		return ret;
-
-	regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR, edid_i2c_addr);
-	regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR,
-		     packet_i2c_addr);
-	regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR, cec_i2c_addr);
-	adv7511_packet_disable(adv7511, 0xffff);
-
-	adv7511->i2c_main = i2c;
-	adv7511->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1);
-	if (!adv7511->i2c_edid)
-		return -ENOMEM;
-
-	if (i2c->irq) {
-		init_waitqueue_head(&adv7511->wq);
-
-		ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
-						adv7511_irq_handler,
-						IRQF_ONESHOT, dev_name(dev),
-						adv7511);
-		if (ret)
-			goto err_i2c_unregister_device;
-	}
-
-	/* CEC is unused for now */
-	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
-		     ADV7511_CEC_CTRL_POWER_DOWN);
-
-	adv7511_power_off(adv7511);
-
-	i2c_set_clientdata(i2c, adv7511);
-
-	adv7511_set_link_config(adv7511, &link_config);
-
-	return 0;
-
-err_i2c_unregister_device:
-	i2c_unregister_device(adv7511->i2c_edid);
-
-	return ret;
-}
-
-static int adv7511_remove(struct i2c_client *i2c)
-{
-	struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
-
-	i2c_unregister_device(adv7511->i2c_edid);
-
-	kfree(adv7511->edid);
-
-	return 0;
-}
-
-static int adv7511_encoder_init(struct i2c_client *i2c, struct drm_device *dev,
-				struct drm_encoder_slave *encoder)
-{
-
-	struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
-
-	encoder->slave_priv = adv7511;
-	encoder->slave_funcs = &adv7511_encoder_funcs;
-
-	adv7511->encoder = &encoder->base;
-
-	return 0;
-}
-
-static const struct i2c_device_id adv7511_i2c_ids[] = {
-	{ "adv7511", 0 },
-	{ "adv7511w", 0 },
-	{ "adv7513", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, adv7511_i2c_ids);
-
-static const struct of_device_id adv7511_of_ids[] = {
-	{ .compatible = "adi,adv7511", },
-	{ .compatible = "adi,adv7511w", },
-	{ .compatible = "adi,adv7513", },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, adv7511_of_ids);
-
-static struct drm_i2c_encoder_driver adv7511_driver = {
-	.i2c_driver = {
-		.driver = {
-			.name = "adv7511",
-			.of_match_table = adv7511_of_ids,
-		},
-		.id_table = adv7511_i2c_ids,
-		.probe = adv7511_probe,
-		.remove = adv7511_remove,
-	},
-
-	.encoder_init = adv7511_encoder_init,
-};
-
-static int __init adv7511_init(void)
-{
-	return drm_i2c_encoder_register(THIS_MODULE, &adv7511_driver);
-}
-module_init(adv7511_init);
-
-static void __exit adv7511_exit(void)
-{
-	drm_i2c_encoder_unregister(&adv7511_driver);
-}
-module_exit(adv7511_exit);
-
-MODULE_AUTHOR("Lars-Peter Clausen <lars at metafoo.de>");
-MODULE_DESCRIPTION("ADV7511 HDMI transmitter driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/i2c/adv7511.h b/drivers/gpu/drm/i2c/adv7511.h
index 38515b3..fccb86e 100644
--- a/drivers/gpu/drm/i2c/adv7511.h
+++ b/drivers/gpu/drm/i2c/adv7511.h
@@ -10,6 +10,8 @@
 #define __DRM_I2C_ADV7511_H__
 
 #include <linux/hdmi.h>
+#include <linux/gpio/consumer.h>
+#include <drm/drmP.h>
 
 #define ADV7511_REG_CHIP_REVISION		0x00
 #define ADV7511_REG_N0				0x01
@@ -286,4 +288,43 @@ struct adv7511_video_config {
 	struct hdmi_avi_infoframe avi_infoframe;
 };
 
+struct adv7511 {
+	struct i2c_client *i2c_main;
+	struct i2c_client *i2c_edid;
+
+	struct regmap *regmap;
+	struct regmap *packet_memory_regmap;
+	enum drm_connector_status status;
+	bool powered;
+
+	unsigned int f_tmds;
+	unsigned int f_audio;
+
+	unsigned int audio_source;
+
+	unsigned int current_edid_segment;
+	uint8_t edid_buf[256];
+	bool edid_read;
+
+	wait_queue_head_t wq;
+	struct drm_encoder *encoder;
+
+	bool embedded_sync;
+	enum adv7511_sync_polarity vsync_polarity;
+	enum adv7511_sync_polarity hsync_polarity;
+	bool rgb;
+
+	struct edid *edid;
+
+	struct gpio_desc *gpio_pd;
+};
+
+int adv7511_packet_enable(struct adv7511 *adv7511, unsigned int packet);
+int adv7511_packet_disable(struct adv7511 *adv7511, unsigned int packet);
+
+#ifdef CONFIG_DRM_I2C_ADV7511_AUDIO
+int adv7511_audio_init(struct device *dev);
+void adv7511_audio_exit(struct device *dev);
+#endif
+
 #endif /* __DRM_I2C_ADV7511_H__ */
diff --git a/drivers/gpu/drm/i2c/adv7511_audio.c b/drivers/gpu/drm/i2c/adv7511_audio.c
new file mode 100644
index 0000000..5562ed5
--- /dev/null
+++ b/drivers/gpu/drm/i2c/adv7511_audio.c
@@ -0,0 +1,310 @@
+/*
+ * Analog Devices ADV7511 HDMI transmitter driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "adv7511.h"
+
+static const struct snd_soc_dapm_widget adv7511_dapm_widgets[] = {
+	SND_SOC_DAPM_OUTPUT("TMDS"),
+	SND_SOC_DAPM_AIF_IN("AIFIN", "Playback", 0, SND_SOC_NOPM, 0, 0),
+};
+
+static const struct snd_soc_dapm_route adv7511_routes[] = {
+	{ "TMDS", NULL, "AIFIN" },
+};
+
+static void adv7511_calc_cts_n(unsigned int f_tmds, unsigned int fs,
+			       unsigned int *cts, unsigned int *n)
+{
+	switch (fs) {
+	case 32000:
+		*n = 4096;
+		break;
+	case 44100:
+		*n = 6272;
+		break;
+	case 48000:
+		*n = 6144;
+		break;
+	}
+
+	*cts = ((f_tmds * *n) / (128 * fs)) * 1000;
+}
+
+static int adv7511_update_cts_n(struct adv7511 *adv7511)
+{
+	unsigned int cts = 0;
+	unsigned int n = 0;
+
+	adv7511_calc_cts_n(adv7511->f_tmds, adv7511->f_audio, &cts, &n);
+
+	regmap_write(adv7511->regmap, ADV7511_REG_N0, (n >> 16) & 0xf);
+	regmap_write(adv7511->regmap, ADV7511_REG_N1, (n >> 8) & 0xff);
+	regmap_write(adv7511->regmap, ADV7511_REG_N2, n & 0xff);
+
+	regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL0,
+		     (cts >> 16) & 0xf);
+	regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL1,
+		     (cts >> 8) & 0xff);
+	regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL2,
+		     cts & 0xff);
+
+	return 0;
+}
+
+static int adv7511_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params,
+			     struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec);
+	unsigned int rate;
+	unsigned int len;
+
+	switch (params_rate(params)) {
+	case 32000:
+		rate = ADV7511_SAMPLE_FREQ_32000;
+		break;
+	case 44100:
+		rate = ADV7511_SAMPLE_FREQ_44100;
+		break;
+	case 48000:
+		rate = ADV7511_SAMPLE_FREQ_48000;
+		break;
+	case 88200:
+		rate = ADV7511_SAMPLE_FREQ_88200;
+		break;
+	case 96000:
+		rate = ADV7511_SAMPLE_FREQ_96000;
+		break;
+	case 176400:
+		rate = ADV7511_SAMPLE_FREQ_176400;
+		break;
+	case 192000:
+		rate = ADV7511_SAMPLE_FREQ_192000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		len = ADV7511_I2S_SAMPLE_LEN_16;
+		break;
+	case SNDRV_PCM_FORMAT_S18_3LE:
+		len = ADV7511_I2S_SAMPLE_LEN_18;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		len = ADV7511_I2S_SAMPLE_LEN_20;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		len = ADV7511_I2S_SAMPLE_LEN_24;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	adv7511->f_audio = params_rate(params);
+
+	adv7511_update_cts_n(adv7511);
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG3,
+			   ADV7511_AUDIO_CFG3_LEN_MASK, len);
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG,
+			   ADV7511_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4);
+
+	return 0;
+}
+
+static int adv7511_set_dai_fmt(struct snd_soc_dai *codec_dai,
+			       unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec);
+	unsigned int audio_source, i2s_format = 0;
+	unsigned int invert_clock;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		audio_source = ADV7511_AUDIO_SOURCE_I2S;
+		i2s_format = ADV7511_I2S_FORMAT_I2S;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		audio_source = ADV7511_AUDIO_SOURCE_I2S;
+		i2s_format = ADV7511_I2S_FORMAT_RIGHT_J;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		audio_source = ADV7511_AUDIO_SOURCE_I2S;
+		i2s_format = ADV7511_I2S_FORMAT_LEFT_J;
+		break;
+	case SND_SOC_DAIFMT_SPDIF:
+		audio_source = ADV7511_AUDIO_SOURCE_SPDIF;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		invert_clock = 0;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		invert_clock = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_SOURCE, 0x70,
+			   audio_source << 4);
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG, BIT(6),
+			   invert_clock << 6);
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_I2S_CONFIG, 0x03,
+			   i2s_format);
+
+	adv7511->audio_source = audio_source;
+
+	return 0;
+}
+
+static int adv7511_set_bias_level(struct snd_soc_codec *codec,
+				  enum snd_soc_bias_level level)
+{
+	struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec);
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		switch (adv7511->audio_source) {
+		case ADV7511_AUDIO_SOURCE_I2S:
+			break;
+		case ADV7511_AUDIO_SOURCE_SPDIF:
+			regmap_update_bits(adv7511->regmap,
+					   ADV7511_REG_AUDIO_CONFIG, BIT(7),
+					   BIT(7));
+			break;
+		}
+		break;
+	case SND_SOC_BIAS_PREPARE:
+		if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) {
+			adv7511_packet_enable(adv7511,
+					ADV7511_PACKET_ENABLE_AUDIO_SAMPLE);
+			adv7511_packet_enable(adv7511,
+					ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME);
+			adv7511_packet_enable(adv7511,
+					ADV7511_PACKET_ENABLE_N_CTS);
+		} else {
+			adv7511_packet_disable(adv7511,
+					ADV7511_PACKET_ENABLE_AUDIO_SAMPLE);
+			adv7511_packet_disable(adv7511,
+					ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME);
+			adv7511_packet_disable(adv7511,
+					ADV7511_PACKET_ENABLE_N_CTS);
+		}
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
+				   BIT(7), 0);
+		break;
+	case SND_SOC_BIAS_OFF:
+		break;
+	}
+	return 0;
+}
+
+#define ADV7511_RATES (SNDRV_PCM_RATE_32000 |\
+		SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
+		SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\
+		SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
+
+#define ADV7511_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\
+		SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
+
+static const struct snd_soc_dai_ops adv7511_dai_ops = {
+	.hw_params	= adv7511_hw_params,
+	/*.set_sysclk	= adv7511_set_dai_sysclk,*/
+	.set_fmt	= adv7511_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver adv7511_dai = {
+	.name = "adv7511",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = ADV7511_RATES,
+		.formats = ADV7511_FORMATS,
+	},
+	.ops = &adv7511_dai_ops,
+};
+
+static int adv7511_suspend(struct snd_soc_codec *codec)
+{
+	return adv7511_set_bias_level(codec, SND_SOC_BIAS_OFF);
+}
+
+static int adv7511_resume(struct snd_soc_codec *codec)
+{
+	return adv7511_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+}
+
+static int adv7511_probe(struct snd_soc_codec *codec)
+{
+	return adv7511_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+}
+
+static int adv7511_remove(struct snd_soc_codec *codec)
+{
+	adv7511_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static struct snd_soc_codec_driver adv7511_codec_driver = {
+	.probe		    = adv7511_probe,
+	.remove		    = adv7511_remove,
+	.suspend	    = adv7511_suspend,
+	.resume		    = adv7511_resume,
+	.set_bias_level	    = adv7511_set_bias_level,
+
+	.dapm_widgets	    = adv7511_dapm_widgets,
+	.num_dapm_widgets   = ARRAY_SIZE(adv7511_dapm_widgets),
+	.dapm_routes	    = adv7511_routes,
+	.num_dapm_routes    = ARRAY_SIZE(adv7511_routes),
+};
+
+int adv7511_audio_init(struct device *dev)
+{
+	return snd_soc_register_codec(dev, &adv7511_codec_driver,
+			&adv7511_dai, 1);
+}
+
+void adv7511_audio_exit(struct device *dev)
+{
+	snd_soc_unregister_codec(dev);
+}
diff --git a/drivers/gpu/drm/i2c/adv7511_core.c b/drivers/gpu/drm/i2c/adv7511_core.c
new file mode 100644
index 0000000..d54256a
--- /dev/null
+++ b/drivers/gpu/drm/i2c/adv7511_core.c
@@ -0,0 +1,1005 @@
+/*
+ * Analog Devices ADV7511 HDMI transmitter driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_encoder_slave.h>
+
+#include "adv7511.h"
+
+static struct adv7511 *encoder_to_adv7511(struct drm_encoder *encoder)
+{
+	return to_encoder_slave(encoder)->slave_priv;
+}
+
+/* ADI recommended values for proper operation. */
+static const struct reg_sequence adv7511_fixed_registers[] = {
+	{ 0x98, 0x03 },
+	{ 0x9a, 0xe0 },
+	{ 0x9c, 0x30 },
+	{ 0x9d, 0x61 },
+	{ 0xa2, 0xa4 },
+	{ 0xa3, 0xa4 },
+	{ 0xe0, 0xd0 },
+	{ 0xf9, 0x00 },
+	{ 0x55, 0x02 },
+};
+
+/* -----------------------------------------------------------------------------
+ * Register access
+ */
+
+static const uint8_t adv7511_register_defaults[] = {
+	0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00 */
+	0x00, 0x00, 0x01, 0x0e, 0xbc, 0x18, 0x01, 0x13,
+	0x25, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */
+	0x46, 0x62, 0x04, 0xa8, 0x00, 0x00, 0x1c, 0x84,
+	0x1c, 0xbf, 0x04, 0xa8, 0x1e, 0x70, 0x02, 0x1e, /* 20 */
+	0x00, 0x00, 0x04, 0xa8, 0x08, 0x12, 0x1b, 0xac,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 */
+	0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0,
+	0x00, 0x50, 0x90, 0x7e, 0x79, 0x70, 0x00, 0x00, /* 40 */
+	0x00, 0xa8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x00, /* 50 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 60 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 70 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 80 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 90 */
+	0x0b, 0x02, 0x00, 0x18, 0x5a, 0x60, 0x00, 0x00,
+	0x00, 0x00, 0x80, 0x80, 0x08, 0x04, 0x00, 0x00, /* a0 */
+	0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x14,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c0 */
+	0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0x04,
+	0x30, 0xff, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, /* d0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01,
+	0x80, 0x75, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, /* e0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x11, 0x00, /* f0 */
+	0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static bool adv7511_register_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case ADV7511_REG_CHIP_REVISION:
+	case ADV7511_REG_SPDIF_FREQ:
+	case ADV7511_REG_CTS_AUTOMATIC1:
+	case ADV7511_REG_CTS_AUTOMATIC2:
+	case ADV7511_REG_VIC_DETECTED:
+	case ADV7511_REG_VIC_SEND:
+	case ADV7511_REG_AUX_VIC_DETECTED:
+	case ADV7511_REG_STATUS:
+	case ADV7511_REG_GC(1):
+	case ADV7511_REG_INT(0):
+	case ADV7511_REG_INT(1):
+	case ADV7511_REG_PLL_STATUS:
+	case ADV7511_REG_AN(0):
+	case ADV7511_REG_AN(1):
+	case ADV7511_REG_AN(2):
+	case ADV7511_REG_AN(3):
+	case ADV7511_REG_AN(4):
+	case ADV7511_REG_AN(5):
+	case ADV7511_REG_AN(6):
+	case ADV7511_REG_AN(7):
+	case ADV7511_REG_HDCP_STATUS:
+	case ADV7511_REG_BCAPS:
+	case ADV7511_REG_BKSV(0):
+	case ADV7511_REG_BKSV(1):
+	case ADV7511_REG_BKSV(2):
+	case ADV7511_REG_BKSV(3):
+	case ADV7511_REG_BKSV(4):
+	case ADV7511_REG_DDC_STATUS:
+	case ADV7511_REG_EDID_READ_CTRL:
+	case ADV7511_REG_BSTATUS(0):
+	case ADV7511_REG_BSTATUS(1):
+	case ADV7511_REG_CHIP_ID_HIGH:
+	case ADV7511_REG_CHIP_ID_LOW:
+		return true;
+	}
+
+	return false;
+}
+
+static const struct regmap_config adv7511_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = 0xff,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults_raw = adv7511_register_defaults,
+	.num_reg_defaults_raw = ARRAY_SIZE(adv7511_register_defaults),
+
+	.volatile_reg = adv7511_register_volatile,
+};
+
+/* -----------------------------------------------------------------------------
+ * Hardware configuration
+ */
+
+static void adv7511_set_colormap(struct adv7511 *adv7511, bool enable,
+				 const uint16_t *coeff,
+				 unsigned int scaling_factor)
+{
+	unsigned int i;
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(1),
+			   ADV7511_CSC_UPDATE_MODE, ADV7511_CSC_UPDATE_MODE);
+
+	if (enable) {
+		for (i = 0; i < 12; ++i) {
+			regmap_update_bits(adv7511->regmap,
+					   ADV7511_REG_CSC_UPPER(i),
+					   0x1f, coeff[i] >> 8);
+			regmap_write(adv7511->regmap,
+				     ADV7511_REG_CSC_LOWER(i),
+				     coeff[i] & 0xff);
+		}
+	}
+
+	if (enable)
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(0),
+				   0xe0, 0x80 | (scaling_factor << 5));
+	else
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(0),
+				   0x80, 0x00);
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(1),
+			   ADV7511_CSC_UPDATE_MODE, 0);
+}
+
+int adv7511_packet_enable(struct adv7511 *adv7511, unsigned int packet)
+{
+	if (packet & 0xff)
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE0,
+				   packet, 0xff);
+
+	if (packet & 0xff00) {
+		packet >>= 8;
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
+				   packet, 0xff);
+	}
+
+	return 0;
+}
+
+int adv7511_packet_disable(struct adv7511 *adv7511, unsigned int packet)
+{
+	if (packet & 0xff)
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE0,
+				   packet, 0x00);
+
+	if (packet & 0xff00) {
+		packet >>= 8;
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
+				   packet, 0x00);
+	}
+
+	return 0;
+}
+
+/* Coefficients for adv7511 color space conversion */
+static const uint16_t adv7511_csc_ycbcr_to_rgb[] = {
+	0x0734, 0x04ad, 0x0000, 0x1c1b,
+	0x1ddc, 0x04ad, 0x1f24, 0x0135,
+	0x0000, 0x04ad, 0x087c, 0x1b77,
+};
+
+static void adv7511_set_config_csc(struct adv7511 *adv7511,
+				   struct drm_connector *connector,
+				   bool rgb)
+{
+	struct adv7511_video_config config;
+	bool output_format_422, output_format_ycbcr;
+	unsigned int mode;
+	uint8_t infoframe[17];
+
+	if (adv7511->edid)
+		config.hdmi_mode = drm_detect_hdmi_monitor(adv7511->edid);
+	else
+		config.hdmi_mode = false;
+
+	hdmi_avi_infoframe_init(&config.avi_infoframe);
+
+	config.avi_infoframe.scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
+
+	if (rgb) {
+		config.csc_enable = false;
+		config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
+	} else {
+		config.csc_scaling_factor = ADV7511_CSC_SCALING_4;
+		config.csc_coefficents = adv7511_csc_ycbcr_to_rgb;
+
+		if ((connector->display_info.color_formats &
+		     DRM_COLOR_FORMAT_YCRCB422) &&
+		    config.hdmi_mode) {
+			config.csc_enable = false;
+			config.avi_infoframe.colorspace =
+				HDMI_COLORSPACE_YUV422;
+		} else {
+			config.csc_enable = true;
+			config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
+		}
+	}
+
+	if (config.hdmi_mode) {
+		mode = ADV7511_HDMI_CFG_MODE_HDMI;
+
+		switch (config.avi_infoframe.colorspace) {
+		case HDMI_COLORSPACE_YUV444:
+			output_format_422 = false;
+			output_format_ycbcr = true;
+			break;
+		case HDMI_COLORSPACE_YUV422:
+			output_format_422 = true;
+			output_format_ycbcr = true;
+			break;
+		default:
+			output_format_422 = false;
+			output_format_ycbcr = false;
+			break;
+		}
+	} else {
+		mode = ADV7511_HDMI_CFG_MODE_DVI;
+		output_format_422 = false;
+		output_format_ycbcr = false;
+	}
+
+	adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
+
+	adv7511_set_colormap(adv7511, config.csc_enable,
+			     config.csc_coefficents,
+			     config.csc_scaling_factor);
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG1, 0x81,
+			   (output_format_422 << 7) | output_format_ycbcr);
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_HDCP_HDMI_CFG,
+			   ADV7511_HDMI_CFG_MODE_MASK, mode);
+
+	hdmi_avi_infoframe_pack(&config.avi_infoframe, infoframe,
+				sizeof(infoframe));
+
+	/* The AVI infoframe id is not configurable */
+	regmap_bulk_write(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME_VERSION,
+			  infoframe + 1, sizeof(infoframe) - 1);
+
+	adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
+}
+
+static void adv7511_set_link_config(struct adv7511 *adv7511,
+				    const struct adv7511_link_config *config)
+{
+	/*
+	 * The input style values documented in the datasheet don't match the
+	 * hardware register field values :-(
+	 */
+	static const unsigned int input_styles[4] = { 0, 2, 1, 3 };
+
+	unsigned int clock_delay;
+	unsigned int color_depth;
+	unsigned int input_id;
+
+	clock_delay = (config->clock_delay + 1200) / 400;
+	color_depth = config->input_color_depth == 8 ? 3
+		    : (config->input_color_depth == 10 ? 1 : 2);
+
+	/* TODO Support input ID 6 */
+	if (config->input_colorspace != HDMI_COLORSPACE_YUV422)
+		input_id = config->input_clock == ADV7511_INPUT_CLOCK_DDR
+			 ? 5 : 0;
+	else if (config->input_clock == ADV7511_INPUT_CLOCK_DDR)
+		input_id = config->embedded_sync ? 8 : 7;
+	else if (config->input_clock == ADV7511_INPUT_CLOCK_2X)
+		input_id = config->embedded_sync ? 4 : 3;
+	else
+		input_id = config->embedded_sync ? 2 : 1;
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG, 0xf,
+			   input_id);
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG1, 0x7e,
+			   (color_depth << 4) |
+			   (input_styles[config->input_style] << 2));
+	regmap_write(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG2,
+		     config->input_justification << 3);
+	regmap_write(adv7511->regmap, ADV7511_REG_TIMING_GEN_SEQ,
+		     config->sync_pulse << 2);
+
+	regmap_write(adv7511->regmap, 0xba, clock_delay << 5);
+
+	adv7511->embedded_sync = config->embedded_sync;
+	adv7511->hsync_polarity = config->hsync_polarity;
+	adv7511->vsync_polarity = config->vsync_polarity;
+	adv7511->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB;
+}
+
+static void adv7511_power_on(struct adv7511 *adv7511)
+{
+	adv7511->current_edid_segment = -1;
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
+			   ADV7511_POWER_POWER_DOWN, 0);
+	if (adv7511->i2c_main->irq) {
+		/*
+		 * Documentation says the INT_ENABLE registers are reset in
+		 * POWER_DOWN mode. My 7511w preserved the bits, however.
+		 * Still, let's be safe and stick to the documentation.
+		 */
+		regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0),
+			     ADV7511_INT0_EDID_READY);
+		regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1),
+			     ADV7511_INT1_DDC_ERROR);
+	}
+
+	/*
+	 * Per spec it is allowed to pulse the HPD signal to indicate that the
+	 * EDID information has changed. Some monitors do this when they wakeup
+	 * from standby or are enabled. When the HPD goes low the adv7511 is
+	 * reset and the outputs are disabled which might cause the monitor to
+	 * go to standby again. To avoid this we ignore the HPD pin for the
+	 * first few seconds after enabling the output.
+	 */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
+			   ADV7511_REG_POWER2_HPD_SRC_MASK,
+			   ADV7511_REG_POWER2_HPD_SRC_NONE);
+
+	/*
+	 * Most of the registers are reset during power down or when HPD is low.
+	 */
+	regcache_sync(adv7511->regmap);
+
+	adv7511->powered = true;
+}
+
+static void adv7511_power_off(struct adv7511 *adv7511)
+{
+	/* TODO: setup additional power down modes */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
+			   ADV7511_POWER_POWER_DOWN,
+			   ADV7511_POWER_POWER_DOWN);
+	regcache_mark_dirty(adv7511->regmap);
+
+	adv7511->powered = false;
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt and hotplug detection
+ */
+
+static bool adv7511_hpd(struct adv7511 *adv7511)
+{
+	unsigned int irq0;
+	int ret;
+
+	ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
+	if (ret < 0)
+		return false;
+
+	if (irq0 & ADV7511_INT0_HPD) {
+		regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
+			     ADV7511_INT0_HPD);
+		return true;
+	}
+
+	return false;
+}
+
+static int adv7511_irq_process(struct adv7511 *adv7511)
+{
+	unsigned int irq0, irq1;
+	int ret;
+
+	ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(1), &irq1);
+	if (ret < 0)
+		return ret;
+
+	regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0);
+	regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
+
+	if (irq0 & ADV7511_INT0_HPD && adv7511->encoder)
+		drm_helper_hpd_irq_event(adv7511->encoder->dev);
+
+	if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
+		adv7511->edid_read = true;
+
+		if (adv7511->i2c_main->irq)
+			wake_up_all(&adv7511->wq);
+	}
+
+	return 0;
+}
+
+static irqreturn_t adv7511_irq_handler(int irq, void *devid)
+{
+	struct adv7511 *adv7511 = devid;
+	int ret;
+
+	ret = adv7511_irq_process(adv7511);
+	return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
+}
+
+/* -----------------------------------------------------------------------------
+ * EDID retrieval
+ */
+
+static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout)
+{
+	int ret;
+
+	if (adv7511->i2c_main->irq) {
+		ret = wait_event_interruptible_timeout(adv7511->wq,
+				adv7511->edid_read, msecs_to_jiffies(timeout));
+	} else {
+		for (; timeout > 0; timeout -= 25) {
+			ret = adv7511_irq_process(adv7511);
+			if (ret < 0)
+				break;
+
+			if (adv7511->edid_read)
+				break;
+
+			msleep(25);
+		}
+	}
+
+	return adv7511->edid_read ? 0 : -EIO;
+}
+
+static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block,
+				  size_t len)
+{
+	struct adv7511 *adv7511 = data;
+	struct i2c_msg xfer[2];
+	uint8_t offset;
+	unsigned int i;
+	int ret;
+
+	if (len > 128)
+		return -EINVAL;
+
+	if (adv7511->current_edid_segment != block / 2) {
+		unsigned int status;
+
+		ret = regmap_read(adv7511->regmap, ADV7511_REG_DDC_STATUS,
+				  &status);
+		if (ret < 0)
+			return ret;
+
+		if (status != 2) {
+			adv7511->edid_read = false;
+			regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT,
+				     block);
+			ret = adv7511_wait_for_edid(adv7511, 200);
+			if (ret < 0)
+				return ret;
+		}
+
+		/* Break this apart, hopefully more I2C controllers will
+		 * support 64 byte transfers than 256 byte transfers
+		 */
+
+		xfer[0].addr = adv7511->i2c_edid->addr;
+		xfer[0].flags = 0;
+		xfer[0].len = 1;
+		xfer[0].buf = &offset;
+		xfer[1].addr = adv7511->i2c_edid->addr;
+		xfer[1].flags = I2C_M_RD;
+		xfer[1].len = 64;
+		xfer[1].buf = adv7511->edid_buf;
+
+		offset = 0;
+
+		for (i = 0; i < 4; ++i) {
+			ret = i2c_transfer(adv7511->i2c_edid->adapter, xfer,
+					   ARRAY_SIZE(xfer));
+			if (ret < 0)
+				return ret;
+			else if (ret != 2)
+				return -EIO;
+
+			xfer[1].buf += 64;
+			offset += 64;
+		}
+
+		adv7511->current_edid_segment = block / 2;
+	}
+
+	if (block % 2 == 0)
+		memcpy(buf, adv7511->edid_buf, len);
+	else
+		memcpy(buf, adv7511->edid_buf + 128, len);
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Encoder operations
+ */
+
+static int adv7511_get_modes(struct drm_encoder *encoder,
+			     struct drm_connector *connector)
+{
+	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
+	struct edid *edid;
+	unsigned int count;
+
+	/* Reading the EDID only works if the device is powered */
+	if (!adv7511->powered) {
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
+				   ADV7511_POWER_POWER_DOWN, 0);
+		if (adv7511->i2c_main->irq) {
+			regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0),
+				     ADV7511_INT0_EDID_READY);
+			regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1),
+				     ADV7511_INT1_DDC_ERROR);
+		}
+		adv7511->current_edid_segment = -1;
+	}
+
+	edid = drm_do_get_edid(connector, adv7511_get_edid_block, adv7511);
+
+	if (!adv7511->powered)
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
+				   ADV7511_POWER_POWER_DOWN,
+				   ADV7511_POWER_POWER_DOWN);
+
+	kfree(adv7511->edid);
+	adv7511->edid = edid;
+	if (!edid)
+		return 0;
+
+	drm_mode_connector_update_edid_property(connector, edid);
+	count = drm_add_edid_modes(connector, edid);
+
+	adv7511_set_config_csc(adv7511, connector, adv7511->rgb);
+
+	return count;
+}
+
+static void adv7511_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
+
+	if (mode == DRM_MODE_DPMS_ON)
+		adv7511_power_on(adv7511);
+	else
+		adv7511_power_off(adv7511);
+}
+
+static enum drm_connector_status
+adv7511_encoder_detect(struct drm_encoder *encoder,
+		       struct drm_connector *connector)
+{
+	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
+	enum drm_connector_status status;
+	unsigned int val;
+	bool hpd;
+	int ret;
+
+	ret = regmap_read(adv7511->regmap, ADV7511_REG_STATUS, &val);
+	if (ret < 0)
+		return connector_status_disconnected;
+
+	if (val & ADV7511_STATUS_HPD)
+		status = connector_status_connected;
+	else
+		status = connector_status_disconnected;
+
+	hpd = adv7511_hpd(adv7511);
+
+	/* The chip resets itself when the cable is disconnected, so in case
+	 * there is a pending HPD interrupt and the cable is connected there was
+	 * at least one transition from disconnected to connected and the chip
+	 * has to be reinitialized. */
+	if (status == connector_status_connected && hpd && adv7511->powered) {
+		regcache_mark_dirty(adv7511->regmap);
+		adv7511_power_on(adv7511);
+		adv7511_get_modes(encoder, connector);
+		if (adv7511->status == connector_status_connected)
+			status = connector_status_disconnected;
+	} else {
+		/* Renable HPD sensing */
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
+				   ADV7511_REG_POWER2_HPD_SRC_MASK,
+				   ADV7511_REG_POWER2_HPD_SRC_BOTH);
+	}
+
+	adv7511->status = status;
+	return status;
+}
+
+static int adv7511_encoder_mode_valid(struct drm_encoder *encoder,
+				      struct drm_display_mode *mode)
+{
+	if (mode->clock > 165000)
+		return MODE_CLOCK_HIGH;
+
+	return MODE_OK;
+}
+
+static void adv7511_encoder_mode_set(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode,
+				     struct drm_display_mode *adj_mode)
+{
+	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
+	unsigned int low_refresh_rate;
+	unsigned int hsync_polarity = 0;
+	unsigned int vsync_polarity = 0;
+
+	if (adv7511->embedded_sync) {
+		unsigned int hsync_offset, hsync_len;
+		unsigned int vsync_offset, vsync_len;
+
+		hsync_offset = adj_mode->crtc_hsync_start -
+			       adj_mode->crtc_hdisplay;
+		vsync_offset = adj_mode->crtc_vsync_start -
+			       adj_mode->crtc_vdisplay;
+		hsync_len = adj_mode->crtc_hsync_end -
+			    adj_mode->crtc_hsync_start;
+		vsync_len = adj_mode->crtc_vsync_end -
+			    adj_mode->crtc_vsync_start;
+
+		/* The hardware vsync generator has a off-by-one bug */
+		vsync_offset += 1;
+
+		regmap_write(adv7511->regmap, ADV7511_REG_HSYNC_PLACEMENT_MSB,
+			     ((hsync_offset >> 10) & 0x7) << 5);
+		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(0),
+			     (hsync_offset >> 2) & 0xff);
+		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(1),
+			     ((hsync_offset & 0x3) << 6) |
+			     ((hsync_len >> 4) & 0x3f));
+		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(2),
+			     ((hsync_len & 0xf) << 4) |
+			     ((vsync_offset >> 6) & 0xf));
+		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(3),
+			     ((vsync_offset & 0x3f) << 2) |
+			     ((vsync_len >> 8) & 0x3));
+		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(4),
+			     vsync_len & 0xff);
+
+		hsync_polarity = !(adj_mode->flags & DRM_MODE_FLAG_PHSYNC);
+		vsync_polarity = !(adj_mode->flags & DRM_MODE_FLAG_PVSYNC);
+	} else {
+		enum adv7511_sync_polarity mode_hsync_polarity;
+		enum adv7511_sync_polarity mode_vsync_polarity;
+
+		/**
+		 * If the input signal is always low or always high we want to
+		 * invert or let it passthrough depending on the polarity of the
+		 * current mode.
+		 **/
+		if (adj_mode->flags & DRM_MODE_FLAG_NHSYNC)
+			mode_hsync_polarity = ADV7511_SYNC_POLARITY_LOW;
+		else
+			mode_hsync_polarity = ADV7511_SYNC_POLARITY_HIGH;
+
+		if (adj_mode->flags & DRM_MODE_FLAG_NVSYNC)
+			mode_vsync_polarity = ADV7511_SYNC_POLARITY_LOW;
+		else
+			mode_vsync_polarity = ADV7511_SYNC_POLARITY_HIGH;
+
+		if (adv7511->hsync_polarity != mode_hsync_polarity &&
+		    adv7511->hsync_polarity !=
+		    ADV7511_SYNC_POLARITY_PASSTHROUGH)
+			hsync_polarity = 1;
+
+		if (adv7511->vsync_polarity != mode_vsync_polarity &&
+		    adv7511->vsync_polarity !=
+		    ADV7511_SYNC_POLARITY_PASSTHROUGH)
+			vsync_polarity = 1;
+	}
+
+	if (mode->vrefresh <= 24000)
+		low_refresh_rate = ADV7511_LOW_REFRESH_RATE_24HZ;
+	else if (mode->vrefresh <= 25000)
+		low_refresh_rate = ADV7511_LOW_REFRESH_RATE_25HZ;
+	else if (mode->vrefresh <= 30000)
+		low_refresh_rate = ADV7511_LOW_REFRESH_RATE_30HZ;
+	else
+		low_refresh_rate = ADV7511_LOW_REFRESH_RATE_NONE;
+
+	regmap_update_bits(adv7511->regmap, 0xfb,
+		0x6, low_refresh_rate << 1);
+	regmap_update_bits(adv7511->regmap, 0x17,
+		0x60, (vsync_polarity << 6) | (hsync_polarity << 5));
+
+	/*
+	 * TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is
+	 * supposed to give better results.
+	 */
+
+	adv7511->f_tmds = mode->clock;
+}
+
+static const struct drm_encoder_slave_funcs adv7511_encoder_funcs = {
+	.dpms = adv7511_encoder_dpms,
+	.mode_valid = adv7511_encoder_mode_valid,
+	.mode_set = adv7511_encoder_mode_set,
+	.detect = adv7511_encoder_detect,
+	.get_modes = adv7511_get_modes,
+};
+
+/* -----------------------------------------------------------------------------
+ * Probe & remove
+ */
+
+static int adv7511_parse_dt(struct device_node *np,
+			    struct adv7511_link_config *config)
+{
+	const char *str;
+	int ret;
+
+	memset(config, 0, sizeof(*config));
+
+	of_property_read_u32(np, "adi,input-depth", &config->input_color_depth);
+	if (config->input_color_depth != 8 && config->input_color_depth != 10 &&
+	    config->input_color_depth != 12)
+		return -EINVAL;
+
+	ret = of_property_read_string(np, "adi,input-colorspace", &str);
+	if (ret < 0)
+		return ret;
+
+	if (!strcmp(str, "rgb"))
+		config->input_colorspace = HDMI_COLORSPACE_RGB;
+	else if (!strcmp(str, "yuv422"))
+		config->input_colorspace = HDMI_COLORSPACE_YUV422;
+	else if (!strcmp(str, "yuv444"))
+		config->input_colorspace = HDMI_COLORSPACE_YUV444;
+	else
+		return -EINVAL;
+
+	ret = of_property_read_string(np, "adi,input-clock", &str);
+	if (ret < 0)
+		return ret;
+
+	if (!strcmp(str, "1x"))
+		config->input_clock = ADV7511_INPUT_CLOCK_1X;
+	else if (!strcmp(str, "2x"))
+		config->input_clock = ADV7511_INPUT_CLOCK_2X;
+	else if (!strcmp(str, "ddr"))
+		config->input_clock = ADV7511_INPUT_CLOCK_DDR;
+	else
+		return -EINVAL;
+
+	if (config->input_colorspace == HDMI_COLORSPACE_YUV422 ||
+	    config->input_clock != ADV7511_INPUT_CLOCK_1X) {
+		ret = of_property_read_u32(np, "adi,input-style",
+					   &config->input_style);
+		if (ret)
+			return ret;
+
+		if (config->input_style < 1 || config->input_style > 3)
+			return -EINVAL;
+
+		ret = of_property_read_string(np, "adi,input-justification",
+					      &str);
+		if (ret < 0)
+			return ret;
+
+		if (!strcmp(str, "left"))
+			config->input_justification =
+				ADV7511_INPUT_JUSTIFICATION_LEFT;
+		else if (!strcmp(str, "evenly"))
+			config->input_justification =
+				ADV7511_INPUT_JUSTIFICATION_EVENLY;
+		else if (!strcmp(str, "right"))
+			config->input_justification =
+				ADV7511_INPUT_JUSTIFICATION_RIGHT;
+		else
+			return -EINVAL;
+
+	} else {
+		config->input_style = 1;
+		config->input_justification = ADV7511_INPUT_JUSTIFICATION_LEFT;
+	}
+
+	of_property_read_u32(np, "adi,clock-delay", &config->clock_delay);
+	if (config->clock_delay < -1200 || config->clock_delay > 1600)
+		return -EINVAL;
+
+	config->embedded_sync = of_property_read_bool(np, "adi,embedded-sync");
+
+	/* Hardcode the sync pulse configurations for now. */
+	config->sync_pulse = ADV7511_INPUT_SYNC_PULSE_NONE;
+	config->vsync_polarity = ADV7511_SYNC_POLARITY_PASSTHROUGH;
+	config->hsync_polarity = ADV7511_SYNC_POLARITY_PASSTHROUGH;
+
+	return 0;
+}
+
+static const int edid_i2c_addr = 0x7e;
+static const int packet_i2c_addr = 0x70;
+static const int cec_i2c_addr = 0x78;
+
+static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+	struct adv7511_link_config link_config;
+	struct adv7511 *adv7511;
+	struct device *dev = &i2c->dev;
+	unsigned int val;
+	int ret;
+
+	if (!dev->of_node)
+		return -EINVAL;
+
+	adv7511 = devm_kzalloc(dev, sizeof(*adv7511), GFP_KERNEL);
+	if (!adv7511)
+		return -ENOMEM;
+
+	adv7511->powered = false;
+	adv7511->status = connector_status_disconnected;
+
+	ret = adv7511_parse_dt(dev->of_node, &link_config);
+	if (ret)
+		return ret;
+
+	/*
+	 * The power down GPIO is optional. If present, toggle it from active to
+	 * inactive to wake up the encoder.
+	 */
+	adv7511->gpio_pd = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_HIGH);
+	if (IS_ERR(adv7511->gpio_pd))
+		return PTR_ERR(adv7511->gpio_pd);
+
+	if (adv7511->gpio_pd) {
+		mdelay(5);
+		gpiod_set_value_cansleep(adv7511->gpio_pd, 0);
+	}
+
+	adv7511->regmap = devm_regmap_init_i2c(i2c, &adv7511_regmap_config);
+	if (IS_ERR(adv7511->regmap))
+		return PTR_ERR(adv7511->regmap);
+
+	ret = regmap_read(adv7511->regmap, ADV7511_REG_CHIP_REVISION, &val);
+	if (ret)
+		return ret;
+	dev_dbg(dev, "Rev. %d\n", val);
+
+	ret = regmap_register_patch(adv7511->regmap, adv7511_fixed_registers,
+				    ARRAY_SIZE(adv7511_fixed_registers));
+	if (ret)
+		return ret;
+
+	regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR, edid_i2c_addr);
+	regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR,
+		     packet_i2c_addr);
+	regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR, cec_i2c_addr);
+	adv7511_packet_disable(adv7511, 0xffff);
+
+	adv7511->i2c_main = i2c;
+	adv7511->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1);
+	if (!adv7511->i2c_edid)
+		return -ENOMEM;
+
+	if (i2c->irq) {
+		init_waitqueue_head(&adv7511->wq);
+
+		ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
+						adv7511_irq_handler,
+						IRQF_ONESHOT, dev_name(dev),
+						adv7511);
+		if (ret)
+			goto err_i2c_unregister_device;
+	}
+
+	/* CEC is unused for now */
+	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
+		     ADV7511_CEC_CTRL_POWER_DOWN);
+
+	adv7511_power_off(adv7511);
+
+	i2c_set_clientdata(i2c, adv7511);
+
+#ifdef CONFIG_DRM_I2C_ADV7511_AUDIO
+	adv7511_audio_init(&i2c->dev);
+#endif
+
+	adv7511_set_link_config(adv7511, &link_config);
+
+	/* Enable HDMI mode */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_HDCP_HDMI_CFG,
+			ADV7511_HDMI_CFG_MODE_MASK,
+			ADV7511_HDMI_CFG_MODE_HDMI);
+
+	return 0;
+
+err_i2c_unregister_device:
+	i2c_unregister_device(adv7511->i2c_edid);
+
+	return ret;
+}
+
+static int adv7511_remove(struct i2c_client *i2c)
+{
+	struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
+
+	i2c_unregister_device(adv7511->i2c_edid);
+
+	kfree(adv7511->edid);
+
+	return 0;
+}
+
+static int adv7511_encoder_init(struct i2c_client *i2c, struct drm_device *dev,
+				struct drm_encoder_slave *encoder)
+{
+
+	struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
+
+	encoder->slave_priv = adv7511;
+	encoder->slave_funcs = &adv7511_encoder_funcs;
+
+	adv7511->encoder = &encoder->base;
+
+	return 0;
+}
+
+static const struct i2c_device_id adv7511_i2c_ids[] = {
+	{ "adv7511", 0 },
+	{ "adv7511w", 0 },
+	{ "adv7513", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adv7511_i2c_ids);
+
+static const struct of_device_id adv7511_of_ids[] = {
+	{ .compatible = "adi,adv7511", },
+	{ .compatible = "adi,adv7511w", },
+	{ .compatible = "adi,adv7513", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, adv7511_of_ids);
+
+static struct drm_i2c_encoder_driver adv7511_driver = {
+	.i2c_driver = {
+		.driver = {
+			.name = "adv7511",
+			.of_match_table = adv7511_of_ids,
+		},
+		.id_table = adv7511_i2c_ids,
+		.probe = adv7511_probe,
+		.remove = adv7511_remove,
+	},
+
+	.encoder_init = adv7511_encoder_init,
+};
+
+static int __init adv7511_init(void)
+{
+	return drm_i2c_encoder_register(THIS_MODULE, &adv7511_driver);
+}
+module_init(adv7511_init);
+
+static void __exit adv7511_exit(void)
+{
+	drm_i2c_encoder_unregister(&adv7511_driver);
+}
+module_exit(adv7511_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars at metafoo.de>");
+MODULE_DESCRIPTION("ADV7511 HDMI transmitter driver");
+MODULE_LICENSE("GPL");
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 964b7de..539c091 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -33,6 +33,7 @@ struct snd_compr_stream;
 #define SND_SOC_DAIFMT_DSP_B		5 /* L data MSB during FRM LRC */
 #define SND_SOC_DAIFMT_AC97		6 /* AC97 */
 #define SND_SOC_DAIFMT_PDM		7 /* Pulse density modulation */
+#define SND_SOC_DAIFMT_SPDIF		8 /* SPDIF */
 
 /* left and right justified also known as MSB and LSB respectively */
 #define SND_SOC_DAIFMT_MSB		SND_SOC_DAIFMT_LEFT_J
-- 
1.9.1




From Jose.Abreu at synopsys.com  Mon Mar 28 07:36:11 2016
From: Jose.Abreu at synopsys.com (Jose Abreu)
Date: Mon, 28 Mar 2016 15:36:11 +0100
Subject: [PATCH 3/3 v2] arc: axs10x: Add support for Designware I2S on DT
In-Reply-To: <cover.1459174494.git.joabreu@synopsys.com>
References: <cover.1459174494.git.joabreu@synopsys.com>
Message-ID: <02e216b1c928bd939c81067346d2807fd38bf1a5.1459174494.git.joabreu@synopsys.com>

Synopsys Designware ARC SDP boards support HDMI audio
output using the ADV7511 HDMI transmitter.

This patchs enables audio output using Designware I2S
driver, ALSA SoC simple audio card and ADV7511 codec.

Signed-off-by: Jose Abreu <joabreu at synopsys.com>
---

Changes v1 -> v2:
* This change was introduced in v2.

 arch/arc/boot/dts/axs10x_mb.dtsi | 49 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 45 insertions(+), 4 deletions(-)

diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
index ab5d570..fc26ede 100644
--- a/arch/arc/boot/dts/axs10x_mb.dtsi
+++ b/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -138,12 +138,23 @@
 			interrupts = <14>;
 		};
 
-		i2c at 0x1e000 {
-			compatible = "snps,designware-i2c";
+		i2s: i2s at 1e000 {
+			compatible = "snps,designware-i2s";
 			reg = <0x1e000 0x100>;
-			clock-frequency = <400000>;
-			clocks = <&i2cclk>;
 			interrupts = <15>;
+			#sound-dai-cells = <0>;
+		};
+
+		sound {
+			compatible = "simple-audio-card";
+			simple-audio-card,name = "AXS10X HDMI Audio";
+			simple-audio-card,format = "i2s";
+			simple-audio-card,cpu {
+				sound-dai = <&i2s>;
+			};
+			simple-audio-card,codec {
+				sound-dai = <&adv7511>;
+			};
 		};
 
 		i2c at 0x1f000 {
@@ -155,6 +166,36 @@
 			clocks = <&i2cclk>;
 			interrupts = <16>;
 
+			adv7511: adv7511 at 39 {
+				compatible = "adi,adv7511";
+				reg = <0x39>;
+				interrupts = <23>;
+				adi,input-depth = <8>;
+				adi,input-colorspace = "rgb";
+				adi,input-clock = "1x";
+				adi,clock-delay = <0x03>;
+				#sound-dai-cells = <0>;
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					/* RGB/YUV input */
+					port at 0 {
+						reg = <0>;
+						adv7511_input: endpoint {
+						};
+					};
+
+					/* HDMI output */
+					port at 1 {
+						reg = <1>;
+						adv7511_output: endpoint {
+						};
+					};
+				};
+			};
+
 			eeprom at 0x54{
 				compatible = "24c01";
 				reg = <0x54>;
-- 
1.9.1




From Alexey.Brodkin at synopsys.com  Mon Mar 28 08:35:46 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Mon, 28 Mar 2016 15:35:46 +0000
Subject: [PATCH 2/3 v2] ASoC: dwc: Add I2S HDMI audio support
In-Reply-To: <538be366488bf0d7633d702f2d0bab16707b7a47.1459174494.git.joabreu@synopsys.com>
References: <cover.1459174494.git.joabreu@synopsys.com>
 <538be366488bf0d7633d702f2d0bab16707b7a47.1459174494.git.joabreu@synopsys.com>
Message-ID: <1459179345.4785.127.camel@synopsys.com>

Hi Jose,

On Mon, 2016-03-28 at 15:36 +0100, Jose Abreu wrote:
> HDMI audio support was added to the AXS board using an
> I2S cpu driver and a custom platform driver.
> 
> The platform driver supports two channels @ 16 bits with
> rates 32k, 44.1k and 48k. ALSA Simple audio card is used to
> glue the cpu, platform and codec driver (adv7511).
> 
> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
> ---
> 
> No changes v1 -> v2.
> 
> ?sound/soc/dwc/Kconfig??????????|???1 +
> ?sound/soc/dwc/designware_i2s.c | 385 +++++++++++++++++++++++++++++++++++++++--
> ?2 files changed, 373 insertions(+), 13 deletions(-)
> 
> diff --git a/sound/soc/dwc/Kconfig b/sound/soc/dwc/Kconfig
> index d50e085..bc3fae7 100644
> --- a/sound/soc/dwc/Kconfig
> +++ b/sound/soc/dwc/Kconfig
> @@ -2,6 +2,7 @@ config SND_DESIGNWARE_I2S
> ?	tristate "Synopsys I2S Device Driver"
> ?	depends on CLKDEV_LOOKUP
> ?	select SND_SOC_GENERIC_DMAENGINE_PCM
> +	select SND_SIMPLE_CARD
> ?	help
> ?	?Say Y or M if you want to add support for I2S driver for
> ?	?Synopsys desigwnware I2S device. The device supports upto
> diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
> index bff258d..0f2f588 100644
> --- a/sound/soc/dwc/designware_i2s.c
> +++ b/sound/soc/dwc/designware_i2s.c
> @@ -84,11 +84,37 @@
> ?#define MAX_CHANNEL_NUM		8
> ?#define MIN_CHANNEL_NUM		2
> ?
> +/* FPGA Version Info */
> +#define FPGA_VER_INFO	0xE0011230
> +#define FPGA_VER_27M	0x000FBED9
> +
> +/* PLL registers addresses */
> +#define PLL_IDIV_ADDR	0xE00100A0
> +#define PLL_FBDIV_ADDR	0xE00100A4
> +#define PLL_ODIV0_ADDR	0xE00100A8
> +#define PLL_ODIV1_ADDR	0xE00100AC

Well I think all is not acceptable.
See all these?FPGA_VER_xxx as well as?PLL_xxx
are strictly ARC SDP specific things and have nothing to do with generic driver.

That's so pity we don't have a driver for all clocks/PLLs on ARC SDP yet.
So as of now I may only propose to use hard-coded fixed clocks as I did with
ARC PGU, see "pguclk" here:
http://lists.infradead.org/pipermail/linux-snps-arc/2016-March/000790.html

Again I'll try to implement missing clock driver sometime soon because
more and more stuff requires it but for now let's use a work-around.

> +struct dw_i2s_pll {
> +	unsigned int rate;
> +	unsigned int data_width;
> +	unsigned int idiv;
> +	unsigned int fbdiv;
> +	unsigned int odiv0;
> +	unsigned int odiv1;
> +};
> +
> +static const struct dw_i2s_pll dw_i2s_pll_cfg_27m[] = {
> +	/* 27Mhz */
> +	{ 32000, 16, 0x104, 0x451, 0x10E38, 0x2000 },
> +	{ 44100, 16, 0x104, 0x596, 0x10D35, 0x2000 },
> +	{ 48000, 16, 0x208, 0xA28, 0x10B2C, 0x2000 },
> +	{ 0, 0, 0, 0, 0, 0 },
> ?};
> ?
> +static const struct dw_i2s_pll dw_i2s_pll_cfg_28m[] = {
> +	/* 28.224Mhz */
> +	{ 32000, 16, 0x82, 0x105, 0x107DF, 0x2000 },
> +	{ 44100, 16, 0x28A, 0x1, 0x10001, 0x2000 },
> +	{ 48000, 16, 0xA28, 0x187, 0x10042, 0x2000 },
> +	{ 0, 0, 0, 0, 0, 0 },
> +};

These 2 hunks as well should go in ARC SDP clocks.

> +static int i2s_pll_cfg(struct i2s_clk_config_data *config)
> +{
> +	const struct dw_i2s_pll *pll_cfg;
> +	u32 rate = config->sample_rate;
> +	u32 data_width = config->data_width;
> +	int i;
> +
> +	if (readl((void *)FPGA_VER_INFO) <= FPGA_VER_27M)
> +		pll_cfg = dw_i2s_pll_cfg_27m;
> +	else
> +		pll_cfg = dw_i2s_pll_cfg_28m;
> +
> +	for (i = 0; pll_cfg[i].rate != 0; i++) {
> +		if ((pll_cfg[i].rate == rate) &&
> +				(pll_cfg[i].data_width == data_width)) {
> +			writel(pll_cfg[i].idiv, (void *)PLL_IDIV_ADDR);
> +			writel(pll_cfg[i].fbdiv, (void *)PLL_FBDIV_ADDR);
> +			writel(pll_cfg[i].odiv0, (void *)PLL_ODIV0_ADDR);
> +			writel(pll_cfg[i].odiv1, (void *)PLL_ODIV1_ADDR);
> +			return 0;
> +		}
> +	}
> +
> +	return -EINVAL;
> +}

Ditto.

-Alexey

From Jose.Abreu at synopsys.com  Mon Mar 28 09:07:28 2016
From: Jose.Abreu at synopsys.com (Jose Abreu)
Date: Mon, 28 Mar 2016 17:07:28 +0100
Subject: [PATCH 2/3 v2] ASoC: dwc: Add I2S HDMI audio support
In-Reply-To: <1459179345.4785.127.camel@synopsys.com>
References: <cover.1459174494.git.joabreu@synopsys.com>
 <538be366488bf0d7633d702f2d0bab16707b7a47.1459174494.git.joabreu@synopsys.com>
 <1459179345.4785.127.camel@synopsys.com>
Message-ID: <56F956C0.80705@synopsys.com>

Hi Alexey,

On 28-03-2016 16:35, Alexey Brodkin wrote:
> Hi Jose,
>
> On Mon, 2016-03-28 at 15:36 +0100, Jose Abreu wrote:
>> HDMI audio support was added to the AXS board using an
>> I2S cpu driver and a custom platform driver.
>>
>> The platform driver supports two channels @ 16 bits with
>> rates 32k, 44.1k and 48k. ALSA Simple audio card is used to
>> glue the cpu, platform and codec driver (adv7511).
>>
>> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
>> ---
>>
>> No changes v1 -> v2.
>>
>>  sound/soc/dwc/Kconfig          |   1 +
>>  sound/soc/dwc/designware_i2s.c | 385 +++++++++++++++++++++++++++++++++++++++--
>>  2 files changed, 373 insertions(+), 13 deletions(-)
>>
>> diff --git a/sound/soc/dwc/Kconfig b/sound/soc/dwc/Kconfig
>> index d50e085..bc3fae7 100644
>> --- a/sound/soc/dwc/Kconfig
>> +++ b/sound/soc/dwc/Kconfig
>> @@ -2,6 +2,7 @@ config SND_DESIGNWARE_I2S
>>  	tristate "Synopsys I2S Device Driver"
>>  	depends on CLKDEV_LOOKUP
>>  	select SND_SOC_GENERIC_DMAENGINE_PCM
>> +	select SND_SIMPLE_CARD
>>  	help
>>  	 Say Y or M if you want to add support for I2S driver for
>>  	 Synopsys desigwnware I2S device. The device supports upto
>> diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
>> index bff258d..0f2f588 100644
>> --- a/sound/soc/dwc/designware_i2s.c
>> +++ b/sound/soc/dwc/designware_i2s.c
>> @@ -84,11 +84,37 @@
>>  #define MAX_CHANNEL_NUM		8
>>  #define MIN_CHANNEL_NUM		2
>>  
>> +/* FPGA Version Info */
>> +#define FPGA_VER_INFO	0xE0011230
>> +#define FPGA_VER_27M	0x000FBED9
>> +
>> +/* PLL registers addresses */
>> +#define PLL_IDIV_ADDR	0xE00100A0
>> +#define PLL_FBDIV_ADDR	0xE00100A4
>> +#define PLL_ODIV0_ADDR	0xE00100A8
>> +#define PLL_ODIV1_ADDR	0xE00100AC
> Well I think all is not acceptable.
> See all these FPGA_VER_xxx as well as PLL_xxx
> are strictly ARC SDP specific things and have nothing to do with generic driver.
>
> That's so pity we don't have a driver for all clocks/PLLs on ARC SDP yet.
> So as of now I may only propose to use hard-coded fixed clocks as I did with
> ARC PGU, see "pguclk" here:
> http://lists.infradead.org/pipermail/linux-snps-arc/2016-March/000790.html
>
> Again I'll try to implement missing clock driver sometime soon because
> more and more stuff requires it but for now let's use a work-around.
Yes, this is a workaround that we are using so that the driver works in ARC SDP
platforms. The driver still has the functionality to operate using a clock
driver (it must be declared in device tree) but if the clock handle is not
declared the driver will assume that must use the internal PLL config options.
This is currently the only option to make it work in ARC SDP.

I will send a v3 soon without this workaround and when the missing clock drivers
are implemented I will re-test this.
>> +struct dw_i2s_pll {
>> +	unsigned int rate;
>> +	unsigned int data_width;
>> +	unsigned int idiv;
>> +	unsigned int fbdiv;
>> +	unsigned int odiv0;
>> +	unsigned int odiv1;
>> +};
>> +
>> +static const struct dw_i2s_pll dw_i2s_pll_cfg_27m[] = {
>> +	/* 27Mhz */
>> +	{ 32000, 16, 0x104, 0x451, 0x10E38, 0x2000 },
>> +	{ 44100, 16, 0x104, 0x596, 0x10D35, 0x2000 },
>> +	{ 48000, 16, 0x208, 0xA28, 0x10B2C, 0x2000 },
>> +	{ 0, 0, 0, 0, 0, 0 },
>>  };
>>  
>> +static const struct dw_i2s_pll dw_i2s_pll_cfg_28m[] = {
>> +	/* 28.224Mhz */
>> +	{ 32000, 16, 0x82, 0x105, 0x107DF, 0x2000 },
>> +	{ 44100, 16, 0x28A, 0x1, 0x10001, 0x2000 },
>> +	{ 48000, 16, 0xA28, 0x187, 0x10042, 0x2000 },
>> +	{ 0, 0, 0, 0, 0, 0 },
>> +};
> These 2 hunks as well should go in ARC SDP clocks.
>
>> +static int i2s_pll_cfg(struct i2s_clk_config_data *config)
>> +{
>> +	const struct dw_i2s_pll *pll_cfg;
>> +	u32 rate = config->sample_rate;
>> +	u32 data_width = config->data_width;
>> +	int i;
>> +
>> +	if (readl((void *)FPGA_VER_INFO) <= FPGA_VER_27M)
>> +		pll_cfg = dw_i2s_pll_cfg_27m;
>> +	else
>> +		pll_cfg = dw_i2s_pll_cfg_28m;
>> +
>> +	for (i = 0; pll_cfg[i].rate != 0; i++) {
>> +		if ((pll_cfg[i].rate == rate) &&
>> +				(pll_cfg[i].data_width == data_width)) {
>> +			writel(pll_cfg[i].idiv, (void *)PLL_IDIV_ADDR);
>> +			writel(pll_cfg[i].fbdiv, (void *)PLL_FBDIV_ADDR);
>> +			writel(pll_cfg[i].odiv0, (void *)PLL_ODIV0_ADDR);
>> +			writel(pll_cfg[i].odiv1, (void *)PLL_ODIV1_ADDR);
>> +			return 0;
>> +		}
>> +	}
>> +
>> +	return -EINVAL;
>> +}
> Ditto.
>
> -Alexey

Best regards,
Jose Miguel Abreu



From architt at codeaurora.org  Tue Mar 29 01:05:25 2016
From: architt at codeaurora.org (Archit Taneja)
Date: Tue, 29 Mar 2016 13:35:25 +0530
Subject: [PATCH 1/3 v2] drm/i2c/adv7511: Add audio support
In-Reply-To: <15b1936d307912ba12df7fa09ec3a7a80ac5fcef.1459174494.git.joabreu@synopsys.com>
References: <cover.1459174494.git.joabreu@synopsys.com>
 <15b1936d307912ba12df7fa09ec3a7a80ac5fcef.1459174494.git.joabreu@synopsys.com>
Message-ID: <56FA3745.3000807@codeaurora.org>

Hi,

On 03/28/2016 08:06 PM, Jose Abreu wrote:
> This patch adds audio support for the ADV7511 HDMI transmitter
> using ALSA SoC.
>
> The code was ported from Analog Devices linux tree from
> commit 1770c4a1e32b ("Merge remote-tracking branch
> 'xilinx/master' into xcomm_zynq"), which is available at:
> 	- https://github.com/analogdevicesinc/linux/
>
> The main core file was renamed from adv7511.c to adv7511_core.c
> so that audio and video compile into a single adv7511.ko module
> and to keep up with Analog Devices kernel tree.
>
> The audio can be disabled using menu-config so it is possible
> to use only video mode.
>
> The HDMI mode is automatically started at boot and the audio
> (when enabled) registers as a codec into ALSA.

Is there a reason why we set the mode to HDMI at probe itself?
Shouldn't it be okay to set the mode later once we read the
EDID off the panel?

Some more comments below.

>
> SPDIF DAI format was also added to ASoC as it is required
> by adv7511 audio.
>
> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
> ---
>
> No changes v1 -> v2.
>
>   drivers/gpu/drm/i2c/Kconfig         |   11 +
>   drivers/gpu/drm/i2c/Makefile        |    2 +
>   drivers/gpu/drm/i2c/adv7511.c       | 1024 -----------------------------------
>   drivers/gpu/drm/i2c/adv7511.h       |   41 ++
>   drivers/gpu/drm/i2c/adv7511_audio.c |  310 +++++++++++
>   drivers/gpu/drm/i2c/adv7511_core.c  | 1005 ++++++++++++++++++++++++++++++++++
>   include/sound/soc-dai.h             |    1 +
>   7 files changed, 1370 insertions(+), 1024 deletions(-)
>   delete mode 100644 drivers/gpu/drm/i2c/adv7511.c
>   create mode 100644 drivers/gpu/drm/i2c/adv7511_audio.c
>   create mode 100644 drivers/gpu/drm/i2c/adv7511_core.c

<snip>

> +
> +static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
> +{
> +	struct adv7511_link_config link_config;
> +	struct adv7511 *adv7511;
> +	struct device *dev = &i2c->dev;
> +	unsigned int val;
> +	int ret;
> +
> +	if (!dev->of_node)
> +		return -EINVAL;
> +
> +	adv7511 = devm_kzalloc(dev, sizeof(*adv7511), GFP_KERNEL);
> +	if (!adv7511)
> +		return -ENOMEM;
> +
> +	adv7511->powered = false;
> +	adv7511->status = connector_status_disconnected;
> +
> +	ret = adv7511_parse_dt(dev->of_node, &link_config);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * The power down GPIO is optional. If present, toggle it from active to
> +	 * inactive to wake up the encoder.
> +	 */
> +	adv7511->gpio_pd = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_HIGH);
> +	if (IS_ERR(adv7511->gpio_pd))
> +		return PTR_ERR(adv7511->gpio_pd);
> +
> +	if (adv7511->gpio_pd) {
> +		mdelay(5);
> +		gpiod_set_value_cansleep(adv7511->gpio_pd, 0);
> +	}
> +
> +	adv7511->regmap = devm_regmap_init_i2c(i2c, &adv7511_regmap_config);
> +	if (IS_ERR(adv7511->regmap))
> +		return PTR_ERR(adv7511->regmap);
> +
> +	ret = regmap_read(adv7511->regmap, ADV7511_REG_CHIP_REVISION, &val);
> +	if (ret)
> +		return ret;
> +	dev_dbg(dev, "Rev. %d\n", val);
> +
> +	ret = regmap_register_patch(adv7511->regmap, adv7511_fixed_registers,
> +				    ARRAY_SIZE(adv7511_fixed_registers));
> +	if (ret)
> +		return ret;
> +
> +	regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR, edid_i2c_addr);
> +	regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR,
> +		     packet_i2c_addr);
> +	regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR, cec_i2c_addr);
> +	adv7511_packet_disable(adv7511, 0xffff);
> +
> +	adv7511->i2c_main = i2c;
> +	adv7511->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1);
> +	if (!adv7511->i2c_edid)
> +		return -ENOMEM;
> +
> +	if (i2c->irq) {
> +		init_waitqueue_head(&adv7511->wq);
> +
> +		ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
> +						adv7511_irq_handler,
> +						IRQF_ONESHOT, dev_name(dev),
> +						adv7511);
> +		if (ret)
> +			goto err_i2c_unregister_device;
> +	}
> +
> +	/* CEC is unused for now */
> +	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
> +		     ADV7511_CEC_CTRL_POWER_DOWN);
> +
> +	adv7511_power_off(adv7511);
> +
> +	i2c_set_clientdata(i2c, adv7511);
> +
> +#ifdef CONFIG_DRM_I2C_ADV7511_AUDIO
> +	adv7511_audio_init(&i2c->dev);
> +#endif

If we intend to have more audio funcs being used by the core in the
future, it would be nice to have NOP audio funcs rather than having
multiple #ifdef checks in the driver when CONFIG_DRM_I2C_ADV7511_AUDIO
isn't set.

> +
> +	adv7511_set_link_config(adv7511, &link_config);
> +
> +	/* Enable HDMI mode */
> +	regmap_update_bits(adv7511->regmap, ADV7511_REG_HDCP_HDMI_CFG,
> +			ADV7511_HDMI_CFG_MODE_MASK,
> +			ADV7511_HDMI_CFG_MODE_HDMI);
> +
> +	return 0;
> +
> +err_i2c_unregister_device:
> +	i2c_unregister_device(adv7511->i2c_edid);
> +
> +	return ret;
> +}
> +
> +static int adv7511_remove(struct i2c_client *i2c)
> +{
> +	struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
> +

Are we missing a call to adv7511_audio_exit() here?

Thanks,
Archit

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
Forum, hosted by The Linux Foundation


From Jose.Abreu at synopsys.com  Tue Mar 29 03:52:07 2016
From: Jose.Abreu at synopsys.com (Jose Abreu)
Date: Tue, 29 Mar 2016 11:52:07 +0100
Subject: [PATCH 1/3 v2] drm/i2c/adv7511: Add audio support
In-Reply-To: <56FA3745.3000807@codeaurora.org>
References: <cover.1459174494.git.joabreu@synopsys.com>
 <15b1936d307912ba12df7fa09ec3a7a80ac5fcef.1459174494.git.joabreu@synopsys.com>
 <56FA3745.3000807@codeaurora.org>
Message-ID: <56FA5E57.2000506@synopsys.com>

Hi Archit,

On 29-03-2016 09:05, Archit Taneja wrote:
> Hi,
>
> On 03/28/2016 08:06 PM, Jose Abreu wrote:
>> This patch adds audio support for the ADV7511 HDMI transmitter
>> using ALSA SoC.
>>
>> The code was ported from Analog Devices linux tree from
>> commit 1770c4a1e32b ("Merge remote-tracking branch
>> 'xilinx/master' into xcomm_zynq"), which is available at:
>>     - https://github.com/analogdevicesinc/linux/
>>
>> The main core file was renamed from adv7511.c to adv7511_core.c
>> so that audio and video compile into a single adv7511.ko module
>> and to keep up with Analog Devices kernel tree.
>>
>> The audio can be disabled using menu-config so it is possible
>> to use only video mode.
>>
>> The HDMI mode is automatically started at boot and the audio
>> (when enabled) registers as a codec into ALSA.
>
> Is there a reason why we set the mode to HDMI at probe itself?
> Shouldn't it be okay to set the mode later once we read the
> EDID off the panel?
>
> Some more comments below.
>

Well, when I was using this in kernel 3.18 (with an older version of the driver)
I noticed that DVI mode was being used even when HDMI was connected so I forced
the driver to start in HDMI mode. There were some changes in the driver so it is
possible that this is no longer needed. Should I drop it?

>>
>> SPDIF DAI format was also added to ASoC as it is required
>> by adv7511 audio.
>>
>> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
>> ---
>>
>> No changes v1 -> v2.
>>
>>   drivers/gpu/drm/i2c/Kconfig         |   11 +
>>   drivers/gpu/drm/i2c/Makefile        |    2 +
>>   drivers/gpu/drm/i2c/adv7511.c       | 1024 -----------------------------------
>>   drivers/gpu/drm/i2c/adv7511.h       |   41 ++
>>   drivers/gpu/drm/i2c/adv7511_audio.c |  310 +++++++++++
>>   drivers/gpu/drm/i2c/adv7511_core.c  | 1005 ++++++++++++++++++++++++++++++++++
>>   include/sound/soc-dai.h             |    1 +
>>   7 files changed, 1370 insertions(+), 1024 deletions(-)
>>   delete mode 100644 drivers/gpu/drm/i2c/adv7511.c
>>   create mode 100644 drivers/gpu/drm/i2c/adv7511_audio.c
>>   create mode 100644 drivers/gpu/drm/i2c/adv7511_core.c
>
> <snip>
>
>> +
>> +static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id
>> *id)
>> +{
>> +    struct adv7511_link_config link_config;
>> +    struct adv7511 *adv7511;
>> +    struct device *dev = &i2c->dev;
>> +    unsigned int val;
>> +    int ret;
>> +
>> +    if (!dev->of_node)
>> +        return -EINVAL;
>> +
>> +    adv7511 = devm_kzalloc(dev, sizeof(*adv7511), GFP_KERNEL);
>> +    if (!adv7511)
>> +        return -ENOMEM;
>> +
>> +    adv7511->powered = false;
>> +    adv7511->status = connector_status_disconnected;
>> +
>> +    ret = adv7511_parse_dt(dev->of_node, &link_config);
>> +    if (ret)
>> +        return ret;
>> +
>> +    /*
>> +     * The power down GPIO is optional. If present, toggle it from active to
>> +     * inactive to wake up the encoder.
>> +     */
>> +    adv7511->gpio_pd = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_HIGH);
>> +    if (IS_ERR(adv7511->gpio_pd))
>> +        return PTR_ERR(adv7511->gpio_pd);
>> +
>> +    if (adv7511->gpio_pd) {
>> +        mdelay(5);
>> +        gpiod_set_value_cansleep(adv7511->gpio_pd, 0);
>> +    }
>> +
>> +    adv7511->regmap = devm_regmap_init_i2c(i2c, &adv7511_regmap_config);
>> +    if (IS_ERR(adv7511->regmap))
>> +        return PTR_ERR(adv7511->regmap);
>> +
>> +    ret = regmap_read(adv7511->regmap, ADV7511_REG_CHIP_REVISION, &val);
>> +    if (ret)
>> +        return ret;
>> +    dev_dbg(dev, "Rev. %d\n", val);
>> +
>> +    ret = regmap_register_patch(adv7511->regmap, adv7511_fixed_registers,
>> +                    ARRAY_SIZE(adv7511_fixed_registers));
>> +    if (ret)
>> +        return ret;
>> +
>> +    regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR, edid_i2c_addr);
>> +    regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR,
>> +             packet_i2c_addr);
>> +    regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR, cec_i2c_addr);
>> +    adv7511_packet_disable(adv7511, 0xffff);
>> +
>> +    adv7511->i2c_main = i2c;
>> +    adv7511->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1);
>> +    if (!adv7511->i2c_edid)
>> +        return -ENOMEM;
>> +
>> +    if (i2c->irq) {
>> +        init_waitqueue_head(&adv7511->wq);
>> +
>> +        ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
>> +                        adv7511_irq_handler,
>> +                        IRQF_ONESHOT, dev_name(dev),
>> +                        adv7511);
>> +        if (ret)
>> +            goto err_i2c_unregister_device;
>> +    }
>> +
>> +    /* CEC is unused for now */
>> +    regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
>> +             ADV7511_CEC_CTRL_POWER_DOWN);
>> +
>> +    adv7511_power_off(adv7511);
>> +
>> +    i2c_set_clientdata(i2c, adv7511);
>> +
>> +#ifdef CONFIG_DRM_I2C_ADV7511_AUDIO
>> +    adv7511_audio_init(&i2c->dev);
>> +#endif
>
> If we intend to have more audio funcs being used by the core in the
> future, it would be nice to have NOP audio funcs rather than having
> multiple #ifdef checks in the driver when CONFIG_DRM_I2C_ADV7511_AUDIO
> isn't set.
>

I will move this ifdef to adv751_audio and use NOP functions.

>> +
>> +    adv7511_set_link_config(adv7511, &link_config);
>> +
>> +    /* Enable HDMI mode */
>> +    regmap_update_bits(adv7511->regmap, ADV7511_REG_HDCP_HDMI_CFG,
>> +            ADV7511_HDMI_CFG_MODE_MASK,
>> +            ADV7511_HDMI_CFG_MODE_HDMI);
>> +
>> +    return 0;
>> +
>> +err_i2c_unregister_device:
>> +    i2c_unregister_device(adv7511->i2c_edid);
>> +
>> +    return ret;
>> +}
>> +
>> +static int adv7511_remove(struct i2c_client *i2c)
>> +{
>> +    struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
>> +
>
> Are we missing a call to adv7511_audio_exit() here?

I followed the code in Analog Devices tree where there is no call to
audio_exit() but indeed you are correct. I will add this call.

>
> Thanks,
> Archit
>

Thanks for your comments!

Best regards,
Jose Miguel Abreu


From Alexey.Brodkin at synopsys.com  Tue Mar 29 04:25:08 2016
From: Alexey.Brodkin at synopsys.com (Alexey Brodkin)
Date: Tue, 29 Mar 2016 11:25:08 +0000
Subject: [PATCH] clk/arc: Add I2S PLL clock driver
In-Reply-To: <e580aaf30e3c66d13693a4e6db0ced1996d37c04.1459246186.git.joabreu@synopsys.com>
References: <e580aaf30e3c66d13693a4e6db0ced1996d37c04.1459246186.git.joabreu@synopsys.com>
Message-ID: <1459250707.3021.31.camel@synopsys.com>

Hi Jose,

On Tue, 2016-03-29 at 11:56 +0100, Jose Abreu wrote:
> The ARC SDP I2S clock can be programmed using a
> specific PLL.
> 
> This patch has the goal of adding a clock driver
> that programs this PLL.
> 
> At this moment the rate values are hardcoded in
> a table but in the future it would be ideal to
> use a function which determines the PLL values
> given the desired rate.
> 
> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
> ---

I believe these kind of patches worth sending to
linux-snps mailing list (at least add it in Cc) so
they won't be lost in time and could be used later as
useful references.

> ?arch/arc/boot/dts/axs10x_mb.dtsi |???5 ++
> ?drivers/clk/Makefile?????????????|???1 +
> ?drivers/clk/arc/Makefile?????????|???1 +
> ?drivers/clk/arc/i2s_pll_clock.c??| 143 +++++++++++++++++++++++++++++++++++++++
> ?4 files changed, 150 insertions(+)
> ?create mode 100644 drivers/clk/arc/Makefile
> ?create mode 100644 drivers/clk/arc/i2s_pll_clock.c
> 
> diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
> index ab5d570..9c68226 100644
> --- a/arch/arc/boot/dts/axs10x_mb.dtsi
> +++ b/arch/arc/boot/dts/axs10x_mb.dtsi
> @@ -23,6 +23,11 @@
> ?				#clock-cells = <0>;
> ?			};
> ?
> +			i2sclk: i2sclk {
> +				compatible = "snps,i2s-pll-clock";
> +				#clock-cells = <0>;
> +			};
> +
> ?			apbclk: apbclk {
> ?				compatible = "fixed-clock";
> ?				clock-frequency = <50000000>;
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 46869d6..620e47f 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -84,3 +84,4 @@ obj-$(CONFIG_X86)			+= x86/
> ?obj-$(CONFIG_ARCH_ZX)			+= zte/
> ?obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
> ?obj-$(CONFIG_H8300)		+= h8300/
> +obj-$(CONFIG_ARC)		+= arc/

Two things here:
?[1] This clock is relevant to only one board but not SoC, CPU core
? ? ?or whole architecture, so it makes sense to make it dependent on
? ? ?the AXS platform, i.e. CONFIG_ARC_PLAT_AXS10X.

?[2] Something similar is applicable to folder name, I would suggest to
? ? ?use "drivers/clk/axs10x"

> diff --git a/drivers/clk/arc/Makefile b/drivers/clk/arc/Makefile
> new file mode 100644
> index 0000000..01996b8
> --- /dev/null
> +++ b/drivers/clk/arc/Makefile
> @@ -0,0 +1 @@
> +obj-y += i2s_pll_clock.o
> diff --git a/drivers/clk/arc/i2s_pll_clock.c b/drivers/clk/arc/i2s_pll_clock.c
> new file mode 100644
> index 0000000..8c401f1
> --- /dev/null
> +++ b/drivers/clk/arc/i2s_pll_clock.c
> @@ -0,0 +1,143 @@
> +/*
> + * Synopsys I2S PLL clock driver

Again that's not generic SNPS I2S clock but clock driver for a particular board.

> + *
> + * drivers/clk/arc/i2s_pll_clock.c

BTW not sure why this path could be needed here.
IMHO that might be safely dropped.

> + *
> + * Copyright (C) 2016 Synopsys
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +#include <linux/clk-provider.h>
> +#include <linux/err.h>
> +#include <linux/device.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +
> +/* FPGA Version Info */
> +#define FPGA_VER_INFO	0xE0011230
> +#define FPGA_VER_27M	0x000FBED9

This is a little bit tricky.
We'll need to do that check in each and every clock driver for AXS10x
and so it worth putting this code in some common location (I mean common
for all axs10x clock drivers).

> +/* PLL registers addresses */
> +#define PLL_IDIV_ADDR	0xE00100A0
> +#define PLL_FBDIV_ADDR	0xE00100A4
> +#define PLL_ODIV0_ADDR	0xE00100A8
> +#define PLL_ODIV1_ADDR	0xE00100AC
>

> +struct i2s_pll_clk {
> +	struct clk_hw hw;
> +};
> +
> +struct i2s_pll_cfg {
> +	unsigned int rate;
> +	unsigned int idiv;
> +	unsigned int fbdiv;
> +	unsigned int odiv0;
> +	unsigned int odiv1;
> +};
> +
> +static const struct i2s_pll_cfg i2s_pll_cfg_27m[] = {
> +	/* 27 Mhz */
> +	{ 1024000, 0x104, 0x451, 0x10E38, 0x2000 },
> +	{ 1411200, 0x104, 0x596, 0x10D35, 0x2000 },
> +	{ 1536000, 0x208, 0xA28, 0x10B2C, 0x2000 },
> +	{ 2048000, 0x82, 0x451, 0x10E38, 0x2000 },
> +	{ 2822400, 0x82, 0x596, 0x10D35, 0x2000 },
> +	{ 3072000, 0x104, 0xA28, 0x10B2C, 0x2000 },
> +	{ 0, 0, 0, 0, 0 },
> +};
> +
> +static const struct i2s_pll_cfg i2s_pll_cfg_28m[] = {
> +	/* 28.224 Mhz */
> +	{ 1024000, 0x82, 0x105, 0x107DF, 0x2000 },
> +	{ 1411200, 0x28A, 0x1, 0x10001, 0x2000 },
> +	{ 1536000, 0xA28, 0x187, 0x10042, 0x2000 },
> +	{ 2048000, 0x41, 0x105, 0x107DF, 0x2000 },
> +	{ 2822400, 0x145, 0x1, 0x10001, 0x2000 },
> +	{ 3072000, 0x514, 0x187, 0x10042, 0x2000 },
> +	{ 0, 0, 0, 0, 0 },
> +};
> +
> +static unsigned long i2s_pll_recalc_rate(struct clk_hw *hw,
> +			unsigned long parent_rate)
> +{
> +	/* TODO */
> +	pr_info("%s: parent_rate=%ld\n", __func__, parent_rate);
> +	return parent_rate;
> +}
> +
> +static long i2s_pll_round_rate(struct clk_hw *hw, unsigned long rate,
> +			unsigned long *prate)
> +{
> +	/* TODO: Round rate to nearest valid rate */
> +	*prate = rate;
> +	pr_info("%s: rate=%ld, prate=%ld\n", __func__, rate, *prate);
> +	return *prate;
> +}

These are now just dummy functions so probably they could be dropped.

> +static int i2s_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> +			unsigned long parent_rate)
> +{
> +	const struct i2s_pll_cfg *pll_cfg;
> +	int i;
> +
> +	if (readl((void *)FPGA_VER_INFO) <= FPGA_VER_27M)
> +		pll_cfg = i2s_pll_cfg_27m;
> +	else
> +		pll_cfg = i2s_pll_cfg_28m;

As I mentioned above we need to check board version in common place and then
just use some variable or structure member for comparison.

Otherwise it looks pretty nice!

-Alexey

From Vineet.Gupta1 at synopsys.com  Tue Mar 29 05:36:50 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 29 Mar 2016 12:36:50 +0000
Subject: [PATCH] clk/arc: Add I2S PLL clock driver
References: <e580aaf30e3c66d13693a4e6db0ced1996d37c04.1459246186.git.joabreu@synopsys.com>
 <1459250707.3021.31.camel@synopsys.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E915E9@us01wembx1.internal.synopsys.com>

On Tuesday 29 March 2016 04:55 PM, Alexey Brodkin wrote:
> Hi Jose,
>
> On Tue, 2016-03-29 at 11:56 +0100, Jose Abreu wrote:
>> The ARC SDP I2S clock can be programmed using a
>> specific PLL.
>>
>> This patch has the goal of adding a clock driver
>> that programs this PLL.
>>
>> At this moment the rate values are hardcoded in
>> a table but in the future it would be ideal to
>> use a function which determines the PLL values
>> given the desired rate.
>>
>> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
>> ---
> I believe these kind of patches worth sending to
> linux-snps mailing list (at least add it in Cc) so
> they won't be lost in time and could be used later as
> useful references.

Please do also CC the common clk maintainers

COMMON CLK FRAMEWORK
M:    Michael Turquette <mturquette at baylibre.com>
M:    Stephen Boyd <sboyd at codeaurora.org>
L:    linux-clk at vger.kernel.org

>
>>  arch/arc/boot/dts/axs10x_mb.dtsi |   5 ++
>>  drivers/clk/Makefile             |   1 +
>>  drivers/clk/arc/Makefile         |   1 +
>>  drivers/clk/arc/i2s_pll_clock.c  | 143 +++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 150 insertions(+)
>>  create mode 100644 drivers/clk/arc/Makefile
>>  create mode 100644 drivers/clk/arc/i2s_pll_clock.c
>>
>> diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
>> index ab5d570..9c68226 100644
>> --- a/arch/arc/boot/dts/axs10x_mb.dtsi
>> +++ b/arch/arc/boot/dts/axs10x_mb.dtsi
>> @@ -23,6 +23,11 @@
>>  				#clock-cells = <0>;
>>  			};
>>  
>> +			i2sclk: i2sclk {
>> +				compatible = "snps,i2s-pll-clock";
>> +				#clock-cells = <0>;
>> +			};
>> +
>>  			apbclk: apbclk {
>>  				compatible = "fixed-clock";
>>  				clock-frequency = <50000000>;
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 46869d6..620e47f 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -84,3 +84,4 @@ obj-$(CONFIG_X86)			+= x86/
>>  obj-$(CONFIG_ARCH_ZX)			+= zte/
>>  obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
>>  obj-$(CONFIG_H8300)		+= h8300/
>> +obj-$(CONFIG_ARC)		+= arc/
> Two things here:
>  [1] This clock is relevant to only one board but not SoC, CPU core
>      or whole architecture, so it makes sense to make it dependent on
>      the AXS platform, i.e. CONFIG_ARC_PLAT_AXS10X.
>
>  [2] Something similar is applicable to folder name, I would suggest to
>      use "drivers/clk/axs10x"
>
>> diff --git a/drivers/clk/arc/Makefile b/drivers/clk/arc/Makefile
>> new file mode 100644
>> index 0000000..01996b8
>> --- /dev/null
>> +++ b/drivers/clk/arc/Makefile
>> @@ -0,0 +1 @@
>> +obj-y += i2s_pll_clock.o
>> diff --git a/drivers/clk/arc/i2s_pll_clock.c b/drivers/clk/arc/i2s_pll_clock.c
>> new file mode 100644
>> index 0000000..8c401f1
>> --- /dev/null
>> +++ b/drivers/clk/arc/i2s_pll_clock.c
>> @@ -0,0 +1,143 @@
>> +/*
>> + * Synopsys I2S PLL clock driver
> Again that's not generic SNPS I2S clock but clock driver for a particular board.
>
>> + *
>> + * drivers/clk/arc/i2s_pll_clock.c
> BTW not sure why this path could be needed here.
> IMHO that might be safely dropped.
>
>> + *
>> + * Copyright (C) 2016 Synopsys
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +#include <linux/clk-provider.h>
>> +#include <linux/err.h>
>> +#include <linux/device.h>
>> +#include <linux/of_address.h>
>> +#include <linux/slab.h>
>> +
>> +/* FPGA Version Info */
>> +#define FPGA_VER_INFO	0xE0011230
>> +#define FPGA_VER_27M	0x000FBED9
> This is a little bit tricky.
> We'll need to do that check in each and every clock driver for AXS10x
> and so it worth putting this code in some common location (I mean common
> for all axs10x clock drivers).
>
>> +/* PLL registers addresses */
>> +#define PLL_IDIV_ADDR	0xE00100A0
>> +#define PLL_FBDIV_ADDR	0xE00100A4
>> +#define PLL_ODIV0_ADDR	0xE00100A8
>> +#define PLL_ODIV1_ADDR	0xE00100AC
>>
>> +struct i2s_pll_clk {
>> +	struct clk_hw hw;
>> +};
>> +
>> +struct i2s_pll_cfg {
>> +	unsigned int rate;
>> +	unsigned int idiv;
>> +	unsigned int fbdiv;
>> +	unsigned int odiv0;
>> +	unsigned int odiv1;
>> +};
>> +
>> +static const struct i2s_pll_cfg i2s_pll_cfg_27m[] = {
>> +	/* 27 Mhz */
>> +	{ 1024000, 0x104, 0x451, 0x10E38, 0x2000 },
>> +	{ 1411200, 0x104, 0x596, 0x10D35, 0x2000 },
>> +	{ 1536000, 0x208, 0xA28, 0x10B2C, 0x2000 },
>> +	{ 2048000, 0x82, 0x451, 0x10E38, 0x2000 },
>> +	{ 2822400, 0x82, 0x596, 0x10D35, 0x2000 },
>> +	{ 3072000, 0x104, 0xA28, 0x10B2C, 0x2000 },
>> +	{ 0, 0, 0, 0, 0 },
>> +};
>> +
>> +static const struct i2s_pll_cfg i2s_pll_cfg_28m[] = {
>> +	/* 28.224 Mhz */
>> +	{ 1024000, 0x82, 0x105, 0x107DF, 0x2000 },
>> +	{ 1411200, 0x28A, 0x1, 0x10001, 0x2000 },
>> +	{ 1536000, 0xA28, 0x187, 0x10042, 0x2000 },
>> +	{ 2048000, 0x41, 0x105, 0x107DF, 0x2000 },
>> +	{ 2822400, 0x145, 0x1, 0x10001, 0x2000 },
>> +	{ 3072000, 0x514, 0x187, 0x10042, 0x2000 },
>> +	{ 0, 0, 0, 0, 0 },
>> +};
>> +
>> +static unsigned long i2s_pll_recalc_rate(struct clk_hw *hw,
>> +			unsigned long parent_rate)
>> +{
>> +	/* TODO */
>> +	pr_info("%s: parent_rate=%ld\n", __func__, parent_rate);
>> +	return parent_rate;
>> +}
>> +
>> +static long i2s_pll_round_rate(struct clk_hw *hw, unsigned long rate,
>> +			unsigned long *prate)
>> +{
>> +	/* TODO: Round rate to nearest valid rate */
>> +	*prate = rate;
>> +	pr_info("%s: rate=%ld, prate=%ld\n", __func__, rate, *prate);
>> +	return *prate;
>> +}
> These are now just dummy functions so probably they could be dropped.
>
>> +static int i2s_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>> +			unsigned long parent_rate)
>> +{
>> +	const struct i2s_pll_cfg *pll_cfg;
>> +	int i;
>> +
>> +	if (readl((void *)FPGA_VER_INFO) <= FPGA_VER_27M)
>> +		pll_cfg = i2s_pll_cfg_27m;
>> +	else
>> +		pll_cfg = i2s_pll_cfg_28m;
> As I mentioned above we need to check board version in common place and then
> just use some variable or structure member for comparison.
>
> Otherwise it looks pretty nice!
>
> -Alexey



From Jose.Abreu at synopsys.com  Tue Mar 29 05:48:43 2016
From: Jose.Abreu at synopsys.com (Jose Abreu)
Date: Tue, 29 Mar 2016 13:48:43 +0100
Subject: [PATCH] clk/arc: Add I2S PLL clock driver
In-Reply-To: <1459250707.3021.31.camel@synopsys.com>
References: <e580aaf30e3c66d13693a4e6db0ced1996d37c04.1459246186.git.joabreu@synopsys.com>
 <1459250707.3021.31.camel@synopsys.com>
Message-ID: <56FA79AB.1040204@synopsys.com>

Hi Alexey,

On 29-03-2016 12:25, Alexey Brodkin wrote:
> Hi Jose,
>
> On Tue, 2016-03-29 at 11:56 +0100, Jose Abreu wrote:
>> The ARC SDP I2S clock can be programmed using a
>> specific PLL.
>>
>> This patch has the goal of adding a clock driver
>> that programs this PLL.
>>
>> At this moment the rate values are hardcoded in
>> a table but in the future it would be ideal to
>> use a function which determines the PLL values
>> given the desired rate.
>>
>> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
>> ---
> I believe these kind of patches worth sending to
> linux-snps mailing list (at least add it in Cc) so
> they won't be lost in time and could be used later as
> useful references.

Agree.

>
>>  arch/arc/boot/dts/axs10x_mb.dtsi |   5 ++
>>  drivers/clk/Makefile             |   1 +
>>  drivers/clk/arc/Makefile         |   1 +
>>  drivers/clk/arc/i2s_pll_clock.c  | 143 +++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 150 insertions(+)
>>  create mode 100644 drivers/clk/arc/Makefile
>>  create mode 100644 drivers/clk/arc/i2s_pll_clock.c
>>
>> diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
>> index ab5d570..9c68226 100644
>> --- a/arch/arc/boot/dts/axs10x_mb.dtsi
>> +++ b/arch/arc/boot/dts/axs10x_mb.dtsi
>> @@ -23,6 +23,11 @@
>>  				#clock-cells = <0>;
>>  			};
>>  
>> +			i2sclk: i2sclk {
>> +				compatible = "snps,i2s-pll-clock";
>> +				#clock-cells = <0>;
>> +			};
>> +
>>  			apbclk: apbclk {
>>  				compatible = "fixed-clock";
>>  				clock-frequency = <50000000>;
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 46869d6..620e47f 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -84,3 +84,4 @@ obj-$(CONFIG_X86)			+= x86/
>>  obj-$(CONFIG_ARCH_ZX)			+= zte/
>>  obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
>>  obj-$(CONFIG_H8300)		+= h8300/
>> +obj-$(CONFIG_ARC)		+= arc/
> Two things here:
>  [1] This clock is relevant to only one board but not SoC, CPU core
>      or whole architecture, so it makes sense to make it dependent on
>      the AXS platform, i.e. CONFIG_ARC_PLAT_AXS10X.
>
>  [2] Something similar is applicable to folder name, I would suggest to
>      use "drivers/clk/axs10x"

I will rename to axs10x and use CONFIG_ARC_PLAT_AXS10X.

>> diff --git a/drivers/clk/arc/Makefile b/drivers/clk/arc/Makefile
>> new file mode 100644
>> index 0000000..01996b8
>> --- /dev/null
>> +++ b/drivers/clk/arc/Makefile
>> @@ -0,0 +1 @@
>> +obj-y += i2s_pll_clock.o
>> diff --git a/drivers/clk/arc/i2s_pll_clock.c b/drivers/clk/arc/i2s_pll_clock.c
>> new file mode 100644
>> index 0000000..8c401f1
>> --- /dev/null
>> +++ b/drivers/clk/arc/i2s_pll_clock.c
>> @@ -0,0 +1,143 @@
>> +/*
>> + * Synopsys I2S PLL clock driver
> Again that's not generic SNPS I2S clock but clock driver for a particular board.
>
>> + *
>> + * drivers/clk/arc/i2s_pll_clock.c
> BTW not sure why this path could be needed here.
> IMHO that might be safely dropped.
>
>> + *
>> + * Copyright (C) 2016 Synopsys
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +#include <linux/clk-provider.h>
>> +#include <linux/err.h>
>> +#include <linux/device.h>
>> +#include <linux/of_address.h>
>> +#include <linux/slab.h>
>> +
>> +/* FPGA Version Info */
>> +#define FPGA_VER_INFO	0xE0011230
>> +#define FPGA_VER_27M	0x000FBED9
> This is a little bit tricky.
> We'll need to do that check in each and every clock driver for AXS10x
> and so it worth putting this code in some common location (I mean common
> for all axs10x clock drivers).
>

This is not common to all clocks. We are expecting a new firmware release which
will change the reference clock input for the I2S PLL from 27Mhz to 28.224 Mhz.
To support both the old and the new firmware we check this version info register
so that we can determine which firmware version is being used. Due to this
change the PLL dividers are different. As the remaining clocks will be
unaffected I think this can remain only in this driver.

>> +/* PLL registers addresses */
>> +#define PLL_IDIV_ADDR	0xE00100A0
>> +#define PLL_FBDIV_ADDR	0xE00100A4
>> +#define PLL_ODIV0_ADDR	0xE00100A8
>> +#define PLL_ODIV1_ADDR	0xE00100AC
>>
>> +struct i2s_pll_clk {
>> +	struct clk_hw hw;
>> +};
>> +
>> +struct i2s_pll_cfg {
>> +	unsigned int rate;
>> +	unsigned int idiv;
>> +	unsigned int fbdiv;
>> +	unsigned int odiv0;
>> +	unsigned int odiv1;
>> +};
>> +
>> +static const struct i2s_pll_cfg i2s_pll_cfg_27m[] = {
>> +	/* 27 Mhz */
>> +	{ 1024000, 0x104, 0x451, 0x10E38, 0x2000 },
>> +	{ 1411200, 0x104, 0x596, 0x10D35, 0x2000 },
>> +	{ 1536000, 0x208, 0xA28, 0x10B2C, 0x2000 },
>> +	{ 2048000, 0x82, 0x451, 0x10E38, 0x2000 },
>> +	{ 2822400, 0x82, 0x596, 0x10D35, 0x2000 },
>> +	{ 3072000, 0x104, 0xA28, 0x10B2C, 0x2000 },
>> +	{ 0, 0, 0, 0, 0 },
>> +};
>> +
>> +static const struct i2s_pll_cfg i2s_pll_cfg_28m[] = {
>> +	/* 28.224 Mhz */
>> +	{ 1024000, 0x82, 0x105, 0x107DF, 0x2000 },
>> +	{ 1411200, 0x28A, 0x1, 0x10001, 0x2000 },
>> +	{ 1536000, 0xA28, 0x187, 0x10042, 0x2000 },
>> +	{ 2048000, 0x41, 0x105, 0x107DF, 0x2000 },
>> +	{ 2822400, 0x145, 0x1, 0x10001, 0x2000 },
>> +	{ 3072000, 0x514, 0x187, 0x10042, 0x2000 },
>> +	{ 0, 0, 0, 0, 0 },
>> +};
>> +
>> +static unsigned long i2s_pll_recalc_rate(struct clk_hw *hw,
>> +			unsigned long parent_rate)
>> +{
>> +	/* TODO */
>> +	pr_info("%s: parent_rate=%ld\n", __func__, parent_rate);
>> +	return parent_rate;
>> +}
>> +
>> +static long i2s_pll_round_rate(struct clk_hw *hw, unsigned long rate,
>> +			unsigned long *prate)
>> +{
>> +	/* TODO: Round rate to nearest valid rate */
>> +	*prate = rate;
>> +	pr_info("%s: rate=%ld, prate=%ld\n", __func__, rate, *prate);
>> +	return *prate;
>> +}
> These are now just dummy functions so probably they could be dropped.

Agree but I will have to check if the clock core needs this functions to be defined.

>> +static int i2s_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>> +			unsigned long parent_rate)
>> +{
>> +	const struct i2s_pll_cfg *pll_cfg;
>> +	int i;
>> +
>> +	if (readl((void *)FPGA_VER_INFO) <= FPGA_VER_27M)
>> +		pll_cfg = i2s_pll_cfg_27m;
>> +	else
>> +		pll_cfg = i2s_pll_cfg_28m;
> As I mentioned above we need to check board version in common place and then
> just use some variable or structure member for comparison.
>
> Otherwise it looks pretty nice!
>
> -Alexey

Thanks for your comments!

Best regards,
Jose Miguel Abreu


From Vineet.Gupta1 at synopsys.com  Tue Mar 29 05:52:07 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 29 Mar 2016 18:22:07 +0530
Subject: [PATCH v6 2/3] clocksource: Add NPS400 timers driver
In-Reply-To: <1458570272-23037-3-git-send-email-noamca@mellanox.com>
References: <1458570272-23037-1-git-send-email-noamca@mellanox.com>
 <1458570272-23037-3-git-send-email-noamca@mellanox.com>
Message-ID: <56FA7A77.6080901@synopsys.com>

On Monday 21 March 2016 07:54 PM, Noam Camus wrote:
> From: Noam Camus <noamc at ezchip.com>
> 
> Add internal tick generator which is shared by all cores.
> Each cluster of cores view it through dedicated address.
> This is used for SMP system where all CPUs synced by same
> clock source.
> 
> Signed-off-by: Noam Camus <noamc at ezchip.com>
> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
> Cc: Rob Herring <robh+dt at kernel.org>
> Cc: Thomas Gleixner <tglx at linutronix.de>
> Cc: John Stultz <john.stultz at linaro.org>
> Acked-by: Vineet Gupta <vgupta at synopsys.com>

@Noam, AFAIKR, Daniel did ack the prev version - can you please double check and
repost this again.

@Daniel, this patch depends on a include/soc header introduced by patch 1/3 of the
series. For 4.7, how should we merge it - take both via ARC tree !

Thx,
-Vineet

> ---
>  .../bindings/timer/ezchip,nps400-timer.txt         |   15 +++
>  drivers/clocksource/Kconfig                        |   10 ++
>  drivers/clocksource/Makefile                       |    1 +
>  drivers/clocksource/timer-nps.c                    |   98 ++++++++++++++++++++
>  4 files changed, 124 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
>  create mode 100644 drivers/clocksource/timer-nps.c
> 
> diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
> new file mode 100644
> index 0000000..c8c03d7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
> @@ -0,0 +1,15 @@
> +NPS Network Processor
> +
> +Required properties:
> +
> +- compatible :	should be "ezchip,nps400-timer"
> +
> +Clocks required for compatible = "ezchip,nps400-timer":
> +- clocks : Must contain a single entry describing the clock input
> +
> +Example:
> +
> +timer {
> +	compatible = "ezchip,nps400-timer";
> +	clocks = <&sysclk>;
> +};
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 2eb5f0e..fa7be50 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -132,6 +132,16 @@ config CLKSRC_TI_32K
>  	  This option enables support for Texas Instruments 32.768 Hz clocksource
>  	  available on many OMAP-like platforms.
>  
> +config CLKSRC_NPS
> +	bool "NPS400 clocksource driver" if COMPILE_TEST
> +	depends on !PHYS_ADDR_T_64BIT
> +	select CLKSRC_MMIO
> +	select CLKSRC_OF if OF
> +	help
> +	  NPS400 clocksource support.
> +	  Got 64 bit counter with update rate up to 1000MHz.
> +	  This counter is accessed via couple of 32 bit memory mapped registers.
> +
>  config CLKSRC_STM32
>  	bool "Clocksource for STM32 SoCs" if !ARCH_STM32
>  	depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index 56bd16e..056cffd 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -46,6 +46,7 @@ obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o
>  obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
>  obj-$(CONFIG_CLKSRC_PISTACHIO)	+= time-pistachio.o
>  obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-32k.o
> +obj-$(CONFIG_CLKSRC_NPS)	+= timer-nps.o
>  
>  obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
>  obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
> diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
> new file mode 100644
> index 0000000..d461089
> --- /dev/null
> +++ b/drivers/clocksource/timer-nps.c
> @@ -0,0 +1,98 @@
> +/*
> + * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/clocksource.h>
> +#include <linux/clockchips.h>
> +#include <linux/clk.h>
> +#include <linux/of.h>
> +#include <linux/of_irq.h>
> +#include <linux/cpu.h>
> +#include <soc/nps/common.h>
> +
> +#define NPS_MSU_TICK_LOW	0xC8
> +#define NPS_CLUSTER_OFFSET	8
> +#define NPS_CLUSTER_NUM		16
> +
> +/* This array is per cluster of CPUs (Each NPS400 cluster got 256 CPUs) */
> +static void *nps_msu_reg_low_addr[NPS_CLUSTER_NUM] __read_mostly;
> +
> +static unsigned long nps_timer_rate;
> +
> +static cycle_t nps_clksrc_read(struct clocksource *clksrc)
> +{
> +	int cluster = raw_smp_processor_id() >> NPS_CLUSTER_OFFSET;
> +
> +	return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]);
> +}
> +
> +static void __init nps_setup_clocksource(struct device_node *node,
> +					 struct clk *clk)
> +{
> +	int ret, cluster;
> +
> +	for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
> +		nps_msu_reg_low_addr[cluster] =
> +			nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
> +				 NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
> +
> +	ret = clk_prepare_enable(clk);
> +	if (ret) {
> +		pr_err("Couldn't enable parent clock\n");
> +		return;
> +	}
> +
> +	nps_timer_rate = clk_get_rate(clk);
> +
> +	ret = clocksource_mmio_init(nps_msu_reg_low_addr, "EZnps-tick",
> +				    nps_timer_rate, 301, 32, nps_clksrc_read);
> +	if (ret) {
> +		pr_err("Couldn't register clock source.\n");
> +		clk_disable_unprepare(clk);
> +	}
> +}
> +
> +static void __init nps_timer_init(struct device_node *node)
> +{
> +	struct clk *clk;
> +
> +	clk = of_clk_get(node, 0);
> +	if (IS_ERR(clk)) {
> +		pr_err("Can't get timer clock.\n");
> +		return;
> +	}
> +
> +	nps_setup_clocksource(node, clk);
> +}
> +
> +CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
> +		       nps_timer_init);
> 



From Vineet.Gupta1 at synopsys.com  Tue Mar 29 05:55:37 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Tue, 29 Mar 2016 18:25:37 +0530
Subject: [PATCH v6 3/3] irqchip: add nps Internal and external irqchips
In-Reply-To: <1458570272-23037-4-git-send-email-noamca@mellanox.com>
References: <1458570272-23037-1-git-send-email-noamca@mellanox.com>
 <1458570272-23037-4-git-send-email-noamca@mellanox.com>
Message-ID: <56FA7B49.5010803@synopsys.com>

On Monday 21 March 2016 07:54 PM, Noam Camus wrote:
> From: Noam Camus <noamc at ezchip.com>
> 
> Adding EZchip NPS400 support.
> NPS internal interrupts are internally handled at
> Multi Thread Manager (MTM) that is signaled for deactivating
> an interrupt.
> External interrupts is handled also at Global Interrupt
> Controller (GIC) e.g. serial and network devices.
> 
> Signed-off-by: Noam Camus <noamc at ezchip.com>
> Cc: Thomas Gleixner <tglx at linutronix.de>
> Cc: Jason Cooper <jason at lakedaemon.net>
> Cc: Marc Zyngier <marc.zyngier at arm.com>

@Noam, this patch is missing the version change metadata - could you please repost
with that added.

@Thomas, @Marc, EZChip platform merge hinges on this patch among others - can I
request one/both of you to please take a look and provide any acks/nacks.

Thx,
-Vineet

> ---
>  .../interrupt-controller/ezchip,nps400-ic.txt      |   17 ++
>  drivers/irqchip/Kconfig                            |    6 +
>  drivers/irqchip/Makefile                           |    1 +
>  drivers/irqchip/irq-eznps.c                        |  165 ++++++++++++++++++++
>  4 files changed, 189 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
>  create mode 100644 drivers/irqchip/irq-eznps.c
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt b/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
> new file mode 100644
> index 0000000..888b2b9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
> @@ -0,0 +1,17 @@
> +EZchip NPS Interrupt Controller
> +
> +Required properties:
> +
> +- compatible : should be "ezchip,nps400-ic"
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source. The value shall be 1.
> +
> +
> +Example:
> +
> +intc: interrupt-controller {
> +	compatible = "ezchip,nps400-ic";
> +	interrupt-controller;
> +	#interrupt-cells = <1>;
> +};
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> index 4d7294e..bc5e775 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -193,3 +193,9 @@ config IRQ_MXS
>  	def_bool y if MACH_ASM9260 || ARCH_MXS
>  	select IRQ_DOMAIN
>  	select STMP_DEVICE
> +
> +config EZNPS_GIC
> +	bool "NPS400 Global Interrupt Manager (GIM)"
> +	select IRQ_DOMAIN
> +	help
> +	  Support the EZchip NPS400 global interrupt controller
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index 177f78f..1390142 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -55,3 +55,4 @@ obj-$(CONFIG_RENESAS_H8S_INTC)		+= irq-renesas-h8s.o
>  obj-$(CONFIG_ARCH_SA1100)		+= irq-sa11x0.o
>  obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
>  obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
> +obj-$(CONFIG_EZNPS_GIC)			+= irq-eznps.o
> diff --git a/drivers/irqchip/irq-eznps.c b/drivers/irqchip/irq-eznps.c
> new file mode 100644
> index 0000000..97e4294
> --- /dev/null
> +++ b/drivers/irqchip/irq-eznps.c
> @@ -0,0 +1,165 @@
> +/*
> + * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/irqchip.h>
> +#include <soc/nps/common.h>
> +
> +#define NPS_NR_CPU_IRQS 8  /* number of interrupt lines of NPS400 CPU */
> +#define NPS_TIMER0_IRQ  3
> +
> +/*
> + * NPS400 core includes an Interrupt Controller (IC) support.
> + * All cores can deactivate level irqs at first level control
> + * at cores mesh layer called MTM.
> + * For devices out side chip e.g. uart, network there is another
> + * level called Global Interrupt Manager (GIM).
> + * This second level can control level and edge interrupt.
> + *
> + * NOTE: AUX_IENABLE and CTOP_AUX_IACK are auxiliary registers
> + * with private HW copy per CPU.
> + */
> +
> +static void nps400_irq_mask(struct irq_data *irqd)
> +{
> +	unsigned int ienb;
> +	unsigned int irq = irqd_to_hwirq(irqd);
> +
> +	ienb = read_aux_reg(AUX_IENABLE);
> +	ienb &= ~(1 << irq);
> +	write_aux_reg(AUX_IENABLE, ienb);
> +}
> +
> +static void nps400_irq_unmask(struct irq_data *irqd)
> +{
> +	unsigned int ienb;
> +	unsigned int irq = irqd_to_hwirq(irqd);
> +
> +	ienb = read_aux_reg(AUX_IENABLE);
> +	ienb |= (1 << irq);
> +	write_aux_reg(AUX_IENABLE, ienb);
> +}
> +
> +static void nps400_irq_eoi_global(struct irq_data *irqd)
> +{
> +	unsigned int __maybe_unused irq = irqd_to_hwirq(irqd);
> +
> +	write_aux_reg(CTOP_AUX_IACK, 1 << irq);
> +
> +	/* Don't ack GIC before all device access attempts are done */
> +	mb();
> +
> +	nps_ack_gic();
> +}
> +
> +static void nps400_irq_eoi(struct irq_data *irqd)
> +{
> +	unsigned int __maybe_unused irq = irqd_to_hwirq(irqd);
> +
> +	write_aux_reg(CTOP_AUX_IACK, 1 << irq);
> +}
> +
> +static struct irq_chip nps400_irq_chip_fasteoi = {
> +	.name		= "NPS400 IC Global",
> +	.irq_mask	= nps400_irq_mask,
> +	.irq_unmask	= nps400_irq_unmask,
> +	.irq_eoi	= nps400_irq_eoi_global,
> +};
> +
> +static struct irq_chip nps400_irq_chip_percpu = {
> +	.name		= "NPS400 IC",
> +	.irq_mask	= nps400_irq_mask,
> +	.irq_unmask	= nps400_irq_unmask,
> +	.irq_eoi	= nps400_irq_eoi,
> +};
> +
> +static int nps400_irq_map(struct irq_domain *d, unsigned int virq,
> +			  irq_hw_number_t hw)
> +{
> +	switch (hw) {
> +	case NPS_TIMER0_IRQ:
> +#ifdef CONFIG_SMP
> +	case IPI_IRQ:
> +#endif
> +		irq_set_percpu_devid(virq);
> +		irq_set_chip_and_handler(virq, &nps400_irq_chip_percpu,
> +					 handle_percpu_devid_irq);
> +		break;
> +	default:
> +		irq_set_chip_and_handler(virq, &nps400_irq_chip_fasteoi,
> +					 handle_fasteoi_irq);
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops nps400_irq_ops = {
> +	.xlate = irq_domain_xlate_onecell,
> +	.map = nps400_irq_map,
> +};
> +
> +static int __init nps400_of_init(struct device_node *node,
> +				 struct device_node *parent)
> +{
> +	static struct irq_domain *nps400_root_domain;
> +
> +	if (parent) {
> +		pr_err("DeviceTree incore ic not a root irq controller\n");
> +		return -EINVAL;
> +	}
> +
> +	nps400_root_domain = irq_domain_add_linear(node, NPS_NR_CPU_IRQS,
> +						   &nps400_irq_ops, NULL);
> +
> +	if (!nps400_root_domain) {
> +		pr_err("nps400 root irq domain not avail\n");
> +		return -ENOMEM;
> +	}
> +
> +	/*
> +	 * Needed for primary domain lookup to succeed
> +	 * This is a primary irqchip, and can never have a parent
> +	 */
> +	irq_set_default_host(nps400_root_domain);
> +
> +#ifdef CONFIG_SMP
> +	irq_create_mapping(nps400_root_domain, IPI_IRQ);
> +#endif
> +
> +	return 0;
> +}
> +IRQCHIP_DECLARE(ezchip_nps400_ic, "ezchip,nps400-ic", nps400_of_init);
> 



From daniel.lezcano at linaro.org  Tue Mar 29 06:21:54 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 29 Mar 2016 15:21:54 +0200
Subject: [PATCH v6 2/3] clocksource: Add NPS400 timers driver
In-Reply-To: <56FA7A77.6080901@synopsys.com>
References: <1458570272-23037-1-git-send-email-noamca@mellanox.com>
 <1458570272-23037-3-git-send-email-noamca@mellanox.com>
 <56FA7A77.6080901@synopsys.com>
Message-ID: <56FA8172.5020008@linaro.org>

On 03/29/2016 02:52 PM, Vineet Gupta wrote:
> On Monday 21 March 2016 07:54 PM, Noam Camus wrote:
>> From: Noam Camus <noamc at ezchip.com>
>>
>> Add internal tick generator which is shared by all cores.
>> Each cluster of cores view it through dedicated address.
>> This is used for SMP system where all CPUs synced by same
>> clock source.
>>
>> Signed-off-by: Noam Camus <noamc at ezchip.com>
>> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
>> Cc: Rob Herring <robh+dt at kernel.org>
>> Cc: Thomas Gleixner <tglx at linutronix.de>
>> Cc: John Stultz <john.stultz at linaro.org>
>> Acked-by: Vineet Gupta <vgupta at synopsys.com>
>
> @Noam, AFAIKR, Daniel did ack the prev version - can you please double check and
> repost this again.
>
> @Daniel, this patch depends on a include/soc header introduced by patch 1/3 of the
> series. For 4.7, how should we merge it - take both via ARC tree !

There are two ways to do this when there are multiple tree dependencies:
   - put a common branch to be shared between trees
   - ask for the maintainer for an acked-by and pick it in a single tree

Given the nature of the patch (initial submission), I agree you pick it 
through your tree.

   -- Daniel

-- 
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog



From broonie at kernel.org  Tue Mar 29 10:00:22 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 29 Mar 2016 10:00:22 -0700
Subject: [PATCH 0/3 v2] Add I2S/ADV7511 audio support for ARC AXS10x boards
In-Reply-To: <cover.1459174494.git.joabreu@synopsys.com>
References: <cover.1459174494.git.joabreu@synopsys.com>
Message-ID: <20160329170022.GT2350@sirena.org.uk>

On Mon, Mar 28, 2016 at 03:36:08PM +0100, Jose Abreu wrote:
> ARC AXS10x platforms consist of a mainboard with several peripherals.
> One of those peripherals is an HDMI output port controlled by the ADV7511
> transmitter.

I'm going to tell you the same thing I tell everyone else working on
HDMI audio integration: you all need to talk to each other and review
each other's code and unless there is a very good reason for it there
should be at least some code sharing.  For example take a look at the
patches Jyri Sarha has been posting recently.  I don't have detailed
knowledge of HDMI and the range of hardware that's out there for it but
I am seeing a number of different people posting patch serieses that
look a lot like each other and like they should be sharing things.

Please also try to keep your CC lists reasonable, the set of people
you've copied on this stuff is enormous and I'm having trouble seeing
why a lot of tehm are included.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-snps-arc/attachments/20160329/e963f8cf/attachment.sig>

From architt at codeaurora.org  Tue Mar 29 10:03:19 2016
From: architt at codeaurora.org (Archit Taneja)
Date: Tue, 29 Mar 2016 22:33:19 +0530
Subject: [PATCH 1/3 v2] drm/i2c/adv7511: Add audio support
In-Reply-To: <56FA5E57.2000506@synopsys.com>
References: <cover.1459174494.git.joabreu@synopsys.com>
 <15b1936d307912ba12df7fa09ec3a7a80ac5fcef.1459174494.git.joabreu@synopsys.com>
 <56FA3745.3000807@codeaurora.org> <56FA5E57.2000506@synopsys.com>
Message-ID: <56FAB557.3060900@codeaurora.org>



On 3/29/2016 4:22 PM, Jose Abreu wrote:
> Hi Archit,
>
> On 29-03-2016 09:05, Archit Taneja wrote:
>> Hi,
>>
>> On 03/28/2016 08:06 PM, Jose Abreu wrote:
>>> This patch adds audio support for the ADV7511 HDMI transmitter
>>> using ALSA SoC.
>>>
>>> The code was ported from Analog Devices linux tree from
>>> commit 1770c4a1e32b ("Merge remote-tracking branch
>>> 'xilinx/master' into xcomm_zynq"), which is available at:
>>>      - https://github.com/analogdevicesinc/linux/
>>>
>>> The main core file was renamed from adv7511.c to adv7511_core.c
>>> so that audio and video compile into a single adv7511.ko module
>>> and to keep up with Analog Devices kernel tree.
>>>
>>> The audio can be disabled using menu-config so it is possible
>>> to use only video mode.
>>>
>>> The HDMI mode is automatically started at boot and the audio
>>> (when enabled) registers as a codec into ALSA.
>>
>> Is there a reason why we set the mode to HDMI at probe itself?
>> Shouldn't it be okay to set the mode later once we read the
>> EDID off the panel?
>>
>> Some more comments below.
>>
>
> Well, when I was using this in kernel 3.18 (with an older version of the driver)
> I noticed that DVI mode was being used even when HDMI was connected so I forced
> the driver to start in HDMI mode. There were some changes in the driver so it is
> possible that this is no longer needed. Should I drop it?

Mode selection works fine with ADV7533 on a 4.5 kernel. I'm assuming it
should work out of the box for ADV7511 too. We should drop this.


>
>>>
>>> SPDIF DAI format was also added to ASoC as it is required
>>> by adv7511 audio.
>>>
>>> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
>>> ---
>>>
>>> No changes v1 -> v2.
>>>
>>>    drivers/gpu/drm/i2c/Kconfig         |   11 +
>>>    drivers/gpu/drm/i2c/Makefile        |    2 +
>>>    drivers/gpu/drm/i2c/adv7511.c       | 1024 -----------------------------------
>>>    drivers/gpu/drm/i2c/adv7511.h       |   41 ++
>>>    drivers/gpu/drm/i2c/adv7511_audio.c |  310 +++++++++++
>>>    drivers/gpu/drm/i2c/adv7511_core.c  | 1005 ++++++++++++++++++++++++++++++++++
>>>    include/sound/soc-dai.h             |    1 +
>>>    7 files changed, 1370 insertions(+), 1024 deletions(-)
>>>    delete mode 100644 drivers/gpu/drm/i2c/adv7511.c
>>>    create mode 100644 drivers/gpu/drm/i2c/adv7511_audio.c
>>>    create mode 100644 drivers/gpu/drm/i2c/adv7511_core.c
>>
>> <snip>
>>
>>> +
>>> +static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id
>>> *id)
>>> +{
>>> +    struct adv7511_link_config link_config;
>>> +    struct adv7511 *adv7511;
>>> +    struct device *dev = &i2c->dev;
>>> +    unsigned int val;
>>> +    int ret;
>>> +
>>> +    if (!dev->of_node)
>>> +        return -EINVAL;
>>> +
>>> +    adv7511 = devm_kzalloc(dev, sizeof(*adv7511), GFP_KERNEL);
>>> +    if (!adv7511)
>>> +        return -ENOMEM;
>>> +
>>> +    adv7511->powered = false;
>>> +    adv7511->status = connector_status_disconnected;
>>> +
>>> +    ret = adv7511_parse_dt(dev->of_node, &link_config);
>>> +    if (ret)
>>> +        return ret;
>>> +
>>> +    /*
>>> +     * The power down GPIO is optional. If present, toggle it from active to
>>> +     * inactive to wake up the encoder.
>>> +     */
>>> +    adv7511->gpio_pd = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_HIGH);
>>> +    if (IS_ERR(adv7511->gpio_pd))
>>> +        return PTR_ERR(adv7511->gpio_pd);
>>> +
>>> +    if (adv7511->gpio_pd) {
>>> +        mdelay(5);
>>> +        gpiod_set_value_cansleep(adv7511->gpio_pd, 0);
>>> +    }
>>> +
>>> +    adv7511->regmap = devm_regmap_init_i2c(i2c, &adv7511_regmap_config);
>>> +    if (IS_ERR(adv7511->regmap))
>>> +        return PTR_ERR(adv7511->regmap);
>>> +
>>> +    ret = regmap_read(adv7511->regmap, ADV7511_REG_CHIP_REVISION, &val);
>>> +    if (ret)
>>> +        return ret;
>>> +    dev_dbg(dev, "Rev. %d\n", val);
>>> +
>>> +    ret = regmap_register_patch(adv7511->regmap, adv7511_fixed_registers,
>>> +                    ARRAY_SIZE(adv7511_fixed_registers));
>>> +    if (ret)
>>> +        return ret;
>>> +
>>> +    regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR, edid_i2c_addr);
>>> +    regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR,
>>> +             packet_i2c_addr);
>>> +    regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR, cec_i2c_addr);
>>> +    adv7511_packet_disable(adv7511, 0xffff);
>>> +
>>> +    adv7511->i2c_main = i2c;
>>> +    adv7511->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1);
>>> +    if (!adv7511->i2c_edid)
>>> +        return -ENOMEM;
>>> +
>>> +    if (i2c->irq) {
>>> +        init_waitqueue_head(&adv7511->wq);
>>> +
>>> +        ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
>>> +                        adv7511_irq_handler,
>>> +                        IRQF_ONESHOT, dev_name(dev),
>>> +                        adv7511);
>>> +        if (ret)
>>> +            goto err_i2c_unregister_device;
>>> +    }
>>> +
>>> +    /* CEC is unused for now */
>>> +    regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
>>> +             ADV7511_CEC_CTRL_POWER_DOWN);
>>> +
>>> +    adv7511_power_off(adv7511);
>>> +
>>> +    i2c_set_clientdata(i2c, adv7511);
>>> +
>>> +#ifdef CONFIG_DRM_I2C_ADV7511_AUDIO
>>> +    adv7511_audio_init(&i2c->dev);
>>> +#endif
>>
>> If we intend to have more audio funcs being used by the core in the
>> future, it would be nice to have NOP audio funcs rather than having
>> multiple #ifdef checks in the driver when CONFIG_DRM_I2C_ADV7511_AUDIO
>> isn't set.
>>
>
> I will move this ifdef to adv751_audio and use NOP functions.

Thanks, I think it should help in the longer run.

>
>>> +
>>> +    adv7511_set_link_config(adv7511, &link_config);
>>> +
>>> +    /* Enable HDMI mode */
>>> +    regmap_update_bits(adv7511->regmap, ADV7511_REG_HDCP_HDMI_CFG,
>>> +            ADV7511_HDMI_CFG_MODE_MASK,
>>> +            ADV7511_HDMI_CFG_MODE_HDMI);
>>> +
>>> +    return 0;
>>> +
>>> +err_i2c_unregister_device:
>>> +    i2c_unregister_device(adv7511->i2c_edid);
>>> +
>>> +    return ret;
>>> +}
>>> +
>>> +static int adv7511_remove(struct i2c_client *i2c)
>>> +{
>>> +    struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
>>> +
>>
>> Are we missing a call to adv7511_audio_exit() here?
>
> I followed the code in Analog Devices tree where there is no call to
> audio_exit() but indeed you are correct. I will add this call.
>

Since we have 3 files for adv7511 now, could we also move the driver
to a separate folder? The long term plan is to convert all the i2c
slave encoder drivers to bridges. Keeping them together would be nicer
when we migrate this driver to the bridge folder.

Thanks,
Archit

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


From broonie at kernel.org  Tue Mar 29 10:31:58 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 29 Mar 2016 10:31:58 -0700
Subject: [PATCH 2/3 v2] ASoC: dwc: Add I2S HDMI audio support
In-Reply-To: <538be366488bf0d7633d702f2d0bab16707b7a47.1459174494.git.joabreu@synopsys.com>
References: <cover.1459174494.git.joabreu@synopsys.com>
 <538be366488bf0d7633d702f2d0bab16707b7a47.1459174494.git.joabreu@synopsys.com>
Message-ID: <20160329173158.GB2350@sirena.org.uk>

On Mon, Mar 28, 2016 at 03:36:10PM +0100, Jose Abreu wrote:
> HDMI audio support was added to the AXS board using an
> I2S cpu driver and a custom platform driver.
> 
> The platform driver supports two channels @ 16 bits with
> rates 32k, 44.1k and 48k. ALSA Simple audio card is used to
> glue the cpu, platform and codec driver (adv7511).

>  sound/soc/dwc/Kconfig          |   1 +
>  sound/soc/dwc/designware_i2s.c | 385 +++++++++++++++++++++++++++++++++++++++--

Your changelog appears to describe the writing of a machine driver but
this is a large patch adding code to an I2S controller driver.  This
means I can't review your patch since I can't tell what it is supposed
to do.  If you've added functionality to this driver you need to send
one or more patches each of which adds a single feature to the driver
together with a changelog which describes what that feature is.

Glancing at the patch I'm not 100% sure that the features you're adding
are part of the Synopsis device but I'm not entirely sure.

>  2 files changed, 373 insertions(+), 13 deletions(-)
> 
> diff --git a/sound/soc/dwc/Kconfig b/sound/soc/dwc/Kconfig
> index d50e085..bc3fae7 100644
> --- a/sound/soc/dwc/Kconfig
> +++ b/sound/soc/dwc/Kconfig
> @@ -2,6 +2,7 @@ config SND_DESIGNWARE_I2S
>  	tristate "Synopsys I2S Device Driver"
>  	depends on CLKDEV_LOOKUP
>  	select SND_SOC_GENERIC_DMAENGINE_PCM
> +	select SND_SIMPLE_CARD

No, this doesn't make sense - the fact that someone has used a Synopsis
I2S controller doesn't mean that they have a system which uses
simple-card.  If the user wants to use simple-card they need to enable
it separately, this is the same pattern we follow for all CPU controller
drivers.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-snps-arc/attachments/20160329/4f161eee/attachment.sig>

From Jose.Abreu at synopsys.com  Tue Mar 29 10:51:34 2016
From: Jose.Abreu at synopsys.com (Jose Abreu)
Date: Tue, 29 Mar 2016 18:51:34 +0100
Subject: [PATCH] clk/arc: Add I2S PLL clock driver
In-Reply-To: <C2D7FE5348E1B147BCA15975FBA23075F4E915E9@us01wembx1.internal.synopsys.com>
References: <e580aaf30e3c66d13693a4e6db0ced1996d37c04.1459246186.git.joabreu@synopsys.com>
 <1459250707.3021.31.camel@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E915E9@us01wembx1.internal.synopsys.com>
Message-ID: <56FAC0A6.5000504@synopsys.com>

Hi Vineet,

On 29-03-2016 13:36, Vineet Gupta wrote:
> On Tuesday 29 March 2016 04:55 PM, Alexey Brodkin wrote:
>> Hi Jose,
>>
>> On Tue, 2016-03-29 at 11:56 +0100, Jose Abreu wrote:
>>> The ARC SDP I2S clock can be programmed using a
>>> specific PLL.
>>>
>>> This patch has the goal of adding a clock driver
>>> that programs this PLL.
>>>
>>> At this moment the rate values are hardcoded in
>>> a table but in the future it would be ideal to
>>> use a function which determines the PLL values
>>> given the desired rate.
>>>
>>> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
>>> ---
>> I believe these kind of patches worth sending to
>> linux-snps mailing list (at least add it in Cc) so
>> they won't be lost in time and could be used later as
>> useful references.
> Please do also CC the common clk maintainers
>
> COMMON CLK FRAMEWORK
> M:    Michael Turquette <mturquette at baylibre.com>
> M:    Stephen Boyd <sboyd at codeaurora.org>
> L:    linux-clk at vger.kernel.org

Well, this was just an experiment and I think this patch is still far from being
ready to go mainline, that's why I did not cc'ed the clk maintainers. I will
send a v2 soon so you can review and if you think its worth sending to mainline
I will do that.

>>>  arch/arc/boot/dts/axs10x_mb.dtsi |   5 ++
>>>  drivers/clk/Makefile             |   1 +
>>>  drivers/clk/arc/Makefile         |   1 +
>>>  drivers/clk/arc/i2s_pll_clock.c  | 143 +++++++++++++++++++++++++++++++++++++++
>>>  4 files changed, 150 insertions(+)
>>>  create mode 100644 drivers/clk/arc/Makefile
>>>  create mode 100644 drivers/clk/arc/i2s_pll_clock.c
>>>
>>> diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
>>> index ab5d570..9c68226 100644
>>> --- a/arch/arc/boot/dts/axs10x_mb.dtsi
>>> +++ b/arch/arc/boot/dts/axs10x_mb.dtsi
>>> @@ -23,6 +23,11 @@
>>>  				#clock-cells = <0>;
>>>  			};
>>>  
>>> +			i2sclk: i2sclk {
>>> +				compatible = "snps,i2s-pll-clock";
>>> +				#clock-cells = <0>;
>>> +			};
>>> +
>>>  			apbclk: apbclk {
>>>  				compatible = "fixed-clock";
>>>  				clock-frequency = <50000000>;
>>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>>> index 46869d6..620e47f 100644
>>> --- a/drivers/clk/Makefile
>>> +++ b/drivers/clk/Makefile
>>> @@ -84,3 +84,4 @@ obj-$(CONFIG_X86)			+= x86/
>>>  obj-$(CONFIG_ARCH_ZX)			+= zte/
>>>  obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
>>>  obj-$(CONFIG_H8300)		+= h8300/
>>> +obj-$(CONFIG_ARC)		+= arc/
>> Two things here:
>>  [1] This clock is relevant to only one board but not SoC, CPU core
>>      or whole architecture, so it makes sense to make it dependent on
>>      the AXS platform, i.e. CONFIG_ARC_PLAT_AXS10X.
>>
>>  [2] Something similar is applicable to folder name, I would suggest to
>>      use "drivers/clk/axs10x"
>>
>>> diff --git a/drivers/clk/arc/Makefile b/drivers/clk/arc/Makefile
>>> new file mode 100644
>>> index 0000000..01996b8
>>> --- /dev/null
>>> +++ b/drivers/clk/arc/Makefile
>>> @@ -0,0 +1 @@
>>> +obj-y += i2s_pll_clock.o
>>> diff --git a/drivers/clk/arc/i2s_pll_clock.c b/drivers/clk/arc/i2s_pll_clock.c
>>> new file mode 100644
>>> index 0000000..8c401f1
>>> --- /dev/null
>>> +++ b/drivers/clk/arc/i2s_pll_clock.c
>>> @@ -0,0 +1,143 @@
>>> +/*
>>> + * Synopsys I2S PLL clock driver
>> Again that's not generic SNPS I2S clock but clock driver for a particular board.
>>
>>> + *
>>> + * drivers/clk/arc/i2s_pll_clock.c
>> BTW not sure why this path could be needed here.
>> IMHO that might be safely dropped.
>>
>>> + *
>>> + * Copyright (C) 2016 Synopsys
>>> + *
>>> + * This file is licensed under the terms of the GNU General Public
>>> + * License version 2. This program is licensed "as is" without any
>>> + * warranty of any kind, whether express or implied.
>>> + */
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/err.h>
>>> +#include <linux/device.h>
>>> +#include <linux/of_address.h>
>>> +#include <linux/slab.h>
>>> +
>>> +/* FPGA Version Info */
>>> +#define FPGA_VER_INFO	0xE0011230
>>> +#define FPGA_VER_27M	0x000FBED9
>> This is a little bit tricky.
>> We'll need to do that check in each and every clock driver for AXS10x
>> and so it worth putting this code in some common location (I mean common
>> for all axs10x clock drivers).
>>
>>> +/* PLL registers addresses */
>>> +#define PLL_IDIV_ADDR	0xE00100A0
>>> +#define PLL_FBDIV_ADDR	0xE00100A4
>>> +#define PLL_ODIV0_ADDR	0xE00100A8
>>> +#define PLL_ODIV1_ADDR	0xE00100AC
>>>
>>> +struct i2s_pll_clk {
>>> +	struct clk_hw hw;
>>> +};
>>> +
>>> +struct i2s_pll_cfg {
>>> +	unsigned int rate;
>>> +	unsigned int idiv;
>>> +	unsigned int fbdiv;
>>> +	unsigned int odiv0;
>>> +	unsigned int odiv1;
>>> +};
>>> +
>>> +static const struct i2s_pll_cfg i2s_pll_cfg_27m[] = {
>>> +	/* 27 Mhz */
>>> +	{ 1024000, 0x104, 0x451, 0x10E38, 0x2000 },
>>> +	{ 1411200, 0x104, 0x596, 0x10D35, 0x2000 },
>>> +	{ 1536000, 0x208, 0xA28, 0x10B2C, 0x2000 },
>>> +	{ 2048000, 0x82, 0x451, 0x10E38, 0x2000 },
>>> +	{ 2822400, 0x82, 0x596, 0x10D35, 0x2000 },
>>> +	{ 3072000, 0x104, 0xA28, 0x10B2C, 0x2000 },
>>> +	{ 0, 0, 0, 0, 0 },
>>> +};
>>> +
>>> +static const struct i2s_pll_cfg i2s_pll_cfg_28m[] = {
>>> +	/* 28.224 Mhz */
>>> +	{ 1024000, 0x82, 0x105, 0x107DF, 0x2000 },
>>> +	{ 1411200, 0x28A, 0x1, 0x10001, 0x2000 },
>>> +	{ 1536000, 0xA28, 0x187, 0x10042, 0x2000 },
>>> +	{ 2048000, 0x41, 0x105, 0x107DF, 0x2000 },
>>> +	{ 2822400, 0x145, 0x1, 0x10001, 0x2000 },
>>> +	{ 3072000, 0x514, 0x187, 0x10042, 0x2000 },
>>> +	{ 0, 0, 0, 0, 0 },
>>> +};
>>> +
>>> +static unsigned long i2s_pll_recalc_rate(struct clk_hw *hw,
>>> +			unsigned long parent_rate)
>>> +{
>>> +	/* TODO */
>>> +	pr_info("%s: parent_rate=%ld\n", __func__, parent_rate);
>>> +	return parent_rate;
>>> +}
>>> +
>>> +static long i2s_pll_round_rate(struct clk_hw *hw, unsigned long rate,
>>> +			unsigned long *prate)
>>> +{
>>> +	/* TODO: Round rate to nearest valid rate */
>>> +	*prate = rate;
>>> +	pr_info("%s: rate=%ld, prate=%ld\n", __func__, rate, *prate);
>>> +	return *prate;
>>> +}
>> These are now just dummy functions so probably they could be dropped.
>>
>>> +static int i2s_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>>> +			unsigned long parent_rate)
>>> +{
>>> +	const struct i2s_pll_cfg *pll_cfg;
>>> +	int i;
>>> +
>>> +	if (readl((void *)FPGA_VER_INFO) <= FPGA_VER_27M)
>>> +		pll_cfg = i2s_pll_cfg_27m;
>>> +	else
>>> +		pll_cfg = i2s_pll_cfg_28m;
>> As I mentioned above we need to check board version in common place and then
>> just use some variable or structure member for comparison.
>>
>> Otherwise it looks pretty nice!
>>
>> -Alexey
>

Best regards,
Jose Miguel Abreu


From Jose.Abreu at synopsys.com  Tue Mar 29 10:54:01 2016
From: Jose.Abreu at synopsys.com (Jose Abreu)
Date: Tue, 29 Mar 2016 18:54:01 +0100
Subject: [PATCH v2] clk/axs10x: Add I2S PLL clock driver
Message-ID: <251a091c0c09d8547d5661966174f9bb0f9aec61.1459272583.git.joabreu@synopsys.com>

The ARC SDP I2S clock can be programmed using a
specific PLL.

This patch has the goal of adding a clock driver
that programs this PLL.

At this moment the rate values are hardcoded in
a table but in the future it would be ideal to
use a function which determines the PLL values
given the desired rate.

Signed-off-by: Jose Abreu <joabreu at synopsys.com>
---

Changes v1 -> v2:
* Renamed folder to axs10x (as suggested by Alexey Brodkin)
* Added more supported rates

 arch/arc/boot/dts/axs10x_mb.dtsi   |   5 ++
 drivers/clk/Makefile               |   1 +
 drivers/clk/axs10x/Makefile        |   1 +
 drivers/clk/axs10x/i2s_pll_clock.c | 149 +++++++++++++++++++++++++++++++++++++
 4 files changed, 156 insertions(+)
 create mode 100644 drivers/clk/axs10x/Makefile
 create mode 100644 drivers/clk/axs10x/i2s_pll_clock.c

diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
index ab5d570..9c68226 100644
--- a/arch/arc/boot/dts/axs10x_mb.dtsi
+++ b/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -23,6 +23,11 @@
 				#clock-cells = <0>;
 			};
 
+			i2sclk: i2sclk {
+				compatible = "snps,i2s-pll-clock";
+				#clock-cells = <0>;
+			};
+
 			apbclk: apbclk {
 				compatible = "fixed-clock";
 				clock-frequency = <50000000>;
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 46869d6..2ca62dc6 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -84,3 +84,4 @@ obj-$(CONFIG_X86)			+= x86/
 obj-$(CONFIG_ARCH_ZX)			+= zte/
 obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
 obj-$(CONFIG_H8300)		+= h8300/
+obj-$(CONFIG_ARC_PLAT_AXS10X)		+= axs10x/
diff --git a/drivers/clk/axs10x/Makefile b/drivers/clk/axs10x/Makefile
new file mode 100644
index 0000000..01996b8
--- /dev/null
+++ b/drivers/clk/axs10x/Makefile
@@ -0,0 +1 @@
+obj-y += i2s_pll_clock.o
diff --git a/drivers/clk/axs10x/i2s_pll_clock.c b/drivers/clk/axs10x/i2s_pll_clock.c
new file mode 100644
index 0000000..145e40e
--- /dev/null
+++ b/drivers/clk/axs10x/i2s_pll_clock.c
@@ -0,0 +1,149 @@
+/*
+ * Synopsys AXS10X SDP I2S PLL clock driver
+ *
+ * Copyright (C) 2016 Synopsys
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+/* FPGA Version Info */
+#define FPGA_VER_INFO	0xE0011230
+#define FPGA_VER_27M	0x000FBED9
+
+/* PLL registers addresses */
+#define PLL_IDIV_ADDR	0xE00100A0
+#define PLL_FBDIV_ADDR	0xE00100A4
+#define PLL_ODIV0_ADDR	0xE00100A8
+#define PLL_ODIV1_ADDR	0xE00100AC
+
+struct i2s_pll_cfg {
+	unsigned int rate;
+	unsigned int idiv;
+	unsigned int fbdiv;
+	unsigned int odiv0;
+	unsigned int odiv1;
+};
+
+static struct i2s_pll_cfg i2s_pll_cfg_27m[] = {
+	/* 27 Mhz */
+	{ 1024000, 0x104, 0x451, 0x10E38, 0x2000 },
+	{ 1411200, 0x104, 0x596, 0x10D35, 0x2000 },
+	{ 1536000, 0x208, 0xA28, 0x10B2C, 0x2000 },
+	{ 2048000, 0x82, 0x451, 0x10E38, 0x2000 },
+	{ 2822400, 0x82, 0x596, 0x10D35, 0x2000 },
+	{ 3072000, 0x104, 0xA28, 0x10B2C, 0x2000 },
+	{ 2116800, 0x82, 0x3CF, 0x10C30, 0x2000 },
+	{ 2304000, 0x104, 0x79E, 0x10B2C, 0x2000 },
+	{ 0, 0, 0, 0, 0 },
+};
+
+static struct i2s_pll_cfg i2s_pll_cfg_28m[] = {
+	/* 28.224 Mhz */
+	{ 1024000, 0x82, 0x105, 0x107DF, 0x2000 },
+	{ 1411200, 0x28A, 0x1, 0x10001, 0x2000 },
+	{ 1536000, 0xA28, 0x187, 0x10042, 0x2000 },
+	{ 2048000, 0x41, 0x105, 0x107DF, 0x2000 },
+	{ 2822400, 0x145, 0x1, 0x10001, 0x2000 },
+	{ 3072000, 0x514, 0x187, 0x10042, 0x2000 },
+	{ 2116800, 0x514, 0x42, 0x10001, 0x2000 },
+	{ 2304000, 0x619, 0x82, 0x10001, 0x2000 },
+	{ 0, 0, 0, 0, 0 },
+};
+
+struct i2s_pll_clk {
+	struct clk_hw hw;
+	struct i2s_pll_cfg *pll_cfg;
+};
+
+static inline struct i2s_pll_clk *to_i2s_pll_clk(struct clk_hw *hw)
+{
+	return container_of(hw, struct i2s_pll_clk, hw);
+}
+
+static unsigned long i2s_pll_recalc_rate(struct clk_hw *hw,
+			unsigned long parent_rate)
+{
+	/* TODO: Recalc rate based on hardware params */
+	return parent_rate;
+}
+
+static long i2s_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+			unsigned long *prate)
+{
+	/* TODO: Round rate to nearest valid rate */
+	*prate = rate;
+	return *prate;
+}
+
+static int i2s_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+			unsigned long parent_rate)
+{
+	struct i2s_pll_cfg *pll_cfg = to_i2s_pll_clk(hw)->pll_cfg;
+	int i;
+
+	for (i = 0; pll_cfg[i].rate != 0; i++) {
+		if (pll_cfg[i].rate == rate) {
+			writel(pll_cfg[i].idiv, (void *)PLL_IDIV_ADDR);
+			writel(pll_cfg[i].fbdiv, (void *)PLL_FBDIV_ADDR);
+			writel(pll_cfg[i].odiv0, (void *)PLL_ODIV0_ADDR);
+			writel(pll_cfg[i].odiv1, (void *)PLL_ODIV1_ADDR);
+			return 0;
+		}
+	}
+
+	pr_err("%s: invalid rate=%ld, parent_rate=%ld\n", __func__,
+			rate, parent_rate);
+	return -EINVAL;
+}
+
+static const struct clk_ops i2s_pll_ops = {
+	.recalc_rate = i2s_pll_recalc_rate,
+	.round_rate = i2s_pll_round_rate,
+	.set_rate = i2s_pll_set_rate,
+};
+
+static void __init i2s_pll_clk_setup(struct device_node *node)
+{
+	const char *clk_name = node->name;
+	struct clk *clk;
+	struct i2s_pll_clk *pll_clk;
+	struct clk_init_data init;
+
+	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
+	if (!pll_clk)
+		return;
+
+	init.name = clk_name;
+	init.ops = &i2s_pll_ops;
+	init.flags = CLK_IS_BASIC;
+	init.num_parents = 0;
+	pll_clk->hw.init = &init;
+
+	clk = clk_register(NULL, &pll_clk->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register %s div clock (%ld)\n",
+				__func__, clk_name, PTR_ERR(clk));
+		goto free_clock;
+	}
+
+	if (readl((void *)FPGA_VER_INFO) <= FPGA_VER_27M)
+		pll_clk->pll_cfg = i2s_pll_cfg_27m;
+	else
+		pll_clk->pll_cfg = i2s_pll_cfg_28m;
+
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	return;
+
+free_clock:
+	kfree(pll_clk);
+}
+
+CLK_OF_DECLARE(i2s_pll_clk, "snps,i2s-pll-clock", i2s_pll_clk_setup);
+
-- 
1.9.1




From broonie at kernel.org  Tue Mar 29 11:22:22 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 29 Mar 2016 11:22:22 -0700
Subject: [PATCH 2/3 v2] ASoC: dwc: Add I2S HDMI audio support
In-Reply-To: <56FAC355.1040705@synopsys.com>
References: <cover.1459174494.git.joabreu@synopsys.com>
 <538be366488bf0d7633d702f2d0bab16707b7a47.1459174494.git.joabreu@synopsys.com>
 <20160329173158.GB2350@sirena.org.uk>
 <56FAC355.1040705@synopsys.com>
Message-ID: <20160329182222.GC2350@sirena.org.uk>

On Tue, Mar 29, 2016 at 07:03:01PM +0100, Jose Abreu wrote:

> The major part of this patch is the adding of an ALSA platform driver so that
> audio comes out of the box in AXS boards but we also added functionalities to
> the i2s driver and performed one bug fix related with the mask/unmask of
> interrupts. I will split the patches but they will depend on each other.

If you want to add a new platform driver you need to add a new platform
driver, not shove the code into an existing driver for a seperate IP.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-snps-arc/attachments/20160329/020e90b1/attachment-0001.sig>

From emil.l.velikov at gmail.com  Wed Mar 30 02:58:42 2016
From: emil.l.velikov at gmail.com (Emil Velikov)
Date: Wed, 30 Mar 2016 10:58:42 +0100
Subject: [PATCH 1/3 v2] drm/i2c/adv7511: Add audio support
In-Reply-To: <15b1936d307912ba12df7fa09ec3a7a80ac5fcef.1459174494.git.joabreu@synopsys.com>
References: <cover.1459174494.git.joabreu@synopsys.com>
 <15b1936d307912ba12df7fa09ec3a7a80ac5fcef.1459174494.git.joabreu@synopsys.com>
Message-ID: <CACvgo53rc2DhQdJUZJB5Lsj57vJGytU7GKqp-O_YZvzH7Df1XA@mail.gmail.com>

Hi Jose,

On 28 March 2016 at 15:36, Jose Abreu <Jose.Abreu at synopsys.com> wrote:
> This patch adds audio support for the ADV7511 HDMI transmitter
> using ALSA SoC.
>
> The code was ported from Analog Devices linux tree from
> commit 1770c4a1e32b ("Merge remote-tracking branch
> 'xilinx/master' into xcomm_zynq"), which is available at:
>         - https://github.com/analogdevicesinc/linux/
>
> The main core file was renamed from adv7511.c to adv7511_core.c
> so that audio and video compile into a single adv7511.ko module
> and to keep up with Analog Devices kernel tree.
>
> The audio can be disabled using menu-config so it is possible
> to use only video mode.
>
> The HDMI mode is automatically started at boot and the audio
> (when enabled) registers as a codec into ALSA.
>
> SPDIF DAI format was also added to ASoC as it is required
> by adv7511 audio.
>
> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
> ---
>
> No changes v1 -> v2.
>
>  drivers/gpu/drm/i2c/Kconfig         |   11 +
>  drivers/gpu/drm/i2c/Makefile        |    2 +
>  drivers/gpu/drm/i2c/adv7511.c       | 1024 -----------------------------------
>  drivers/gpu/drm/i2c/adv7511.h       |   41 ++
>  drivers/gpu/drm/i2c/adv7511_audio.c |  310 +++++++++++
>  drivers/gpu/drm/i2c/adv7511_core.c  | 1005 ++++++++++++++++++++++++++++++++++
Please keep the file rename separate (and use -M flag when generating
the patch) from the introduction of audio support. Having to check 1k
LOC movement alongside the introduction of new one is a bit...
suboptimal.

Regards,
Emil


From Vineet.Gupta1 at synopsys.com  Thu Mar 31 00:34:40 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Thu, 31 Mar 2016 07:34:40 +0000
Subject: [PATCH] clk/arc: Add I2S PLL clock driver
References: <e580aaf30e3c66d13693a4e6db0ced1996d37c04.1459246186.git.joabreu@synopsys.com>
 <1459250707.3021.31.camel@synopsys.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4E915E9@us01wembx1.internal.synopsys.com>
 <56FAC0A6.5000504@synopsys.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4E91822@us01wembx1.internal.synopsys.com>

On Tuesday 29 March 2016 11:21 PM, Jose Abreu wrote:

Well, this was just an experiment and I think this patch is still far from being
ready to go mainline, that's why I did not cc'ed the clk maintainers. I will
send a v2 soon so you can review and if you think its worth sending to mainline
I will do that.


It never hurts to CC actual maintainer as they will be able to provide you the best feedback.
Each of us have our domain expertise so I may review your code superficially but only the person who knows the subsystem inside-out can tell you exactly what to do.

They are grumpy at times and might bitch a bit but as they they "it is your code that gets criticized - not you"
I've learnt this myself over the years :-)

-Vineet


From Jose.Abreu at synopsys.com  Thu Mar 31 02:37:20 2016
From: Jose.Abreu at synopsys.com (Jose Abreu)
Date: Thu, 31 Mar 2016 10:37:20 +0100
Subject: [PATCH 2/3 v2] ASoC: dwc: Add I2S HDMI audio support
In-Reply-To: <20160329182222.GC2350@sirena.org.uk>
References: <cover.1459174494.git.joabreu@synopsys.com>
 <538be366488bf0d7633d702f2d0bab16707b7a47.1459174494.git.joabreu@synopsys.com>
 <20160329173158.GB2350@sirena.org.uk> <56FAC355.1040705@synopsys.com>
 <20160329182222.GC2350@sirena.org.uk>
Message-ID: <56FCEFD0.8090509@synopsys.com>

Hi Mark,

On 29-03-2016 19:22, Mark Brown wrote:
> On Tue, Mar 29, 2016 at 07:03:01PM +0100, Jose Abreu wrote:
>
>> The major part of this patch is the adding of an ALSA platform driver so that
>> audio comes out of the box in AXS boards but we also added functionalities to
>> the i2s driver and performed one bug fix related with the mask/unmask of
>> interrupts. I will split the patches but they will depend on each other.
> If you want to add a new platform driver you need to add a new platform
> driver, not shove the code into an existing driver for a seperate IP.
>

I can separate the platform driver into a new file but they will have to be
compiled into the same module as the new additions to the i2s driver depend on
functions of the platform driver (see i2s_irq_handler()). Or should I divide
this into two modules and add a Kconfig option to the platform driver? Besides
this I first wanted the driver to be compiled into the same module so that it is
compatible with kernel 3.18 where simple audio card requires that platform
driver == cpu driver.

Best regards,
Jose Miguel Abreu


From Jose.Abreu at synopsys.com  Thu Mar 31 05:57:56 2016
From: Jose.Abreu at synopsys.com (Jose Abreu)
Date: Thu, 31 Mar 2016 13:57:56 +0100
Subject: [PATCH 1/3 v2] drm/i2c/adv7511: Add audio support
In-Reply-To: <56FAB557.3060900@codeaurora.org>
References: <cover.1459174494.git.joabreu@synopsys.com>
 <15b1936d307912ba12df7fa09ec3a7a80ac5fcef.1459174494.git.joabreu@synopsys.com>
 <56FA3745.3000807@codeaurora.org> <56FA5E57.2000506@synopsys.com>
 <56FAB557.3060900@codeaurora.org>
Message-ID: <56FD1ED4.4040200@synopsys.com>

Hi Archit,


On 29-03-2016 18:03, Archit Taneja wrote:
>
>
> On 3/29/2016 4:22 PM, Jose Abreu wrote:
>> Hi Archit,
>>
>> On 29-03-2016 09:05, Archit Taneja wrote:
>>> Hi,
>>>
>>> On 03/28/2016 08:06 PM, Jose Abreu wrote:
>>>> This patch adds audio support for the ADV7511 HDMI transmitter
>>>> using ALSA SoC.
>>>>
>>>> The code was ported from Analog Devices linux tree from
>>>> commit 1770c4a1e32b ("Merge remote-tracking branch
>>>> 'xilinx/master' into xcomm_zynq"), which is available at:
>>>>      - https://github.com/analogdevicesinc/linux/
>>>>
>>>> The main core file was renamed from adv7511.c to adv7511_core.c
>>>> so that audio and video compile into a single adv7511.ko module
>>>> and to keep up with Analog Devices kernel tree.
>>>>
>>>> The audio can be disabled using menu-config so it is possible
>>>> to use only video mode.
>>>>
>>>> The HDMI mode is automatically started at boot and the audio
>>>> (when enabled) registers as a codec into ALSA.
>>>
>>> Is there a reason why we set the mode to HDMI at probe itself?
>>> Shouldn't it be okay to set the mode later once we read the
>>> EDID off the panel?
>>>
>>> Some more comments below.
>>>
>>
>> Well, when I was using this in kernel 3.18 (with an older version of the driver)
>> I noticed that DVI mode was being used even when HDMI was connected so I forced
>> the driver to start in HDMI mode. There were some changes in the driver so it is
>> possible that this is no longer needed. Should I drop it?
>
> Mode selection works fine with ADV7533 on a 4.5 kernel. I'm assuming it
> should work out of the box for ADV7511 too. We should drop this.
>
>

Ok, will drop.

>>
>>>>
>>>> SPDIF DAI format was also added to ASoC as it is required
>>>> by adv7511 audio.
>>>>
>>>> Signed-off-by: Jose Abreu <joabreu at synopsys.com>
>>>> ---
>>>>
>>>> No changes v1 -> v2.
>>>>
>>>>    drivers/gpu/drm/i2c/Kconfig         |   11 +
>>>>    drivers/gpu/drm/i2c/Makefile        |    2 +
>>>>    drivers/gpu/drm/i2c/adv7511.c       | 1024
>>>> -----------------------------------
>>>>    drivers/gpu/drm/i2c/adv7511.h       |   41 ++
>>>>    drivers/gpu/drm/i2c/adv7511_audio.c |  310 +++++++++++
>>>>    drivers/gpu/drm/i2c/adv7511_core.c  | 1005
>>>> ++++++++++++++++++++++++++++++++++
>>>>    include/sound/soc-dai.h             |    1 +
>>>>    7 files changed, 1370 insertions(+), 1024 deletions(-)
>>>>    delete mode 100644 drivers/gpu/drm/i2c/adv7511.c
>>>>    create mode 100644 drivers/gpu/drm/i2c/adv7511_audio.c
>>>>    create mode 100644 drivers/gpu/drm/i2c/adv7511_core.c
>>>
>>> <snip>
>>>
>>>> +
>>>> +static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id
>>>> *id)
>>>> +{
>>>> +    struct adv7511_link_config link_config;
>>>> +    struct adv7511 *adv7511;
>>>> +    struct device *dev = &i2c->dev;
>>>> +    unsigned int val;
>>>> +    int ret;
>>>> +
>>>> +    if (!dev->of_node)
>>>> +        return -EINVAL;
>>>> +
>>>> +    adv7511 = devm_kzalloc(dev, sizeof(*adv7511), GFP_KERNEL);
>>>> +    if (!adv7511)
>>>> +        return -ENOMEM;
>>>> +
>>>> +    adv7511->powered = false;
>>>> +    adv7511->status = connector_status_disconnected;
>>>> +
>>>> +    ret = adv7511_parse_dt(dev->of_node, &link_config);
>>>> +    if (ret)
>>>> +        return ret;
>>>> +
>>>> +    /*
>>>> +     * The power down GPIO is optional. If present, toggle it from active to
>>>> +     * inactive to wake up the encoder.
>>>> +     */
>>>> +    adv7511->gpio_pd = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_HIGH);
>>>> +    if (IS_ERR(adv7511->gpio_pd))
>>>> +        return PTR_ERR(adv7511->gpio_pd);
>>>> +
>>>> +    if (adv7511->gpio_pd) {
>>>> +        mdelay(5);
>>>> +        gpiod_set_value_cansleep(adv7511->gpio_pd, 0);
>>>> +    }
>>>> +
>>>> +    adv7511->regmap = devm_regmap_init_i2c(i2c, &adv7511_regmap_config);
>>>> +    if (IS_ERR(adv7511->regmap))
>>>> +        return PTR_ERR(adv7511->regmap);
>>>> +
>>>> +    ret = regmap_read(adv7511->regmap, ADV7511_REG_CHIP_REVISION, &val);
>>>> +    if (ret)
>>>> +        return ret;
>>>> +    dev_dbg(dev, "Rev. %d\n", val);
>>>> +
>>>> +    ret = regmap_register_patch(adv7511->regmap, adv7511_fixed_registers,
>>>> +                    ARRAY_SIZE(adv7511_fixed_registers));
>>>> +    if (ret)
>>>> +        return ret;
>>>> +
>>>> +    regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR, edid_i2c_addr);
>>>> +    regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR,
>>>> +             packet_i2c_addr);
>>>> +    regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR, cec_i2c_addr);
>>>> +    adv7511_packet_disable(adv7511, 0xffff);
>>>> +
>>>> +    adv7511->i2c_main = i2c;
>>>> +    adv7511->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1);
>>>> +    if (!adv7511->i2c_edid)
>>>> +        return -ENOMEM;
>>>> +
>>>> +    if (i2c->irq) {
>>>> +        init_waitqueue_head(&adv7511->wq);
>>>> +
>>>> +        ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
>>>> +                        adv7511_irq_handler,
>>>> +                        IRQF_ONESHOT, dev_name(dev),
>>>> +                        adv7511);
>>>> +        if (ret)
>>>> +            goto err_i2c_unregister_device;
>>>> +    }
>>>> +
>>>> +    /* CEC is unused for now */
>>>> +    regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
>>>> +             ADV7511_CEC_CTRL_POWER_DOWN);
>>>> +
>>>> +    adv7511_power_off(adv7511);
>>>> +
>>>> +    i2c_set_clientdata(i2c, adv7511);
>>>> +
>>>> +#ifdef CONFIG_DRM_I2C_ADV7511_AUDIO
>>>> +    adv7511_audio_init(&i2c->dev);
>>>> +#endif
>>>
>>> If we intend to have more audio funcs being used by the core in the
>>> future, it would be nice to have NOP audio funcs rather than having
>>> multiple #ifdef checks in the driver when CONFIG_DRM_I2C_ADV7511_AUDIO
>>> isn't set.
>>>
>>
>> I will move this ifdef to adv751_audio and use NOP functions.
>
> Thanks, I think it should help in the longer run.
>
>>
>>>> +
>>>> +    adv7511_set_link_config(adv7511, &link_config);
>>>> +
>>>> +    /* Enable HDMI mode */
>>>> +    regmap_update_bits(adv7511->regmap, ADV7511_REG_HDCP_HDMI_CFG,
>>>> +            ADV7511_HDMI_CFG_MODE_MASK,
>>>> +            ADV7511_HDMI_CFG_MODE_HDMI);
>>>> +
>>>> +    return 0;
>>>> +
>>>> +err_i2c_unregister_device:
>>>> +    i2c_unregister_device(adv7511->i2c_edid);
>>>> +
>>>> +    return ret;
>>>> +}
>>>> +
>>>> +static int adv7511_remove(struct i2c_client *i2c)
>>>> +{
>>>> +    struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
>>>> +
>>>
>>> Are we missing a call to adv7511_audio_exit() here?
>>
>> I followed the code in Analog Devices tree where there is no call to
>> audio_exit() but indeed you are correct. I will add this call.
>>
>
> Since we have 3 files for adv7511 now, could we also move the driver
> to a separate folder? The long term plan is to convert all the i2c
> slave encoder drivers to bridges. Keeping them together would be nicer
> when we migrate this driver to the bridge folder.

Ok, will move to separate folder.

>
> Thanks,
> Archit
>

Best regards,
Jose Miguel Abreu


From jslaby at suse.cz  Thu Mar 31 00:55:53 2016
From: jslaby at suse.cz (Jiri Slaby)
Date: Thu, 31 Mar 2016 09:55:53 +0200
Subject: [PATCH v2 2/4] exit_thread: remove empty bodies
In-Reply-To: <1459410955-5422-1-git-send-email-jslaby@suse.cz>
References: <1459410955-5422-1-git-send-email-jslaby@suse.cz>
Message-ID: <1459410955-5422-2-git-send-email-jslaby@suse.cz>

Define HAVE_EXIT_THREAD for archs which want to do something in
exit_thread. For others, let's define exit_thread as an empty inline.

This is a cleanup before we change the prototype of exit_thread to
accept a task parameter.

Signed-off-by: Jiri Slaby <jslaby at suse.cz>
Cc: Richard Henderson <rth at twiddle.net>
Cc: Ivan Kokshaysky <ink at jurassic.park.msu.ru>
Cc: Matt Turner <mattst88 at gmail.com>
Cc: Vineet Gupta <vgupta at synopsys.com>
Cc: Russell King <linux at arm.linux.org.uk>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
Cc: Haavard Skinnemoen <hskinnemoen at gmail.com>
Cc: Hans-Christian Egtvedt <egtvedt at samfundet.no>
Cc: Steven Miao <realmz6 at gmail.com>
Cc: Mark Salter <msalter at redhat.com>
Cc: Aurelien Jacquiot <a-jacquiot at ti.com>
Cc: Mikael Starvik <starvik at axis.com>
Cc: Jesper Nilsson <jesper.nilsson at axis.com>
Cc: Yoshinori Sato <ysato at users.sourceforge.jp>
Cc: Richard Kuo <rkuo at codeaurora.org>
Cc: Geert Uytterhoeven <geert at linux-m68k.org>
Cc: James Hogan <james.hogan at imgtec.com>
Cc: Michal Simek <monstr at monstr.eu>
Cc: Ralf Baechle <ralf at linux-mips.org>
Cc: David Howells <dhowells at redhat.com>
Cc: Koichi Yasutake <yasutake.koichi at jp.panasonic.com>
Cc: Ley Foon Tan <lftan at altera.com>
Cc: Jonas Bonn <jonas at southpole.se>
Cc: "James E.J. Bottomley" <jejb at parisc-linux.org>
Cc: Helge Deller <deller at gmx.de>
Cc: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Cc: Paul Mackerras <paulus at samba.org>
Cc: Michael Ellerman <mpe at ellerman.id.au>
Cc: Martin Schwidefsky <schwidefsky at de.ibm.com>
Cc: Heiko Carstens <heiko.carstens at de.ibm.com>
Cc: Chen Liqin <liqin.linux at gmail.com>
Cc: Lennox Wu <lennox.wu at gmail.com>
Cc: Rich Felker <dalias at libc.org>
Cc: "David S. Miller" <davem at davemloft.net>
Cc: Chris Metcalf <cmetcalf at mellanox.com>
Cc: Jeff Dike <jdike at addtoit.com>
Cc: Richard Weinberger <richard at nod.at>
Cc: Guan Xuetao <gxt at mprc.pku.edu.cn>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: "H. Peter Anvin" <hpa at zytor.com>
Cc: x86 at kernel.org
Cc: Tony Luck <tony.luck at intel.com>
Cc: Fenghua Yu <fenghua.yu at intel.com>
Cc: Chris Zankel <chris at zankel.net>
Cc: Max Filippov <jcmvbkbc at gmail.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: linux-kernel at vger.kernel.org
Cc: linux-alpha at vger.kernel.org
Cc: linux-snps-arc at lists.infradead.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: adi-buildroot-devel at lists.sourceforge.net
Cc: linux-c6x-dev at linux-c6x.org
Cc: linux-cris-kernel at axis.com
Cc: linux-ia64 at vger.kernel.org
Cc: uclinux-h8-devel at lists.sourceforge.jp
Cc: linux-hexagon at vger.kernel.org
Cc: linux-m68k at lists.linux-m68k.org
Cc: linux-metag at vger.kernel.org
Cc: linux-mips at linux-mips.org
Cc: linux-am33-list at redhat.com
Cc: nios2-dev at lists.rocketboards.org
Cc: linux-parisc at vger.kernel.org
Cc: linuxppc-dev at lists.ozlabs.org
Cc: linux-s390 at vger.kernel.org
Cc: linux-sh at vger.kernel.org
Cc: sparclinux at vger.kernel.org
Cc: user-mode-linux-devel at lists.sourceforge.net
Cc: user-mode-linux-user at lists.sourceforge.net
Cc: linux-xtensa at linux-xtensa.org
---
 arch/Kconfig                            |  5 +++++
 arch/alpha/kernel/process.c             |  8 --------
 arch/arc/kernel/process.c               |  7 -------
 arch/arm/Kconfig                        |  1 +
 arch/arm64/kernel/process.c             |  7 -------
 arch/avr32/Kconfig                      |  1 +
 arch/blackfin/include/asm/processor.h   |  7 -------
 arch/c6x/kernel/process.c               |  4 ----
 arch/cris/Kconfig                       |  1 +
 arch/cris/arch-v10/kernel/process.c     |  9 ---------
 arch/frv/include/asm/processor.h        |  7 -------
 arch/h8300/include/asm/processor.h      |  7 -------
 arch/hexagon/kernel/process.c           |  7 -------
 arch/ia64/Kconfig                       |  1 +
 arch/m32r/kernel/process.c              |  9 ---------
 arch/m68k/include/asm/processor.h       |  7 -------
 arch/metag/Kconfig                      |  1 +
 arch/metag/include/asm/processor.h      |  2 --
 arch/microblaze/include/asm/processor.h | 10 ----------
 arch/mips/include/asm/processor.h       |  4 ----
 arch/mn10300/Kconfig                    |  1 +
 arch/nios2/include/asm/processor.h      |  5 -----
 arch/openrisc/include/asm/processor.h   |  9 ---------
 arch/parisc/kernel/process.c            |  7 -------
 arch/powerpc/kernel/process.c           |  4 ----
 arch/s390/Kconfig                       |  1 +
 arch/score/kernel/process.c             |  2 --
 arch/sh/Kconfig                         |  1 +
 arch/sh/kernel/process_32.c             |  7 -------
 arch/sparc/Kconfig                      |  1 +
 arch/tile/Kconfig                       |  1 +
 arch/um/kernel/process.c                |  4 ----
 arch/unicore32/kernel/process.c         |  7 -------
 arch/x86/Kconfig                        |  1 +
 arch/xtensa/Kconfig                     |  1 +
 include/linux/sched.h                   |  7 +++++++
 36 files changed, 24 insertions(+), 140 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 81869a5e7e17..0f298f9123dc 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -517,6 +517,11 @@ config HAVE_ARCH_MMAP_RND_BITS
 	  - ARCH_MMAP_RND_BITS_MIN
 	  - ARCH_MMAP_RND_BITS_MAX
 
+config HAVE_EXIT_THREAD
+	bool
+	help
+	  An architecture implements exit_thread.
+
 config ARCH_MMAP_RND_BITS_MIN
 	int
 
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 84d13263ce46..b483156698d5 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -210,14 +210,6 @@ start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
 }
 EXPORT_SYMBOL(start_thread);
 
-/*
- * Free current thread data structures etc..
- */
-void
-exit_thread(void)
-{
-}
-
 void
 flush_thread(void)
 {
diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c
index a3f750e76b68..b5db9e7fd649 100644
--- a/arch/arc/kernel/process.c
+++ b/arch/arc/kernel/process.c
@@ -183,13 +183,6 @@ void flush_thread(void)
 {
 }
 
-/*
- * Free any architecture-specific thread data structures, etc.
- */
-void exit_thread(void)
-{
-}
-
 int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 {
 	return 0;
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index cdfa6c2b7626..0846026c84de 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -50,6 +50,7 @@ config ARM
 	select HAVE_DMA_CONTIGUOUS if MMU
 	select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) && !CPU_ENDIAN_BE32 && MMU
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU
+	select HAVE_EXIT_THREAD
 	select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
 	select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL)
 	select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 80624829db61..5655f756e4f2 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -200,13 +200,6 @@ void show_regs(struct pt_regs * regs)
 	__show_regs(regs);
 }
 
-/*
- * Free current thread data structures etc..
- */
-void exit_thread(void)
-{
-}
-
 static void tls_thread_flush(void)
 {
 	asm ("msr tpidr_el0, xzr");
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index b6878eb64884..37d9c02be634 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -4,6 +4,7 @@ config AVR32
 	# that we usually don't need on AVR32.
 	select EXPERT
 	select HAVE_CLK
+	select HAVE_EXIT_THREAD
 	select HAVE_OPROFILE
 	select HAVE_KPROBES
 	select VIRT_TO_BUS
diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h
index 7acd46653df3..0c265aba94ad 100644
--- a/arch/blackfin/include/asm/processor.h
+++ b/arch/blackfin/include/asm/processor.h
@@ -76,13 +76,6 @@ static inline void release_thread(struct task_struct *dead_task)
 }
 
 /*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
-/*
  * Return saved PC of a blocked thread.
  */
 #define thread_saved_pc(tsk)	(tsk->thread.pc)
diff --git a/arch/c6x/kernel/process.c b/arch/c6x/kernel/process.c
index 3ae9f5a166a0..0ee7686a78f3 100644
--- a/arch/c6x/kernel/process.c
+++ b/arch/c6x/kernel/process.c
@@ -82,10 +82,6 @@ void flush_thread(void)
 {
 }
 
-void exit_thread(void)
-{
-}
-
 /*
  * Do necessary setup to start up a newly executed thread.
  */
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index e086f9e93728..10a5ccb85cd6 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -62,6 +62,7 @@ config CRIS
 	select OLD_SIGSUSPEND
 	select OLD_SIGACTION
 	select ARCH_REQUIRE_GPIOLIB
+	select HAVE_EXIT_THREAD if ETRAX_ARCH_V32
 	select IRQ_DOMAIN if ETRAX_ARCH_V32
 	select OF if ETRAX_ARCH_V32
 	select OF_EARLY_FLATTREE if ETRAX_ARCH_V32
diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c
index 02b783457be0..96e5afef6b47 100644
--- a/arch/cris/arch-v10/kernel/process.c
+++ b/arch/cris/arch-v10/kernel/process.c
@@ -35,15 +35,6 @@ void default_idle(void)
 	local_irq_enable();
 }
 
-/*
- * Free current thread data structures etc..
- */
-
-void exit_thread(void)
-{
-	/* Nothing needs to be done.  */
-}
-
 /* if the watchdog is enabled, we can simply disable interrupts and go
  * into an eternal loop, and the watchdog will reset the CPU after 0.1s
  * if on the other hand the watchdog wasn't enabled, we just enable it and wait
diff --git a/arch/frv/include/asm/processor.h b/arch/frv/include/asm/processor.h
index ae8d423e79d9..73f0a79ad8e6 100644
--- a/arch/frv/include/asm/processor.h
+++ b/arch/frv/include/asm/processor.h
@@ -97,13 +97,6 @@ extern asmlinkage void *restore_user_regs(const struct user_context *target, ...
 #define forget_segments()		do { } while (0)
 
 /*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
-/*
  * Return saved PC of a blocked thread.
  */
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h
index 54e3fd83c336..111df7397ac7 100644
--- a/arch/h8300/include/asm/processor.h
+++ b/arch/h8300/include/asm/processor.h
@@ -111,13 +111,6 @@ static inline void release_thread(struct task_struct *dead_task)
 }
 
 /*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
-/*
  * Return saved PC of a blocked thread.
  */
 unsigned long thread_saved_pc(struct task_struct *tsk);
diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c
index a9ebd471823a..d9edfd3fc52a 100644
--- a/arch/hexagon/kernel/process.c
+++ b/arch/hexagon/kernel/process.c
@@ -137,13 +137,6 @@ void release_thread(struct task_struct *dead_task)
 }
 
 /*
- * Free any architecture-specific thread data structures, etc.
- */
-void exit_thread(void)
-{
-}
-
-/*
  * Some archs flush debug and FPU info here
  */
 void flush_thread(void)
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index b534ebab36ea..f80758cb7157 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -18,6 +18,7 @@ config IA64
 	select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
 	select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
 	select HAVE_UNSTABLE_SCHED_CLOCK
+	select HAVE_EXIT_THREAD
 	select HAVE_IDE
 	select HAVE_OPROFILE
 	select HAVE_KPROBES
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index e69221d581d5..a88b1f01e91f 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -101,15 +101,6 @@ void show_regs(struct pt_regs * regs)
 #endif
 }
 
-/*
- * Free current thread data structures etc..
- */
-void exit_thread(void)
-{
-	/* Nothing to do. */
-	DPRINTK("pid = %d\n", current->pid);
-}
-
 void flush_thread(void)
 {
 	DPRINTK("pid = %d\n", current->pid);
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index 20dda1d4b860..a6ce2ec8d693 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -153,13 +153,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-/*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
 
 unsigned long get_wchan(struct task_struct *p);
diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig
index a0fa88da3e31..e47a08d72819 100644
--- a/arch/metag/Kconfig
+++ b/arch/metag/Kconfig
@@ -11,6 +11,7 @@ config METAG
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DEBUG_STACKOVERFLOW
 	select HAVE_DYNAMIC_FTRACE
+	select HAVE_EXIT_THREAD
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
 	select HAVE_KERNEL_BZIP2
diff --git a/arch/metag/include/asm/processor.h b/arch/metag/include/asm/processor.h
index 0838ca699764..a0333ebcac35 100644
--- a/arch/metag/include/asm/processor.h
+++ b/arch/metag/include/asm/processor.h
@@ -134,8 +134,6 @@ static inline void release_thread(struct task_struct *dead_task)
 #define copy_segments(tsk, mm)		do { } while (0)
 #define release_segments(mm)		do { } while (0)
 
-extern void exit_thread(void);
-
 /*
  * Return saved PC of a blocked thread.
  */
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h
index 497a988d79c2..c38d0dd91134 100644
--- a/arch/microblaze/include/asm/processor.h
+++ b/arch/microblaze/include/asm/processor.h
@@ -70,11 +70,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-/* Free all resources held by a thread. */
-static inline void exit_thread(void)
-{
-}
-
 extern unsigned long thread_saved_pc(struct task_struct *t);
 
 extern unsigned long get_wchan(struct task_struct *p);
@@ -127,11 +122,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-/* Free current thread data structures etc.  */
-static inline void exit_thread(void)
-{
-}
-
 /* Return saved (kernel) PC of a blocked thread.  */
 #  define thread_saved_pc(tsk)	\
 	((tsk)->thread.regs ? (tsk)->thread.regs->r15 : 0)
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 06469df2b638..cfa15bad43af 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -359,10 +359,6 @@ static inline void flush_thread(void)
 {
 }
 
-static inline void exit_thread(void)
-{
-}
-
 unsigned long get_wchan(struct task_struct *p);
 
 #define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + \
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
index 06ddb5501ab1..9627e81a6cbb 100644
--- a/arch/mn10300/Kconfig
+++ b/arch/mn10300/Kconfig
@@ -1,5 +1,6 @@
 config MN10300
 	def_bool y
+	select HAVE_EXIT_THREAD
 	select HAVE_OPROFILE
 	select HAVE_UID16
 	select GENERIC_IRQ_SHOW
diff --git a/arch/nios2/include/asm/processor.h b/arch/nios2/include/asm/processor.h
index c2ba45c159c7..1c953f0cadbf 100644
--- a/arch/nios2/include/asm/processor.h
+++ b/arch/nios2/include/asm/processor.h
@@ -75,11 +75,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-/* Free current thread data structures etc.. */
-static inline void exit_thread(void)
-{
-}
-
 /* Return saved PC of a blocked thread. */
 #define thread_saved_pc(tsk)	((tsk)->thread.kregs->ea)
 
diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h
index 4d235e3d2534..70334c9f7d24 100644
--- a/arch/openrisc/include/asm/processor.h
+++ b/arch/openrisc/include/asm/processor.h
@@ -85,15 +85,6 @@ void release_thread(struct task_struct *);
 unsigned long get_wchan(struct task_struct *p);
 
 /*
- * Free current thread data structures etc..
- */
-
-extern inline void exit_thread(void)
-{
-	/* Nothing needs to be done.  */
-}
-
-/*
  * Return saved PC of a blocked thread. For now, this is the "user" PC
  */
 extern unsigned long thread_saved_pc(struct task_struct *t);
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 809905a811ed..40639439d8b3 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -144,13 +144,6 @@ void machine_power_off(void)
 void (*pm_power_off)(void) = machine_power_off;
 EXPORT_SYMBOL(pm_power_off);
 
-/*
- * Free current thread data structures etc..
- */
-void exit_thread(void)
-{
-}
-
 void flush_thread(void)
 {
 	/* Only needs to handle fpu stuff or perf monitors.
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 612df305886b..e323020d91dd 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1326,10 +1326,6 @@ void show_regs(struct pt_regs * regs)
 		show_instructions(regs);
 }
 
-void exit_thread(void)
-{
-}
-
 void flush_thread(void)
 {
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 43b25835325f..37941df616d9 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -130,6 +130,7 @@ config S390
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_DYNAMIC_FTRACE_WITH_REGS
+	select HAVE_EXIT_THREAD
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FUNCTION_TRACER
diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c
index a1519ad3d49d..aae9480706c2 100644
--- a/arch/score/kernel/process.c
+++ b/arch/score/kernel/process.c
@@ -56,8 +56,6 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
 	regs->regs[0] = sp;
 }
 
-void exit_thread(void) {}
-
 /*
  * When a process does an "exec", machine state like FPU and debug
  * registers need to be reset.  This is a hook function for that.
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 7ed20fc3fc81..cb93af8f8017 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -71,6 +71,7 @@ config SUPERH32
 
 config SUPERH64
 	def_bool ARCH = "sh64"
+	select HAVE_EXIT_THREAD
 	select KALLSYMS
 
 config ARCH_DEFCONFIG
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index 2885fc9d9dcd..ee12e9451874 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -76,13 +76,6 @@ void start_thread(struct pt_regs *regs, unsigned long new_pc,
 }
 EXPORT_SYMBOL(start_thread);
 
-/*
- * Free current thread data structures etc..
- */
-void exit_thread(void)
-{
-}
-
 void flush_thread(void)
 {
 	struct task_struct *tsk = current;
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 57ffaf285c2f..b66aea06e9c9 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -20,6 +20,7 @@ config SPARC
 	select HAVE_OPROFILE
 	select HAVE_ARCH_KGDB if !SMP || SPARC64
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_EXIT_THREAD
 	select SYSCTL_EXCEPTION_TRACE
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 81719302b056..174746225577 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -3,6 +3,7 @@
 
 config TILE
 	def_bool y
+	select HAVE_EXIT_THREAD
 	select HAVE_PERF_EVENTS
 	select USE_PMC if PERF_EVENTS
 	select HAVE_DMA_API_DEBUG
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 48af59aae129..0b04711f1f18 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -103,10 +103,6 @@ void interrupt_end(void)
 		tracehook_notify_resume(regs);
 }
 
-void exit_thread(void)
-{
-}
-
 int get_current_pid(void)
 {
 	return task_pid_nr(current);
diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c
index b008e9961465..00299c927852 100644
--- a/arch/unicore32/kernel/process.c
+++ b/arch/unicore32/kernel/process.c
@@ -201,13 +201,6 @@ void show_regs(struct pt_regs *regs)
 	__backtrace();
 }
 
-/*
- * Free current thread data structures etc..
- */
-void exit_thread(void)
-{
-}
-
 void flush_thread(void)
 {
 	struct thread_info *thread = current_thread_info();
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 6bc6f9832d67..8f6196084eac 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -105,6 +105,7 @@ config X86
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_DYNAMIC_FTRACE_WITH_REGS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_EXIT_THREAD
 	select HAVE_FENTRY			if X86_64
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_GRAPH_FP_TEST
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index e832d3e9835e..c6b2ee78b617 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -15,6 +15,7 @@ config XTENSA
 	select GENERIC_PCI_IOMAP
 	select GENERIC_SCHED_CLOCK
 	select HAVE_DMA_API_DEBUG
+	select HAVE_EXIT_THREAD
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUTEX_CMPXCHG if !MMU
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 362c0e20ebbb..de5370802828 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2646,7 +2646,14 @@ static inline int copy_thread_tls(
 }
 #endif
 extern void flush_thread(void);
+
+#ifdef CONFIG_HAVE_EXIT_THREAD
 extern void exit_thread(void);
+#else
+static inline void exit_thread(void)
+{
+}
+#endif
 
 extern void exit_files(struct task_struct *);
 extern void __cleanup_sighand(struct sighand_struct *);
-- 
2.7.4



From broonie at kernel.org  Thu Mar 31 09:56:42 2016
From: broonie at kernel.org (Mark Brown)
Date: Thu, 31 Mar 2016 09:56:42 -0700
Subject: [PATCH 2/3 v2] ASoC: dwc: Add I2S HDMI audio support
In-Reply-To: <56FCEFD0.8090509@synopsys.com>
References: <cover.1459174494.git.joabreu@synopsys.com>
 <538be366488bf0d7633d702f2d0bab16707b7a47.1459174494.git.joabreu@synopsys.com>
 <20160329173158.GB2350@sirena.org.uk>
 <56FAC355.1040705@synopsys.com>
 <20160329182222.GC2350@sirena.org.uk>
 <56FCEFD0.8090509@synopsys.com>
Message-ID: <20160331165642.GG2350@sirena.org.uk>

On Thu, Mar 31, 2016 at 10:37:20AM +0100, Jose Abreu wrote:
> On 29-03-2016 19:22, Mark Brown wrote:

> > If you want to add a new platform driver you need to add a new platform
> > driver, not shove the code into an existing driver for a seperate IP.

> I can separate the platform driver into a new file but they will have to be
> compiled into the same module as the new additions to the i2s driver depend on
> functions of the platform driver (see i2s_irq_handler()). Or should I divide

No, that's not at all acceptable.  The Designware IP is not specific to
your system, you can't make it depend on your platform driver.  The
kernel needs to work on other people's systems too.  You need to work
through and/or extend the abstractions the framework provides to
separate the drivers for different IPs.

> this into two modules and add a Kconfig option to the platform driver? Besides
> this I first wanted the driver to be compiled into the same module so that it is
> compatible with kernel 3.18 where simple audio card requires that platform
> driver == cpu driver.

That's not OK upstream, we're working on the current kernel not on
random old kernels.  We don't carry compatibility code to enable current
kernel code to be run on years old kernels.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-snps-arc/attachments/20160331/22fcdcbc/attachment.sig>

From Jose.Abreu at synopsys.com  Thu Mar 31 10:08:14 2016
From: Jose.Abreu at synopsys.com (Jose Abreu)
Date: Thu, 31 Mar 2016 18:08:14 +0100
Subject: [PATCH v3] clk/axs10x: Add I2S PLL clock driver
Message-ID: <4018d5e586f6a5b37c665000fbec8f6aad9388f3.1459443839.git.joabreu@synopsys.com>

The ARC SDP I2S clock can be programmed using a
specific PLL.

This patch has the goal of adding a clock driver
that programs this PLL.

At this moment the rate values are hardcoded in
a table but in the future it would be ideal to
use a function which determines the PLL values
given the desired rate.

Signed-off-by: Jose Abreu <joabreu at synopsys.com>
---

Changes v2 -> v3:
* Implemented recalc_rate

Changes v1 -> v2:
* Renamed folder to axs10x (as suggested by Alexey Brodkin)
* Added more supported rates

 arch/arc/boot/dts/axs10x_mb.dtsi   |   5 ++
 drivers/clk/Makefile               |   1 +
 drivers/clk/axs10x/Makefile        |   1 +
 drivers/clk/axs10x/i2s_pll_clock.c | 163 +++++++++++++++++++++++++++++++++++++
 4 files changed, 170 insertions(+)
 create mode 100644 drivers/clk/axs10x/Makefile
 create mode 100644 drivers/clk/axs10x/i2s_pll_clock.c

diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
index ab5d570..9c68226 100644
--- a/arch/arc/boot/dts/axs10x_mb.dtsi
+++ b/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -23,6 +23,11 @@
 				#clock-cells = <0>;
 			};
 
+			i2sclk: i2sclk {
+				compatible = "snps,i2s-pll-clock";
+				#clock-cells = <0>;
+			};
+
 			apbclk: apbclk {
 				compatible = "fixed-clock";
 				clock-frequency = <50000000>;
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 46869d6..2ca62dc6 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -84,3 +84,4 @@ obj-$(CONFIG_X86)			+= x86/
 obj-$(CONFIG_ARCH_ZX)			+= zte/
 obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
 obj-$(CONFIG_H8300)		+= h8300/
+obj-$(CONFIG_ARC_PLAT_AXS10X)		+= axs10x/
diff --git a/drivers/clk/axs10x/Makefile b/drivers/clk/axs10x/Makefile
new file mode 100644
index 0000000..01996b8
--- /dev/null
+++ b/drivers/clk/axs10x/Makefile
@@ -0,0 +1 @@
+obj-y += i2s_pll_clock.o
diff --git a/drivers/clk/axs10x/i2s_pll_clock.c b/drivers/clk/axs10x/i2s_pll_clock.c
new file mode 100644
index 0000000..f050e70
--- /dev/null
+++ b/drivers/clk/axs10x/i2s_pll_clock.c
@@ -0,0 +1,163 @@
+/*
+ * Synopsys AXS10X SDP I2S PLL clock driver
+ *
+ * Copyright (C) 2016 Synopsys
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+/* FPGA Version Info */
+#define FPGA_VER_INFO	0xE0011230
+#define FPGA_VER_27M	0x000FBED9
+
+/* PLL registers addresses */
+#define PLL_IDIV_ADDR	0xE00100A0
+#define PLL_FBDIV_ADDR	0xE00100A4
+#define PLL_ODIV0_ADDR	0xE00100A8
+#define PLL_ODIV1_ADDR	0xE00100AC
+
+struct i2s_pll_cfg {
+	unsigned int rate;
+	unsigned int idiv;
+	unsigned int fbdiv;
+	unsigned int odiv0;
+	unsigned int odiv1;
+};
+
+static struct i2s_pll_cfg i2s_pll_cfg_27m[] = {
+	/* 27 Mhz */
+	{ 1024000, 0x104, 0x451, 0x10E38, 0x2000 },
+	{ 1411200, 0x104, 0x596, 0x10D35, 0x2000 },
+	{ 1536000, 0x208, 0xA28, 0x10B2C, 0x2000 },
+	{ 2048000, 0x82, 0x451, 0x10E38, 0x2000 },
+	{ 2822400, 0x82, 0x596, 0x10D35, 0x2000 },
+	{ 3072000, 0x104, 0xA28, 0x10B2C, 0x2000 },
+	{ 2116800, 0x82, 0x3CF, 0x10C30, 0x2000 },
+	{ 2304000, 0x104, 0x79E, 0x10B2C, 0x2000 },
+	{ 0, 0, 0, 0, 0 },
+};
+
+static struct i2s_pll_cfg i2s_pll_cfg_28m[] = {
+	/* 28.224 Mhz */
+	{ 1024000, 0x82, 0x105, 0x107DF, 0x2000 },
+	{ 1411200, 0x28A, 0x1, 0x10001, 0x2000 },
+	{ 1536000, 0xA28, 0x187, 0x10042, 0x2000 },
+	{ 2048000, 0x41, 0x105, 0x107DF, 0x2000 },
+	{ 2822400, 0x145, 0x1, 0x10001, 0x2000 },
+	{ 3072000, 0x514, 0x187, 0x10042, 0x2000 },
+	{ 2116800, 0x514, 0x42, 0x10001, 0x2000 },
+	{ 2304000, 0x619, 0x82, 0x10001, 0x2000 },
+	{ 0, 0, 0, 0, 0 },
+};
+
+struct i2s_pll_clk {
+	struct clk_hw hw;
+	unsigned long ref_clk;
+	struct i2s_pll_cfg *pll_cfg;
+};
+
+static inline struct i2s_pll_clk *to_i2s_pll_clk(struct clk_hw *hw)
+{
+	return container_of(hw, struct i2s_pll_clk, hw);
+}
+
+static unsigned int i2s_pll_get_value(unsigned int val)
+{
+	return ((val & 0x3F) + ((val >> 6) & 0x3F));
+}
+
+static unsigned long i2s_pll_recalc_rate(struct clk_hw *hw,
+			unsigned long parent_rate)
+{
+	struct i2s_pll_clk *clk = to_i2s_pll_clk(hw);
+	unsigned int idiv, fbdiv, odiv;
+
+	idiv = i2s_pll_get_value(readl((void *)PLL_IDIV_ADDR));
+	fbdiv = i2s_pll_get_value(readl((void *)PLL_FBDIV_ADDR));
+	odiv = i2s_pll_get_value(readl((void *)PLL_ODIV0_ADDR));
+
+	return (((clk->ref_clk / idiv ) * fbdiv) / odiv);
+}
+
+static long i2s_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+			unsigned long *prate)
+{
+	/* TODO: Round rate to nearest valid rate */
+	return rate;
+}
+
+static int i2s_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+			unsigned long parent_rate)
+{
+	struct i2s_pll_cfg *pll_cfg = to_i2s_pll_clk(hw)->pll_cfg;
+	int i;
+
+	for (i = 0; pll_cfg[i].rate != 0; i++) {
+		if (pll_cfg[i].rate == rate) {
+			writel(pll_cfg[i].idiv, (void *)PLL_IDIV_ADDR);
+			writel(pll_cfg[i].fbdiv, (void *)PLL_FBDIV_ADDR);
+			writel(pll_cfg[i].odiv0, (void *)PLL_ODIV0_ADDR);
+			writel(pll_cfg[i].odiv1, (void *)PLL_ODIV1_ADDR);
+			return 0;
+		}
+	}
+
+	pr_err("%s: invalid rate=%ld, parent_rate=%ld\n", __func__,
+			rate, parent_rate);
+	return -EINVAL;
+}
+
+static const struct clk_ops i2s_pll_ops = {
+	.recalc_rate = i2s_pll_recalc_rate,
+	.round_rate = i2s_pll_round_rate,
+	.set_rate = i2s_pll_set_rate,
+};
+
+static void __init i2s_pll_clk_setup(struct device_node *node)
+{
+	const char *clk_name = node->name;
+	struct clk *clk;
+	struct i2s_pll_clk *pll_clk;
+	struct clk_init_data init;
+
+	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
+	if (!pll_clk)
+		return;
+
+	init.name = clk_name;
+	init.ops = &i2s_pll_ops;
+	init.flags = CLK_IS_BASIC;
+	init.num_parents = 0;
+	pll_clk->hw.init = &init;
+
+	clk = clk_register(NULL, &pll_clk->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register %s div clock (%ld)\n",
+				__func__, clk_name, PTR_ERR(clk));
+		goto free_clock;
+	}
+
+	if (readl((void *)FPGA_VER_INFO) <= FPGA_VER_27M) {
+		pll_clk->ref_clk = 27000000;
+		pll_clk->pll_cfg = i2s_pll_cfg_27m;
+	} else {
+		pll_clk->ref_clk = 28224000;
+		pll_clk->pll_cfg = i2s_pll_cfg_28m;
+	}
+
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	return;
+
+free_clock:
+	kfree(pll_clk);
+}
+
+CLK_OF_DECLARE(i2s_pll_clk, "snps,i2s-pll-clock", i2s_pll_clk_setup);
+
-- 
1.9.1




