Devicetree
 help / color / mirror / Atom feed
* [PATCH v5 08/12] drm/sun4i: Add A83T support
From: Maxime Ripard @ 2017-12-21 11:02 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel, linux-kernel, Mark Rutland, Rob Herring,
	linux-arm-kernel, plaes, icenowy, Thomas Petazzoni,
	jernej.skrabec, devicetree, thierry.reding, Laurent Pinchart
In-Reply-To: <cover.e5a47cc96ec5274dd932daa2bde47df073087da9.1513854122.git-series.maxime.ripard@free-electrons.com>

Add support for the A83T display pipeline.

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_drv.c   |  1 +
 drivers/gpu/drm/sun4i/sun4i_tcon.c  |  5 +++++
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 11 +++++++++++
 3 files changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 49215d91c853..6f5e721b545e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -347,6 +347,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
 	{ .compatible = "allwinner,sun6i-a31s-display-engine" },
 	{ .compatible = "allwinner,sun7i-a20-display-engine" },
 	{ .compatible = "allwinner,sun8i-a33-display-engine" },
+	{ .compatible = "allwinner,sun8i-a83t-display-engine" },
 	{ .compatible = "allwinner,sun8i-v3s-display-engine" },
 	{ }
 };
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 33b1a493fc0a..b78fed809992 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -1133,6 +1133,10 @@ static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
 	.has_lvds_alt		= true,
 };
 
+static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
+	/* nothing is supported */
+};
+
 static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
 	/* nothing is supported */
 };
@@ -1145,6 +1149,7 @@ const struct of_device_id sun4i_tcon_of_table[] = {
 	{ .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
 	{ .compatible = "allwinner,sun7i-a20-tcon", .data = &sun7i_a20_quirks },
 	{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
+	{ .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks },
 	{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
 	{ }
 };
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 3a610a87cbd2..2cbb2de6d39c 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -478,6 +478,13 @@ static int sun8i_mixer_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
+	.ccsc		= 0,
+	.scaler_mask	= 0xf,
+	.ui_num		= 3,
+	.vi_num		= 1,
+};
+
 static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
 	.vi_num = 2,
 	.ui_num = 1,
@@ -488,6 +495,10 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
 
 static const struct of_device_id sun8i_mixer_of_table[] = {
 	{
+		.compatible = "allwinner,sun8i-a83t-de2-mixer-0",
+		.data = &sun8i_a83t_mixer0_cfg,
+	},
+	{
 		.compatible = "allwinner,sun8i-v3s-de2-mixer",
 		.data = &sun8i_v3s_mixer_cfg,
 	},
-- 
git-series 0.9.1

^ permalink raw reply related

* [PATCH v5 07/12] drm/sun4i: Add LVDS support
From: Maxime Ripard @ 2017-12-21 11:02 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, jernej.skrabec, plaes, devicetree,
	linux-kernel, dri-devel, Rob Herring, thierry.reding,
	Laurent Pinchart, linux-arm-kernel, icenowy
In-Reply-To: <cover.e5a47cc96ec5274dd932daa2bde47df073087da9.1513854122.git-series.maxime.ripard@free-electrons.com>

The TCON supports the LVDS interface to output to a panel or a bridge.
Let's add support for it.

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/Makefile     |   1 +-
 drivers/gpu/drm/sun4i/sun4i_lvds.c | 177 ++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_lvds.h |  12 ++-
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 239 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  29 ++++-
 5 files changed, 456 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 82a6ac57fbe3..2b37a6abbb1d 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -15,6 +15,7 @@ sun8i-mixer-y			+= sun8i_mixer.o sun8i_ui_layer.o \
 
 sun4i-tcon-y			+= sun4i_crtc.o
 sun4i-tcon-y			+= sun4i_dotclock.o
+sun4i-tcon-y			+= sun4i_lvds.o
 sun4i-tcon-y			+= sun4i_tcon.o
 sun4i-tcon-y			+= sun4i_rgb.o
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
new file mode 100644
index 000000000000..be3f14d7746d
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ */
+
+#include <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+
+#include "sun4i_crtc.h"
+#include "sun4i_tcon.h"
+#include "sun4i_lvds.h"
+
+struct sun4i_lvds {
+	struct drm_connector	connector;
+	struct drm_encoder	encoder;
+
+	struct sun4i_tcon	*tcon;
+};
+
+static inline struct sun4i_lvds *
+drm_connector_to_sun4i_lvds(struct drm_connector *connector)
+{
+	return container_of(connector, struct sun4i_lvds,
+			    connector);
+}
+
+static inline struct sun4i_lvds *
+drm_encoder_to_sun4i_lvds(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct sun4i_lvds,
+			    encoder);
+}
+
+static int sun4i_lvds_get_modes(struct drm_connector *connector)
+{
+	struct sun4i_lvds *lvds =
+		drm_connector_to_sun4i_lvds(connector);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	return drm_panel_get_modes(tcon->panel);
+}
+
+static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = {
+	.get_modes	= sun4i_lvds_get_modes,
+};
+
+static void
+sun4i_lvds_connector_destroy(struct drm_connector *connector)
+{
+	struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	drm_panel_detach(tcon->panel);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs sun4i_lvds_con_funcs = {
+	.fill_modes		= drm_helper_probe_single_connector_modes,
+	.destroy		= sun4i_lvds_connector_destroy,
+	.reset			= drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
+};
+
+static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder)
+{
+	struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	DRM_DEBUG_DRIVER("Enabling LVDS output\n");
+
+	if (!IS_ERR(tcon->panel)) {
+		drm_panel_prepare(tcon->panel);
+		drm_panel_enable(tcon->panel);
+	}
+}
+
+static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder)
+{
+	struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
+	struct sun4i_tcon *tcon = lvds->tcon;
+
+	DRM_DEBUG_DRIVER("Disabling LVDS output\n");
+
+	if (!IS_ERR(tcon->panel)) {
+		drm_panel_disable(tcon->panel);
+		drm_panel_unprepare(tcon->panel);
+	}
+}
+
+static const struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = {
+	.disable	= sun4i_lvds_encoder_disable,
+	.enable		= sun4i_lvds_encoder_enable,
+};
+
+static const struct drm_encoder_funcs sun4i_lvds_enc_funcs = {
+	.destroy	= drm_encoder_cleanup,
+};
+
+int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon)
+{
+	struct drm_encoder *encoder;
+	struct drm_bridge *bridge;
+	struct sun4i_lvds *lvds;
+	int ret;
+
+	lvds = devm_kzalloc(drm->dev, sizeof(*lvds), GFP_KERNEL);
+	if (!lvds)
+		return -ENOMEM;
+	lvds->tcon = tcon;
+	encoder = &lvds->encoder;
+
+	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
+					  &tcon->panel, &bridge);
+	if (ret) {
+		dev_info(drm->dev, "No panel or bridge found... LVDS output disabled\n");
+		return 0;
+	}
+
+	drm_encoder_helper_add(&lvds->encoder,
+			       &sun4i_lvds_enc_helper_funcs);
+	ret = drm_encoder_init(drm,
+			       &lvds->encoder,
+			       &sun4i_lvds_enc_funcs,
+			       DRM_MODE_ENCODER_LVDS,
+			       NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialise the lvds encoder\n");
+		goto err_out;
+	}
+
+	/* The LVDS encoder can only work with the TCON channel 0 */
+	lvds->encoder.possible_crtcs = BIT(drm_crtc_index(&tcon->crtc->crtc));
+
+	if (tcon->panel) {
+		drm_connector_helper_add(&lvds->connector,
+					 &sun4i_lvds_con_helper_funcs);
+		ret = drm_connector_init(drm, &lvds->connector,
+					 &sun4i_lvds_con_funcs,
+					 DRM_MODE_CONNECTOR_LVDS);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't initialise the lvds connector\n");
+			goto err_cleanup_connector;
+		}
+
+		drm_mode_connector_attach_encoder(&lvds->connector,
+						  &lvds->encoder);
+
+		ret = drm_panel_attach(tcon->panel, &lvds->connector);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't attach our panel\n");
+			goto err_cleanup_connector;
+		}
+	}
+
+	if (bridge) {
+		ret = drm_bridge_attach(encoder, bridge, NULL);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't attach our bridge\n");
+			goto err_cleanup_connector;
+		}
+	}
+
+	return 0;
+
+err_cleanup_connector:
+	drm_encoder_cleanup(&lvds->encoder);
+err_out:
+	return ret;
+}
+EXPORT_SYMBOL(sun4i_lvds_init);
diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.h b/drivers/gpu/drm/sun4i/sun4i_lvds.h
new file mode 100644
index 000000000000..f3e90faa3082
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.h
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ */
+
+#ifndef _SUN4I_LVDS_H_
+#define _SUN4I_LVDS_H_
+
+int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon);
+
+#endif /* _SUN4I_LVDS_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 46e28ca1f676..33b1a493fc0a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -31,10 +31,52 @@
 #include "sun4i_crtc.h"
 #include "sun4i_dotclock.h"
 #include "sun4i_drv.h"
+#include "sun4i_lvds.h"
 #include "sun4i_rgb.h"
 #include "sun4i_tcon.h"
 #include "sunxi_engine.h"
 
+static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
+{
+	struct drm_connector *connector;
+	struct drm_connector_list_iter iter;
+
+	drm_connector_list_iter_begin(encoder->dev, &iter);
+	drm_for_each_connector_iter(connector, &iter)
+		if (connector->encoder == encoder) {
+			drm_connector_list_iter_end(&iter);
+			return connector;
+		}
+	drm_connector_list_iter_end(&iter);
+
+	return NULL;
+}
+
+static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
+{
+	struct drm_connector *connector;
+	struct drm_display_info *info;
+
+	connector = sun4i_tcon_get_connector(encoder);
+	if (!connector)
+		return -EINVAL;
+
+	info = &connector->display_info;
+	if (info->num_bus_formats != 1)
+		return -EINVAL;
+
+	switch (info->bus_formats[0]) {
+	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
+		return 18;
+
+	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
+	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
+		return 24;
+	}
+
+	return -EINVAL;
+}
+
 static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
 					  bool enabled)
 {
@@ -65,13 +107,63 @@ static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
 		clk_disable_unprepare(clk);
 }
 
+static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon,
+				       const struct drm_encoder *encoder,
+				       bool enabled)
+{
+	if (enabled) {
+		u8 val;
+
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
+				   SUN4I_TCON0_LVDS_IF_EN,
+				   SUN4I_TCON0_LVDS_IF_EN);
+
+		/*
+		 * As their name suggest, these values only apply to the A31
+		 * and later SoCs. We'll have to rework this when merging
+		 * support for the older SoCs.
+		 */
+		regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+			     SUN6I_TCON0_LVDS_ANA0_C(2) |
+			     SUN6I_TCON0_LVDS_ANA0_V(3) |
+			     SUN6I_TCON0_LVDS_ANA0_PD(2) |
+			     SUN6I_TCON0_LVDS_ANA0_EN_LDO);
+		udelay(2);
+
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+				   SUN6I_TCON0_LVDS_ANA0_EN_MB,
+				   SUN6I_TCON0_LVDS_ANA0_EN_MB);
+		udelay(2);
+
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+				   SUN6I_TCON0_LVDS_ANA0_EN_DRVC,
+				   SUN6I_TCON0_LVDS_ANA0_EN_DRVC);
+
+		if (sun4i_tcon_get_pixel_depth(encoder) == 18)
+			val = 7;
+		else
+			val = 0xf;
+
+		regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+				  SUN6I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
+				  SUN6I_TCON0_LVDS_ANA0_EN_DRVD(val));
+	} else {
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
+				   SUN4I_TCON0_LVDS_IF_EN, 0);
+	}
+}
+
 void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
 			   const struct drm_encoder *encoder,
 			   bool enabled)
 {
+	bool is_lvds = false;
 	int channel;
 
 	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_LVDS:
+		is_lvds = true;
+		/* Fallthrough */
 	case DRM_MODE_ENCODER_NONE:
 		channel = 0;
 		break;
@@ -84,10 +176,16 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
 		return;
 	}
 
+	if (is_lvds && !enabled)
+		sun4i_tcon_lvds_set_status(tcon, encoder, false);
+
 	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
 			   SUN4I_TCON_GCTL_TCON_ENABLE,
 			   enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
 
+	if (is_lvds && enabled)
+		sun4i_tcon_lvds_set_status(tcon, encoder, true);
+
 	sun4i_tcon_channel_set_status(tcon, channel, enabled);
 }
 
@@ -170,6 +268,75 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
 		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
 }
 
+static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
+				      const struct drm_encoder *encoder,
+				      const struct drm_display_mode *mode)
+{
+	unsigned int bp;
+	u8 clk_delay;
+	u32 reg, val = 0;
+
+	tcon->dclk_min_div = 7;
+	tcon->dclk_max_div = 7;
+	sun4i_tcon0_mode_set_common(tcon, mode);
+
+	/* Adjust clock delay */
+	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
+	regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
+			   SUN4I_TCON0_CTL_CLK_DELAY_MASK,
+			   SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
+
+	/*
+	 * This is called a backporch in the register documentation,
+	 * but it really is the back porch + hsync
+	 */
+	bp = mode->crtc_htotal - mode->crtc_hsync_start;
+	DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
+			 mode->crtc_htotal, bp);
+
+	/* Set horizontal display timings */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
+		     SUN4I_TCON0_BASIC1_H_TOTAL(mode->htotal) |
+		     SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
+
+	/*
+	 * This is called a backporch in the register documentation,
+	 * but it really is the back porch + hsync
+	 */
+	bp = mode->crtc_vtotal - mode->crtc_vsync_start;
+	DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
+			 mode->crtc_vtotal, bp);
+
+	/* Set vertical display timings */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
+		     SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
+		     SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
+
+	reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0 |
+		SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL |
+		SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL;
+	if (sun4i_tcon_get_pixel_depth(encoder) == 24)
+		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
+	else
+		reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
+
+	regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
+
+	/* Setup the polarity of the various signals */
+	if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
+		val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
+
+	if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
+		val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
+
+	regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
+
+	/* Map output pins to channel 0 */
+	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
+			   SUN4I_TCON_GCTL_IOMAP_MASK,
+			   SUN4I_TCON_GCTL_IOMAP_TCON0);
+}
+
 static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
 				     const struct drm_display_mode *mode)
 {
@@ -336,6 +503,9 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
 			 const struct drm_display_mode *mode)
 {
 	switch (encoder->encoder_type) {
+	case DRM_MODE_ENCODER_LVDS:
+		sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
+		break;
 	case DRM_MODE_ENCODER_NONE:
 		sun4i_tcon0_mode_set_rgb(tcon, mode);
 		sun4i_tcon_set_mux(tcon, 0, encoder);
@@ -667,7 +837,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 	struct drm_device *drm = data;
 	struct sun4i_drv *drv = drm->dev_private;
 	struct sunxi_engine *engine;
+	struct device_node *remote;
 	struct sun4i_tcon *tcon;
+	bool has_lvds_rst, has_lvds_alt, can_lvds;
 	int ret;
 
 	engine = sun4i_tcon_find_engine(drv, dev->of_node);
@@ -698,6 +870,54 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
+	/*
+	 * This can only be made optional since we've had DT nodes
+	 * without the LVDS reset properties.
+	 *
+	 * If the property is missing, just disable LVDS, and print a
+	 * warning.
+	 */
+	tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
+	if (IS_ERR(tcon->lvds_rst)) {
+		dev_err(dev, "Couldn't get our reset line\n");
+		return PTR_ERR(tcon->lvds_rst);
+	} else if (tcon->lvds_rst) {
+		has_lvds_rst = true;
+		reset_control_reset(tcon->lvds_rst);
+	} else {
+		has_lvds_rst = false;
+	}
+
+	/*
+	 * This can only be made optional since we've had DT nodes
+	 * without the LVDS reset properties.
+	 *
+	 * If the property is missing, just disable LVDS, and print a
+	 * warning.
+	 */
+	if (tcon->quirks->has_lvds_alt) {
+		tcon->lvds_pll = devm_clk_get(dev, "lvds-alt");
+		if (IS_ERR(tcon->lvds_pll)) {
+			if (PTR_ERR(tcon->lvds_pll) == -ENOENT) {
+				has_lvds_alt = false;
+			} else {
+				dev_err(dev, "Couldn't get the LVDS PLL\n");
+				return PTR_ERR(tcon->lvds_rst);
+			}
+		} else {
+			has_lvds_alt = true;
+		}
+	}
+
+	if (!has_lvds_rst || (tcon->quirks->has_lvds_alt && !has_lvds_alt)) {
+		dev_warn(dev,
+			 "Missing LVDS properties, Please upgrade your DT\n");
+		dev_warn(dev, "LVDS output disabled\n");
+		can_lvds = false;
+	} else {
+		can_lvds = true;
+	}
+
 	ret = sun4i_tcon_init_clocks(dev, tcon);
 	if (ret) {
 		dev_err(dev, "Couldn't init our TCON clocks\n");
@@ -729,7 +949,21 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		goto err_free_dotclock;
 	}
 
-	ret = sun4i_rgb_init(drm, tcon);
+	/*
+	 * If we have an LVDS panel connected to the TCON, we should
+	 * just probe the LVDS connector. Otherwise, just probe RGB as
+	 * we used to.
+	 */
+	remote = of_graph_get_remote_node(dev->of_node, 1, 0);
+	if (of_device_is_compatible(remote, "panel-lvds"))
+		if (can_lvds)
+			ret = sun4i_lvds_init(drm, tcon);
+		else
+			ret = -EINVAL;
+	else
+		ret = sun4i_rgb_init(drm, tcon);
+	of_node_put(remote);
+
 	if (ret < 0)
 		goto err_free_dotclock;
 
@@ -879,6 +1113,7 @@ static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
 
 static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
 	.has_channel_1		= true,
+	.has_lvds_alt		= true,
 	.needs_de_be_mux	= true,
 	.set_mux		= sun6i_tcon_set_mux,
 };
@@ -895,7 +1130,7 @@ static const struct sun4i_tcon_quirks sun7i_a20_quirks = {
 };
 
 static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
-	/* nothing is supported */
+	.has_lvds_alt		= true,
 };
 
 static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index bd3ad7684870..b761c7b823c5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -70,7 +70,21 @@
 #define SUN4I_TCON0_TTL2_REG			0x78
 #define SUN4I_TCON0_TTL3_REG			0x7c
 #define SUN4I_TCON0_TTL4_REG			0x80
+
 #define SUN4I_TCON0_LVDS_IF_REG			0x84
+#define SUN4I_TCON0_LVDS_IF_EN				BIT(31)
+#define SUN4I_TCON0_LVDS_IF_BITWIDTH_MASK		BIT(26)
+#define SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS		(1 << 26)
+#define SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS		(0 << 26)
+#define SUN4I_TCON0_LVDS_IF_CLK_SEL_MASK		BIT(20)
+#define SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0		(1 << 20)
+#define SUN4I_TCON0_LVDS_IF_CLK_POL_MASK		BIT(4)
+#define SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL		(1 << 4)
+#define SUN4I_TCON0_LVDS_IF_CLK_POL_INV			(0 << 4)
+#define SUN4I_TCON0_LVDS_IF_DATA_POL_MASK		GENMASK(3, 0)
+#define SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL		(0xf)
+#define SUN4I_TCON0_LVDS_IF_DATA_POL_INV		(0)
+
 #define SUN4I_TCON0_IO_POL_REG			0x88
 #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase)		((phase & 3) << 28)
 #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE		BIT(25)
@@ -131,6 +145,16 @@
 #define SUN4I_TCON_CEU_RANGE_G_REG		0x144
 #define SUN4I_TCON_CEU_RANGE_B_REG		0x148
 #define SUN4I_TCON_MUX_CTRL_REG			0x200
+
+#define SUN4I_TCON0_LVDS_ANA0_REG		0x220
+#define SUN6I_TCON0_LVDS_ANA0_EN_MB			BIT(31)
+#define SUN6I_TCON0_LVDS_ANA0_EN_LDO			BIT(30)
+#define SUN6I_TCON0_LVDS_ANA0_EN_DRVC			BIT(24)
+#define SUN6I_TCON0_LVDS_ANA0_EN_DRVD(x)		(((x) & 0xf) << 20)
+#define SUN6I_TCON0_LVDS_ANA0_C(x)			(((x) & 3) << 17)
+#define SUN6I_TCON0_LVDS_ANA0_V(x)			(((x) & 3) << 8)
+#define SUN6I_TCON0_LVDS_ANA0_PD(x)			(((x) & 3) << 4)
+
 #define SUN4I_TCON1_FILL_CTL_REG		0x300
 #define SUN4I_TCON1_FILL_BEG0_REG		0x304
 #define SUN4I_TCON1_FILL_END0_REG		0x308
@@ -149,6 +173,7 @@ struct sun4i_tcon;
 
 struct sun4i_tcon_quirks {
 	bool	has_channel_1;	/* a33 does not have channel 1 */
+	bool	has_lvds_alt;	/* Does the LVDS clock have a parent other than the TCON clock? */
 	bool	needs_de_be_mux; /* sun6i needs mux to select backend */
 
 	/* callback to handle tcon muxing options */
@@ -167,6 +192,9 @@ struct sun4i_tcon {
 	struct clk			*sclk0;
 	struct clk			*sclk1;
 
+	/* Possible mux for the LVDS clock */
+	struct clk			*lvds_pll;
+
 	/* Pixel clock */
 	struct clk			*dclk;
 	u8				dclk_max_div;
@@ -174,6 +202,7 @@ struct sun4i_tcon {
 
 	/* Reset control */
 	struct reset_control		*lcd_rst;
+	struct reset_control		*lvds_rst;
 
 	struct drm_panel		*panel;
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related

* [PATCH v5 06/12] drm/sun4i: Create minimal multipliers and dividers
From: Maxime Ripard @ 2017-12-21 11:02 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, jernej.skrabec, plaes, devicetree,
	linux-kernel, dri-devel, Rob Herring, thierry.reding,
	Laurent Pinchart, linux-arm-kernel, icenowy
In-Reply-To: <cover.e5a47cc96ec5274dd932daa2bde47df073087da9.1513854122.git-series.maxime.ripard@free-electrons.com>

The various outputs the TCON can provide have different constraints on the
dotclock divider. Let's make them configurable by the various mode_set
functions.

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_dotclock.c | 10 +++++++---
 drivers/gpu/drm/sun4i/sun4i_tcon.c     |  2 ++
 drivers/gpu/drm/sun4i/sun4i_tcon.h     |  2 ++
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
index d401156490f3..023f39bda633 100644
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
+++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
@@ -17,8 +17,9 @@
 #include "sun4i_dotclock.h"
 
 struct sun4i_dclk {
-	struct clk_hw	hw;
-	struct regmap	*regmap;
+	struct clk_hw		hw;
+	struct regmap		*regmap;
+	struct sun4i_tcon	*tcon;
 };
 
 static inline struct sun4i_dclk *hw_to_dclk(struct clk_hw *hw)
@@ -73,11 +74,13 @@ static unsigned long sun4i_dclk_recalc_rate(struct clk_hw *hw,
 static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
 				  unsigned long *parent_rate)
 {
+	struct sun4i_dclk *dclk = hw_to_dclk(hw);
+	struct sun4i_tcon *tcon = dclk->tcon;
 	unsigned long best_parent = 0;
 	u8 best_div = 1;
 	int i;
 
-	for (i = 6; i <= 127; i++) {
+	for (i = tcon->dclk_min_div; i <= tcon->dclk_max_div; i++) {
 		unsigned long ideal = rate * i;
 		unsigned long rounded;
 
@@ -167,6 +170,7 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
 	dclk = devm_kzalloc(dev, sizeof(*dclk), GFP_KERNEL);
 	if (!dclk)
 		return -ENOMEM;
+	dclk->tcon = tcon;
 
 	init.name = clk_name;
 	init.ops = &sun4i_dclk_ops;
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index ea056a3d2131..46e28ca1f676 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -177,6 +177,8 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
 	u8 clk_delay;
 	u32 val = 0;
 
+	tcon->dclk_min_div = 6;
+	tcon->dclk_max_div = 127;
 	sun4i_tcon0_mode_set_common(tcon, mode);
 
 	/* Adjust clock delay */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 839266a38505..bd3ad7684870 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -169,6 +169,8 @@ struct sun4i_tcon {
 
 	/* Pixel clock */
 	struct clk			*dclk;
+	u8				dclk_max_div;
+	u8				dclk_min_div;
 
 	/* Reset control */
 	struct reset_control		*lcd_rst;
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related

* [PATCH v5 05/12] drm/sun4i: Force the mixer rate at 150MHz
From: Maxime Ripard @ 2017-12-21 11:02 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, jernej.skrabec, plaes, devicetree,
	linux-kernel, dri-devel, Rob Herring, thierry.reding,
	Laurent Pinchart, linux-arm-kernel, icenowy
In-Reply-To: <cover.e5a47cc96ec5274dd932daa2bde47df073087da9.1513854122.git-series.maxime.ripard@free-electrons.com>

It seems like the mixer can only run properly when clocked at 150MHz. In
order to have something more robust than simply a fire-and-forget
assigned-clocks-rate, let's put that in the code.

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 10 ++++++++++
 drivers/gpu/drm/sun4i/sun8i_mixer.h |  3 +++
 2 files changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 29ceeb016d72..3a610a87cbd2 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -398,6 +398,15 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 		ret = PTR_ERR(mixer->mod_clk);
 		goto err_disable_bus_clk;
 	}
+
+	/*
+	 * It seems that we need to enforce that rate for whatever
+	 * reason for the mixer to be functional. Make sure it's the
+	 * case.
+	 */
+	if (mixer->cfg->mod_rate)
+		clk_set_rate(mixer->mod_clk, mixer->cfg->mod_rate);
+
 	clk_prepare_enable(mixer->mod_clk);
 
 	list_add_tail(&mixer->engine.list, &drv->engine_list);
@@ -474,6 +483,7 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
 	.ui_num = 1,
 	.scaler_mask = 0x3,
 	.ccsc = 0,
+	.mod_rate = 150000000,
 };
 
 static const struct of_device_id sun8i_mixer_of_table[] = {
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index bc58040a88f9..f34e70c42adf 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -121,12 +121,15 @@ struct de2_fmt_info {
  *	Set value to 0 if this is first mixer or second mixer with VEP support.
  *	Set value to 1 if this is second mixer without VEP support. Other values
  *	are invalid.
+ * @mod_rate: module clock rate that needs to be set in order to have
+ *	a functional block.
  */
 struct sun8i_mixer_cfg {
 	int		vi_num;
 	int		ui_num;
 	int		scaler_mask;
 	int		ccsc;
+	unsigned long	mod_rate;
 };
 
 struct sun8i_mixer {
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related

* [PATCH v5 04/12] dt-bindings: display: sun4i-drm: Add A83T pipeline
From: Maxime Ripard @ 2017-12-21 11:02 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, jernej.skrabec, plaes, devicetree,
	linux-kernel, dri-devel, Rob Herring, thierry.reding,
	Laurent Pinchart, linux-arm-kernel, icenowy
In-Reply-To: <cover.e5a47cc96ec5274dd932daa2bde47df073087da9.1513854122.git-series.maxime.ripard@free-electrons.com>

The A83T has two video pipelines in parallel that looks quite similar to
the other SoCs.

The video planes are handled through a controller called the mixer, and the
video signal is then passed to the timing controller (TCON).

And while there is two instances of the mixers and TCONs, they have a
significant number of differences. The TCONs are quite easy to deal with,
one is supposed to generate TV (in the broader term, so including things
like HDMI) signals, the other one LCD (so RGB, LVDS, DSI) signals. And
while they are called TCON0 and TCON1 in the A83t datasheet, newer SoCs
call them TCON-TV and TCON-LCD, which seems more appropriate.

However, the mixers differ mostly by their capabilities, with some features
being available only in the first one, or the number of planes they expose,
but also through their register layout. And while the capabilities could be
represented as properties, the register layout differences would need to
express all the registers offsets as properties, which is usually quite
bad. Especially since documentation on that hardware block is close to
non-existant and we don't even have the list of all those registers in the
first place.

So let's call them mixer 0 and 1 in our compatibles, even though the name
is pretty bad...

At the moment, we only have tested the code on a board that has a single
display output, so we're leaving the tcon-tv and mixer1 out.

Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 1e21cfaac9e2..9f073af4c711 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -93,6 +93,7 @@ Required properties:
    * allwinner,sun6i-a31s-tcon
    * allwinner,sun7i-a20-tcon
    * allwinner,sun8i-a33-tcon
+   * allwinner,sun8i-a83t-tcon-lcd
    * allwinner,sun8i-v3s-tcon
  - reg: base address and size of memory-mapped region
  - interrupts: interrupt associated to this IP
@@ -225,6 +226,7 @@ supported.
 
 Required properties:
   - compatible: value must be one of:
+    * allwinner,sun8i-a83t-de2-mixer-0
     * allwinner,sun8i-v3s-de2-mixer
   - reg: base address and size of the memory-mapped region.
   - clocks: phandles to the clocks feeding the mixer
@@ -254,6 +256,7 @@ Required properties:
     * allwinner,sun6i-a31s-display-engine
     * allwinner,sun7i-a20-display-engine
     * allwinner,sun8i-a33-display-engine
+    * allwinner,sun8i-a83t-display-engine
     * allwinner,sun8i-v3s-display-engine
 
   - allwinner,pipelines: list of phandle to the display engine
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related

* [PATCH v5 03/12] dt-bindings: display: sun4i-drm: Add LVDS properties
From: Maxime Ripard @ 2017-12-21 11:02 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, jernej.skrabec, plaes, devicetree,
	linux-kernel, dri-devel, Rob Herring, thierry.reding,
	Laurent Pinchart, linux-arm-kernel, icenowy
In-Reply-To: <cover.e5a47cc96ec5274dd932daa2bde47df073087da9.1513854122.git-series.maxime.ripard@free-electrons.com>

Some clocks and resets supposed to drive the LVDS logic in the display
engine have been overlooked when the driver was first introduced.

Add those additional resources to the binding, and we'll deal with the ABI
stability in the code.

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt |  9 +++++++-
 1 file changed, 9 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 50cc72ee1168..1e21cfaac9e2 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -121,6 +121,15 @@ Required properties:
 On SoCs other than the A33 and V3s, there is one more clock required:
    - 'tcon-ch1': The clock driving the TCON channel 1
 
+On SoCs that support LVDS (all SoCs but the A13, H3, H5 and V3s), you
+need one more reset line:
+   - 'lvds': The reset line driving the LVDS logic
+
+And on the SoCs newer than the A31 (sun6i and sun8i families), you
+need one more clock line:
+   - 'lvds-alt': An alternative clock source, separate from the TCON channel 0
+                 clock, that can be used to drive the LVDS clock
+
 DRC
 ---
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related

* [PATCH v5 02/12] drm/panel: lvds: Add support for the power-supply property
From: Maxime Ripard @ 2017-12-21 11:02 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, jernej.skrabec, plaes, devicetree,
	linux-kernel, dri-devel, Rob Herring, thierry.reding,
	Laurent Pinchart, linux-arm-kernel, icenowy
In-Reply-To: <cover.e5a47cc96ec5274dd932daa2bde47df073087da9.1513854122.git-series.maxime.ripard@free-electrons.com>

A significant number of panels need to power up a regulator in order to
operate properly. Add support for the power-supply property to enable and
disable such a regulator whenever needed.

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/panel/panel-lvds.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-lvds.c b/drivers/gpu/drm/panel/panel-lvds.c
index e2d57c01200b..57e38a9e7ab4 100644
--- a/drivers/gpu/drm/panel/panel-lvds.c
+++ b/drivers/gpu/drm/panel/panel-lvds.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 
 #include <drm/drmP.h>
@@ -39,6 +40,7 @@ struct panel_lvds {
 	bool data_mirror;
 
 	struct backlight_device *backlight;
+	struct regulator *supply;
 
 	struct gpio_desc *enable_gpio;
 	struct gpio_desc *reset_gpio;
@@ -69,6 +71,9 @@ static int panel_lvds_unprepare(struct drm_panel *panel)
 	if (lvds->enable_gpio)
 		gpiod_set_value_cansleep(lvds->enable_gpio, 0);
 
+	if (lvds->supply)
+		regulator_disable(lvds->supply);
+
 	return 0;
 }
 
@@ -76,6 +81,17 @@ static int panel_lvds_prepare(struct drm_panel *panel)
 {
 	struct panel_lvds *lvds = to_panel_lvds(panel);
 
+	if (lvds->supply) {
+		int err;
+
+		err = regulator_enable(lvds->supply);
+		if (err < 0) {
+			dev_err(lvds->dev, "failed to enable supply: %d\n",
+				err);
+			return err;
+		}
+	}
+
 	if (lvds->enable_gpio)
 		gpiod_set_value_cansleep(lvds->enable_gpio, 1);
 
@@ -196,6 +212,13 @@ static int panel_lvds_probe(struct platform_device *pdev)
 	if (ret < 0)
 		return ret;
 
+	lvds->supply = devm_regulator_get_optional(lvds->dev, "power");
+	if (IS_ERR(lvds->supply)) {
+		ret = PTR_ERR(lvds->supply);
+		dev_err(lvds->dev, "failed to request regulator: %d\n", ret);
+		return ret;
+	}
+
 	/* Get GPIOs and backlight controller. */
 	lvds->enable_gpio = devm_gpiod_get_optional(lvds->dev, "enable",
 						     GPIOD_OUT_LOW);
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related

* [PATCH v5 01/12] dt-bindings: panel: lvds: Document power-supply property
From: Maxime Ripard @ 2017-12-21 11:02 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: Mark Rutland, Thomas Petazzoni, jernej.skrabec, plaes, devicetree,
	linux-kernel, dri-devel, Rob Herring, thierry.reding,
	Laurent Pinchart, linux-arm-kernel, icenowy
In-Reply-To: <cover.e5a47cc96ec5274dd932daa2bde47df073087da9.1513854122.git-series.maxime.ripard@free-electrons.com>

The power-supply property is used by a vast majority of panels, including
panel-simple. Let's document it as a common property

Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/display/panel/panel-common.txt | 6 ++++++
 Documentation/devicetree/bindings/display/panel/panel-lvds.txt   | 1 +
 Documentation/devicetree/bindings/display/panel/simple-panel.txt | 2 +-
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/panel/panel-common.txt b/Documentation/devicetree/bindings/display/panel/panel-common.txt
index ec52c472c845..125ea68052af 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-common.txt
+++ b/Documentation/devicetree/bindings/display/panel/panel-common.txt
@@ -78,6 +78,12 @@ used for panels that implement compatible control signals.
   while active. Active high reset signals can be supported by inverting the
   GPIO specifier polarity flag.
 
+Power
+-----
+
+- power-supply: many display panels need an additional power supply in
+  order to be fully powered-up. For such panels, power-supply contains
+  a phandle to the regulator powering the panel.
 
 Backlight
 ---------
diff --git a/Documentation/devicetree/bindings/display/panel/panel-lvds.txt b/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
index b938269f841e..250850a2150b 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
+++ b/Documentation/devicetree/bindings/display/panel/panel-lvds.txt
@@ -32,6 +32,7 @@ Optional properties:
 - label: See panel-common.txt.
 - gpios: See panel-common.txt.
 - backlight: See panel-common.txt.
+- power-supply: See panel-common.txt.
 - data-mirror: If set, reverse the bit order described in the data mappings
   below on all data lanes, transmitting bits for slots 6 to 0 instead of
   0 to 6.
diff --git a/Documentation/devicetree/bindings/display/panel/simple-panel.txt b/Documentation/devicetree/bindings/display/panel/simple-panel.txt
index 1341bbf4aa3d..16d8ff088b7d 100644
--- a/Documentation/devicetree/bindings/display/panel/simple-panel.txt
+++ b/Documentation/devicetree/bindings/display/panel/simple-panel.txt
@@ -1,7 +1,7 @@
 Simple display panel
 
 Required properties:
-- power-supply: regulator to provide the supply voltage
+- power-supply: See panel-common.txt
 
 Optional properties:
 - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related

* [PATCH v5 00/12] drm/sun4i: Add A83t LVDS support
From: Maxime Ripard @ 2017-12-21 11:02 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, Chen-Yu Tsai, Maxime Ripard
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mark Rutland, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	plaes-q/aMd4JkU83YtjvyW6yDsg, icenowy-h8G6r0blFSE,
	Thomas Petazzoni, jernej.skrabec-gGgVlfcn5nU,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	thierry.reding-Re5JQEeQqe8AvxtiuMwx3w, Laurent Pinchart

Hi,

Here is an attempt at supporting the LVDS output in our DRM driver. This
has been tested on the A83T (with DE2), but since everything is basically
in the TCON, it should also be usable on the older SoCs with minor
modifications.

This was the occasion to refactor a bunch of things. The most notable ones
would be the documentation, and split of the UI layers in the mixer code,
and the switch to kfifo for our endpoint parsing code in the driver that
fixes an issue introduced by the switch to BFS.

Let me know what you think,
Maxime

Changes from v4:
  - Changed the order of the clk_prepare_enable and clk_set_rate for the
    mixer module clock
  - Squash the two DT PWM patches
  - Removed the output pins muxing
  - Changed the flag to tell if you have an LVDS alternate clock to
    has_lvds_alt
  - Used SPDX headers

Changes from v3:
  - Collect the tags
  - Use SPDX headers when possible
  - Added the new mixer configuration options
  - Changed the LVDS clock for lvds-alt instead of lvds-pll
  - Removed the MIPI PLL from the A31s
  - Changed the LVDS_ANA0 macros name to reflect the generation they were
    introduced in, and added a comment to mention the changes needed to
    support the older SoCs

Changes from v2:
  - Move the module clock rate to the mixer structure
  - Adjusted the simple-panel documentation for power-supply
  - Changed the compatible for the first A83t mixer to mixer 0
  - Rebased on top of current drm-misc
  - Split out the A83t bindings in its separate patch

Changes from v1:
  - Added a fix for the error path handling in the TCON
  - Enable the TCON by default
  - Removed the patch that changes the channels offset but kept most of the
    modifications as a cleanup
  - Deal with the LVDS clock being able to have another PLL parent on some
    SoCs
  - Renamed the TCON compatible to TCON-TV, following the convention used
    on newer SoCs
  - Removed the hardcoded timings
  - Moved LVDS enable quirks to a separate function
  - Used clock indices define in the DT
  - Removed the hardcoded clock rate in the DT and moved it to the driver
  - Changed sun8i_mixer_planes to sun8i_mixer_ui_planes to be consistent
  - Added the various tags collected
  - Rebased on top of 4.15

Maxime Ripard (12):
  dt-bindings: panel: lvds: Document power-supply property
  drm/panel: lvds: Add support for the power-supply property
  dt-bindings: display: sun4i-drm: Add LVDS properties
  dt-bindings: display: sun4i-drm: Add A83T pipeline
  drm/sun4i: Force the mixer rate at 150MHz
  drm/sun4i: Create minimal multipliers and dividers
  drm/sun4i: Add LVDS support
  drm/sun4i: Add A83T support
  ARM: dts: sun8i: a83t: Add display pipeline
  ARM: dts: sun8i: a83t: Enable the PWM
  ARM: dts: sun8i: a83t: Add LVDS pins group
  ARM: dts: sun8i: a711: Enable the LCD

 Documentation/devicetree/bindings/display/panel/panel-common.txt |   6 ++-
 Documentation/devicetree/bindings/display/panel/panel-lvds.txt   |   1 +-
 Documentation/devicetree/bindings/display/panel/simple-panel.txt |   2 +-
 Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt    |  12 ++++-
 arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts                        |  61 ++++++++++++++++++-
 arch/arm/boot/dts/sun8i-a83t.dtsi                                |  99 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/panel/panel-lvds.c                               |  23 +++++++-
 drivers/gpu/drm/sun4i/Makefile                                   |   1 +-
 drivers/gpu/drm/sun4i/sun4i_dotclock.c                           |  10 ++-
 drivers/gpu/drm/sun4i/sun4i_drv.c                                |   1 +-
 drivers/gpu/drm/sun4i/sun4i_lvds.c                               | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_lvds.h                               |  12 ++++-
 drivers/gpu/drm/sun4i/sun4i_tcon.c                               | 244 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_tcon.h                               |  31 +++++++++-
 drivers/gpu/drm/sun4i/sun8i_mixer.c                              |  21 ++++++-
 drivers/gpu/drm/sun4i/sun8i_mixer.h                              |   3 +-
 16 files changed, 699 insertions(+), 5 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h

base-commit: 99239c7ba0214ec99011378a6ca1bcd589c3dc98
-- 
git-series 0.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* RE: [PATCH 8/9] ARM: dts: iwg22d-sodimm: Sound DMA support via SRC on DTS
From: Biju Das @ 2017-12-21 11:01 UTC (permalink / raw)
  To: Simon Horman
  Cc: Rob Herring, Mark Rutland, Magnus Damm, Chris Paterson,
	Fabrizio Castro, devicetree@vger.kernel.org,
	linux-renesas-soc@vger.kernel.org
In-Reply-To: <20171221104443.rk6prrib4gdi7qyz@verge.net.au>

Hi Simon,

> -----Original Message-----
> From: Simon Horman [mailto:horms@verge.net.au]
> Sent: 21 December 2017 10:45
> To: Biju Das <biju.das@bp.renesas.com>
> Cc: Rob Herring <robh+dt@kernel.org>; Mark Rutland
> <mark.rutland@arm.com>; Magnus Damm <magnus.damm@gmail.com>;
> Chris Paterson <Chris.Paterson2@renesas.com>; Fabrizio Castro
> <fabrizio.castro@bp.renesas.com>; devicetree@vger.kernel.org; linux-renesas-
> soc@vger.kernel.org
> Subject: Re: [PATCH 8/9] ARM: dts: iwg22d-sodimm: Sound DMA support via
> SRC on DTS
>
> On Wed, Dec 20, 2017 at 08:02:04PM +0000, Biju Das wrote:
> > DMA transfer to/from SRC
> >
> >      DMA      DMApp
> > [MEM] -> [SRC] -> [SSIU] -> [SSI]
> >
> >      DMA      DMApp
> > [MEM] <- [SRC] <- [SSIU] <- [SSI]
> >
> > Current sound driver is supporting SSI/SRC random connection.
> > So, this patch is trying
> > SSI3 -> SRC3
> > SSI4 <- SRC4
>
> I am curious to know why the selection here differs from that present in
> iwg20d-q7-common. Is it an arbitrary decision?
>
> Likewise for other uses of ssi*, src* and dvc* in this patchset.

For ssi*,  on this board, SSI3/4 interface is connected to Audio In/Out.

For src*,  the original bsp from iwave is using src3/src4, also it is arbitrary as per the data sheet.

For dvc*,  Again it is arbitrary as per the data sheet.

> >
> > Signed-off-by: Biju Das <biju.das@bp.renesas.com>
> > Reviewed-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> > ---
> >  arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts
> > b/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts
> > index 0f880c1..2cac57c 100644
> > --- a/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts
> > +++ b/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts
> > @@ -183,8 +183,8 @@
> >
> >  rcar_sound,dai {
> >  dai0 {
> > -playback = <&ssi3>;
> > -capture = <&ssi4>;
> > +playback = <&ssi3 &src3>;
> > +capture = <&ssi4 &src4>;
> >  };
> >  };
> >  };
> > --
> > 1.9.1
> >


[https://www2.renesas.eu/media/email/unicef_2017.jpg]

This Christmas, instead of sending out cards, Renesas Electronics Europe have decided to support Unicef with a donation. For further details click here<https://www.unicef.org/> to find out about the valuable work they do, helping children all over the world.
We would like to take this opportunity to wish you a Merry Christmas and a prosperous New Year.



Renesas Electronics Europe Ltd, Dukes Meadow, Millboard Road, Bourne End, Buckinghamshire, SL8 5FH, UK. Registered in England & Wales under Registered No. 04586709.

^ permalink raw reply

* Re: [PATCH] nios2: dts: Remove leading 0x and 0s from bindings notation
From: Tobias Klauser @ 2017-12-21 10:48 UTC (permalink / raw)
  To: Mathieu Malaterre
  Cc: Rob Herring, Mark Rutland, Ley Foon Tan,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	nios2-dev-g9ZBwUv/Ih/yUk5EbOjzuce+I+R0W71w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Walter Goossens
In-Reply-To: <20171214165359.28112-1-malat-8fiUuRrzOP0dnm+yROfE0A@public.gmane.org>

On 2017-12-14 at 17:53:59 +0100, Mathieu Malaterre <malat-8fiUuRrzOP0dnm+yROfE0A@public.gmane.org> wrote:
> Improve the DTS files by removing all the leading "0x" and zeros to fix the
> following dtc warnings:
> 
> Warning (unit_address_format): Node /XXX unit name should not have leading "0x"
> 
> and
> 
> Warning (unit_address_format): Node /XXX unit name should not have leading 0s
> 
> Converted using the following command:
> 
> find . -type f \( -iname *.dts -o -iname *.dtsi \) -exec sed -E -i -e "s/@0x([0-9a-fA-F\.]+)\s?\{/@\L\1 \{/g" -e "s/@0+([0-9a-fA-F\.]+)\s?\{/@\L\1 \{/g" {} +
> 
> For simplicity, two sed expressions were used to solve each warnings separately.
> 
> To make the regex expression more robust a few other issues were resolved,
> namely setting unit-address to lower case, and adding a whitespace before the
> the opening curly brace:
> 
> https://elinux.org/Device_Tree_Linux#Linux_conventions
> 
> This is a follow up to commit 4c9847b7375a ("dt-bindings: Remove leading 0x from bindings notation")
> 
> Reported-by: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
> Suggested-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Signed-off-by: Mathieu Malaterre <malat-8fiUuRrzOP0dnm+yROfE0A@public.gmane.org>

Reviewed-by: Tobias Klauser <tklauser-93Khv+1bN0NyDzI6CaY1VQ@public.gmane.org>

This file was originally generated by sopc2dts [1], so it'll probably
need updating as well (Cc'ing Walter).

[1] https://github.com/wgoossens/sopc2dts

> ---
>  arch/nios2/boot/dts/3c120_devboard.dts | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/nios2/boot/dts/3c120_devboard.dts b/arch/nios2/boot/dts/3c120_devboard.dts
> index 36ccdf05837d..56f4b5df6d65 100644
> --- a/arch/nios2/boot/dts/3c120_devboard.dts
> +++ b/arch/nios2/boot/dts/3c120_devboard.dts
> @@ -29,7 +29,7 @@
>  		#address-cells = <1>;
>  		#size-cells = <0>;
>  
> -		cpu: cpu@0x0 {
> +		cpu: cpu@0 {
>  			device_type = "cpu";
>  			compatible = "altr,nios2-1.0";
>  			reg = <0x00000000>;
> @@ -69,7 +69,7 @@
>  		compatible = "altr,avalon", "simple-bus";
>  		bus-frequency = <125000000>;
>  
> -		pb_cpu_to_io: bridge@0x8000000 {
> +		pb_cpu_to_io: bridge@8000000 {
>  			compatible = "simple-bus";
>  			reg = <0x08000000 0x00800000>;
>  			#address-cells = <1>;
> @@ -83,7 +83,7 @@
>  				<0x00008000 0x08008000 0x00000020>,
>  				<0x00400000 0x08400000 0x00000020>;
>  
> -			timer_1ms: timer@0x400000 {
> +			timer_1ms: timer@400000 {
>  				compatible = "altr,timer-1.0";
>  				reg = <0x00400000 0x00000020>;
>  				interrupt-parent = <&cpu>;
> @@ -91,7 +91,7 @@
>  				clock-frequency = <125000000>;
>  			};
>  
> -			timer_0: timer@0x8000 {
> +			timer_0: timer@8000 {
>  				compatible = "altr,timer-1.0";
>  				reg = < 0x00008000 0x00000020 >;
>  				interrupt-parent = < &cpu >;
> @@ -99,14 +99,14 @@
>  				clock-frequency = < 125000000 >;
>  			};
>  
> -			jtag_uart: serial@0x4d50 {
> +			jtag_uart: serial@4d50 {
>  				compatible = "altr,juart-1.0";
>  				reg = <0x00004d50 0x00000008>;
>  				interrupt-parent = <&cpu>;
>  				interrupts = <1>;
>  			};
>  
> -			tse_mac: ethernet@0x4000 {
> +			tse_mac: ethernet@4000 {
>  				compatible = "altr,tse-1.0";
>  				reg = <0x00004000 0x00000400>,
>  					<0x00004400 0x00000040>,
> @@ -133,7 +133,7 @@
>  				};
>  			};
>  
> -			uart: serial@0x4c80 {
> +			uart: serial@4c80 {
>  				compatible = "altr,uart-1.0";
>  				reg = <0x00004c80 0x00000020>;
>  				interrupt-parent = <&cpu>;
> @@ -143,7 +143,7 @@
>  			};
>  		};
>  
> -		cfi_flash_64m: flash@0x0 {
> +		cfi_flash_64m: flash@0 {
>  			compatible = "cfi-flash";
>  			reg = <0x00000000 0x04000000>;
>  			bank-width = <2>;
> -- 
> 2.11.0
> 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH V4 3/7] PCI: tegra: Remove PCI_REASSIGN_ALL_BUS flag for Tegra PCIe
From: Lorenzo Pieralisi @ 2017-12-21 10:46 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Manikanta Maddireddy, cyndis-/1wQRMveznE,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, jonathanh-DDmLM1+adcrQT0dZR+AlfA,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	frowand.list-Re5JQEeQqe8AvxtiuMwx3w, rjw-LthD3rsA81gm4RdzfppkhA,
	tglx-hfZtesqFncYOwBW4kG4KsQ, vidyas-DDmLM1+adcrQT0dZR+AlfA,
	kthota-DDmLM1+adcrQT0dZR+AlfA, linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, linux-pm-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20171220193011.GA31757@ulmo>

On Wed, Dec 20, 2017 at 08:30:11PM +0100, Thierry Reding wrote:
> On Fri, Dec 15, 2017 at 05:36:43PM +0000, Lorenzo Pieralisi wrote:
> > On Fri, Dec 08, 2017 at 02:28:09PM +0530, Manikanta Maddireddy wrote:
> > > Primary, secondary and subordinate default bus numbers are 0 in Tegra and
> > > it is expecting SW to program these numbers in configration space.
> > > 
> > > pci_scan_bridge_extend() function programs these numbers in configuration
> > > space if secondary & subordinate bus numbers are 0 or PCI_REASSIGN_ALL_BUS
> > > flag is set. Since secondary & subordinate default bus numbers are 0,
> > > PCI_REASSIGN_ALL_BUS flag can be removed for Tegra PCIe.
> > > 
> > > Signed-off-by: Manikanta Maddireddy <mmaddireddy-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> > > ---
> > > V3:
> > > * new patch in V3
> > > V4:
> > > * no change in this patch
> > > 
> > >  drivers/pci/host/pci-tegra.c | 1 -
> > >  1 file changed, 1 deletion(-)
> > > 
> > > diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
> > > index a549c5899e26..0d91f1a3a6b4 100644
> > > --- a/drivers/pci/host/pci-tegra.c
> > > +++ b/drivers/pci/host/pci-tegra.c
> > > @@ -2604,7 +2604,6 @@ static int tegra_pcie_probe(struct platform_device *pdev)
> > >  
> > >  	tegra_pcie_enable_ports(pcie);
> > >  
> > > -	pci_add_flags(PCI_REASSIGN_ALL_BUS);
> > 
> > This looks obviously OK to me but I need Thierry's ACK to queue it.
> 
> Just as an additional note: I think the real reason why this is okay to
> do is because we reset the PCI host controller in the kernel driver, so
> any bus assignments done by the firmware are reset as well.
> 
> Acked-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

Thank you. This series needs rebasing, we should try to untangle
the dependencies between series so that I can actually apply some
of these patches that make sense on their own.

Lorenzo

^ permalink raw reply

* Re: [PATCH V2 9/9] ARM: dts: stm32: add initial support of stm32mp157c eval board
From: Alexandre Torgue @ 2017-12-21 10:44 UTC (permalink / raw)
  To: Linus Walleij
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Arnd Bergmann, Russell King, linux-kernel@vger.kernel.org,
	Rob Herring, Linux ARM, Maxime Coquelin, Gerald Baeza,
	Ludovic Barre
In-Reply-To: <CACRpkdYE+u1o_KDDihX7=7RLNDkkFDOCFsQtBKBZW0i6123ZoQ@mail.gmail.com>



On 12/21/2017 10:18 AM, Linus Walleij wrote:
> On Wed, Dec 20, 2017 at 10:19 AM, Alexandre Torgue
> <alexandre.torgue@st.com> wrote:
>> On 12/20/2017 08:44 AM, Linus Walleij wrote:
> 
>>> gpio-line-names = "foo", "bar" ...;
>>>
>>> See for example
>>> arch/arm/boot/dts/bcm2835-rpi-a.dts
>>> arch/arm/boot/dts/ste-snowball.dts
> (...)
>>
>> It looks like useful for pins used as gpio line. Are you saying that we also
>> have to describe pins used as Alternate Function ?
> 
> No. The use of the names is up to the platform maintainer (you),
> leaving a blank string for non-GPIO lines is just fine.
> 
> Some platforms add the name of the actual function used by the
> line on the design, if it is not GPIO, sometimes something in
> brachets like "[i2c0-SDA]" that says what it is used for and explains
> why you can't use it for GPIO on this setup.
> 
> But just leaving it blank is just as good.

Ok thanks Linus. I will take it into account. It could be useful to add 
it for MCU and future MPU boards.

Regards
Alex


> 
> Yours,
> Linus Walleij
> 

^ permalink raw reply

* Re: [PATCH 8/9] ARM: dts: iwg22d-sodimm: Sound DMA support via SRC on DTS
From: Simon Horman @ 2017-12-21 10:44 UTC (permalink / raw)
  To: Biju Das
  Cc: Rob Herring, Mark Rutland, Magnus Damm, Chris Paterson,
	Fabrizio Castro, devicetree, linux-renesas-soc
In-Reply-To: <1513800125-53213-9-git-send-email-biju.das@bp.renesas.com>

On Wed, Dec 20, 2017 at 08:02:04PM +0000, Biju Das wrote:
> DMA transfer to/from SRC
> 
>      DMA      DMApp
> [MEM] -> [SRC] -> [SSIU] -> [SSI]
> 
>      DMA      DMApp
> [MEM] <- [SRC] <- [SSIU] <- [SSI]
> 
> Current sound driver is supporting SSI/SRC random connection.
> So, this patch is trying
> SSI3 -> SRC3
> SSI4 <- SRC4

I am curious to know why the selection here differs from that
present in iwg20d-q7-common. Is it an arbitrary decision?

Likewise for other uses of ssi*, src* and dvc* in this patchset.

> 
> Signed-off-by: Biju Das <biju.das@bp.renesas.com>
> Reviewed-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> ---
>  arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts b/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts
> index 0f880c1..2cac57c 100644
> --- a/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts
> +++ b/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts
> @@ -183,8 +183,8 @@
>  
>  	rcar_sound,dai {
>  		dai0 {
> -			playback = <&ssi3>;
> -			capture = <&ssi4>;
> +			playback = <&ssi3 &src3>;
> +			capture = <&ssi4 &src4>;
>  		};
>  	};
>  };
> -- 
> 1.9.1
> 

^ permalink raw reply

* Re: [PATCH v2 5/7] dt-bindings: i3c: Document core bindings
From: Boris Brezillon @ 2017-12-21 10:41 UTC (permalink / raw)
  To: Rob Herring
  Cc: Wolfram Sang, linux-i2c, Jonathan Corbet, linux-doc,
	Greg Kroah-Hartman, Arnd Bergmann, Przemyslaw Sroka,
	Arkadiusz Golec, Alan Douglas, Bartosz Folta, Damian Kos,
	Alicja Jurasik-Urbaniak, Cyprian Wronka, Suresh Punnoose,
	Thomas Petazzoni, Nishanth Menon, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, devicetree
In-Reply-To: <20171220180645.pis34opfwawakmqc@rob-hp-laptop>

On Wed, 20 Dec 2017 12:06:45 -0600
Rob Herring <robh@kernel.org> wrote:

> On Sat, Dec 16, 2017 at 07:35:37PM +0100, Boris Brezillon wrote:
> > On Sat, 16 Dec 2017 11:20:40 -0600
> > Rob Herring <robh@kernel.org> wrote:
> >   
> > > On Thu, Dec 14, 2017 at 04:16:08PM +0100, Boris Brezillon wrote:  
> > > > A new I3C subsystem has been added and a generic description has been
> > > > created to represent the I3C bus and the devices connected on it.
> > > > 
> > > > Document this generic representation.  
> 
> [...]
> 
> > > So please define the node 
> > > name to be "i3c-controller". That's more inline with other node names 
> > > than i3c-master that you used below.  
> > 
> > Hm, not sure i3c-controller is appropriate though, because you can have
> > slave controllers. Maybe i3c-host, but I'd prefer to keep the term
> > master since it's employed everywhere in the spec. I can also be
> > i3c-master-controller if you prefer.  
> 
> Okay, i3c-master is fine. Just make it explicit.

Okay.

> 
> > > > +I3C devices
> > > > +===========
> > > > +
> > > > +All I3C devices are supposed to support DAA (Dynamic Address Assignment), and
> > > > +are thus discoverable. So, by default, I3C devices do not have to be described
> > > > +in the device tree.
> > > > +This being said, one might want to attach extra resources to these devices,
> > > > +and those resources may have to be described in the device tree, which in turn
> > > > +means we have to describe I3C devices.
> > > > +
> > > > +Another use case for describing an I3C device in the device tree is when this
> > > > +I3C device has a static address and we want to assign it a specific dynamic
> > > > +address before the DAA takes place (so that other devices on the bus can't
> > > > +take this dynamic address).
> > > > +
> > > > +Required properties
> > > > +-------------------
> > > > +- i3c-pid: PID (Provisional ID). 64-bit property which is used to match a
> > > > +	   device discovered during DAA with its device tree definition. The
> > > > +	   PID is supposed to be unique on a given bus, which guarantees a 1:1
> > > > +	   match. This property becomes optional if a reg property is defined,
> > > > +	   meaning that the device has a static address.    
> > > 
> > > What determines this number?  
> > 
> > Part of it is fixed (manufacturer and part id) and the last few bits
> > represent the device instance on the bus (so you can have several
> > identical devices on the same bus). The manufacturer and part ids
> > should be statically assigned during production, instance id is usually
> > configurable through extra pins that you drive high or low at reset
> > time.  
> 
> Sounds like an I2C address at least for the pin strapping part...

The address space of this instance-id is smaller (4bits) than the I2C
one (7bits), and more importantly, the instance-id is not required to
be unique, it's the aggregation of the vendor-id, part-id and
instance-id that has to be unique. So, if you were thinking about using
this id to uniquely identify the device on the bus it's not a good idea.

> 
> > > > +
> > > > +Optional properties
> > > > +-------------------
> > > > +- reg: static address. Only valid is the device has a static address.
> > > > +- i3c-dynamic-address: dynamic address to be assigned to this device. This
> > > > +		       property depends on the reg property.    
> > > 
> > > Perhaps "assigned-address" property would be appropriate. I'm not all 
> > > that familiar with it though.  
> > 
> > Again, the spec use the term "dynamic address" everywhere, and I'd like
> > to stay as close as possible to the spec.  
> 
> I looked at assigned-addresses a bit more and that won't really fit 
> because it should be the same format as reg. So I think reg should 
> always be the PID as that is fixed and always present. Then the DAA 
> address is separate and can be the i3c-dynamic-address property.
> 
> However, there's still part I don't understand...
> 
> > > > +		/* I3C device with a static address. */
> > > > +		thermal_sensor: sensor@68 {
> > > > +			reg = <0x68>;
> > > > +			i3c-dynamic-address = <0xa>;  
> 
> I'm confused as to how/why you have both reg and dynamic address?

Some I3C devices have an I2C address (also called static or legacy
address in a few places). The static/I2C/legacy address is used until
the I3C device is assigned a dynamic address by the master. The whole
point of specifying both an I2C address (through the reg property) and
a dynamic address (through the i3c-dynamic-address) is to tell the
controller that a specific dynamic address should be assigned to this
device using the SETSADA (Set Dynamic Address from Static Address)
command before a DAA (Dynamic Address Assignment) procedure is started.
This way, the device will not participate to the DAA (because it
already has a valid DA) and the dynamic address can't be assigned to
a different device (which is one of the problem with the automatic DAA
procedure).

> 
> > > > +		};
> > > > +
> > > > +		/*
> > > > +		 * I3C device without a static address but requiring resources
> > > > +		 * described in the DT.
> > > > +		 */
> > > > +		sensor2 {    
> > > 
> > > It's not great that we can't follow using generic node names. Maybe the 
> > > PID can be used as the address? In USB for example, we use hub ports for 
> > > DT addresses rather than USB addresses since those are dynamic.  
> > 
> > Hm, the problem is, we may have 2 numbering schemes here: one where reg
> > is used (reg representing the I2C/static address), and another one
> > where the PID is used.
> > If you're okay with mixing those 2 schemes, then I'm fine with that too.  
> 
> Mixing I2C devices and I3C devices, yes. But you need to mix in a single 
> device? IOW, do I3C devices also have an I2C address?

Yes, some of them have both.

^ permalink raw reply

* Re: [PATCH v2 2/5] mtd: nand: add reworked Marvell NAND controller driver
From: Boris Brezillon @ 2017-12-21 10:14 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: David Woodhouse, Brian Norris, Marek Vasut, Richard Weinberger,
	Cyrille Pitchen, Rob Herring, Mark Rutland, Jason Cooper,
	Andrew Lunn, Gregory Clement, Sebastian Hesselbarth, Russell King,
	Daniel Mack, Haojian Zhuang, Robert Jarzmik, Eric Miao,
	Catalin Marinas, Will Deacon,
	Ezequiel Garcia <ezequiel.garcia>
In-Reply-To: <20171219132942.27433-3-miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

Hi Miquel,

On Tue, 19 Dec 2017 14:29:39 +0100
Miquel Raynal <miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:

> Add marvell_nand driver which aims at replacing the existing pxa3xx_nand
> driver.
> 
> The new driver intends to be easier to understand and follows the brand
> new NAND framework rules by implementing hooks for every pattern the
> controller might support and referencing them inside a parser object
> that will be given to the core at each ->exec_op() call.
> 
> Raw accessors are implemented, useful to test/debug memory/filesystem
> corruptions. Userspace binaries contained in the mtd-utils package may
> now be used and their output trusted.
> 
> Timings may not be kept from the bootloader anymore, the timings used
> for instance in U-Boot were not optimal and it supposed to have NAND
> support (and initialized) in the bootloader.

Hm, AFAIR the old driver was able to dynamically adjust the timings
when the NAND was ONFI compliant.

> 
> Thanks to the improved timings, implementation of ONFI mode 5 support
> (with EDO managed by adding a delay on data sampling), merging the
> commands together and optimizing writes in the command registers, the
> new driver may achieve faster throughputs in both directions.
> Measurements show an improvement of about +23% read throughput and +24%
> write throughput. These measurements have been done with an
> Armada-385-DB-AP (4kiB NAND pages forced in 4-bit strength BCH ECC
> correction) using the userspace tool 'flash_speed' from the MTD test
> suite.
> 
> Besides these important topics, the new driver addresses several
> unsolved known issues in the old driver which:
> - did not work with ECC soft neither with ECC none ;
> - relied on naked read/write (which is unchanged) while the NFCv1
>   embedded in the pxa3xx platforms do not implement it, so several
>   NAND commands did not actually ever work without any notice (like
>   reading the ONFI PARAM_PAGE or SET/GET_FEATURES) ;
> - wrote the OOB data correctly, but was not able to read it correctly
>   past the first OOB data chunk ;
> - did not displayed ECC bytes ;

	    ^display

and I'm not even sure display is the right term here. How about
'retrieve'.

> - used device tree bindings that did not allow more than one NAND chip,
>   and did not allow to choose the correct chip select if not
>   incrementing from 0. Plus, the Ready/Busy line used had to be 0.
> 
> Old device tree bindings are still supported but deprecated. A more
> hierarchical view has to be used to keep the controller and the NAND
> chip structures clearly separated both inside the device tree and also
> in the driver code.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> Tested-by: Sean Nyekjaer <sean.nyekjaer-rjjw5hvvQKZaa/9Udqfwiw@public.gmane.org>
> Tested-by: Willy Tarreau <w@1wt.eu>
> ---
>  drivers/mtd/nand/Kconfig        |   12 +
>  drivers/mtd/nand/Makefile       |    1 +
>  drivers/mtd/nand/marvell_nand.c | 2942 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 2955 insertions(+)
>  create mode 100644 drivers/mtd/nand/marvell_nand.c
> 
> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> index 859eb7790c46..9e141e03f5c2 100644
> --- a/drivers/mtd/nand/Kconfig
> +++ b/drivers/mtd/nand/Kconfig
> @@ -323,6 +323,18 @@ config MTD_NAND_PXA3xx
>  	  platforms (XP, 370, 375, 38x, 39x) and 64-bit Armada
>  	  platforms (7K, 8K) (NFCv2).
>  
> +config MTD_NAND_MARVELL
> +	tristate "NAND controller support on Marvell boards"
> +	depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU || \
> +		   COMPILE_TEST
> +	depends on HAS_IOMEM
> +	help
> +	  This enables the NAND flash controller driver for Marvell boards,
> +	  including:
> +	  - PXA3xx processors (NFCv1)
> +	  - 32-bit Armada platforms (XP, 37x, 38x, 39x) (NFCv2)
> +	  - 64-bit Aramda platforms (7k, 8k) (NFCv2)
> +
>  config MTD_NAND_SLC_LPC32XX
>  	tristate "NXP LPC32xx SLC Controller"
>  	depends on ARCH_LPC32XX
> diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
> index 118a1349aad3..921634ba400c 100644
> --- a/drivers/mtd/nand/Makefile
> +++ b/drivers/mtd/nand/Makefile
> @@ -32,6 +32,7 @@ obj-$(CONFIG_MTD_NAND_OMAP2) 		+= omap2_nand.o
>  obj-$(CONFIG_MTD_NAND_OMAP_BCH_BUILD)	+= omap_elm.o
>  obj-$(CONFIG_MTD_NAND_CM_X270)		+= cmx270_nand.o
>  obj-$(CONFIG_MTD_NAND_PXA3xx)		+= pxa3xx_nand.o
> +obj-$(CONFIG_MTD_NAND_MARVELL)		+= marvell_nand.o
>  obj-$(CONFIG_MTD_NAND_TMIO)		+= tmio_nand.o
>  obj-$(CONFIG_MTD_NAND_PLATFORM)		+= plat_nand.o
>  obj-$(CONFIG_MTD_NAND_PASEMI)		+= pasemi_nand.o
> diff --git a/drivers/mtd/nand/marvell_nand.c b/drivers/mtd/nand/marvell_nand.c
> new file mode 100644
> index 000000000000..0a5432bcda6a
> --- /dev/null
> +++ b/drivers/mtd/nand/marvell_nand.c
> @@ -0,0 +1,2942 @@
> +/*
> + * Marvell NAND flash controller driver
> + *
> + * Copyright (C) 2017 Marvell
> + * Author: Miquel RAYNAL <miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * SPDX-License-Identifier: GPL-2.0

AFAIU (maybe I'm wrong), this should be a single line comment
(C++-style) on the first line of the file:

// SPDX-License-Identifier: GPL-2.0
/*
 * Marvell NAND flash controller driver
 *
 * Copyright (C) 2017 Marvell
 * Author: Miquel RAYNAL <miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
 */

> + */
> +
> +#include <linux/module.h>
> +#include <linux/clk.h>
> +#include <linux/mtd/rawnand.h>
> +#include <linux/of_platform.h>
> +#include <linux/iopoll.h>
> +#include <linux/interrupt.h>
> +#include <linux/slab.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +#include <asm/unaligned.h>
> +
> +#include <linux/dmaengine.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/dma/pxa-dma.h>
> +#include <linux/platform_data/mtd-nand-pxa3xx.h>
> +
> +/* Data FIFO granularity, FIFO reads/writes must be a multiple of this length */
> +#define FIFO_DEPTH		8
> +#define FIFO_REP(x)		(x / sizeof(u32))
> +#define BCH_SEQ_READS		(32 / FIFO_DEPTH)
> +/* NFC does not support transfers of larger chunks at a time */
> +#define MAX_CHUNK_SIZE		2112
> +/* NFCv1 cannot read more that 7 bytes of ID */
> +#define NFCV1_READID_LEN	7
> +/* Polling is done at a pace of POLL_PERIOD us until POLL_TIMEOUT is reached */
> +#define POLL_PERIOD		0
> +#define POLL_TIMEOUT		100000
> +/* Interrupt maximum wait period in ms */
> +#define IRQ_TIMEOUT		1000
> +/* Latency in clock cycles between SoC pins and NFC logic */
> +#define MIN_RD_DEL_CNT		3
> +/* Maximum number of contiguous address cycles */
> +#define MAX_ADDRESS_CYC_NFCV1	5
> +#define MAX_ADDRESS_CYC_NFCV2	7
> +/* System control registers/bits to enable the NAND controller on some SoCs */
> +#define GENCONF_SOC_DEVICE_MUX	0x208
> +#define GENCONF_SOC_DEVICE_MUX_NFC_EN BIT(0)
> +#define GENCONF_SOC_DEVICE_MUX_ECC_CLK_RST BIT(20)
> +#define GENCONF_SOC_DEVICE_MUX_ECC_CORE_RST BIT(21)
> +#define GENCONF_SOC_DEVICE_MUX_NFC_INT_EN BIT(25)
> +#define GENCONF_CLK_GATING_CTRL	0x220
> +#define GENCONF_CLK_GATING_CTRL_ND_GATE BIT(2)
> +#define GENCONF_ND_CLK_CTRL	0x700
> +#define GENCONF_ND_CLK_CTRL_EN	BIT(0)
> +
> +/* NAND controller data flash control register */
> +#define NDCR			0x00
> +/* NAND interface timing parameter 0 register */
> +#define NDTR0			0x04
> +/* NAND interface timing parameter 1 register */
> +#define NDTR1			0x0C
> +/* NAND controller status register */
> +#define NDSR			0x14
> +/* NAND ECC control register */
> +#define NDECCCTRL		0x28
> +/* NAND controller data buffer register */
> +#define NDDB			0x40
> +/* NAND controller command buffer 0 register */
> +#define NDCB0			0x48
> +/* NAND controller command buffer 1 register */
> +#define NDCB1			0x4C
> +/* NAND controller command buffer 2 register */
> +#define NDCB2			0x50
> +/* NAND controller command buffer 3 register */
> +#define NDCB3			0x54

Just nitpicking, but I find it clearer when register offsets and
register fields are defined next to each other:

#define MY_REG		0xYYYY
#define MY_REG_FIELDX	BIT(X)
...

> +
> +/* Data flash control register bitfields */
> +#define NDCR_ALL_INT		GENMASK(11, 0)
> +#define NDCR_CS1_CMDDM		BIT(7)
> +#define NDCR_CS0_CMDDM		BIT(8)
> +#define NDCR_RDYM		BIT(11)
> +#define NDCR_ND_ARB_EN		BIT(12)
> +#define NDCR_RA_START		BIT(15)
> +#define NDCR_RD_ID_CNT(x)	(min_t(unsigned int, x, 0x7) << 16)
> +#define NDCR_PAGE_SZ(x)		(x >= 2048 ? BIT(24) : 0)
> +#define NDCR_DWIDTH_M		BIT(26)
> +#define NDCR_DWIDTH_C		BIT(27)
> +#define NDCR_ND_RUN		BIT(28)
> +#define NDCR_DMA_EN		BIT(29)
> +#define NDCR_ECC_EN		BIT(30)
> +#define NDCR_SPARE_EN		BIT(31)
> +

[...]

> +
> +/*

You seem to use the kerneldoc format, so you should probably start all
your comments with:

/**

> + * Marvell ECC engine works differently than the others, in order to limit the
> + * size of the IP, hardware engineers choose to set a fixed strength at 16 bits

					 ^chose

> + * per subpage, and depending on a the desired strength needed by the NAND chip,
> + * a particular layout mixing data/spare/ecc is defined, with a possible last
> + * chunk smaller that the others.
> + *
> + * @writesize:		Full page size on which the layout applies
> + * @chunk:		Desired ECC chunk size on which the layout applies
> + * @strength:		Desired ECC strength (per chunk size bytes) on which the
> + *			layout applies
> + * @full_chunk_cnt:	Number of full-sized chunks, which is the number of
> + *			repetitions of the pattern:
> + *			(data_bytes + spare_bytes + ecc_bytes).
> + * @data_bytes:		Number of data bytes per chunk
> + * @spare_bytes:	Number of spare bytes per chunk
> + * @ecc_bytes:		Number of ecc bytes per chunk
> + * @last_chunk_cnt:	If there is a last chunk with a different size than
> + *			the first ones, the next fields may not be empty

A boolean named has_last_chunk would be more appropriate since you can
only have one last chunk.

> + * @last_data_bytes:	Number of data bytes in the last chunk
> + * @last_spare_bytes:	Number of spare bytes in the last chunk
> + * @last_ecc_bytes:	Number of ecc bytes in the last chunk
> + */
> +struct marvell_hw_ecc_layout {
> +	/* Constraints */
> +	int writesize;
> +	int chunk;
> +	int strength;
> +	/* Corresponding layout */
> +	int full_chunk_cnt;
> +	int data_bytes;
> +	int spare_bytes;
> +	int ecc_bytes;
> +	int last_chunk_cnt;
> +	int last_data_bytes;
> +	int last_spare_bytes;
> +	int last_ecc_bytes;
> +};
> +

[...]

> +/*
> + * NAND controller structure: stores Marvell NAND controller information
> + *
> + * @controller:		Base controller structure
> + * @dev:		Parent device (used to print error messages)
> + * @regs:		NAND controller registers
> + * @ecc_clk:		ECC block clock, two times the NAND controller clock
> + * @complete:		Completion object to wait for NAND controller events
> + * @assigned_cs:	Bitmask describing already assigned CS lines
> + * @chips:		List containing all the NAND chips attached to
> + *			this NAND controller
> + * @caps:		NAND controller capabilities for each compatible string
> + * @buf:		Controller local buffer to store a part of the read
> + *			buffer when the read operation was not 8 bytes aligned
> + *			as is the FIFO.
> + * @buf_pos:		Position in the 'buf' buffer
> + * @dma_chan:		DMA channel (NFCv1 only)
> + * @dma_buf:		32-bit aligned buffer for DMA transfers (NFCv1 only)
> + */
> +struct marvell_nfc {
> +	struct nand_hw_control controller;
> +	struct device *dev;
> +	void __iomem *regs;
> +	struct clk *ecc_clk;
> +	struct completion complete;
> +	unsigned long assigned_cs;
> +	struct list_head chips;
> +	struct nand_chip *selected_chip;
> +	const struct marvell_nfc_caps *caps;
> +
> +	/*
> +	 * Buffer handling: @buf will be accessed byte-per-byter but also
> +	 * int-per-int when exchanging data with the NAND controller FIFO,
> +	 * 32-bit alignment is then required.
> +	 */
> +	u8 buf[FIFO_DEPTH] __aligned(sizeof(u32));
> +	int buf_pos;

I'm almost sure you don't need this temporary buffer. Every time it's
used locally, so just allocate an u32 buf[2] on the stack where you
need it and you should be good.

> +
> +	/* DMA (NFCv1 only) */
> +	bool use_dma;
> +	struct dma_chan *dma_chan;
> +	u8 *dma_buf;
> +};
> +

[...]

> +/*
> + * Derives a duration in numbers of clock cycles.
> + *
> + * @ps: Duration in pico-seconds
> + * @period_ns:  Clock period in nano-seconds
> + *
> + * Convert the duration in nano-seconds, then divide by the period and
> + * return the number of clock periods.
> + */
> +#define TO_CYCLES(ps, period_ns) (DIV_ROUND_UP(ps / 1000, period_ns))
> +
> +/*
> + * NAND driver structure filled during the parsing of the ->exec_op() subop
> + * subset of instructions.
> + *
> + * @ndcb:		Array for the values of the NDCBx registers

			Array of values written to NDCBx registers

> + * @cle_ale_delay_ns:	Optional delay after the last CMD or ADDR cycle
> + * @rdy_timeout_ms:	Timeout for waits on Ready/Busy pin
> + * @rdy_delay_ns:	Optional delay after waiting for the RB pin
> + * @data_delay_ns:	Optional delay after the data xfer
> + * @data_instr_idx:	Index of the data instruction in the subop
> + * @data_instr:		Pointer to the data instruction in the subop
> + */
> +struct marvell_nfc_op {
> +	u32 ndcb[4];
> +	unsigned int cle_ale_delay_ns;
> +	unsigned int rdy_timeout_ms;
> +	unsigned int rdy_delay_ns;
> +	unsigned int data_delay_ns;
> +	unsigned int data_instr_idx;
> +	const struct nand_op_instr *data_instr;
> +};

[...]

> +
> +/*
> + * The core may ask the controller to use only 8-bit accesses while usually
> + * using 16-bit accesses. Later function may blindly call this one with a

			     ^Later, callers of this function may ...

> + * boolean to indicate if 8-bit accesses must be enabled of disabled without

							    ^or

> + * knowing if 16-bit accesses are actually in use.
> + */

I'd move this comment in the code...

> +static void marvell_nfc_force_byte_access(struct nand_chip *chip,
> +					  bool force_8bit)
> +{
> +	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
> +	u32 ndcr;
> +

... like here:

	/*
	 * Callers of this function do not verify if the NAND is
	 * using a 16-bit or an 8-bit bus for normal operations, so we
	 * need to take care of that here by leaving the configuration
	 * unchanged if the NAND does not have the NAND_BUSWIDTH_16
	 * flag set.
	 */

> +	if (!(chip->options & NAND_BUSWIDTH_16))
> +		return;
> +
> +	ndcr = readl_relaxed(nfc->regs + NDCR);
> +
> +	if (force_8bit)
> +		ndcr &= ~(NDCR_DWIDTH_M | NDCR_DWIDTH_C);
> +	else
> +		ndcr |= NDCR_DWIDTH_M | NDCR_DWIDTH_C;
> +
> +	writel_relaxed(ndcr, nfc->regs + NDCR);
> +}

[...]

> +
> +/*
> + * Any time a command has to be sent to the controller, the following sequence
> + * has to be followed:
> + * - call marvell_nfc_prepare_cmd()
> + *      -> activate the ND_RUN bit that will kind of 'start a job'
> + *      -> wait the signal indicating the NFC is waiting for a command
> + * - send the command (cmd and address cycles)
> + * - enventually send or receive the data
> + * - call marvell_nfc_end_cmd() with the corresponding flag
> + *      -> wait the flag to be triggered or cancel the job with a timeout
> + *
> + * The following functions are helpers to do this job and keep in the
> + * specialized functions the code that really does the operations.

I would rephrase it like that:
"
The following helpers are here to factorize the code a bit so that
specialized functions responsible for executing the actual NAND
operations do not have to replicate the same code blocks.
"

> + */
> +static int marvell_nfc_prepare_cmd(struct nand_chip *chip)
> +{
> +	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
> +	u32 ndcr, val;
> +	int ret;
> +
> +	/* Poll ND_RUN and clear NDSR before issuing any command */
> +	ret = marvell_nfc_wait_ndrun(chip);
> +	if (ret) {
> +		dev_err(nfc->dev, "Last operation did not suceed\n");
> +		return ret;
> +	}
> +
> +	ndcr = readl_relaxed(nfc->regs + NDCR);
> +	writel_relaxed(readl_relaxed(nfc->regs + NDSR), nfc->regs + NDSR);
> +
> +	/* Assert ND_RUN bit and wait the NFC to be ready */
> +	writel_relaxed(ndcr | NDCR_ND_RUN, nfc->regs + NDCR);
> +	ret = readl_relaxed_poll_timeout(nfc->regs + NDSR, val,
> +					 val & NDSR_WRCMDREQ,
> +					 POLL_PERIOD, POLL_TIMEOUT);
> +	if (ret) {
> +		dev_err(nfc->dev, "Timeout on WRCMDRE\n");
> +		return -ETIMEDOUT;
> +	}
> +
> +	/* Command may be written, clear WRCMDREQ status bit */
> +	writel_relaxed(NDSR_WRCMDREQ, nfc->regs + NDSR);
> +
> +	return 0;
> +}


[...]

> +
> +static void marvell_nfc_select_chip(struct mtd_info *mtd, int die_nr)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
> +	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
> +	u32 ndcr;
> +
> +	if (chip == nfc->selected_chip && die_nr == marvell_nand->selected_die)
> +		return;
> +
> +	if (die_nr < 0 || die_nr >= marvell_nand->nsels) {
> +		nfc->selected_chip = NULL;
> +		marvell_nand->selected_die = -1;
> +		return;
> +	}
> +
> +	/*
> +	 * Do not change the timing registers when using the DT property
> +	 * marvell,nand-keep-config; in that case ->ndtr0 and ->ndtr1 from the
> +	 * marvell_nand structure are supposedly empty.
> +	 */
> +	if (marvell_nand->ndtr0 && marvell_nand->ndtr1) {
> +		writel_relaxed(marvell_nand->ndtr0, nfc->regs + NDTR0);
> +		writel_relaxed(marvell_nand->ndtr1, nfc->regs + NDTR1);
> +	}
> +
> +	ndcr = readl_relaxed(nfc->regs + NDCR);
> +
> +	/* Ensure controller is not blocked; also clear some fields */
> +	ndcr &= ~(NDCR_ND_RUN | NDCR_DWIDTH_M | NDCR_DWIDTH_C |
> +		  NDCR_PAGE_SZ(2048));
> +
> +	/* Adapt bus width */
> +	if (chip->options & NAND_BUSWIDTH_16)
> +		ndcr |= NDCR_DWIDTH_M | NDCR_DWIDTH_C;
> +
> +	/* Page size as seen by the controller, either 512B or 2kiB */
> +	ndcr |= NDCR_PAGE_SZ(mtd->writesize);

I wonder if we couldn't prepare the value of ->ndcr at probe time
(just like we prepare ->ndtrX) so that the only thing you'd have to do
here is a

	writel_relaxed(ndcr, nfc->regs + NDCR);

> +
> +	/* Update the control register */
> +	writel_relaxed(ndcr,  nfc->regs + NDCR);
> +
> +	/* Also reset the interrupt status register */
> +	marvell_nfc_clear_int(nfc, NDCR_ALL_INT);
> +
> +	nfc->selected_chip = chip;
> +	marvell_nand->selected_die = die_nr;
> +}
> +

[...]


> +
> +/* Read/write PIO/DMA accessors */
> +static int marvell_nfc_xfer_data_dma(struct marvell_nfc *nfc,
> +				     enum dma_data_direction direction,
> +				     unsigned int len)
> +{
> +	unsigned int dma_len = min_t(int, ALIGN(len, 32), MAX_CHUNK_SIZE);
> +	struct dma_async_tx_descriptor *tx;
> +	struct scatterlist sg;
> +	dma_cookie_t cookie;
> +	int ret;
> +
> +	marvell_nfc_enable_dma(nfc);
> +	/* Prepare the DMA transfer */
> +	sg_init_one(&sg, nfc->dma_buf, dma_len);
> +	dma_map_sg(nfc->dma_chan->device->dev, &sg, 1, direction);
> +	tx = dmaengine_prep_slave_sg(nfc->dma_chan, &sg, 1,
> +				     direction == DMA_FROM_DEVICE ?
> +				     DMA_DEV_TO_MEM : DMA_MEM_TO_DEV,
> +				     DMA_PREP_INTERRUPT);
> +	if (!tx) {
> +		dev_err(nfc->dev, "Could not prepare DMA S/G list\n");
> +		return -ENXIO;
> +	}
> +
> +	/* Do the task and wait for it to finish */
> +	cookie = dmaengine_submit(tx);
> +	ret = dma_submit_error(cookie);
> +	if (ret)
> +		return -EIO;
> +
> +	dma_async_issue_pending(nfc->dma_chan);
> +	ret = marvell_nfc_wait_cmdd(nfc->selected_chip);
> +	dma_unmap_sg(nfc->dma_chan->device->dev, &sg, 1, direction);
> +	marvell_nfc_disable_dma(nfc);
> +	if (ret) {
> +		dev_err(nfc->dev, "Timeout waiting for DMA (status: %d)\n",
> +			dmaengine_tx_status(nfc->dma_chan, cookie, NULL));
> +		dmaengine_terminate_all(nfc->dma_chan);
> +		return -ETIMEDOUT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int marvell_nfc_xfer_data_in_pio(struct marvell_nfc *nfc, u8 *in,
> +					unsigned int len)
> +{
> +	unsigned int last_len = len % FIFO_DEPTH;
> +	unsigned int last_full_offset = round_down(len, FIFO_DEPTH);
> +	int i;
> +
> +	for (i = 0; i < last_full_offset; i += FIFO_DEPTH)
> +		ioread32_rep(nfc->regs + NDDB, in + i, FIFO_REP(FIFO_DEPTH));
> +
> +	if (last_len) {
> +		ioread32_rep(nfc->regs + NDDB, nfc->buf, FIFO_REP(FIFO_DEPTH));
> +		memcpy(in + last_full_offset, nfc->buf, last_len);

This is where you should declare your temporary buffer:

		u32 tmpbuf[FIFO_REP(FIFO_DEPTH)];
		ioread32_rep(nfc->regs + NDDB, tmpbuf, sizeof(tmpbuf));
		memcpy(in + last_full_offset, tmpbuf, last_len);
> +	}
> +
> +	return 0;
> +}
> +

[...]


> +
> +/*
> + * Check a chunk is correct or not according to hardware ECC engine.
> + * mtd->ecc_stats.corrected is updated, as well as max_bitflips, however
> + * mtd->ecc_stats.failure is not, the function will instead return a non-zero
> + * value indicating that a check on the emptyness of the subpage must be
> + * performed before declaring the subpage corrupted.
> + */
> +static int marvell_nfc_hw_ecc_correct(struct nand_chip *chip,
> +				      unsigned int *max_bitflips)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
> +	int bf = 0;
> +	u32 ndsr;
> +
> +	ndsr = readl_relaxed(nfc->regs + NDSR);
> +
> +	/* Check uncorrectable error flag */
> +	if (ndsr & NDSR_UNCERR) {
> +		writel_relaxed(ndsr, nfc->regs + NDSR);
> +
> +		/*
> +		 * Do not increment ->ecc_stats.failed now, instead, return a
> +		 * non-zero value to indicate that this chunk was apparently
> +		 * bad, and it should be check to see if it empty or not. If
> +		 * the chunk (with ECC bytes) is not declared empty, the calling
> +		 * function must increment the failure count.
> +		 */
> +		return -EIO;

-EBADMSG would be better, just to be consistent with the error code
returned in case of ECC errors elsewhere.

> +	}
> +
> +	/* Check correctable error flag */
> +	if (ndsr & NDSR_CORERR) {
> +		writel_relaxed(ndsr, nfc->regs + NDSR);
> +
> +		if (chip->ecc.algo == NAND_ECC_BCH)
> +			bf = NDSR_ERRCNT(ndsr);
> +		else
> +			bf = 1;
> +	}
> +
> +	/* Update the stats and max_bitflips */
> +	mtd->ecc_stats.corrected += bf;
> +	*max_bitflips = max_t(unsigned int, *max_bitflips, bf);
> +
> +	return 0;
> +}
> +
> +/* Hamming read helpers */
> +static int marvell_nfc_hw_ecc_hmg_do_read_page(struct nand_chip *chip, u8 *buf,
> +					       bool oob_required, bool raw,
> +					       int page)
> +{
> +	struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
> +	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
> +	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
> +	struct marvell_nfc_op nfc_op = {
> +		.ndcb[0] = NDCB0_CMD_TYPE(TYPE_READ) |
> +			   NDCB0_ADDR_CYC(marvell_nand->addr_cyc) |
> +			   NDCB0_DBC |
> +			   NDCB0_CMD1(NAND_CMD_READ0) |
> +			   NDCB0_CMD2(NAND_CMD_READSTART),
> +		.ndcb[1] = NDCB1_ADDRS_PAGE(page),
> +		.ndcb[2] = NDCB2_ADDR5_PAGE(page),
> +	};
> +	unsigned int oob_bytes = 0;
> +	int ret;
> +
> +	/* NFCv2 needs more information about the operation being executed */
> +	if (nfc->caps->is_nfcv2)
> +		nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_MONOLITHIC_RW);
> +
> +	ret = marvell_nfc_prepare_cmd(chip);
> +	if (ret)
> +		return ret;
> +
> +	if (oob_required) {
> +		oob_bytes = lt->spare_bytes;

AFAIR, you have to read the spare bytes when raw is false, so this
should be something like:

	if (oob_required || !raw)

This being said, we don't really care about performances when reading
in raw mode, so you could just drop the oob_required argument and always
read the OOB bytes.

> +		if (raw)
> +			oob_bytes += lt->ecc_bytes;
> +	}
> +
> +	marvell_nfc_send_cmd(chip, &nfc_op);
> +	ret = marvell_nfc_end_cmd(chip, NDSR_RDDREQ,
> +				  "RDDREQ while draining FIFO (data/oob)");
> +	if (ret)
> +		return ret;
> +
> +	/* Read the page then the OOB area */
> +	if (nfc->use_dma) {
> +		marvell_nfc_xfer_data_dma(nfc, DMA_FROM_DEVICE,
> +					  lt->data_bytes + oob_bytes);
> +		memcpy(buf, nfc->dma_buf, lt->data_bytes);
> +		memcpy(chip->oob_poi + (raw ? 0 : lt->ecc_bytes),
> +		       nfc->dma_buf + lt->data_bytes, oob_bytes);
> +	} else {
> +		marvell_nfc_xfer_data_in_pio(nfc, buf, lt->data_bytes);
> +		marvell_nfc_xfer_data_in_pio(nfc, chip->oob_poi, oob_bytes);
> +	}
> +
> +	ret = marvell_nfc_wait_cmdd(chip);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +

[...]

> +
> +static int marvell_nfc_hw_ecc_hmg_read_page(struct mtd_info *mtd,
> +					    struct nand_chip *chip,
> +					    u8 *buf, int oob_required,
> +					    int page)
> +{
> +	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
> +	int max_bitflips = 0, ret;
> +
> +	/*
> +	 * Reading/Writing a given page must always be performed with the same
> +	 * configuration regarding the state of the SPARE_EN bit or ECC bytes
> +	 * will not be present at the same location (writing only data, without
> +	 * SPARE_EN will put the ECC bytes at the beginning of the OOB area,
> +	 * while writing with the SPARE_EN bit (hence, also writing free OOB
> +	 * bytes) will put first the spare bytes then, at the end of the OOB
> +	 * area, the ECC bytes. Choices has been made to always read/write OOB
> +	 * area (padding with 0xFF is handled by the core for writes).

IMHO, this comment should go next to the place where you actually set
the SPARE_EN bit. This way you don't have to duplicate the same comment
block in various places.

> +	 */
> +

Drop this empty line.

> +	marvell_nfc_enable_hw_ecc(chip);
> +	marvell_nfc_hw_ecc_hmg_do_read_page(chip, buf, true, false, page);
> +	ret = marvell_nfc_hw_ecc_correct(chip, &max_bitflips);
> +	marvell_nfc_disable_hw_ecc(chip);
> +
> +	if (!ret)
> +		return max_bitflips;
> +
> +	/*
> +	 * Re-read the OOB area in raw mode if ECC failures have been detected
> +	 * to check for empty pages.
> +	 */
> +	nand_change_read_column_op(chip, lt->data_bytes + lt->spare_bytes,
> +				   chip->oob_poi + lt->spare_bytes,
> +				   lt->ecc_bytes, false);
> +	marvell_nfc_check_empty_chunk(chip, buf, lt->data_bytes, chip->oob_poi,
> +				      lt->spare_bytes, chip->oob_poi +
> +				      lt->spare_bytes, lt->ecc_bytes,
> +				      &max_bitflips);
> +
> +	return max_bitflips;
> +}
> +

[...]

> +
> +/* Hamming write helpers */
> +static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip,
> +						const u8 *buf,
> +						bool oob_required, bool raw,
> +						int page)
> +{
> +	struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
> +	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
> +	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
> +	struct marvell_nfc_op nfc_op = {
> +		.ndcb[0] = NDCB0_CMD_TYPE(TYPE_WRITE) |
> +			   NDCB0_ADDR_CYC(marvell_nand->addr_cyc) |
> +			   NDCB0_CMD1(NAND_CMD_SEQIN) |
> +			   NDCB0_CMD2(NAND_CMD_PAGEPROG) |
> +			   NDCB0_DBC,
> +		.ndcb[1] = NDCB1_ADDRS_PAGE(page),
> +		.ndcb[2] = NDCB2_ADDR5_PAGE(page),
> +	};
> +	int oob_bytes = 0;
> +	int ret;
> +
> +	/* NFCv2 needs more information about the operation being executed */
> +	if (nfc->caps->is_nfcv2)
> +		nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_MONOLITHIC_RW);
> +
> +	ret = marvell_nfc_prepare_cmd(chip);
> +	if (ret)
> +		return ret;
> +
> +	if (oob_required) {

Same comment as for the marvell_nfc_hw_ecc_hmg_read_page() function:
just drop the oob_required argument to simplify the logic.

> +		oob_bytes = lt->spare_bytes;
> +		if (raw)
> +			oob_bytes += lt->ecc_bytes;
> +	}
> +
> +	marvell_nfc_send_cmd(chip, &nfc_op);
> +	ret = marvell_nfc_end_cmd(chip, NDSR_WRDREQ,
> +				  "WRDREQ while loading FIFO (data)");
> +	if (ret)
> +		return ret;
> +
> +	/* Write the page then the OOB area */
> +	if (nfc->use_dma) {
> +		memcpy(nfc->dma_buf, buf, lt->data_bytes);
> +		if (oob_required)
> +			memcpy(nfc->dma_buf + lt->data_bytes, chip->oob_poi,
> +			       oob_bytes);
> +		marvell_nfc_xfer_data_dma(nfc, DMA_TO_DEVICE, lt->data_bytes +
> +					  lt->ecc_bytes + lt->spare_bytes);
> +	} else {
> +		marvell_nfc_xfer_data_out_pio(nfc, buf, lt->data_bytes);
> +		if (oob_required)
> +			marvell_nfc_xfer_data_out_pio(nfc, chip->oob_poi,
> +						      oob_bytes);
> +	}
> +
> +	ret = marvell_nfc_wait_cmdd(chip);
> +	if (ret)
> +		return ret;
> +
> +	ret = marvell_nfc_wait_op(chip,
> +				  chip->data_interface.timings.sdr.tPROG_max);
> +	return ret;
> +}
> +

[...]

> +static int marvell_nfc_hw_ecc_hmg_write_page(struct mtd_info *mtd,
> +					     struct nand_chip *chip,
> +					     const u8 *buf,
> +					     int oob_required, int page)
> +{
> +	int ret;
> +
> +	/*
> +	 * Reading/Writing a given page must always be performed with the same
> +	 * configuration regarding the state of the SPARE_EN bit or ECC bytes
> +	 * will not be present at the same location (writing only data, without
> +	 * SPARE_EN will put the ECC bytes at the beginning of the OOB area,
> +	 * while writing with the SPARE_EN bit (hence, also writing free OOB
> +	 * bytes) will put first the spare bytes then, at the end of the OOB
> +	 * area, the ECC bytes. Choices has been made to always read/write OOB
> +	 * area (padding with 0xFF is handled by the core for writes).
> +	 */

Same as above: drop the comment.

> +
> +	marvell_nfc_enable_hw_ecc(chip);
> +	ret = marvell_nfc_hw_ecc_hmg_do_write_page(chip, buf, true, false,
> +						   page);
> +	marvell_nfc_disable_hw_ecc(chip);
> +
> +	return ret;
> +}
> +

[...]

> +
> +static void marvell_nfc_hw_ecc_bch_read_chunk(struct nand_chip *chip, int chunk,
> +					      u8 *data, unsigned int data_len,
> +					      u8 *spare, unsigned int spare_len,
> +					      int page)
> +{
> +	struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
> +	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
> +	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
> +	int nchunks = lt->full_chunk_cnt + lt->last_chunk_cnt;
> +	int i, ret;
> +	struct marvell_nfc_op nfc_op = {
> +		.ndcb[0] = NDCB0_CMD_TYPE(TYPE_READ) |
> +			   NDCB0_ADDR_CYC(marvell_nand->addr_cyc) |
> +			   NDCB0_LEN_OVRD,
> +		.ndcb[1] = NDCB1_ADDRS_PAGE(page),
> +		.ndcb[2] = NDCB2_ADDR5_PAGE(page),
> +		.ndcb[3] = data_len + spare_len,
> +	};
> +
> +	ret = marvell_nfc_prepare_cmd(chip);
> +	if (ret)
> +		return;
> +
> +	if (chunk == 0)
> +		nfc_op.ndcb[0] |= NDCB0_DBC |
> +				  NDCB0_CMD1(NAND_CMD_READ0) |
> +				  NDCB0_CMD2(NAND_CMD_READSTART);
> +
> +	/*
> +	 * Trigger the naked read operation only on the last chunk.
> +	 * Otherwise, use monolithic read.
> +	 */
> +	if (nchunks == 1 || (chunk < nchunks - 1))
> +		nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_MONOLITHIC_RW);
> +	else
> +		nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_LAST_NAKED_RW);
> +
> +	marvell_nfc_send_cmd(chip, &nfc_op);
> +
> +	/*
> +	 * According to the datasheet, when reading from NDDB
> +	 * with BCH enabled, after each 32 bytes reads, we
> +	 * have to make sure that the NDSR.RDDREQ bit is set.
> +	 *
> +	 * Drain the FIFO, 8 32-bit reads at a time, and skip
> +	 * the polling on the last read.
> +	 *
> +	 * Length is a multiple of 32 bytes, hence it is a multiple of 8 too.
> +	 */
> +

Drop the empty line.

> +	for (i = 0; i < data_len; i += FIFO_DEPTH * BCH_SEQ_READS) {
> +		marvell_nfc_end_cmd(chip, NDSR_RDDREQ,
> +				    "RDDREQ while draining FIFO (data)");
> +		marvell_nfc_xfer_data_in_pio(nfc, data,
> +					     FIFO_DEPTH * BCH_SEQ_READS);
> +		data += FIFO_DEPTH * BCH_SEQ_READS;
> +	}
> +
> +	for (i = 0; i < spare_len; i += FIFO_DEPTH * BCH_SEQ_READS) {
> +		marvell_nfc_end_cmd(chip, NDSR_RDDREQ,
> +				    "RDDREQ while draining FIFO (OOB)");
> +		marvell_nfc_xfer_data_in_pio(nfc, spare,
> +					     FIFO_DEPTH * BCH_SEQ_READS);
> +		spare += FIFO_DEPTH * BCH_SEQ_READS;
> +	}
> +}
> +
> +static int marvell_nfc_hw_ecc_bch_read_page(struct mtd_info *mtd,
> +					    struct nand_chip *chip,
> +					    u8 *buf, int oob_required,
> +					    int page)
> +{
> +	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
> +	int nchunks = lt->full_chunk_cnt + lt->last_chunk_cnt;
> +	int data_len = lt->data_bytes, spare_len = lt->spare_bytes, ecc_len;
> +	u8 *data = buf, *spare = chip->oob_poi, *ecc;
> +	int max_bitflips = 0;
> +	u32 failure_mask = 0;
> +	int chunk, ecc_offset_in_page, ret;
> +
> +	/*
> +	 * With BCH, OOB is not fully used (and thus not read entirely), not
> +	 * expected bytes could show up at the end of the OOB buffer if not
> +	 * explicitly erased.
> +	 */
> +	if (oob_required)
> +		memset(chip->oob_poi, 0xFF, mtd->oobsize);
> +
> +	marvell_nfc_enable_hw_ecc(chip);
> +
> +	for (chunk = 0; chunk < nchunks; chunk++) {
> +		/* Update length for the last chunk */
> +		if (chunk >= lt->full_chunk_cnt) {
> +			data_len = lt->last_data_bytes;
> +			spare_len = lt->last_spare_bytes;
> +		}
> +
> +		/* Read the chunk and detect number of bitflips */
> +		marvell_nfc_hw_ecc_bch_read_chunk(chip, chunk, data, data_len,
> +						  spare, spare_len, page);
> +		ret = marvell_nfc_hw_ecc_correct(chip, &max_bitflips);
> +		if (ret)
> +			failure_mask |= BIT(chunk);
> +
> +		data += data_len;
> +		spare += spare_len;
> +	}
> +
> +	marvell_nfc_disable_hw_ecc(chip);
> +
> +	if (!failure_mask)
> +		return max_bitflips;
> +
> +	/*
> +	 * Please note that dumping the ECC bytes during a normal read with OOB
> +	 * area would add a significant overhead as ECC bytes are "consumed" by
> +	 * the controller in normal mode and must be re-read in raw mode. To
> +	 * avoid dropping the performances, we prefer not to include them. The
> +	 * user should re-read the page in raw mode if ECC bytes are required.
> +	 *
> +	 * However, for any subpage read error reported by ->correct(), the ECC
> +	 * bytes must be read in raw mode and the full subpage must be checked
> +	 * to see if it is entirely empty of if there was an actual error.

Nice explanation!

> +	 */
> +

Extra empty

> +	for (chunk = 0; chunk < nchunks; chunk++) {
> +		/* No failure reported for this chunk, move to the next one */
> +		if (!(failure_mask & BIT(chunk)))
> +			continue;
> +
> +		/* Derive ECC bytes positions (in page/buffer) and length */
> +		ecc = chip->oob_poi +
> +			(lt->full_chunk_cnt * lt->spare_bytes) +
> +			(lt->last_chunk_cnt * lt->last_spare_bytes) +
> +			(chunk * ALIGN(lt->ecc_bytes, 32));
> +		ecc_offset_in_page =
> +			(chunk * (lt->data_bytes + lt->spare_bytes +
> +				  lt->ecc_bytes)) +
> +			(chunk < lt->full_chunk_cnt ?
> +			 lt->data_bytes + lt->spare_bytes :
> +			 lt->last_data_bytes + lt->last_spare_bytes);
> +		ecc_len = chunk < lt->full_chunk_cnt ?
> +			lt->ecc_bytes : lt->last_ecc_bytes;
> +
> +		/* Do the actual raw read of the ECC bytes */
> +		nand_change_read_column_op(chip, ecc_offset_in_page,
> +					   ecc, ecc_len, false);
> +
> +		/* Derive data/spare bytes positions (in buffer) and length */
> +		data = buf + (chunk * lt->data_bytes);
> +		data_len = chunk < lt->full_chunk_cnt ?
> +			lt->data_bytes : lt->last_data_bytes;
> +		spare = chip->oob_poi + (chunk * (lt->spare_bytes +
> +						  lt->ecc_bytes));
> +		spare_len = chunk < lt->full_chunk_cnt ?
> +			lt->spare_bytes : lt->last_spare_bytes;
> +
> +		/* Check the entire chunk (data + spare + ecc) for emptyness */
> +		marvell_nfc_check_empty_chunk(chip, data, data_len, spare,
> +					      spare_len, ecc, ecc_len,
> +					      &max_bitflips);
> +	}
> +
> +	return max_bitflips;
> +}
> +

[...]

> +
> +/*
> + * HW ECC layouts, identical to old pxa3xx_nand driver,
> + * to be fully backward compatible.
> + */
> +static int marvell_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
> +				      struct mtd_oob_region *oobregion)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
> +	int nchunks = lt->full_chunk_cnt;
> +
> +	if (section >= nchunks)
> +		return -ERANGE;
> +
> +	oobregion->offset = ((lt->spare_bytes + lt->ecc_bytes) * section) +
> +		lt->spare_bytes;
> +	oobregion->length = lt->ecc_bytes;

We discussed about fixing the layouts to expose all free bytes at
the beginning of the OOB area and all ECC bytes at the end. It doesn't
seem to be the case here.

> +
> +	return 0;
> +}
> +
> +static int marvell_nand_ooblayout_free(struct mtd_info *mtd, int section,
> +				       struct mtd_oob_region *oobregion)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
> +	int nchunks = lt->full_chunk_cnt;
> +
> +	if (section >= nchunks)
> +		return -ERANGE;
> +
> +	if (!lt->spare_bytes)
> +		return 0;
> +
> +	oobregion->offset = section * (lt->spare_bytes + lt->ecc_bytes);
> +	oobregion->length = lt->spare_bytes;
> +	if (!section) {
> +		/*
> +		 * Bootrom looks in bytes 0 & 5 for bad blocks for the
> +		 * 4KB page / 4bit BCH combination.
> +		 */
> +		if (mtd->writesize == SZ_4K && lt->data_bytes == SZ_2K) {
> +			oobregion->offset += 6;
> +			oobregion->length -= 6;
> +		} else {
> +			oobregion->offset += 2;
> +			oobregion->length -= 2;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct mtd_ooblayout_ops marvell_nand_ooblayout_ops = {
> +	.ecc = marvell_nand_ooblayout_ecc,
> +	.free = marvell_nand_ooblayout_free,
> +};
> +

[...]

> +
> +static int marvell_nand_ecc_init(struct mtd_info *mtd,
> +				 struct nand_ecc_ctrl *ecc)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
> +	int ret;
> +
> +	if ((ecc->mode != NAND_ECC_NONE) && (!ecc->size || !ecc->strength)) {
> +		if (chip->ecc_step_ds && chip->ecc_strength_ds) {
> +			ecc->size = chip->ecc_step_ds;
> +			ecc->strength = chip->ecc_strength_ds;
> +		} else {
> +			dev_info(nfc->dev,
> +				 "No minimum ECC strength, using 1b/512B\n");
> +			ecc->size = 512;
> +			ecc->strength = 1;
> +		}
> +	}
> +
> +	switch (ecc->mode) {
> +	case NAND_ECC_HW:
> +		ret = marvell_nand_hw_ecc_ctrl_init(mtd, ecc);
> +		if (ret)
> +			return ret;
> +		break;
> +	case NAND_ECC_NONE:
> +		chip->ecc.algo = 0;

No need to set ecc->algo to 0 here.

> +	case NAND_ECC_SOFT:

You should probably do a check on ->writesize, especially for NFCv1
when used in ECC_NONE of ECC_SOFT, since you can't write/read arbitrary
size.

> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +

[...]

> +static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
> +				  struct device_node *np)
> +{
> +	struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(dev);
> +	struct marvell_nand_chip *marvell_nand;
> +	struct mtd_info *mtd;
> +	struct nand_chip *chip;
> +	int nsels, ret, i;
> +	u32 cs, rb;
> +
> +	/*
> +	 * The legacy "num-cs" property indicates the number of CS on the only
> +	 * chip connected to the controller (legacy bindings does not support
> +	 * more than one chip). CS are only incremented one by one while the RB
> +	 * pin is always the #0.
> +	 *
> +	 * When not using legacy bindings, a couple of "reg" and "marvell,rb"
> +	 * properties must be filled. For each chip, expressed as a subnode,
> +	 * "reg" points to the CS lines and "marvell,rb" to the RB line.
> +	 */
> +	if (pdata) {
> +		nsels = 1;
> +	} else if (nfc->caps->legacy_of_bindings) {
> +		if (!of_get_property(np, "num-cs", &nsels)) {
> +			dev_err(dev, "missing num-cs property\n");
> +			return -EINVAL;
> +		}
> +	} else {
> +		if (!of_get_property(np, "reg", &nsels)) {
> +			dev_err(dev, "missing reg property\n");
> +			return -EINVAL;
> +		}
> +	}
> +
> +	if (!pdata)
> +		nsels /= sizeof(u32);
> +	if (!nsels) {
> +		dev_err(dev, "invalid reg property size\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Alloc the nand chip structure */
> +	marvell_nand = devm_kzalloc(dev, sizeof(*marvell_nand) +
> +				    (nsels *
> +				     sizeof(struct marvell_nand_chip_sel)),
> +				    GFP_KERNEL);
> +	if (!marvell_nand) {
> +		dev_err(dev, "could not allocate chip structure\n");
> +		return -ENOMEM;
> +	}
> +
> +	marvell_nand->nsels = nsels;
> +	marvell_nand->selected_die = -1;
> +
> +	for (i = 0; i < nsels; i++) {
> +		if (pdata || nfc->caps->legacy_of_bindings) {
> +			/*
> +			 * Legacy bindings use the CS lines in natural
> +			 * order (0, 1, ...)
> +			 */
> +			cs = i;
> +		} else {
> +			/* Retrieve CS id */
> +			ret = of_property_read_u32_index(np, "reg", i, &cs);
> +			if (ret) {
> +				dev_err(dev, "could not retrieve reg property: %d\n",
> +					ret);
> +				return ret;
> +			}
> +		}
> +
> +		if (cs >= nfc->caps->max_cs_nb) {
> +			dev_err(dev, "invalid reg value: %u (max CS = %d)\n",
> +				cs, nfc->caps->max_cs_nb);
> +			return -EINVAL;
> +		}
> +
> +		if (test_and_set_bit(cs, &nfc->assigned_cs)) {
> +			dev_err(dev, "CS %d already assigned\n", cs);
> +			return -EINVAL;
> +		}
> +
> +		/*
> +		 * The cs variable represents the chip select id, which must be
> +		 * converted in bit fields for NDCB0 and NDCB2 to select the
> +		 * right chip. Unfortunately, due to a lack of information on
> +		 * the subject and incoherent documentation, the user should not
> +		 * use CS1 and CS3 at all as asserting them is not supported in
> +		 * a reliable way (due to multiplexing inside ADDR5 field).
> +		 */
> +		marvell_nand->sels[i].cs = cs;
> +		switch (cs) {
> +		case 0:
> +		case 2:
> +			marvell_nand->sels[i].ndcb0_csel = 0;
> +			break;
> +		case 1:
> +		case 3:
> +			marvell_nand->sels[i].ndcb0_csel = NDCB0_CSEL;
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +
> +		/* Retrieve RB id */
> +		if (pdata || nfc->caps->legacy_of_bindings) {
> +			/* Legacy bindings always use RB #0 */
> +			rb = 0;
> +		} else {
> +			ret = of_property_read_u32_index(np, "marvell,rb", i,
> +							 &rb);
> +			if (ret) {
> +				dev_err(dev,
> +					"could not retrieve RB property: %d\n",
> +					ret);
> +				return ret;
> +			}
> +		}
> +
> +		if (rb >= nfc->caps->max_rb_nb) {
> +			dev_err(dev, "invalid reg value: %u (max RB = %d)\n",
> +				rb, nfc->caps->max_rb_nb);
> +			return -EINVAL;
> +		}
> +
> +		marvell_nand->sels[i].rb = rb;
> +	}
> +
> +	chip = &marvell_nand->chip;
> +	chip->controller = &nfc->controller;
> +	nand_set_flash_node(chip, np);
> +
> +	chip->exec_op = marvell_nfc_exec_op;
> +	chip->select_chip = marvell_nfc_select_chip;
> +	if (nfc->caps->is_nfcv2 &&
> +	    !of_property_read_bool(np, "marvell,nand-keep-config"))
> +		chip->setup_data_interface = marvell_nfc_setup_data_interface;
> +
> +	mtd = nand_to_mtd(chip);
> +	mtd->dev.parent = dev;
> +
> +	/*
> +	 * Default to HW ECC engine mode. If the nand-ecc-mode property is given
> +	 * in the DT node, this entry will be overwritten in nand_scan_ident().
> +	 */
> +	chip->ecc.mode = NAND_ECC_HW;
> +
> +	ret = nand_scan_ident(mtd, marvell_nand->nsels, NULL);
> +	if (ret) {
> +		dev_err(dev, "could not identify the nand chip\n");
> +		return ret;
> +	}
> +
> +	if (pdata && pdata->flash_bbt)
> +		chip->bbt_options |= NAND_BBT_USE_FLASH;
> +
> +	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
> +		/*
> +		 * We'll use a bad block table stored in-flash and don't
> +		 * allow writing the bad block marker to the flash.
> +		 */
> +		chip->bbt_options |= NAND_BBT_NO_OOB_BBM;
> +		chip->bbt_td = &bbt_main_descr;
> +		chip->bbt_md = &bbt_mirror_descr;
> +	}
> +
> +	/*
> +	 * With RA_START bit set in NDCR, columns takes two address cycles. This
> +	 * means addressing a chip with more than 256 pages needs a fifth
> +	 * address cycle. Addressing a chip using CS 2 or 3 should also needs
> +	 * this additional cycle but due to insistance in the documentation and
> +	 * lack of hardware to test this situation, this case has been dropped
> +	 * and is not supported by this driver.
> +	 */
> +	marvell_nand->addr_cyc = 4;
> +	if (chip->options & NAND_ROW_ADDR_3)
> +		marvell_nand->addr_cyc = 5;
> +
> +	if (pdata) {
> +		chip->ecc.size = pdata->ecc_step_size;
> +		chip->ecc.strength = pdata->ecc_strength;
> +	}
> +
> +	ret = marvell_nand_ecc_init(mtd, &chip->ecc);
> +	if (ret) {
> +		dev_err(dev, "ECC init failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	if (chip->ecc.mode == NAND_ECC_HW) {
> +		/*
> +		 * Subpage write not available with hardware ECC, prohibit also
> +		 * subpage read as in userspace subpage acces would still be

							^ access

> +		 * allowed and subpage write, if used, would lead to numerous
> +		 * uncorrectable ECC errors.
> +		 */
> +		chip->options |= NAND_NO_SUBPAGE_WRITE;
> +	}
> +
> +	if (pdata || nfc->caps->legacy_of_bindings) {
> +		/*
> +		 * We keep the MTD name unchanged to avoid breaking platforms
> +		 * where the MTD cmdline parser is used and the bootloader
> +		 * has not been updated to use the new naming scheme.
> +		 */
> +		mtd->name = "pxa3xx_nand-0";
> +	} else if (!mtd->name) {
> +		/*
> +		 * If the new bindings are used and the bootloader has not been
> +		 * updated to pass a new mtdparts parameter on the cmdline, you
> +		 * should define the following property in your NAND node, ie:
> +		 *
> +		 *	label = "main-storage";
> +		 *
> +		 * This way, mtd->name will be set by the core when
> +		 * nand_set_flash_node() is called.
> +		 */
> +		mtd->name = devm_kasprintf(nfc->dev, GFP_KERNEL,
> +					   "%s:nand.%d", dev_name(nfc->dev),
> +					   marvell_nand->sels[0].cs);
> +		if (!mtd->name) {
> +			dev_err(nfc->dev, "Failed to allocate mtd->name\n");
> +			return -ENOMEM;
> +		}
> +	}
> +
> +	ret = nand_scan_tail(mtd);
> +	if (ret) {
> +		dev_err(dev, "nand_scan_tail failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	if (pdata)
> +		/* Legacy bindings support only one chip */
> +		ret = mtd_device_register(mtd, pdata->parts[0],
> +					  pdata->nr_parts[0]);
> +	else
> +		ret = mtd_device_register(mtd, NULL, 0);
> +	if (ret) {
> +		dev_err(dev, "failed to register mtd device: %d\n", ret);
> +		nand_release(mtd);
> +		return ret;
> +	}
> +
> +	list_add_tail(&marvell_nand->node, &nfc->chips);
> +
> +	return 0;
> +}
> +
> +static int marvell_nand_chips_init(struct device *dev, struct marvell_nfc *nfc)
> +{
> +	struct device_node *np = dev->of_node;
> +	struct device_node *nand_np;
> +	int max_cs = nfc->caps->max_cs_nb;
> +	int nchips;
> +	int ret;
> +
> +	if (!np)
> +		nchips = 1;
> +	else
> +		nchips = of_get_child_count(np);
> +
> +	if (nchips > max_cs) {
> +		dev_err(dev, "too many NAND chips: %d (max = %d CS)\n", nchips,
> +			max_cs);
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * Legacy bindings do not use child nodes to exhibit NAND chip
> +	 * properties and layout. Instead, NAND properties are mixed with the
> +	 * controller's and a single subnode presents the memory layout.

"
	   controller ones, and partitions are defined as direct
	   subnodes of the NAND controller node.
"

> +	 */
> +	if (nfc->caps->legacy_of_bindings) {
> +		ret = marvell_nand_chip_init(dev, nfc, np);
> +		return ret;
> +	}
> +
> +	for_each_child_of_node(np, nand_np) {
> +		ret = marvell_nand_chip_init(dev, nfc, nand_np);
> +		if (ret) {
> +			of_node_put(nand_np);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +

That's all I see for now.

Really nice rework you've done here.

Thanks,

Boris


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v3 3/4] regulator: core: Parse coupled regulators properties
From: Maciej Purski @ 2017-12-21 10:08 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-kernel, devicetree, Liam Girdwood, Rob Herring,
	Mark Rutland, Marek Szyprowski, Bartlomiej Zolnierkiewicz
In-Reply-To: <20171212113511.GF16323@sirena.org.uk>



On 12/12/2017 12:35 PM, Mark Brown wrote:
> On Thu, Dec 07, 2017 at 10:46:14AM +0100, Maciej Purski wrote:
>> (...)
>> +	mutex_lock(&regulator_list_mutex);
>> +	regulator_resolve_coupling(rdev);
>> +	mutex_unlock(&regulator_list_mutex);
>> +
> 
> I'd really expect us to be failing to probe if we run into an error.
> Otherwise we could end up doing bad things to the hardware at runtime
> later on, or confusing ourselves and crashing with partially set up
> datastructures.  


We cannot fail to probe if some of the regulators are not registered 
successfully, as depending on the probing sequence, there will be some 
regulators, which won't be available when registering others. We can fail when 
resolving coupling if we encounter other errors such as max_spread not provided 
or disability to set voltage. Maybe that is what you meant.

> It's also not 100% clear to me how we handle the case
> where only some of the coupled regulators have probed.
> 

I have two ideas how to handle it. We can prohibit setting the voltage and 
always fail on attempt to set voltage of a coupled regulator. Or we can just 
ignore it and set voltage of the regulator without checking the unregistered ones.

^ permalink raw reply

* Re: [PATCH v6 00/18] dwc MSI fixes, ARTPEC-6 EP mode support, ARTPEC-7 SoC support
From: Lorenzo Pieralisi @ 2017-12-21 10:02 UTC (permalink / raw)
  To: Niklas Cassel
  Cc: linux-arm-kernel-VrBV9hrLPhE, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-omap-u79uwXL29TY76Z2rM5mHXA, Niklas Cassel,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20171219232940.659-1-niklas.cassel-VrBV9hrLPhE@public.gmane.org>

On Wed, Dec 20, 2017 at 12:29:21AM +0100, Niklas Cassel wrote:
> This is a series that adds:
> - PCI endpoint mode support in the ARTPEC-6 driver.
> - ARTPEC-7 SoC support in the ARTPEC-6 driver (the SoCs are very similar).
> - Small fixes for MSI in designware-ep and designware-host,
>   needed to get endpoint mode support working for ARTPEC-6.
> - Cleanups in pci-dra7xx to better prepare for endpoint mode in other
>   DWC based PCIe drivers.
> 
> Changes since V5:
> -Dropped GFP_DMA32 from "PCI: dwc: Use the DMA-API to get the MSI address"
>  so that we use the exact same GFP flags as before.
> -Rewrote commit message for "PCI: dwc: Make cpu_addr_fixup take struct
> dw_pcie as argument" to be more detailed.
> 
> Niklas Cassel (18):
>   PCI: dwc: Use the DMA-API to get the MSI address
>   PCI: designware-ep: dw_pcie_ep_set_msi() should only set MMC bits
>   PCI: designware-ep: Read-only registers need DBI_RO_WR_EN to be
>     writable
>   PCI: designware-ep: Pre-allocate memory for MSI in dw_pcie_ep_init
>   PCI: designware-ep: Remove static keyword from dw_pcie_ep_reset_bar()
>   PCI: designware-ep: Add generic function for raising MSI irq
>   PCI: dwc: dra7xx: Refactor Kconfig and Makefile handling for host/ep
>     mode
>   PCI: dwc: dra7xx: Assign pp->ops in dra7xx_add_pcie_port() rather than
>     in probe
>   PCI: dwc: dra7xx: Help compiler to remove unused code
>   PCI: dwc: artpec6: Remove unused defines
>   PCI: dwc: artpec6: Use BIT and GENMASK macros
>   PCI: dwc: artpec6: Split artpec6_pcie_establish_link() into smaller
>     functions
>   bindings: PCI: artpec: Add support for endpoint mode
>   PCI: dwc: artpec6: Add support for endpoint mode
>   PCI: dwc: Make cpu_addr_fixup take struct dw_pcie as argument
>   PCI: dwc: artpec6: Deassert the core before waiting for PHY
>   bindings: PCI: artpec: Add support for the ARTPEC-7 SoC
>   PCI: dwc: artpec6: Add support for the ARTPEC-7 SoC
> 
>  .../devicetree/bindings/pci/axis,artpec6-pcie.txt  |   5 +-
>  drivers/pci/dwc/Kconfig                            |  68 +--
>  drivers/pci/dwc/Makefile                           |   4 +-
>  drivers/pci/dwc/pci-dra7xx.c                       |  27 +-
>  drivers/pci/dwc/pcie-artpec6.c                     | 470 ++++++++++++++++++---
>  drivers/pci/dwc/pcie-designware-ep.c               |  59 ++-
>  drivers/pci/dwc/pcie-designware-host.c             |  15 +-
>  drivers/pci/dwc/pcie-designware.c                  |   2 +-
>  drivers/pci/dwc/pcie-designware.h                  |  22 +-
>  9 files changed, 554 insertions(+), 118 deletions(-)

Applied to pci/dwc for v4.16.

Thanks,
Lorenzo
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 3/9] ARM: dts: r8a7745: Add sound support
From: Geert Uytterhoeven @ 2017-12-21 10:02 UTC (permalink / raw)
  To: Biju Das
  Cc: Rob Herring, Mark Rutland, Simon Horman, Magnus Damm,
	Chris Paterson, Fabrizio Castro, devicetree, Linux-Renesas
In-Reply-To: <1513800125-53213-4-git-send-email-biju.das@bp.renesas.com>

On Wed, Dec 20, 2017 at 9:01 PM, Biju Das <biju.das@bp.renesas.com> wrote:
> Define the generic r8a7745(RZ/G1E) part of the sound device node.
>
> This patch is based on the r8a7794 sound work by Sergei Shtylyov.
>
> Signed-off-by: Biju Das <biju.das@bp.renesas.com>
> Reviewed-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

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

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

^ permalink raw reply

* Re: [PATCH 4/9] ARM: dts: iwg22d-sodimm: Enable SGTL5000 audio codec
From: Geert Uytterhoeven @ 2017-12-21  9:53 UTC (permalink / raw)
  To: Biju Das
  Cc: Rob Herring, Mark Rutland, Simon Horman, Magnus Damm,
	Chris Paterson, Fabrizio Castro, devicetree, Linux-Renesas
In-Reply-To: <1513800125-53213-5-git-send-email-biju.das@bp.renesas.com>

On Wed, Dec 20, 2017 at 9:02 PM, Biju Das <biju.das@bp.renesas.com> wrote:
> This patch enables SGTL5000 audio codec on the carrier board.
>
> Signed-off-by: Biju Das <biju.das@bp.renesas.com>
> Reviewed-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

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

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

^ permalink raw reply

* Re: [PATCH] dt-bindings: gpio: rcar: Correct SoC family name for R8A7778
From: Linus Walleij @ 2017-12-21  9:53 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Rob Herring, Mark Rutland, linux-gpio,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Renesas
In-Reply-To: <1513699422-27671-1-git-send-email-geert+renesas@glider.be>

On Tue, Dec 19, 2017 at 5:03 PM, Geert Uytterhoeven
<geert+renesas@glider.be> wrote:

> R8A7778 is R-Car (not R-Mobile) M1.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>

Patch applied with the ACKs.

Yours,
Linus Walleij

^ permalink raw reply

* Re: [PATCH 2/9] ARM: dts: r8a7745: Add audio DMAC support
From: Geert Uytterhoeven @ 2017-12-21  9:39 UTC (permalink / raw)
  To: Biju Das
  Cc: Rob Herring, Mark Rutland, Simon Horman, Magnus Damm,
	Chris Paterson, Fabrizio Castro,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Linux-Renesas
In-Reply-To: <1513800125-53213-3-git-send-email-biju.das-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>

On Wed, Dec 20, 2017 at 9:01 PM, Biju Das <biju.das-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org> wrote:
> Instantiate the audio DMA controller on the r8a7745 device tree.
>
> Signed-off-by: Biju Das <biju.das-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>
> Reviewed-by: Fabrizio Castro <fabrizio.castro-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>

Reviewed-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/9] ARM: dts: r8a7745: Add audio clocks
From: Geert Uytterhoeven @ 2017-12-21  9:37 UTC (permalink / raw)
  To: Biju Das
  Cc: Rob Herring, Mark Rutland, Simon Horman, Magnus Damm,
	Chris Paterson, Fabrizio Castro,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Linux-Renesas
In-Reply-To: <1513800125-53213-2-git-send-email-biju.das-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>

On Wed, Dec 20, 2017 at 9:01 PM, Biju Das <biju.das-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org> wrote:
> Describe the external audio clocks required by the sound driver.
> Boards that provide audio clocks need to override the clock frequencies.
>
> Signed-off-by: Biju Das <biju.das-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>
> Reviewed-by: Fabrizio Castro <fabrizio.castro-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>

Reviewed-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/3] ARM: dts: r8a7740: Correct TPU register block size
From: Simon Horman @ 2017-12-21  9:32 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Thierry Reding, Rob Herring, Mark Rutland, Magnus Damm, linux-pwm,
	devicetree, linux-renesas-soc
In-Reply-To: <20171220082306.zdtntqbajyy666zv@verge.net.au>

On Wed, Dec 20, 2017 at 09:23:07AM +0100, Simon Horman wrote:
> On Tue, Dec 19, 2017 at 05:02:05PM +0100, Geert Uytterhoeven wrote:
> > The Timer Pulse Unit has registers that lie outside the declared
> > register block.  Enlarge the register block size to fix this.
> > 
> > Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> > ---
> > This was probably based on the old platform code, which also assumed a
> > register block size of 0x100.
> 
> Reviewed-by: Simon Horman <simon.horman@netronome.com>
> 
> With reference to "User's Manual: Hardware" v2.00.

... and applied for v4.16.

^ permalink raw reply

* Re: [PATCH v17 0/5] ZII RAVE platform driver
From: Pavel Machek @ 2017-12-21  9:30 UTC (permalink / raw)
  To: Andrey Smirnov
  Cc: Lee Jones, Greg Kroah-Hartman, cphealy-Re5JQEeQqe8AvxtiuMwx3w,
	Andy Shevchenko, Lucas Stach, Nikita Yushchenko, Guenter Roeck,
	Rob Herring, Mark Rutland, Johan Hovold,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Sebastian Reichel,
	Philippe Ombredanne
In-Reply-To: <20171221065118.29726-1-andrew.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 553 bytes --]

> Everyone:
> 
> This patch series is v17 of the driver for supervisory processor found
> on RAVE series of devices from ZII. Supervisory processor is a PIC
> microcontroller connected to various electrical subsystems on RAVE
> devices whose firmware implements protocol to command/qery them.

query.

Can we please get this patch merged? We really don't want to see v34
of this patch...
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply


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