* [PATCH] drm: sun8i-ui/vi: Fix layer zpos change/atomic modesetting
From: megous @ 2019-09-14 22:03 UTC (permalink / raw)
To: Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai
Cc: Ondrej Jirman, linux-arm-kernel, dri-devel, linux-kernel
From: Ondrej Jirman <megous@megous.com>
There are various issues that this re-work of sun8i_[uv]i_layer_enable
function fixes:
- Make sure that we re-initialize zpos on reset
- Minimize register updates by doing them only when state changes
- Fix issue where DE pipe might get disabled even if it is no longer
used by the layer that's currently calling sun8i_ui_layer_enable
- .atomic_disable callback is not really needed because .atomic_update
can do the disable too, so drop the duplicate code
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 112 ++++++++++++++++---------
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 112 ++++++++++++++++---------
2 files changed, 142 insertions(+), 82 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index dd2a1c851939..b88e8ac5ad1c 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -24,10 +24,11 @@
#include "sun8i_ui_scaler.h"
static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
- int overlay, bool enable, unsigned int zpos,
- unsigned int old_zpos)
+ int overlay, bool was_enabled, bool enable,
+ unsigned int zpos, unsigned int old_zpos)
{
u32 val, bld_base, ch_base;
+ unsigned int old_pipe_ch;
bld_base = sun8i_blender_base(mixer);
ch_base = sun8i_channel_base(mixer, channel);
@@ -35,28 +36,57 @@ static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
DRM_DEBUG_DRIVER("%sabling channel %d overlay %d\n",
enable ? "En" : "Dis", channel, overlay);
- if (enable)
- val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
- else
- val = 0;
+ if (!was_enabled != !enable) {
+ val = enable ? SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN : 0;
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay),
- SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
-
- if (!enable || zpos != old_zpos) {
regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
- SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
- 0);
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay),
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
+ }
- regmap_update_bits(mixer->engine.regs,
+ /*
+ * If this layer was enabled and is being disabled or if it is
+ * enabled and just changing zpos, clear the old route, if it is
+ * still configured to this layer in HW.
+ */
+ if ((was_enabled && !enable) || (enable && zpos != old_zpos)) {
+ /* get channel the pipe for old_zpos is routed to from the HW */
+ regmap_read(mixer->engine.regs,
SUN8I_MIXER_BLEND_ROUTE(bld_base),
- SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
- 0);
+ &old_pipe_ch);
+ old_pipe_ch &= SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos);
+ old_pipe_ch >>= SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(old_zpos);
+
+ /*
+ * Check that pipe for old_zpos is still routed to our layer,
+ * and clear/disable it if it is.
+ */
+
+ if (old_pipe_ch == channel) {
+ DRM_DEBUG_DRIVER("chan=%d en=%d->%d zpos=%d->%d\n",
+ channel, was_enabled, enable, old_zpos, zpos);
+
+ DRM_DEBUG_DRIVER(" disable pipe %d\n", old_zpos);
+
+ regmap_update_bits(mixer->engine.regs,
+ SUN8I_MIXER_BLEND_ROUTE(bld_base),
+ SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
+ 0);
+
+ regmap_update_bits(mixer->engine.regs,
+ SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
+ SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
+ 0);
+ }
}
- if (enable) {
+ /*
+ * If enabling this layer or changin zpos, set route to this layer.
+ */
+ if ((enable && !was_enabled) || (enable && zpos != old_zpos)) {
+ DRM_DEBUG_DRIVER("chan=%d en=%d->%d zpos=%d->%d\n",
+ channel, was_enabled, enable, old_zpos, zpos);
+
val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
regmap_update_bits(mixer->engine.regs,
@@ -69,6 +99,8 @@ static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
SUN8I_MIXER_BLEND_ROUTE(bld_base),
SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
val);
+
+ DRM_DEBUG_DRIVER(" enable pipe %d <- ch %d\n", zpos, channel);
}
}
@@ -261,45 +293,43 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
true, true);
}
-static void sun8i_ui_layer_atomic_disable(struct drm_plane *plane,
- struct drm_plane_state *old_state)
+static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
{
struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
+ unsigned int zpos = plane->state->normalized_zpos;
unsigned int old_zpos = old_state->normalized_zpos;
struct sun8i_mixer *mixer = layer->mixer;
+ bool was_enabled = old_state->crtc && old_state->visible;
+ bool enable = plane->state->crtc && plane->state->visible;
- sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, false, 0,
- old_zpos);
+ if (enable) {
+ sun8i_ui_layer_update_coord(mixer, layer->channel,
+ layer->overlay, plane, zpos);
+ sun8i_ui_layer_update_formats(mixer, layer->channel,
+ layer->overlay, plane);
+ sun8i_ui_layer_update_buffer(mixer, layer->channel,
+ layer->overlay, plane);
+ }
+
+ sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay,
+ was_enabled, enable, zpos, old_zpos);
}
-static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
- struct drm_plane_state *old_state)
+void sun8i_ui_layer_plane_reset(struct drm_plane *plane)
{
struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
- unsigned int zpos = plane->state->normalized_zpos;
- unsigned int old_zpos = old_state->normalized_zpos;
- struct sun8i_mixer *mixer = layer->mixer;
- if (!plane->state->visible) {
- sun8i_ui_layer_enable(mixer, layer->channel,
- layer->overlay, false, 0, old_zpos);
+ drm_atomic_helper_plane_reset(plane);
+ if (!plane->state)
return;
- }
- sun8i_ui_layer_update_coord(mixer, layer->channel,
- layer->overlay, plane, zpos);
- sun8i_ui_layer_update_formats(mixer, layer->channel,
- layer->overlay, plane);
- sun8i_ui_layer_update_buffer(mixer, layer->channel,
- layer->overlay, plane);
- sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay,
- true, zpos, old_zpos);
+ plane->state->zpos = layer->channel;
}
static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = {
.prepare_fb = drm_gem_fb_prepare_fb,
.atomic_check = sun8i_ui_layer_atomic_check,
- .atomic_disable = sun8i_ui_layer_atomic_disable,
.atomic_update = sun8i_ui_layer_atomic_update,
};
@@ -308,7 +338,7 @@ static const struct drm_plane_funcs sun8i_ui_layer_funcs = {
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.destroy = drm_plane_cleanup,
.disable_plane = drm_atomic_helper_disable_plane,
- .reset = drm_atomic_helper_plane_reset,
+ .reset = sun8i_ui_layer_plane_reset,
.update_plane = drm_atomic_helper_update_plane,
};
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index bd0e6a52d1d8..675ebcdac00b 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -18,10 +18,11 @@
#include "sun8i_vi_scaler.h"
static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
- int overlay, bool enable, unsigned int zpos,
- unsigned int old_zpos)
+ int overlay, bool was_enabled, bool enable,
+ unsigned int zpos, unsigned int old_zpos)
{
u32 val, bld_base, ch_base;
+ unsigned int old_pipe_ch;
bld_base = sun8i_blender_base(mixer);
ch_base = sun8i_channel_base(mixer, channel);
@@ -29,28 +30,57 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
DRM_DEBUG_DRIVER("%sabling VI channel %d overlay %d\n",
enable ? "En" : "Dis", channel, overlay);
- if (enable)
- val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN;
- else
- val = 0;
-
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
- SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
+ if (!was_enabled != !enable) {
+ val = enable ? SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN : 0;
- if (!enable || zpos != old_zpos) {
regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
- SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
- 0);
+ SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
+ SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
+ }
- regmap_update_bits(mixer->engine.regs,
+ /*
+ * If this layer was enabled and is being disabled or if it is
+ * enabled and just changing zpos, clear the old route, if it is
+ * still configured to this layer in HW.
+ */
+ if ((was_enabled && !enable) || (enable && zpos != old_zpos)) {
+ /* get channel the pipe for old_zpos is routed to from the HW */
+ regmap_read(mixer->engine.regs,
SUN8I_MIXER_BLEND_ROUTE(bld_base),
- SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
- 0);
+ &old_pipe_ch);
+ old_pipe_ch &= SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos);
+ old_pipe_ch >>= SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(old_zpos);
+
+ /*
+ * Check that pipe for old_zpos is still routed to our layer,
+ * and clear/disable it if it is.
+ */
+
+ if (old_pipe_ch == channel) {
+ DRM_DEBUG_DRIVER("chan=%d en=%d->%d zpos=%d->%d\n",
+ channel, was_enabled, enable, old_zpos, zpos);
+
+ DRM_DEBUG_DRIVER(" disable pipe %d\n", old_zpos);
+
+ regmap_update_bits(mixer->engine.regs,
+ SUN8I_MIXER_BLEND_ROUTE(bld_base),
+ SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
+ 0);
+
+ regmap_update_bits(mixer->engine.regs,
+ SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
+ SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
+ 0);
+ }
}
- if (enable) {
+ /*
+ * If enabling this layer or changin zpos, set route to this layer.
+ */
+ if ((enable && !was_enabled) || (enable && zpos != old_zpos)) {
+ DRM_DEBUG_DRIVER("chan=%d en=%d->%d zpos=%d->%d\n",
+ channel, was_enabled, enable, old_zpos, zpos);
+
val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
regmap_update_bits(mixer->engine.regs,
@@ -63,6 +93,8 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
SUN8I_MIXER_BLEND_ROUTE(bld_base),
SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
val);
+
+ DRM_DEBUG_DRIVER(" enable pipe %d <- ch %d\n", zpos, channel);
}
}
@@ -345,45 +377,43 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
true, true);
}
-static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane,
- struct drm_plane_state *old_state)
+static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
{
struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
+ unsigned int zpos = plane->state->normalized_zpos;
unsigned int old_zpos = old_state->normalized_zpos;
struct sun8i_mixer *mixer = layer->mixer;
+ bool was_enabled = old_state->crtc && old_state->visible;
+ bool enable = plane->state->crtc && plane->state->visible;
- sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0,
- old_zpos);
+ if (enable) {
+ sun8i_vi_layer_update_coord(mixer, layer->channel,
+ layer->overlay, plane, zpos);
+ sun8i_vi_layer_update_formats(mixer, layer->channel,
+ layer->overlay, plane);
+ sun8i_vi_layer_update_buffer(mixer, layer->channel,
+ layer->overlay, plane);
+ }
+
+ sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay,
+ was_enabled, enable, zpos, old_zpos);
}
-static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
- struct drm_plane_state *old_state)
+void sun8i_vi_layer_plane_reset(struct drm_plane *plane)
{
struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
- unsigned int zpos = plane->state->normalized_zpos;
- unsigned int old_zpos = old_state->normalized_zpos;
- struct sun8i_mixer *mixer = layer->mixer;
- if (!plane->state->visible) {
- sun8i_vi_layer_enable(mixer, layer->channel,
- layer->overlay, false, 0, old_zpos);
+ drm_atomic_helper_plane_reset(plane);
+ if (!plane->state)
return;
- }
- sun8i_vi_layer_update_coord(mixer, layer->channel,
- layer->overlay, plane, zpos);
- sun8i_vi_layer_update_formats(mixer, layer->channel,
- layer->overlay, plane);
- sun8i_vi_layer_update_buffer(mixer, layer->channel,
- layer->overlay, plane);
- sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay,
- true, zpos, old_zpos);
+ plane->state->zpos = layer->channel;
}
static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
.prepare_fb = drm_gem_fb_prepare_fb,
.atomic_check = sun8i_vi_layer_atomic_check,
- .atomic_disable = sun8i_vi_layer_atomic_disable,
.atomic_update = sun8i_vi_layer_atomic_update,
};
@@ -392,7 +422,7 @@ static const struct drm_plane_funcs sun8i_vi_layer_funcs = {
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.destroy = drm_plane_cleanup,
.disable_plane = drm_atomic_helper_disable_plane,
- .reset = drm_atomic_helper_plane_reset,
+ .reset = sun8i_vi_layer_plane_reset,
.update_plane = drm_atomic_helper_update_plane,
};
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH] drm: sun8i-ui/vi: Fix layer zpos change/atomic modesetting
From: Ondřej Jirman @ 2019-09-14 22:15 UTC (permalink / raw)
To: Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai
Cc: linux-arm-kernel, dri-devel, linux-kernel
In-Reply-To: <20190914220337.646719-1-megous@megous.com>
On Sun, Sep 15, 2019 at 12:03:37AM +0200, megous hlavni wrote:
> From: Ondrej Jirman <megous@megous.com>
>
> There are various issues that this re-work of sun8i_[uv]i_layer_enable
> function fixes:
>
> - Make sure that we re-initialize zpos on reset
> - Minimize register updates by doing them only when state changes
> - Fix issue where DE pipe might get disabled even if it is no longer
> used by the layer that's currently calling sun8i_ui_layer_enable
> - .atomic_disable callback is not really needed because .atomic_update
> can do the disable too, so drop the duplicate code
See more discussion here:
https://groups.google.com/d/msg/linux-sunxi/9A7ukdtvNpM/2Z2bAhA9AwAJ
o.
> Signed-off-by: Ondrej Jirman <megous@megous.com>
> ---
> drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 112 ++++++++++++++++---------
> drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 112 ++++++++++++++++---------
> 2 files changed, 142 insertions(+), 82 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
> index dd2a1c851939..b88e8ac5ad1c 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
> @@ -24,10 +24,11 @@
> #include "sun8i_ui_scaler.h"
>
> static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
> - int overlay, bool enable, unsigned int zpos,
> - unsigned int old_zpos)
> + int overlay, bool was_enabled, bool enable,
> + unsigned int zpos, unsigned int old_zpos)
> {
> u32 val, bld_base, ch_base;
> + unsigned int old_pipe_ch;
>
> bld_base = sun8i_blender_base(mixer);
> ch_base = sun8i_channel_base(mixer, channel);
> @@ -35,28 +36,57 @@ static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
> DRM_DEBUG_DRIVER("%sabling channel %d overlay %d\n",
> enable ? "En" : "Dis", channel, overlay);
>
> - if (enable)
> - val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
> - else
> - val = 0;
> + if (!was_enabled != !enable) {
> + val = enable ? SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN : 0;
>
> - regmap_update_bits(mixer->engine.regs,
> - SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay),
> - SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
> -
> - if (!enable || zpos != old_zpos) {
> regmap_update_bits(mixer->engine.regs,
> - SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
> - SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
> - 0);
> + SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay),
> + SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
> + }
>
> - regmap_update_bits(mixer->engine.regs,
> + /*
> + * If this layer was enabled and is being disabled or if it is
> + * enabled and just changing zpos, clear the old route, if it is
> + * still configured to this layer in HW.
> + */
> + if ((was_enabled && !enable) || (enable && zpos != old_zpos)) {
> + /* get channel the pipe for old_zpos is routed to from the HW */
> + regmap_read(mixer->engine.regs,
> SUN8I_MIXER_BLEND_ROUTE(bld_base),
> - SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
> - 0);
> + &old_pipe_ch);
> + old_pipe_ch &= SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos);
> + old_pipe_ch >>= SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(old_zpos);
> +
> + /*
> + * Check that pipe for old_zpos is still routed to our layer,
> + * and clear/disable it if it is.
> + */
> +
> + if (old_pipe_ch == channel) {
> + DRM_DEBUG_DRIVER("chan=%d en=%d->%d zpos=%d->%d\n",
> + channel, was_enabled, enable, old_zpos, zpos);
> +
> + DRM_DEBUG_DRIVER(" disable pipe %d\n", old_zpos);
> +
> + regmap_update_bits(mixer->engine.regs,
> + SUN8I_MIXER_BLEND_ROUTE(bld_base),
> + SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
> + 0);
> +
> + regmap_update_bits(mixer->engine.regs,
> + SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
> + SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
> + 0);
> + }
> }
>
> - if (enable) {
> + /*
> + * If enabling this layer or changin zpos, set route to this layer.
> + */
> + if ((enable && !was_enabled) || (enable && zpos != old_zpos)) {
> + DRM_DEBUG_DRIVER("chan=%d en=%d->%d zpos=%d->%d\n",
> + channel, was_enabled, enable, old_zpos, zpos);
> +
> val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
>
> regmap_update_bits(mixer->engine.regs,
> @@ -69,6 +99,8 @@ static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
> SUN8I_MIXER_BLEND_ROUTE(bld_base),
> SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
> val);
> +
> + DRM_DEBUG_DRIVER(" enable pipe %d <- ch %d\n", zpos, channel);
> }
> }
>
> @@ -261,45 +293,43 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
> true, true);
> }
>
> -static void sun8i_ui_layer_atomic_disable(struct drm_plane *plane,
> - struct drm_plane_state *old_state)
> +static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
> + struct drm_plane_state *old_state)
> {
> struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
> + unsigned int zpos = plane->state->normalized_zpos;
> unsigned int old_zpos = old_state->normalized_zpos;
> struct sun8i_mixer *mixer = layer->mixer;
> + bool was_enabled = old_state->crtc && old_state->visible;
> + bool enable = plane->state->crtc && plane->state->visible;
>
> - sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, false, 0,
> - old_zpos);
> + if (enable) {
> + sun8i_ui_layer_update_coord(mixer, layer->channel,
> + layer->overlay, plane, zpos);
> + sun8i_ui_layer_update_formats(mixer, layer->channel,
> + layer->overlay, plane);
> + sun8i_ui_layer_update_buffer(mixer, layer->channel,
> + layer->overlay, plane);
> + }
> +
> + sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay,
> + was_enabled, enable, zpos, old_zpos);
> }
>
> -static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
> - struct drm_plane_state *old_state)
> +void sun8i_ui_layer_plane_reset(struct drm_plane *plane)
> {
> struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
> - unsigned int zpos = plane->state->normalized_zpos;
> - unsigned int old_zpos = old_state->normalized_zpos;
> - struct sun8i_mixer *mixer = layer->mixer;
>
> - if (!plane->state->visible) {
> - sun8i_ui_layer_enable(mixer, layer->channel,
> - layer->overlay, false, 0, old_zpos);
> + drm_atomic_helper_plane_reset(plane);
> + if (!plane->state)
> return;
> - }
>
> - sun8i_ui_layer_update_coord(mixer, layer->channel,
> - layer->overlay, plane, zpos);
> - sun8i_ui_layer_update_formats(mixer, layer->channel,
> - layer->overlay, plane);
> - sun8i_ui_layer_update_buffer(mixer, layer->channel,
> - layer->overlay, plane);
> - sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay,
> - true, zpos, old_zpos);
> + plane->state->zpos = layer->channel;
> }
>
> static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = {
> .prepare_fb = drm_gem_fb_prepare_fb,
> .atomic_check = sun8i_ui_layer_atomic_check,
> - .atomic_disable = sun8i_ui_layer_atomic_disable,
> .atomic_update = sun8i_ui_layer_atomic_update,
> };
>
> @@ -308,7 +338,7 @@ static const struct drm_plane_funcs sun8i_ui_layer_funcs = {
> .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> .destroy = drm_plane_cleanup,
> .disable_plane = drm_atomic_helper_disable_plane,
> - .reset = drm_atomic_helper_plane_reset,
> + .reset = sun8i_ui_layer_plane_reset,
> .update_plane = drm_atomic_helper_update_plane,
> };
>
> diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
> index bd0e6a52d1d8..675ebcdac00b 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
> @@ -18,10 +18,11 @@
> #include "sun8i_vi_scaler.h"
>
> static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
> - int overlay, bool enable, unsigned int zpos,
> - unsigned int old_zpos)
> + int overlay, bool was_enabled, bool enable,
> + unsigned int zpos, unsigned int old_zpos)
> {
> u32 val, bld_base, ch_base;
> + unsigned int old_pipe_ch;
>
> bld_base = sun8i_blender_base(mixer);
> ch_base = sun8i_channel_base(mixer, channel);
> @@ -29,28 +30,57 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
> DRM_DEBUG_DRIVER("%sabling VI channel %d overlay %d\n",
> enable ? "En" : "Dis", channel, overlay);
>
> - if (enable)
> - val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN;
> - else
> - val = 0;
> -
> - regmap_update_bits(mixer->engine.regs,
> - SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
> - SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
> + if (!was_enabled != !enable) {
> + val = enable ? SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN : 0;
>
> - if (!enable || zpos != old_zpos) {
> regmap_update_bits(mixer->engine.regs,
> - SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
> - SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
> - 0);
> + SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
> + SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
> + }
>
> - regmap_update_bits(mixer->engine.regs,
> + /*
> + * If this layer was enabled and is being disabled or if it is
> + * enabled and just changing zpos, clear the old route, if it is
> + * still configured to this layer in HW.
> + */
> + if ((was_enabled && !enable) || (enable && zpos != old_zpos)) {
> + /* get channel the pipe for old_zpos is routed to from the HW */
> + regmap_read(mixer->engine.regs,
> SUN8I_MIXER_BLEND_ROUTE(bld_base),
> - SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
> - 0);
> + &old_pipe_ch);
> + old_pipe_ch &= SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos);
> + old_pipe_ch >>= SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(old_zpos);
> +
> + /*
> + * Check that pipe for old_zpos is still routed to our layer,
> + * and clear/disable it if it is.
> + */
> +
> + if (old_pipe_ch == channel) {
> + DRM_DEBUG_DRIVER("chan=%d en=%d->%d zpos=%d->%d\n",
> + channel, was_enabled, enable, old_zpos, zpos);
> +
> + DRM_DEBUG_DRIVER(" disable pipe %d\n", old_zpos);
> +
> + regmap_update_bits(mixer->engine.regs,
> + SUN8I_MIXER_BLEND_ROUTE(bld_base),
> + SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
> + 0);
> +
> + regmap_update_bits(mixer->engine.regs,
> + SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
> + SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
> + 0);
> + }
> }
>
> - if (enable) {
> + /*
> + * If enabling this layer or changin zpos, set route to this layer.
> + */
> + if ((enable && !was_enabled) || (enable && zpos != old_zpos)) {
> + DRM_DEBUG_DRIVER("chan=%d en=%d->%d zpos=%d->%d\n",
> + channel, was_enabled, enable, old_zpos, zpos);
> +
> val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
>
> regmap_update_bits(mixer->engine.regs,
> @@ -63,6 +93,8 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
> SUN8I_MIXER_BLEND_ROUTE(bld_base),
> SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
> val);
> +
> + DRM_DEBUG_DRIVER(" enable pipe %d <- ch %d\n", zpos, channel);
> }
> }
>
> @@ -345,45 +377,43 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
> true, true);
> }
>
> -static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane,
> - struct drm_plane_state *old_state)
> +static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
> + struct drm_plane_state *old_state)
> {
> struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
> + unsigned int zpos = plane->state->normalized_zpos;
> unsigned int old_zpos = old_state->normalized_zpos;
> struct sun8i_mixer *mixer = layer->mixer;
> + bool was_enabled = old_state->crtc && old_state->visible;
> + bool enable = plane->state->crtc && plane->state->visible;
>
> - sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0,
> - old_zpos);
> + if (enable) {
> + sun8i_vi_layer_update_coord(mixer, layer->channel,
> + layer->overlay, plane, zpos);
> + sun8i_vi_layer_update_formats(mixer, layer->channel,
> + layer->overlay, plane);
> + sun8i_vi_layer_update_buffer(mixer, layer->channel,
> + layer->overlay, plane);
> + }
> +
> + sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay,
> + was_enabled, enable, zpos, old_zpos);
> }
>
> -static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
> - struct drm_plane_state *old_state)
> +void sun8i_vi_layer_plane_reset(struct drm_plane *plane)
> {
> struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
> - unsigned int zpos = plane->state->normalized_zpos;
> - unsigned int old_zpos = old_state->normalized_zpos;
> - struct sun8i_mixer *mixer = layer->mixer;
>
> - if (!plane->state->visible) {
> - sun8i_vi_layer_enable(mixer, layer->channel,
> - layer->overlay, false, 0, old_zpos);
> + drm_atomic_helper_plane_reset(plane);
> + if (!plane->state)
> return;
> - }
>
> - sun8i_vi_layer_update_coord(mixer, layer->channel,
> - layer->overlay, plane, zpos);
> - sun8i_vi_layer_update_formats(mixer, layer->channel,
> - layer->overlay, plane);
> - sun8i_vi_layer_update_buffer(mixer, layer->channel,
> - layer->overlay, plane);
> - sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay,
> - true, zpos, old_zpos);
> + plane->state->zpos = layer->channel;
> }
>
> static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
> .prepare_fb = drm_gem_fb_prepare_fb,
> .atomic_check = sun8i_vi_layer_atomic_check,
> - .atomic_disable = sun8i_vi_layer_atomic_disable,
> .atomic_update = sun8i_vi_layer_atomic_update,
> };
>
> @@ -392,7 +422,7 @@ static const struct drm_plane_funcs sun8i_vi_layer_funcs = {
> .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> .destroy = drm_plane_cleanup,
> .disable_plane = drm_atomic_helper_disable_plane,
> - .reset = drm_atomic_helper_plane_reset,
> + .reset = sun8i_vi_layer_plane_reset,
> .update_plane = drm_atomic_helper_update_plane,
> };
>
> --
> 2.23.0
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH V7 2/3] arm64/mm: Hold memory hotplug lock while walking for kernel page table dump
From: Balbir Singh @ 2019-09-15 2:35 UTC (permalink / raw)
To: Anshuman Khandual, linux-mm, linux-kernel, linux-arm-kernel, akpm,
catalin.marinas, will
Cc: mark.rutland, mhocko, david, ira.weiny, steve.capper, mgorman,
steven.price, broonie, cai, ard.biesheuvel, cpandya, arunks,
dan.j.williams, Robin.Murphy, logang, valentin.schneider,
suzuki.poulose, osalvador
In-Reply-To: <1567503958-25831-3-git-send-email-anshuman.khandual@arm.com>
On 3/9/19 7:45 pm, Anshuman Khandual wrote:
> The arm64 page table dump code can race with concurrent modification of the
> kernel page tables. When a leaf entries are modified concurrently, the dump
> code may log stale or inconsistent information for a VA range, but this is
> otherwise not harmful.
>
> When intermediate levels of table are freed, the dump code will continue to
> use memory which has been freed and potentially reallocated for another
> purpose. In such cases, the dump code may dereference bogus addresses,
> leading to a number of potential problems.
>
> Intermediate levels of table may by freed during memory hot-remove,
> which will be enabled by a subsequent patch. To avoid racing with
> this, take the memory hotplug lock when walking the kernel page table.
>
> Acked-by: David Hildenbrand <david@redhat.com>
> Acked-by: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
> ---
> arch/arm64/mm/ptdump_debugfs.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm64/mm/ptdump_debugfs.c b/arch/arm64/mm/ptdump_debugfs.c
> index 064163f25592..b5eebc8c4924 100644
> --- a/arch/arm64/mm/ptdump_debugfs.c
> +++ b/arch/arm64/mm/ptdump_debugfs.c
> @@ -1,5 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0
> #include <linux/debugfs.h>
> +#include <linux/memory_hotplug.h>
> #include <linux/seq_file.h>
>
> #include <asm/ptdump.h>
> @@ -7,7 +8,10 @@
> static int ptdump_show(struct seq_file *m, void *v)
> {
> struct ptdump_info *info = m->private;
> +
> + get_online_mems();
> ptdump_walk_pgd(m, info);
> + put_online_mems();
Looks sane, BTW, checking other arches they might have the same race.
Is there anything special about the arch?
Acked-by: Balbir Singh <bsingharora@gmail.com>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* RE: [PATCH RFC 11/14] arm64: Move the ASID allocator code in a separate file
From: Anup Patel @ 2019-09-15 5:03 UTC (permalink / raw)
To: Palmer Dabbelt, will@kernel.org
Cc: aou@eecs.berkeley.edu, Arnd Bergmann, julien.thierry@arm.com,
marc.zyngier@arm.com, catalin.marinas@arm.com,
suzuki.poulose@arm.com, Will Deacon, linux-kernel@vger.kernel.org,
iommu@lists.linux-foundation.org, rppt@linux.ibm.com,
Christoph Hellwig, Atish Patra, julien.grall@arm.com,
guoren@kernel.org, gary@garyguo.net, Paul Walmsley,
christoffer.dall@arm.com, james.morse@arm.com,
linux-riscv@lists.infradead.org, kvmarm@lists.cs.columbia.edu,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <mhng-166dcd4f-9483-4aab-a83a-914d70ddb5a4@palmer-si-x1e>
> -----Original Message-----
> From: linux-kernel-owner@vger.kernel.org <linux-kernel-
> owner@vger.kernel.org> On Behalf Of Palmer Dabbelt
> Sent: Saturday, September 14, 2019 7:31 PM
> To: will@kernel.org
> Cc: guoren@kernel.org; Will Deacon <will.deacon@arm.com>;
> julien.thierry@arm.com; aou@eecs.berkeley.edu; james.morse@arm.com;
> Arnd Bergmann <arnd@arndb.de>; suzuki.poulose@arm.com;
> marc.zyngier@arm.com; catalin.marinas@arm.com; Anup Patel
> <Anup.Patel@wdc.com>; linux-kernel@vger.kernel.org;
> rppt@linux.ibm.com; Christoph Hellwig <hch@infradead.org>; Atish Patra
> <Atish.Patra@wdc.com>; julien.grall@arm.com; gary@garyguo.net; Paul
> Walmsley <paul.walmsley@sifive.com>; christoffer.dall@arm.com; linux-
> riscv@lists.infradead.org; kvmarm@lists.cs.columbia.edu; linux-arm-
> kernel@lists.infradead.org; iommu@lists.linux-foundation.org
> Subject: Re: [PATCH RFC 11/14] arm64: Move the ASID allocator code in a
> separate file
>
> On Thu, 12 Sep 2019 07:02:56 PDT (-0700), will@kernel.org wrote:
> > On Sun, Sep 08, 2019 at 07:52:55AM +0800, Guo Ren wrote:
> >> On Mon, Jun 24, 2019 at 6:40 PM Will Deacon <will@kernel.org> wrote:
> >> > > I'll keep my system use the same ASID for SMP + IOMMU :P
> >> >
> >> > You will want a separate allocator for that:
> >> >
> >> > https://lkml.kernel.org/r/20190610184714.6786-2-jean-philippe.bruck
> >> > er@arm.com
> >>
> >> Yes, it is hard to maintain ASID between IOMMU and CPUMMU or
> >> different system, because it's difficult to synchronize the IO_ASID
> >> when the CPU ASID is rollover.
> >> But we could still use hardware broadcast TLB invalidation
> >> instruction to uniformly manage the ASID and IO_ASID, or OTHER_ASID in
> our IOMMU.
> >
> > That's probably a bad idea, because you'll likely stall execution on
> > the CPU until the IOTLB has completed invalidation. In the case of
> > ATS, I think an endpoint ATC is permitted to take over a minute to
> > respond. In reality, I suspect the worst you'll ever see would be in
> > the msec range, but that's still an unacceptable period of time to hold a
> CPU.
> >
> >> Welcome to join our disscusion:
> >> "Introduce an implementation of IOMMU in linux-riscv"
> >> 9 Sep 2019, 10:45 Jade-room-I&II (Corinthia Hotel Lisbon) RISC-V MC
> >
> > I attended this session, but it unfortunately raised many more
> > questions than it answered.
>
> Ya, we're a long way from figuring this out.
For everyone's reference, here is our first attempt at RISC-V ASID allocator:
http://archive.lwn.net:8080/linux-kernel/20190329045111.14040-1-anup.patel@wdc.com/T/#u
Regards,
Anup
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] ARM: dts: imx6dl: SolidRun: add phy node with 100Mb/s max-speed
From: Baruch Siach @ 2019-09-15 6:30 UTC (permalink / raw)
To: Andrew Lunn
Cc: Mark Rutland,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Fabio Estevam, Sascha Hauer, tinywrkb, Russell King, open list,
Rob Herring, NXP Linux Team, Pengutronix Kernel Team, Shawn Guo,
linux-arm-kernel
In-Reply-To: <20190910185033.GD9761@lunn.ch>
Hi Andrew,
On Tue, Sep 10 2019, Andrew Lunn wrote:
> On Tue, Sep 10, 2019 at 06:55:07PM +0300, tinywrkb wrote:
>> Cubox-i Solo/DualLite carrier board has 100Mb/s magnetics while the
>> Atheros AR8035 PHY on the MicroSoM v1.3 CPU module is a 1GbE PHY device.
>>
>> Since commit 5502b218e001 ("net: phy: use phy_resolve_aneg_linkmode in
>> genphy_read_status") ethernet is broken on Cubox-i Solo/DualLite devices.
>
> Hi Tinywrkb
>
> You emailed lots of people, but missed the PHY maintainers :-(
>
> Are you sure this is the patch which broken it? Did you do a git
> bisect.
Tinywrkb confirmed to me in private communication that revert of
5502b218e001 fixes Ethernet for him on effected system.
He also referred me to an old Cubox-i spec that lists 10/100 Ethernet
only for i.MX6 Solo/DualLite variants of Cubox-i. It turns out that
there was a plan to use a different 10/100 PHY for Solo/DualLite
SOMs. This plan never materialized. All SolidRun i.MX6 SOMs use the same
AR8035 PHY that supports 1Gb.
Commit 5502b218e001 might be triggering a hardware issue on the affected
Cubox-i. I could not reproduce the issue here with Cubox-i and a Dual
SOM variant running v5.3-rc8. I have no Solo/DualLite variant handy at
the moment.
baruch
--
http://baruch.siach.name/blog/ ~. .~ Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
- baruch@tkos.co.il - tel: +972.52.368.4656, http://www.tkos.co.il -
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [RFC PATCH V4 2/4] media: platform: Add Mediatek sensor interface driver KConfig
From: Louis Kuo @ 2019-09-15 6:50 UTC (permalink / raw)
To: hans.verkuil, laurent.pinchart+renesas, tfiga, keiichiw,
matthias.bgg, mchehab
Cc: devicetree, Sean.Cheng, Rynn.Wu, srv_heupstream, Jerry-ch.Chen,
jungo.lin, sj.huang, yuzhao, linux-mediatek, zwisler, louis.kuo,
christie.yu, frederic.chen, linux-arm-kernel, linux-media
In-Reply-To: <20190915065004.20257-1-louis.kuo@mediatek.com>
This patch adds KConfig for sensor interface driver. Sensor interface
driver
is a MIPI-CSI2 host driver, namely, a HW camera interface controller.
It support a widely adopted, simple, high-speed protocol primarily
intended
for point-to-point image and video transmission between cameras and host
devices.
Signed-off-by: Louis Kuo <louis.kuo@mediatek.com>
---
drivers/media/platform/mtk-isp/Kconfig | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 drivers/media/platform/mtk-isp/Kconfig
diff --git a/drivers/media/platform/mtk-isp/Kconfig b/drivers/media/platform/mtk-isp/Kconfig
new file mode 100644
index 000000000000..bc7fd01808b3
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/Kconfig
@@ -0,0 +1,17 @@
+config MTK_SENINF
+ bool "Mediatek mipi csi2 driver"
+ depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+ depends on MEDIA_CAMERA_SUPPORT
+ select V4L2_FWNODE
+
+ default n
+ help
+ This driver provides a mipi-csi2 host driver used as a
+ interface to connect camera with Mediatek's
+ MT8183 SOCs. It is able to handle multiple cameras
+ at the same time.
+
+ Choose y if you want to use Mediatek SoCs to create image
+ capture application such as video recording and still image
+ capture.
+
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [RFC PATCH V4 0/4] media: support Mediatek sensor interface driver
From: Louis Kuo @ 2019-09-15 6:50 UTC (permalink / raw)
To: hans.verkuil, laurent.pinchart+renesas, tfiga, keiichiw,
matthias.bgg, mchehab
Cc: devicetree, Sean.Cheng, Rynn.Wu, srv_heupstream, Jerry-ch.Chen,
jungo.lin, sj.huang, yuzhao, linux-mediatek, zwisler, louis.kuo,
christie.yu, frederic.chen, linux-arm-kernel, linux-media
Hello,
This is the RFC patch adding Sensor Inferface(seninf) driver on
Mediatek mt8183 SoC, which will be used in camera features on CrOS application.
It belongs to the first Mediatek's camera driver series based on V4L2 and media controller framework.
I posted the main part of the seninf driver as RFC to discuss first and would like some review comments
on the overall structure of the driver.
The driver is implemented with V4L2 framework.
1. Register as a V4L2 sub-device.
2. Only one entity with sink pads linked to camera sensors for choosing desired camera sensor by setup link
and with source pads linked to cam-io for routing different types of decoded packet datas to PASS1 driver
to generate sensor image frame and meta-data.
The overall file structure of the seninf driver is as following:
* mtk_seninf.c: Implement software and HW control flow of seninf driver.
* mtk_seninf_def.h: Define data structure and enumeration.
* mtk_seninf_reg.h: Define HW register R/W macros and HW register names.
[ V4: use recommended coding style, re-arrange and remove redundant code, change endpoint parsing method ]
media: platform: mtk-isp: Add Mediatek sensor interface driver
media: platform: Add Mediatek sensor interface driver KConfig
dt-bindings: mt8183: Add sensor interface dt-bindings
dts: arm64: mt8183: Add sensor interface nodes
.../bindings/media/mediatek-seninf.txt | 30 +
arch/arm64/boot/dts/mediatek/mt8183.dtsi | 14 +
drivers/media/platform/Makefile | 2 +
drivers/media/platform/mtk-isp/Kconfig | 17 +
drivers/media/platform/mtk-isp/Makefile | 3 +
.../media/platform/mtk-isp/isp_50/Makefile | 5 +
.../platform/mtk-isp/isp_50/seninf/Makefile | 6 +
.../mtk-isp/isp_50/seninf/mtk_seninf.c | 1011 +++++++++++++++++
.../mtk-isp/isp_50/seninf/mtk_seninf_def.h | 59 +
.../mtk-isp/isp_50/seninf/mtk_seninf_reg.h | 853 ++++++++++++++
10 files changed, 2000 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/mediatek-seninf.txt
create mode 100644 drivers/media/platform/mtk-isp/Kconfig
create mode 100644 drivers/media/platform/mtk-isp/Makefile
create mode 100644 drivers/media/platform/mtk-isp/isp_50/Makefile
create mode 100644 drivers/media/platform/mtk-isp/isp_50/seninf/Makefile
create mode 100644 drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf.c
create mode 100644 drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf_def.h
create mode 100644 drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf_reg.h
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [RFC PATCH V4 4/4] dts: arm64: mt8183: Add sensor interface nodes
From: Louis Kuo @ 2019-09-15 6:50 UTC (permalink / raw)
To: hans.verkuil, laurent.pinchart+renesas, tfiga, keiichiw,
matthias.bgg, mchehab
Cc: devicetree, Sean.Cheng, Rynn.Wu, srv_heupstream, Jerry-ch.Chen,
jungo.lin, sj.huang, yuzhao, linux-mediatek, zwisler, louis.kuo,
christie.yu, frederic.chen, linux-arm-kernel, linux-media
In-Reply-To: <20190915065004.20257-1-louis.kuo@mediatek.com>
Add nodes for Mediatek's sensor interface device. Sensor interface module
embedded in Mediatek SOCs, works as a HW camera interface controller
intended for image and data transmission between cameras and host devices.
Signed-off-by: Louis Kuo <louis.kuo@mediatek.com>
---
arch/arm64/boot/dts/mediatek/mt8183.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index 66aaa07f6cec..f1d081b99867 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -506,4 +506,18 @@
#clock-cells = <1>;
};
};
+
+ seninf: seninf@1a040000 {
+ compatible = "mediatek,mt8183-seninf";
+ reg = <0 0x1a040000 0 0x8000>,
+ <0 0x11C80000 0 0x6000>;
+ reg-names = "base_reg", "rx_reg";
+ interrupts = <GIC_SPI 251 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&scpsys MT8183_POWER_DOMAIN_CAM>;
+ clocks = <&camsys CLK_CAM_SENINF>,
+ <&topckgen CLK_TOP_MUX_SENINF>;
+ clock-names = "CLK_CAM_SENINF", "CLK_TOP_MUX_SENINF";
+ status = "disabled";
+ };
+ };
};
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [RFC PATCH V4 3/4] dt-bindings: mt8183: Add sensor interface dt-bindings
From: Louis Kuo @ 2019-09-15 6:50 UTC (permalink / raw)
To: hans.verkuil, laurent.pinchart+renesas, tfiga, keiichiw,
matthias.bgg, mchehab
Cc: devicetree, Sean.Cheng, Rynn.Wu, srv_heupstream, Jerry-ch.Chen,
jungo.lin, sj.huang, yuzhao, linux-mediatek, zwisler, louis.kuo,
christie.yu, frederic.chen, linux-arm-kernel, linux-media
In-Reply-To: <20190915065004.20257-1-louis.kuo@mediatek.com>
This patch adds the DT binding documentation for the sensor interface
module in Mediatek SoCs.
Signed-off-by: Louis Kuo <louis.kuo@mediatek.com>
---
.../bindings/media/mediatek-seninf.txt | 30 +++++++++++++++++++
1 file changed, 30 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/mediatek-seninf.txt
diff --git a/Documentation/devicetree/bindings/media/mediatek-seninf.txt b/Documentation/devicetree/bindings/media/mediatek-seninf.txt
new file mode 100644
index 000000000000..bf2eb801cb47
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/mediatek-seninf.txt
@@ -0,0 +1,30 @@
+* Mediatek seninf MIPI-CSI2 host driver
+
+Seninf MIPI-CSI2 host driver is a HW camera interface controller. It support a widely adopted,
+simple, high-speed protocol primarily intended for point-to-point image and video
+transmission between cameras and host devices.
+
+Required properties:
+ - compatible: "mediatek,mt8183-seninf"
+ - reg: Must contain an entry for each entry in reg-names.
+ - reg-names: Must include the following entries:
+ "base_reg": seninf registers base
+ "rx_reg": Rx analog registers base
+ - interrupts: interrupt number to the cpu.
+ - clocks : clock name from clock manager
+ - clock-names: must be CLK_CAM_SENINF and CLK_TOP_MUX_SENINF.
+ It is the clocks of seninf
+
+Example:
+ seninf: seninf@1a040000 {
+ compatible = "mediatek,mt8183-seninf";
+ reg = <0 0x1a040000 0 0x8000>,
+ <0 0x11C80000 0 0x6000>;
+ reg-names = "base_reg", "rx_reg";
+ interrupts = <GIC_SPI 251 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&scpsys MT8183_POWER_DOMAIN_CAM>;
+ clocks = <&camsys CLK_CAM_SENINF>,
+ <&topckgen CLK_TOP_MUX_SENINF>;
+ clock-names = "CLK_CAM_SENINF", "CLK_TOP_MUX_SENINF";
+ }
+
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [RFC PATCH V4 1/4] media: platform: mtk-isp: Add Mediatek sensor interface driver
From: Louis Kuo @ 2019-09-15 6:50 UTC (permalink / raw)
To: hans.verkuil, laurent.pinchart+renesas, tfiga, keiichiw,
matthias.bgg, mchehab
Cc: devicetree, Sean.Cheng, Rynn.Wu, srv_heupstream, Jerry-ch.Chen,
jungo.lin, sj.huang, yuzhao, linux-mediatek, zwisler, louis.kuo,
christie.yu, frederic.chen, linux-arm-kernel, linux-media
In-Reply-To: <20190915065004.20257-1-louis.kuo@mediatek.com>
This patch adds Mediat:ek's sensor interface driver. Sensor interface
driver
is a MIPI-CSI2 host driver, namely, a HW camera interface controller.
It support a widely adopted, simple, high-speed protocol primarily
intended
for point-to-point image and video transmission between cameras and host
devices.
The mtk-isp directory will contain drivers for multiple IP blocks found in
Mediatek ISP system. It will include ISP Pass 1 driver, sensor interface
driver, DIP driver and face detection driver.
Signed-off-by: Louis Kuo <louis.kuo@mediatek.com>
---
drivers/media/platform/Makefile | 2 +
drivers/media/platform/mtk-isp/Makefile | 3 +
.../media/platform/mtk-isp/isp_50/Makefile | 5 +
.../platform/mtk-isp/isp_50/seninf/Makefile | 6 +
.../mtk-isp/isp_50/seninf/mtk_seninf.c | 1011 +++++++++++++++++
.../mtk-isp/isp_50/seninf/mtk_seninf_def.h | 59 +
.../mtk-isp/isp_50/seninf/mtk_seninf_reg.h | 853 ++++++++++++++
7 files changed, 1939 insertions(+)
create mode 100644 drivers/media/platform/mtk-isp/Makefile
create mode 100644 drivers/media/platform/mtk-isp/isp_50/Makefile
create mode 100644 drivers/media/platform/mtk-isp/isp_50/seninf/Makefile
create mode 100644 drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf.c
create mode 100644 drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf_def.h
create mode 100644 drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf_reg.h
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 7cbbd925124c..b0f4543f2f86 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -73,6 +73,8 @@ obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip/rga/
obj-y += omap/
+obj-y += mtk-isp/
+
obj-$(CONFIG_VIDEO_AM437X_VPFE) += am437x/
obj-$(CONFIG_VIDEO_XILINX) += xilinx/
diff --git a/drivers/media/platform/mtk-isp/Makefile b/drivers/media/platform/mtk-isp/Makefile
new file mode 100644
index 000000000000..c17fb3fc3340
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += isp_50/
diff --git a/drivers/media/platform/mtk-isp/isp_50/Makefile b/drivers/media/platform/mtk-isp/isp_50/Makefile
new file mode 100644
index 000000000000..8b4a792328e5
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/isp_50/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+ifeq ($(CONFIG_MTK_SENINF),y)
+obj-y += seninf/
+endif
diff --git a/drivers/media/platform/mtk-isp/isp_50/seninf/Makefile b/drivers/media/platform/mtk-isp/isp_50/seninf/Makefile
new file mode 100644
index 000000000000..bf193feb0ce9
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/isp_50/seninf/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+MODULE = mtk_seninf
+LIB_FILES = mtk_seninf
+
+obj-$(CONFIG_MTK_SENINF) += mtk_seninf.o
diff --git a/drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf.c b/drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf.c
new file mode 100644
index 000000000000..3253510cf7fd
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf.c
@@ -0,0 +1,1011 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/of_graph.h>
+#include <linux/of_irq.h>
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#endif
+#include <linux/videodev2.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-async.h>
+#include "mtk_seninf_reg.h"
+#include "mtk_seninf_def.h"
+
+static inline int is_4d1c(unsigned int port)
+{
+ return (port < CFG_CSI_PORT_0A);
+}
+
+static inline int is_cdphy_combo(unsigned int port)
+{
+ return (port == CFG_CSI_PORT_0A ||
+ port == CFG_CSI_PORT_0B ||
+ port == CFG_CSI_PORT_0);
+}
+
+struct sensor_cfg {
+ unsigned char clock_lane;
+ unsigned short num_data_lanes;
+};
+
+struct mtk_seninf {
+ struct v4l2_subdev subdev;
+ struct v4l2_async_notifier notifier;
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_subdev_format fmt[NUM_PADS];
+ struct device *dev;
+ struct media_pad pads[NUM_PADS];
+ struct sensor_cfg sensor[NUM_SENSORS];
+ unsigned int num_clks;
+ struct clk_bulk_data *clks;
+ void __iomem *base_reg;
+ void __iomem *rx_reg;
+ unsigned char *csi2_rx[CFG_CSI_PORT_MAX_NUM];
+ unsigned int port;
+ unsigned int mux_sel;
+};
+
+static unsigned int mtk_seninf_get_dpcm(struct mtk_seninf *priv)
+{
+ int dpcm;
+
+ switch (priv->fmt[priv->port].format.code) {
+ case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
+ case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
+ case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
+ case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
+ dpcm = 0x2a;
+ break;
+ default:
+ dpcm = 0;
+ break;
+ }
+
+ return dpcm;
+}
+
+static unsigned int mtk_seninf_map_fmt(struct mtk_seninf *priv)
+{
+ int fmtidx = 0;
+
+ switch (priv->fmt[priv->port].format.code) {
+ case MEDIA_BUS_FMT_SBGGR8_1X8:
+ case MEDIA_BUS_FMT_SGBRG8_1X8:
+ case MEDIA_BUS_FMT_SGRBG8_1X8:
+ case MEDIA_BUS_FMT_SRGGB8_1X8:
+ fmtidx = 0;
+ break;
+ case MEDIA_BUS_FMT_SGRBG10_1X10:
+ case MEDIA_BUS_FMT_SRGGB10_1X10:
+ case MEDIA_BUS_FMT_SBGGR10_1X10:
+ case MEDIA_BUS_FMT_SGBRG10_1X10:
+ fmtidx = 1;
+ break;
+ case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
+ case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
+ case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
+ case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
+ fmtidx = 0;
+ break;
+ case MEDIA_BUS_FMT_SBGGR12_1X12:
+ case MEDIA_BUS_FMT_SGBRG12_1X12:
+ case MEDIA_BUS_FMT_SGRBG12_1X12:
+ case MEDIA_BUS_FMT_SRGGB12_1X12:
+ fmtidx = 2;
+ break;
+ case MEDIA_BUS_FMT_UYVY8_1X16:
+ case MEDIA_BUS_FMT_VYUY8_1X16:
+ case MEDIA_BUS_FMT_YUYV8_1X16:
+ case MEDIA_BUS_FMT_YVYU8_1X16:
+ fmtidx = 3;
+ break;
+ case MEDIA_BUS_FMT_JPEG_1X8:
+ case MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8:
+ fmtidx = 7;
+ break;
+ }
+
+ return fmtidx;
+}
+
+static u32 mtk_seninf_csi_port_to_seninf(u32 port)
+{
+ static const u32 port_to_seninf[] = {
+ [CFG_CSI_PORT_0] = SENINF_1,
+ [CFG_CSI_PORT_1] = SENINF_3,
+ [CFG_CSI_PORT_2] = SENINF_5,
+ [CFG_CSI_PORT_0A] = SENINF_1,
+ [CFG_CSI_PORT_0B] = SENINF_2,
+ };
+ if (WARN_ON(port >= ARRAY_SIZE(port_to_seninf)))
+ return -EINVAL;
+
+ return port_to_seninf[port];
+}
+
+static void mtk_seninf_set_mux(struct mtk_seninf *priv,
+ int seninf)
+{
+ unsigned int mux = priv->mux_sel;
+ void *pseninf_top = priv->base_reg;
+ void *pseninf = priv->base_reg + 0x1000 * mux;
+ unsigned int val;
+ unsigned int pix_sel_ext;
+ unsigned int pix_sel;
+ unsigned int hs_pol = 0;
+ unsigned int vs_pol = 0;
+ unsigned int pixel_mode = ONE_PIXEL_MODE;
+ unsigned int input_data_type;
+
+ /* Enable mux */
+ writel(0x7fffffff & readl(pseninf + SENINF1_MUX_CTRL) |
+ 0x80000000, pseninf + SENINF1_MUX_CTRL);
+
+ input_data_type = mtk_seninf_map_fmt(priv);
+ /* Set mux ctrl */
+ writel(0xffff0fff & readl(pseninf + SENINF1_MUX_CTRL) |
+ 0x8000, pseninf + SENINF1_MUX_CTRL);
+
+ writel(0xfffffffc & readl(pseninf + SENINF1_MUX_CTRL_EXT) |
+ 0x1, pseninf + SENINF1_MUX_CTRL_EXT);
+
+ switch (pixel_mode) {
+ case 1: /* 2 Pixel */
+ pix_sel_ext = 0;
+ pix_sel = 1 << 8;
+ break;
+ case 2: /* 4 Pixel */
+ pix_sel_ext = 1 << 4;
+ pix_sel = 0;
+ break;
+ default: /* 1 Pixel */
+ pix_sel_ext = 0;
+ pix_sel = 0;
+ break;
+ }
+
+ writel(0xffffffef & readl(pseninf + SENINF1_MUX_CTRL_EXT) |
+ pix_sel_ext, pseninf + SENINF1_MUX_CTRL_EXT);
+ writel(0xfffffeff & readl(pseninf + SENINF1_MUX_CTRL) |
+ pix_sel, pseninf + SENINF1_MUX_CTRL);
+
+ val = 0;
+ if (input_data_type != JPEG_FMT)
+ val = 0x20000000;
+
+ writel(0xcfffffff & readl(pseninf + SENINF1_MUX_CTRL) |
+ val, pseninf + SENINF1_MUX_CTRL);
+
+ if (input_data_type != JPEG_FMT)
+ writel(0xf000ffff & readl(pseninf + SENINF1_MUX_CTRL) |
+ 0x6df0000, pseninf + SENINF1_MUX_CTRL);
+ else
+ writel(0xf000ffff & readl(pseninf + SENINF1_MUX_CTRL) |
+ 0x61e0000, pseninf + SENINF1_MUX_CTRL);
+
+ writel((0xfffff9ff) & readl(pseninf + SENINF1_MUX_CTRL) |
+ (hs_pol << 10) | (vs_pol << 9), pseninf + SENINF1_MUX_CTRL);
+
+ val = (readl(pseninf + SENINF1_MUX_CTRL) | 0x3) & 0xFFFFFFFC;
+ writel(val, pseninf + SENINF1_MUX_CTRL);
+
+ /* Set top mux */
+ val = (readl(pseninf_top + SENINF_TOP_MUX_CTRL) &
+ (~(0xF << (mux * 4)))) | ((seninf & 0xF) << (mux * 4));
+ writel(val, pseninf + SENINF_TOP_MUX_CTRL);
+}
+
+static void mtk_seninf_set_dphy(struct mtk_seninf *priv, unsigned int seninf)
+{
+ void *pmipi_rx_base = priv->csi2_rx[CFG_CSI_PORT_0];
+ unsigned int port = priv->port;
+ void *pmipi_rx = priv->csi2_rx[port];
+ void *pmipi_rx_conf = priv->base_reg + 0x1000 * seninf;
+
+ /* Set analog phy mode to DPHY */
+ if (is_cdphy_combo(port))
+ writel(0xfffffffe & readl(pmipi_rx + MIPI_RX_ANA00_CSI0A)
+ , pmipi_rx + MIPI_RX_ANA00_CSI0A);
+
+ /* 4D1C: MIPIRX_ANALOG_A_BASE = 0x00001A40 */
+ if (is_4d1c(port))
+ writel((0xffffe49f & readl(pmipi_rx + MIPI_RX_ANA00_CSI0A)) |
+ 0x1a40, pmipi_rx + MIPI_RX_ANA00_CSI0A);
+ else /* MIPIRX_ANALOG_BASE = 0x100 */
+ writel((0xffffe49f & readl(pmipi_rx + MIPI_RX_ANA00_CSI0A)) |
+ 0x100, pmipi_rx + MIPI_RX_ANA00_CSI0A);
+
+ if (is_cdphy_combo(port))
+ writel(0xfffffffe & readl(pmipi_rx + MIPI_RX_ANA00_CSI0B)
+ , pmipi_rx + MIPI_RX_ANA00_CSI0B);
+
+ /* Only 4d1c need set CSIB: MIPIRX_ANALOG_B_BASE = 0x00001240 */
+ if (is_4d1c(port))
+ writel(0xffffe49f & readl(pmipi_rx + MIPI_RX_ANA00_CSI0B) |
+ 0x1240, pmipi_rx + MIPI_RX_ANA00_CSI0B);
+ else /* MIPIRX_ANALOG_BASE = 0x100 */
+ writel(0xffffe49f & readl(pmipi_rx + MIPI_RX_ANA00_CSI0B) |
+ 0x100, pmipi_rx + MIPI_RX_ANA00_CSI0B);
+
+ /* Byte clock invert */
+ writel(0xfffffff8 & readl(pmipi_rx + MIPI_RX_ANAA8_CSI0A) |
+ 0x7, pmipi_rx + MIPI_RX_ANAA8_CSI0A);
+ if (is_4d1c(port))
+ writel(0xfffffff8 & readl(pmipi_rx + MIPI_RX_ANAA8_CSI0B) |
+ 0x7, pmipi_rx + MIPI_RX_ANAA8_CSI0B);
+
+ /* Start ANA EQ tuning */
+ if (is_cdphy_combo(port)) {
+ writel(0xffffff0f & readl(pmipi_rx + MIPI_RX_ANA18_CSI0A) |
+ 0x50, pmipi_rx + MIPI_RX_ANA18_CSI0A);
+ writel(0xff0fffff & readl(pmipi_rx + MIPI_RX_ANA1C_CSI0A) |
+ 0x500000, pmipi_rx + MIPI_RX_ANA1C_CSI0A);
+ writel(0xff0fffff & readl(pmipi_rx + MIPI_RX_ANA20_CSI0A) |
+ 0x500000, pmipi_rx + MIPI_RX_ANA20_CSI0A);
+ if (is_4d1c(port)) { /* 4d1c */
+ writel(0xffffff0f &
+ readl(pmipi_rx + MIPI_RX_ANA18_CSI0B) |
+ 0x50, pmipi_rx + MIPI_RX_ANA18_CSI0B);
+ writel(0xff0fffff &
+ readl(pmipi_rx + MIPI_RX_ANA1C_CSI0B) |
+ 0x500000, pmipi_rx + MIPI_RX_ANA1C_CSI0B);
+ writel(0xff0fffff &
+ readl(pmipi_rx + MIPI_RX_ANA20_CSI0B) |
+ 0x500000, pmipi_rx + MIPI_RX_ANA20_CSI0B);
+ }
+ } else {
+ writel(0xff0fff0f & readl(pmipi_rx + MIPI_RX_ANA18_CSI1A) |
+ 0x500050, pmipi_rx + MIPI_RX_ANA18_CSI1A);
+ writel(0xffffff0f & readl(pmipi_rx + MIPI_RX_ANA1C_CSI1A) |
+ 0x50, pmipi_rx + MIPI_RX_ANA1C_CSI1A);
+
+ if (is_4d1c(port)) { /* 4d1c */
+ writel(0xff0fff0f &
+ readl(pmipi_rx + MIPI_RX_ANA18_CSI1B) |
+ 0x500050, pmipi_rx + MIPI_RX_ANA18_CSI1B);
+ writel(0xffffff0f &
+ readl(pmipi_rx + MIPI_RX_ANA1C_CSI1B) |
+ 0x50, pmipi_rx + MIPI_RX_ANA1C_CSI1B);
+ }
+ }
+
+ /* End ANA EQ tuning */
+ writel(0x90, pmipi_rx_base + MIPI_RX_ANA40_CSI0A);
+ writel(0xffffff & readl(pmipi_rx + MIPI_RX_ANA24_CSI0A) |
+ 0x40000000, pmipi_rx + MIPI_RX_ANA24_CSI0A);
+ if (is_4d1c(port))
+ writel(0xffffff & readl(pmipi_rx + MIPI_RX_ANA24_CSI0B) |
+ 0x40000000, pmipi_rx + MIPI_RX_ANA24_CSI0B);
+ writel(0xfffcffff & readl(pmipi_rx + MIPI_RX_WRAPPER80_CSI0A)
+ , pmipi_rx + MIPI_RX_WRAPPER80_CSI0A);
+ if (is_4d1c(port))
+ writel(0xfffcffff & readl(pmipi_rx + MIPI_RX_WRAPPER80_CSI0B)
+ , pmipi_rx + MIPI_RX_WRAPPER80_CSI0B);
+ /* ANA power on */
+ writel(0xfffffff7 & readl(pmipi_rx + MIPI_RX_ANA00_CSI0A) |
+ 0x8, pmipi_rx + MIPI_RX_ANA00_CSI0A);
+ if (is_4d1c(port))
+ writel(0xfffffff7 & readl(pmipi_rx + MIPI_RX_ANA00_CSI0B) |
+ 0x8, pmipi_rx + MIPI_RX_ANA00_CSI0B);
+
+ usleep_range(20, 40);
+ writel(0xfffffff7 & readl(pmipi_rx + MIPI_RX_ANA00_CSI0A) |
+ 0x8, pmipi_rx + MIPI_RX_ANA00_CSI0A);
+ if (is_4d1c(port))
+ writel(0xfffffffb & readl(pmipi_rx + MIPI_RX_ANA00_CSI0B) |
+ 0x4, pmipi_rx + MIPI_RX_ANA00_CSI0B);
+
+ udelay(1);
+ /* 4d1c: MIPIRX_CONFIG_CSI_BASE = 0xC9000000; */
+ if (is_4d1c(port)) {
+ writel(0xffffff &
+ readl(pmipi_rx_conf + MIPI_RX_CON24_CSI0) |
+ 0xc9000000, pmipi_rx_conf + MIPI_RX_CON24_CSI0);
+ } else { /* 2d1c: MIPIRX_CONFIG_CSI_BASE = 0xE4000000; */
+ writel(0xffffff &
+ readl(pmipi_rx_conf + MIPI_RX_CON24_CSI0) |
+ 0xe4000000, pmipi_rx_conf + MIPI_RX_CON24_CSI0);
+ }
+}
+
+static void mtk_seninf_set_csi_mipi(struct mtk_seninf *priv,
+ unsigned int seninf)
+{
+ void *seninf_base = priv->base_reg;
+ void *pseninf = priv->base_reg + 0x1000 * seninf;
+ unsigned int dpcm = mtk_seninf_get_dpcm(priv);
+ unsigned int data_lane_num = priv->sensor[priv->port].num_data_lanes;
+ unsigned int cal_sel;
+ unsigned int data_header_order = 1;
+ unsigned int pad_sel = PAD_10BIT;
+ unsigned int val = 0;
+
+ dev_dbg(priv->dev, "IS_4D1C %d port %d\n",
+ is_4d1c(priv->port), priv->port);
+
+ switch (priv->port) {
+ case CFG_CSI_PORT_1:
+ cal_sel = 1;
+ writel(0x7ffff8fe & readl(seninf_base +
+ SENINF_TOP_PHY_SENINF_CTL_CSI1) | 0x80000200
+ , seninf_base + SENINF_TOP_PHY_SENINF_CTL_CSI1);
+ break;
+ case CFG_CSI_PORT_2:
+ cal_sel = 2;
+ writel(0x7ffff8fe & readl(seninf_base +
+ SENINF_TOP_PHY_SENINF_CTL_CSI2) | 0x80000200
+ , seninf_base + SENINF_TOP_PHY_SENINF_CTL_CSI2);
+ break;
+ case CFG_CSI_PORT_0:
+ cal_sel = 0;
+ writel(0x7ffff8fe & readl(seninf_base +
+ SENINF_TOP_PHY_SENINF_CTL_CSI0) | 0x80000200
+ , seninf_base + SENINF_TOP_PHY_SENINF_CTL_CSI0);
+ break;
+ case CFG_CSI_PORT_0A:
+ case CFG_CSI_PORT_0B:
+ cal_sel = 0;
+ writel(0x7fffc8fe & readl(seninf_base +
+ SENINF_TOP_PHY_SENINF_CTL_CSI0) | 0x80001100
+ , seninf_base + SENINF_TOP_PHY_SENINF_CTL_CSI0);
+ break;
+ }
+
+ /* First Enable Sensor interface and select pad (0x1a04_0200) */
+ writel(readl(pseninf + SENINF1_CTRL) | 0x1
+ , pseninf + SENINF1_CTRL);
+ writel(0x8fffffff & readl(pseninf + SENINF1_CTRL) |
+ (pad_sel << 28), pseninf + SENINF1_CTRL);
+ writel(0xffff0fff & readl(pseninf + SENINF1_CTRL)
+ , pseninf + SENINF1_CTRL);
+ writel(0xffffff9f & readl(pseninf + SENINF1_CTRL_EXT) |
+ 0x40, pseninf + SENINF1_CTRL_EXT);
+
+ mtk_seninf_set_dphy(priv, seninf);
+
+ /* DPCM Enable */
+ val = 1 << ((dpcm == 0x2a) ? 15 : ((dpcm & 0xF) + 7));
+ writel(val, pseninf + SENINF1_CSI2_DPCM);
+
+ /* Settle delay */
+ writel(0xffff00ff & readl(pseninf + SENINF1_CSI2_LNRD_TIMING) |
+ (SENINF_SETTLE_DELAY << 8), pseninf + SENINF1_CSI2_LNRD_TIMING);
+ /* CSI2 control */
+ val = readl(pseninf + SENINF1_CSI2_CTL) | (data_header_order << 16) |
+ 0x10 | ((1 << data_lane_num) - 1);
+ writel(val, pseninf + SENINF1_CSI2_CTL);
+ writel(0xfffff3f8 & readl(pseninf + SENINF1_CSI2_RESYNC_MERGE_CTL) |
+ 0x3, pseninf + SENINF1_CSI2_RESYNC_MERGE_CTL);
+ writel(0xfffff800 & readl(pseninf + SENINF1_CSI2_MODE)
+ , pseninf + SENINF1_CSI2_MODE);
+ writel(0x1dff00, pseninf + SENINF1_CSI2_DPHY_SYNC);
+ writel(0xfffffffe & readl(pseninf + SENINF1_CSI2_SPARE0)
+ , pseninf + SENINF1_CSI2_SPARE0);
+ writel(0xf5ffff7f & readl(pseninf + SENINF1_CSI2_CTL) |
+ 0x2000000, pseninf + SENINF1_CSI2_CTL);
+ writel(0xffffff00 & readl(pseninf + SENINF1_CSI2_HS_TRAIL) |
+ SENINF_HS_TRAIL_PARAMETER, pseninf + SENINF1_CSI2_HS_TRAIL);
+
+ /* Set debug port to output packet number */
+ writel(0x8000001A, pseninf + SENINF1_CSI2_DGB_SEL);
+ /* Enable CSI2 IRQ mask */
+ /* Turn on all interrupt */
+ writel(0xffffffff, pseninf + SENINF1_CSI2_INT_EN);
+ /* Write clear CSI2 IRQ */
+ writel(0xffffffff, pseninf + SENINF1_CSI2_INT_STATUS);
+ /* Enable CSI2 Extend IRQ mask */
+ /* Turn on all interrupt */
+ writel(0x0000001f, pseninf + SENINF1_CSI2_INT_EN_EXT);
+ writel(0xffffff7f & readl(pseninf + SENINF1_CTRL) |
+ 0x80, pseninf + SENINF1_CTRL);
+
+ udelay(1);
+ writel(0xffffff7f & readl(pseninf + SENINF1_CTRL)
+ , pseninf + SENINF1_CTRL);
+}
+
+static int mtk_seninf_power_on(struct mtk_seninf *priv)
+{
+ void *pseninf = priv->base_reg;
+ struct device *dev = priv->dev;
+ int seninf;
+ int ret;
+
+ seninf = mtk_seninf_csi_port_to_seninf(priv->port);
+ if (seninf < 0) {
+ dev_err(dev, "seninf port mapping fail\n");
+ return -EINVAL;
+ }
+
+ ret = pm_runtime_get_sync(priv->dev);
+ if (ret < 0) {
+ dev_err(priv->dev, "Failed to pm_runtime_get_sync: %d\n", ret);
+ pm_runtime_put(priv->dev);
+ return ret;
+ }
+
+ /* Configure timestamp */
+ writel(readl(pseninf + SENINF1_CTRL) | 0x1
+ , pseninf + SENINF1_CTRL);
+ writel(0xffffffbfU & readl(pseninf + SENINF1_CTRL_EXT) |
+ 0x40, pseninf + SENINF1_CTRL_EXT);
+ writel(SENINF_TIMESTAMP_STEP, pseninf + SENINF_TG1_TM_STP);
+
+ mtk_seninf_set_csi_mipi(priv, (unsigned int)seninf);
+
+ mtk_seninf_set_mux(priv, (unsigned int)seninf);
+
+ writel(0x0, pseninf + SENINF_TOP_CAM_MUX_CTRL);
+
+ return 0;
+}
+
+static void mtk_seninf_power_off(struct mtk_seninf *priv)
+{
+ void *pmipi_rx = priv->csi2_rx[priv->port];
+ unsigned int seninf = mtk_seninf_csi_port_to_seninf(priv->port);
+ void *pseninf = priv->base_reg + 0x1000 * seninf;
+
+ /* Disable CSI2(2.5G) first */
+ writel(readl(pseninf + SENINF1_CSI2_CTL) & 0xFFFFFFE0
+ , pseninf + SENINF1_CSI2_CTL);
+ /* Disable mipi BG */
+ switch (priv->port) {
+ case CFG_CSI_PORT_0A:
+ writel(0xfffffff3 & readl(pmipi_rx + MIPI_RX_ANA00_CSI0A)
+ , pmipi_rx + MIPI_RX_ANA00_CSI0A);
+ break;
+ case CFG_CSI_PORT_0B:
+ writel(0xfffffff3 & readl(pmipi_rx + MIPI_RX_ANA00_CSI0B)
+ , pmipi_rx + MIPI_RX_ANA00_CSI0B);
+ break;
+ default:
+ writel(0xfffffff3 & readl(pmipi_rx + MIPI_RX_ANA00_CSI0A)
+ , pmipi_rx + MIPI_RX_ANA00_CSI0A);
+ writel(0xfffffff3 & readl(pmipi_rx + MIPI_RX_ANA00_CSI0B)
+ , pmipi_rx + MIPI_RX_ANA00_CSI0B);
+ break;
+ }
+
+ pm_runtime_put(priv->dev);
+}
+
+static const struct v4l2_mbus_framefmt mtk_seninf_default_fmt = {
+ .code = MEDIA_BUS_FMT_SBGGR10_1X10,
+ .width = DEFAULT_WIDTH,
+ .height = DEFAULT_HEIGHT,
+ .field = V4L2_FIELD_NONE,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .xfer_func = V4L2_XFER_FUNC_DEFAULT,
+ .ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT,
+ .quantization = V4L2_QUANTIZATION_DEFAULT,
+};
+
+static void init_fmt(struct mtk_seninf *priv)
+{
+ unsigned int i;
+
+ for (i = 0; i < NUM_PADS; i++)
+ priv->fmt[i].format = mtk_seninf_default_fmt;
+}
+
+static int seninf_init_cfg(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg)
+{
+ struct v4l2_mbus_framefmt *mf;
+ unsigned int i;
+
+ for (i = 0; i < sd->entity.num_pads; i++) {
+ mf = v4l2_subdev_get_try_format(sd, cfg, i);
+ *mf = mtk_seninf_default_fmt;
+ }
+
+ return 0;
+}
+
+static int seninf_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *fmt)
+{
+ struct mtk_seninf *priv = container_of(sd, struct mtk_seninf, subdev);
+
+ if (fmt->format.code == ~0U || fmt->format.code == 0)
+ fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
+ } else {
+ priv->fmt[fmt->pad].pad = fmt->pad;
+ priv->fmt[fmt->pad].format.code = fmt->format.code;
+ priv->fmt[fmt->pad].format.width = fmt->format.width;
+ priv->fmt[fmt->pad].format.height = fmt->format.height;
+ }
+
+ return 0;
+}
+
+static int seninf_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *fmt)
+{
+ struct mtk_seninf *priv = container_of(sd, struct mtk_seninf, subdev);
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
+ } else {
+ fmt->format.code = priv->fmt[fmt->pad].format.code;
+ fmt->format.width = priv->fmt[fmt->pad].format.width;
+ fmt->format.height = priv->fmt[fmt->pad].format.height;
+ fmt->format.field = priv->fmt[fmt->pad].format.field;
+ fmt->format.colorspace = priv->fmt[fmt->pad].format.colorspace;
+ fmt->format.xfer_func = priv->fmt[fmt->pad].format.xfer_func;
+ fmt->format.ycbcr_enc = priv->fmt[fmt->pad].format.ycbcr_enc;
+ fmt->format.quantization =
+ priv->fmt[fmt->pad].format.quantization;
+ }
+
+ return 0;
+}
+
+static int seninf_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ struct mtk_seninf *priv = container_of(sd, struct mtk_seninf, subdev);
+
+ if (code->index >= NUM_PADS)
+ return -EINVAL;
+ code->code = priv->fmt[code->index].format.code;
+
+ return 0;
+}
+
+static int seninf_s_stream(struct v4l2_subdev *sd, int on)
+{
+ struct mtk_seninf *priv = container_of(sd, struct mtk_seninf, subdev);
+ int ret = 0;
+
+ if (on)
+ ret = mtk_seninf_power_on(priv);
+ else
+ mtk_seninf_power_off(priv);
+
+ return ret;
+};
+
+static const struct v4l2_subdev_pad_ops seninf_subdev_pad_ops = {
+ .init_cfg = seninf_init_cfg,
+ .set_fmt = seninf_set_fmt,
+ .get_fmt = seninf_get_fmt,
+ .enum_mbus_code = seninf_enum_mbus_code,
+};
+
+static const struct v4l2_subdev_video_ops seninf_subdev_video_ops = {
+ .s_stream = seninf_s_stream,
+};
+
+static struct v4l2_subdev_core_ops seninf_subdev_core_ops = {
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static struct v4l2_subdev_ops seninf_subdev_ops = {
+ .core = &seninf_subdev_core_ops,
+ .video = &seninf_subdev_video_ops,
+ .pad = &seninf_subdev_pad_ops,
+};
+
+static int seninf_link_setup(struct media_entity *entity,
+ const struct media_pad *local,
+ const struct media_pad *remote, u32 flags)
+{
+ struct v4l2_subdev *sd;
+ struct mtk_seninf *priv;
+ struct device *dev;
+
+ sd = media_entity_to_v4l2_subdev(entity);
+ priv = v4l2_get_subdevdata(sd);
+ dev = priv->dev;
+ dev_dbg(dev, "mtk_seninf: remote %d-%d, local %d-%d\n"
+ , remote->entity->graph_obj.id, remote->index
+ , local->entity->graph_obj.id, local->index);
+ dev_dbg(dev, "local->flags %d flags %d\n", local->flags, flags);
+
+ if ((local->flags & MEDIA_PAD_FL_SOURCE) &&
+ (flags & MEDIA_LNK_FL_ENABLED)) {
+ dev_dbg(dev, "set cam mux %d\n", local->index);
+ priv->mux_sel = local->index - CAM_MUX_IDX_MIN;
+ }
+
+ if ((local->flags & MEDIA_PAD_FL_SINK) &&
+ (flags & MEDIA_LNK_FL_ENABLED)) {
+ dev_dbg(dev, "set sensor port\n", local->index);
+ /* Select port */
+ priv->port = local->index;
+ if (priv->port >= NUM_SENSORS) {
+ dev_err(dev, "port index is over number of ports\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static const struct media_entity_operations seninf_media_ops = {
+ .link_setup = seninf_link_setup,
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+struct sensor_async_subdev {
+ struct v4l2_async_subdev asd;
+ u32 port;
+ u32 lanes;
+};
+
+static int mtk_seninf_notifier_bound
+ (struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+ struct mtk_seninf *priv =
+ container_of(notifier, struct mtk_seninf, notifier);
+ struct sensor_async_subdev *s_asd =
+ container_of(asd, struct sensor_async_subdev, asd);
+ int ret;
+
+ dev_dbg(priv->dev, "%s bounded with port:%d lanes: %d\n",
+ sd->entity.name, s_asd->port, s_asd->lanes);
+
+ priv->sensor[s_asd->port].num_data_lanes = s_asd->lanes;
+
+ ret = media_create_pad_link(&sd->entity, 0, &priv->subdev.entity,
+ s_asd->port, 0);
+ if (ret) {
+ dev_err(priv->dev, "failed to create link for %s\n",
+ sd->entity.name);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_async_notifier_operations mtk_seninf_async_ops = {
+ .bound = mtk_seninf_notifier_bound,
+};
+
+static int mtk_seninf_fwnode_parse(struct device *dev,
+ struct v4l2_fwnode_endpoint *vep,
+ struct v4l2_async_subdev *asd)
+{
+ struct sensor_async_subdev *s_asd =
+ container_of(asd, struct sensor_async_subdev, asd);
+
+ if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) {
+ dev_err(dev, "Only CSI2 bus type is currently supported\n");
+ return -EINVAL;
+ }
+
+ s_asd->port = vep->base.port;
+ s_asd->lanes = vep->bus.mipi_csi2.num_data_lanes;
+
+ return 0;
+}
+
+static int seninf_enable_test_pattern(struct mtk_seninf *priv, u32 pattern)
+{
+ void *pseninf = priv->base_reg;
+ struct device *dev = priv->dev;
+ unsigned int val;
+
+ switch (pattern) {
+ case TEST_GEN_PATTERN:
+ writel(0xC00, pseninf + SENINF_TOP_CTRL);
+ writel(0x1001, pseninf + SENINF1_CTRL);
+ writel(0x96DF1080, pseninf + SENINF1_MUX_CTRL);
+ writel(0x8000007F, pseninf + SENINF1_MUX_INTEN);
+ writel(0x0, pseninf + SENINF1_MUX_SPARE);
+ writel(0xE2000, pseninf + SENINF1_MUX_CTRL_EXT);
+ writel(0x0, pseninf + SENINF1_MUX_CTRL_EXT);
+ writel(0x404C1, pseninf + SENINF_TG1_TM_CTL);
+ val = (priv->fmt[priv->port].format.height + 0x100) << 16
+ | priv->fmt[priv->port].format.width + 0x100;
+ writel(val, pseninf + SENINF_TG1_TM_SIZE);
+ writel(0x0, pseninf + SENINF_TG1_TM_CLK);
+ writel(0x1, pseninf + SENINF_TG1_TM_STP);
+ writel(readl(pseninf + SENINF1_CTRL_EXT) | 0x02
+ , pseninf + SENINF1_CTRL_EXT);
+ break;
+ case TEST_DUMP_DEBUG_INFO:
+ /* Sensor Interface Control */
+ dev_dbg(dev,
+ "SENINF_CSI2_CTL SENINF1:0x%x, 2:0x%x, 3:0x%x, 5:0x%x\n"
+ , readl(pseninf + SENINF1_CSI2_CTL)
+ , readl(pseninf + SENINF2_CSI2_CTL)
+ , readl(pseninf + SENINF3_CSI2_CTL)
+ , readl(pseninf + SENINF5_CSI2_CTL));
+ /* Read width/height */
+ /* Read interrupt status */
+ dev_dbg(dev, "SENINF1_IRQ:0x%x, 2:0x%x, 3:0x%x, 5:0x%x\n"
+ , readl(pseninf + SENINF1_CSI2_INT_STATUS)
+ , readl(pseninf + SENINF2_CSI2_INT_STATUS)
+ , readl(pseninf + SENINF3_CSI2_INT_STATUS)
+ , readl(pseninf + SENINF5_CSI2_INT_STATUS));
+ /* Mux1 */
+ dev_dbg(dev, "SENINF1_MUX_CTRL:0x%x, INTSTA:0x%x, DEBUG_2(0x%x)\n",
+ readl(pseninf + SENINF1_MUX_CTRL),
+ readl(pseninf + SENINF1_MUX_INTSTA),
+ readl(pseninf + SENINF1_MUX_DEBUG_2));
+ if (readl(pseninf + SENINF1_MUX_INTSTA) & 0x1) {
+ writel(0xffffffff, pseninf + SENINF1_MUX_INTSTA);
+ usleep_range(1000, 1000 * 2);
+ dev_warn(dev, "overrun CTRL:%x INTSTA:%x DEBUG_2:%x\n"
+ , readl(pseninf + SENINF1_MUX_CTRL)
+ , readl(pseninf + SENINF1_MUX_INTSTA)
+ , readl(pseninf + SENINF1_MUX_DEBUG_2));
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int seninf_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct mtk_seninf *priv = container_of(ctrl->handler,
+ struct mtk_seninf, ctrl_handler);
+
+ switch (ctrl->id) {
+ case V4L2_CID_TEST_PATTERN:
+ return seninf_enable_test_pattern(priv, ctrl->val);
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops seninf_ctrl_ops = {
+ .s_ctrl = seninf_set_ctrl,
+};
+
+static const char * const seninf_test_pattern_menu[] = {
+ "Horizontal bars",
+ "Monitor status",
+};
+
+static int seninf_initialize_controls(struct mtk_seninf *priv)
+{
+ struct v4l2_ctrl_handler *handler;
+ int ret;
+
+ handler = &priv->ctrl_handler;
+ ret = v4l2_ctrl_handler_init(handler, 2);
+ if (ret)
+ return ret;
+ v4l2_ctrl_new_std_menu_items(handler, &seninf_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(seninf_test_pattern_menu) - 1,
+ 0, 0, seninf_test_pattern_menu);
+
+ if (handler->error) {
+ ret = handler->error;
+ dev_err(priv->dev,
+ "Failed to init controls(%d)\n", ret);
+ goto err_free_handler;
+ }
+
+ priv->subdev.ctrl_handler = handler;
+ return 0;
+
+err_free_handler:
+ v4l2_ctrl_handler_free(handler);
+
+ return ret;
+}
+
+static int mtk_seninf_media_register(struct mtk_seninf *priv)
+{
+ struct v4l2_subdev *sd = &priv->subdev;
+ struct media_pad *pads = priv->pads;
+ struct device *dev = priv->dev;
+ int i;
+ int ret;
+
+ v4l2_subdev_init(sd, &seninf_subdev_ops);
+
+ init_fmt(priv);
+ ret = seninf_initialize_controls(priv);
+ if (ret) {
+ dev_err(dev, "Failed to initialize controls\n");
+ return ret;
+ }
+
+ sd->flags |= (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS);
+
+ priv->subdev.dev = dev;
+ snprintf(sd->name, V4L2_SUBDEV_NAME_SIZE, "%s",
+ dev_name(dev));
+ v4l2_set_subdevdata(sd, priv);
+
+ sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+ sd->entity.ops = &seninf_media_ops;
+
+ for (i = 0; i < NUM_SENSORS; i++)
+ pads[i].flags = MEDIA_PAD_FL_SINK;
+
+ for (i = CAM_MUX_IDX_MIN; i < NUM_PADS; i++)
+ pads[i].flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_pads_init(&sd->entity, NUM_PADS, pads);
+ if (ret < 0)
+ goto err_free_handler;
+
+ v4l2_async_notifier_init(&priv->notifier);
+ for (i = 0; i < NUM_SENSORS; ++i) {
+ ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port
+ (dev, &priv->notifier, sizeof(struct sensor_async_subdev)
+ , i, mtk_seninf_fwnode_parse);
+ if (ret < 0)
+ goto err_clean_entity;
+ }
+
+ priv->subdev.subdev_notifier = &priv->notifier;
+ priv->notifier.ops = &mtk_seninf_async_ops;
+ ret = v4l2_async_subdev_notifier_register(sd, &priv->notifier);
+ if (ret < 0) {
+ dev_err(dev, "v4l2 async notifier register failed\n");
+ goto err_clean_notififer;
+ }
+
+ ret = v4l2_async_register_subdev(sd);
+ if (ret < 0) {
+ dev_err(dev, "v4l2 async register subdev failed\n");
+ goto err_clean_notififer;
+ }
+ return 0;
+
+err_clean_notififer:
+ v4l2_async_notifier_cleanup(&priv->notifier);
+err_clean_entity:
+ media_entity_cleanup(&sd->entity);
+err_free_handler:
+ v4l2_ctrl_handler_free(&priv->ctrl_handler);
+
+ return ret;
+}
+
+static int seninf_probe(struct platform_device *pdev)
+{
+ /* List of clocks required by seninf */
+ static const char * const clk_names[] = {
+ "CLK_CAM_SENINF", "CLK_TOP_MUX_SENINF"
+ };
+ struct resource *res;
+ struct mtk_seninf *priv;
+ struct device *dev = &pdev->dev;
+ int i, ret;
+
+ dev_err(dev, "seninf probe +\n");
+
+ priv = devm_kzalloc(dev, sizeof(struct mtk_seninf), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ memset(priv, 0, sizeof(struct mtk_seninf));
+
+ dev_set_drvdata(dev, priv);
+ priv->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->base_reg = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->base_reg))
+ return PTR_ERR(priv->base_reg);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ priv->rx_reg = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->rx_reg))
+ return PTR_ERR(priv->rx_reg);
+
+ priv->csi2_rx[CFG_CSI_PORT_0] = priv->rx_reg;
+ priv->csi2_rx[CFG_CSI_PORT_0A] = priv->rx_reg;
+ priv->csi2_rx[CFG_CSI_PORT_0B] = priv->rx_reg + 0x1000;
+ priv->csi2_rx[CFG_CSI_PORT_1] = priv->rx_reg + 0x2000;
+ priv->csi2_rx[CFG_CSI_PORT_2] = priv->rx_reg + 0x4000;
+
+ priv->num_clks = ARRAY_SIZE(clk_names);
+ priv->clks = devm_kcalloc(dev, priv->num_clks,
+ sizeof(*priv->clks), GFP_KERNEL);
+ if (!priv->clks)
+ return -ENOMEM;
+
+ for (i = 0; i < priv->num_clks; ++i)
+ priv->clks[i].id = clk_names[i];
+
+ ret = devm_clk_bulk_get(dev, priv->num_clks, priv->clks);
+ if (ret) {
+ dev_err(dev, "failed to get seninf clock:%d\n", ret);
+ return ret;
+ }
+
+ ret = mtk_seninf_media_register(priv);
+
+ pm_runtime_enable(dev);
+ dev_info(dev, "seninf probe -\n");
+
+ return ret;
+}
+
+static int seninf_pm_suspend(struct device *dev)
+{
+ struct mtk_seninf *priv = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "seninf runtime suspend\n");
+ clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
+
+ return 0;
+}
+
+static int seninf_pm_resume(struct device *dev)
+{
+ struct mtk_seninf *priv = dev_get_drvdata(dev);
+ int ret;
+
+ dev_dbg(dev, "seninf runtime resume\n");
+ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
+ if (ret) {
+ dev_err(dev, "failed to enable clock:%d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops runtime_pm_ops = {
+ SET_RUNTIME_PM_OPS(seninf_pm_suspend, seninf_pm_resume, NULL)
+};
+
+static int seninf_remove(struct platform_device *pdev)
+{
+ struct mtk_seninf *priv = dev_get_drvdata(&pdev->dev);
+ struct v4l2_subdev *subdev = &priv->subdev;
+
+ media_entity_cleanup(&subdev->entity);
+ v4l2_async_unregister_subdev(subdev);
+ v4l2_ctrl_handler_free(&priv->ctrl_handler);
+
+ pm_runtime_disable(priv->dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id mtk_seninf_of_match[] = {
+ {.compatible = "mediatek,mt8183-seninf"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, mtk_seninf_of_match);
+#endif
+
+static struct platform_driver seninf_pdrv = {
+ .driver = {
+ .name = "seninf",
+ .pm = &runtime_pm_ops,
+ .of_match_table = of_match_ptr(mtk_seninf_of_match),
+ },
+ .probe = seninf_probe,
+ .remove = seninf_remove,
+};
+
+module_platform_driver(seninf_pdrv);
+
+MODULE_DESCRIPTION("MTK seninf driver");
+MODULE_AUTHOR("Louis Kuo <louis.kuo@mediatek.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("MTK:mtk_seninf");
diff --git a/drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf_def.h b/drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf_def.h
new file mode 100644
index 000000000000..f2c0ea7c9800
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf_def.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __SENINF_DRV_DEF_H__
+#define __SENINF_DRV_DEF_H__
+
+#define SENINF_TIMESTAMP_STEP 0x67
+#define SENINF_SETTLE_DELAY 0x15
+#define SENINF_HS_TRAIL_PARAMETER 0x8
+
+#define NUM_PADS 12
+#define NUM_SENSORS 4
+#define CAM_MUX_IDX_MIN NUM_SENSORS
+#define DEFAULT_WIDTH 1600
+#define DEFAULT_HEIGHT 1200
+
+#define PAD_10BIT 0
+
+enum {
+ TEST_GEN_PATTERN = 0x0,
+ TEST_DUMP_DEBUG_INFO,
+};
+
+enum {
+ CFG_CSI_PORT_0 = 0x0, /* 4D1C */
+ CFG_CSI_PORT_1, /* 4D1C */
+ CFG_CSI_PORT_2, /* 4D1C */
+ CFG_CSI_PORT_0A, /* 2D1C */
+ CFG_CSI_PORT_0B, /* 2D1C */
+ CFG_CSI_PORT_MAX_NUM,
+ CFG_CSI_PORT_NONE /*for non-MIPI sensor */
+};
+
+enum {
+ ONE_PIXEL_MODE = 0x0,
+ TWO_PIXEL_MODE = 0x1,
+ FOUR_PIXEL_MODE = 0x2,
+};
+
+enum {
+ SENINF_1 = 0x0,
+ SENINF_2 = 0x1,
+ SENINF_3 = 0x2,
+ SENINF_4 = 0x3,
+ SENINF_5 = 0x4,
+ SENINF_NUM,
+};
+
+enum {
+ RAW_8BIT_FMT = 0x0,
+ RAW_10BIT_FMT = 0x1,
+ RAW_12BIT_FMT = 0x2,
+ YUV422_FMT = 0x3,
+ RAW_14BIT_FMT = 0x4,
+ RGB565_MIPI_FMT = 0x5,
+ RGB888_MIPI_FMT = 0x6,
+ JPEG_FMT = 0x7
+};
+
+#endif /*__SENINF_DRV_DEF_H__ */
diff --git a/drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf_reg.h b/drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf_reg.h
new file mode 100644
index 000000000000..5f7e10916f35
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/isp_50/seninf/mtk_seninf_reg.h
@@ -0,0 +1,853 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _SENINF_REG_H_
+#define _SENINF_REG_H_
+
+/* 0x11c80000..0x11c850ac */
+#define MIPI_RX_ANA00_CSI0A 0x0000
+#define MIPI_RX_ANA04_CSI0A 0x0004
+#define MIPI_RX_ANA08_CSI0A 0x0008
+#define MIPI_RX_ANA0C_CSI0A 0x000C
+#define MIPI_RX_ANA10_CSI0A 0x0010
+#define MIPI_RX_ANA14_CSI0A 0x0014
+#define MIPI_RX_ANA18_CSI0A 0x0018
+#define MIPI_RX_ANA1C_CSI0A 0x001C
+#define MIPI_RX_ANA20_CSI0A 0x0020
+#define MIPI_RX_ANA24_CSI0A 0x0024
+#define MIPI_RX_ANA28_CSI0A 0x0028
+#define MIPI_RX_ANA2C_CSI0A 0x002C
+#define MIPI_RX_ANA34_CSI0A 0x0034
+#define MIPI_RX_ANA38_CSI0A 0x0038
+#define MIPI_RX_ANA40_CSI0A 0x0040
+#define MIPI_RX_ANA48_CSI0A 0x0048
+#define MIPI_RX_WRAPPER80_CSI0A 0x0080
+#define MIPI_RX_WRAPPER84_CSI0A 0x0084
+#define MIPI_RX_WRAPPER88_CSI0A 0x0088
+#define MIPI_RX_WRAPPER8C_CSI0A 0x008C
+#define MIPI_RX_WRAPPER90_CSI0A 0x0090
+#define MIPI_RX_WRAPPER94_CSI0A 0x0094
+#define MIPI_RX_WRAPPER98_CSI0A 0x0098
+#define MIPI_RX_WRAPPER9C_CSI0A 0x009C
+#define MIPI_RX_ANAA4_CSI0A 0x00A4
+#define MIPI_RX_ANAA8_CSI0A 0x00A8
+#define MIPI_RX_ANA00_CSI0B 0x1000
+#define MIPI_RX_ANA04_CSI0B 0x1004
+#define MIPI_RX_ANA08_CSI0B 0x1008
+#define MIPI_RX_ANA0C_CSI0B 0x100C
+#define MIPI_RX_ANA10_CSI0B 0x1010
+#define MIPI_RX_ANA14_CSI0B 0x1014
+#define MIPI_RX_ANA18_CSI0B 0x1018
+#define MIPI_RX_ANA1C_CSI0B 0x101C
+#define MIPI_RX_ANA20_CSI0B 0x1020
+#define MIPI_RX_ANA24_CSI0B 0x1024
+#define MIPI_RX_ANA28_CSI0B 0x1028
+#define MIPI_RX_ANA2C_CSI0B 0x102C
+#define MIPI_RX_ANA34_CSI0B 0x1034
+#define MIPI_RX_ANA38_CSI0B 0x1038
+#define MIPI_RX_ANA48_CSI0B 0x1048
+#define MIPI_RX_WRAPPER80_CSI0B 0x1080
+#define MIPI_RX_WRAPPER84_CSI0B 0x1084
+#define MIPI_RX_WRAPPER88_CSI0B 0x1088
+#define MIPI_RX_WRAPPER8C_CSI0B 0x108C
+#define MIPI_RX_WRAPPER90_CSI0B 0x1090
+#define MIPI_RX_WRAPPER94_CSI0B 0x1094
+#define MIPI_RX_WRAPPER98_CSI0B 0x1098
+#define MIPI_RX_WRAPPER9C_CSI0B 0x109C
+#define MIPI_RX_ANAA4_CSI0B 0x10A4
+#define MIPI_RX_ANAA8_CSI0B 0x10A8
+#define MIPI_RX_ANA00_CSI1A 0x2000
+#define MIPI_RX_ANA04_CSI1A 0x2004
+#define MIPI_RX_ANA08_CSI1A 0x2008
+#define MIPI_RX_ANA0C_CSI1A 0x200C
+#define MIPI_RX_ANA10_CSI1A 0x2010
+#define MIPI_RX_ANA18_CSI1A 0x2018
+#define MIPI_RX_ANA1C_CSI1A 0x201C
+#define MIPI_RX_ANA24_CSI1A 0x2024
+#define MIPI_RX_ANA48_CSI1A 0x2048
+#define MIPI_RX_WRAPPER80_CSI1A 0x2080
+#define MIPI_RX_WRAPPER84_CSI1A 0x2084
+#define MIPI_RX_WRAPPER88_CSI1A 0x2088
+#define MIPI_RX_WRAPPER8C_CSI1A 0x208C
+#define MIPI_RX_WRAPPER90_CSI1A 0x2090
+#define MIPI_RX_WRAPPER94_CSI1A 0x2094
+#define MIPI_RX_WRAPPER98_CSI1A 0x2098
+#define MIPI_RX_WRAPPER9C_CSI1A 0x209C
+#define MIPI_RX_ANAA4_CSI1A 0x20A4
+#define MIPI_RX_ANAA8_CSI1A 0x20A8
+#define MIPI_RX_ANA00_CSI1B 0x3000
+#define MIPI_RX_ANA04_CSI1B 0x3004
+#define MIPI_RX_ANA08_CSI1B 0x3008
+#define MIPI_RX_ANA0C_CSI1B 0x300C
+#define MIPI_RX_ANA10_CSI1B 0x3010
+#define MIPI_RX_ANA18_CSI1B 0x3018
+#define MIPI_RX_ANA1C_CSI1B 0x301C
+#define MIPI_RX_ANA24_CSI1B 0x3024
+#define MIPI_RX_ANA48_CSI1B 0x3048
+#define MIPI_RX_WRAPPER80_CSI1B 0x3080
+#define MIPI_RX_WRAPPER84_CSI1B 0x3084
+#define MIPI_RX_WRAPPER88_CSI1B 0x3088
+#define MIPI_RX_WRAPPER8C_CSI1B 0x308C
+#define MIPI_RX_WRAPPER90_CSI1B 0x3090
+#define MIPI_RX_WRAPPER94_CSI1B 0x3094
+#define MIPI_RX_WRAPPER98_CSI1B 0x3098
+#define MIPI_RX_WRAPPER9C_CSI1B 0x309C
+#define MIPI_RX_ANAA4_CSI1B 0x30A4
+#define MIPI_RX_ANAA8_CSI1B 0x30A8
+#define MIPI_RX_ANA00_CSI2A 0x4000
+#define MIPI_RX_ANA04_CSI2A 0x4004
+#define MIPI_RX_ANA08_CSI2A 0x4008
+#define MIPI_RX_ANA0C_CSI2A 0x400C
+#define MIPI_RX_ANA10_CSI2A 0x4010
+#define MIPI_RX_ANA18_CSI2A 0x4018
+#define MIPI_RX_ANA1C_CSI2A 0x401C
+#define MIPI_RX_ANA24_CSI2A 0x4024
+#define MIPI_RX_ANA48_CSI2A 0x4048
+#define MIPI_RX_WRAPPER80_CSI2A 0x4080
+#define MIPI_RX_WRAPPER84_CSI2A 0x4084
+#define MIPI_RX_WRAPPER88_CSI2A 0x4088
+#define MIPI_RX_WRAPPER8C_CSI2A 0x408C
+#define MIPI_RX_WRAPPER90_CSI2A 0x4090
+#define MIPI_RX_WRAPPER94_CSI2A 0x4094
+#define MIPI_RX_WRAPPER98_CSI2A 0x4098
+#define MIPI_RX_WRAPPER9C_CSI2A 0x409C
+#define MIPI_RX_ANAA4_CSI2A 0x40A4
+#define MIPI_RX_ANAA8_CSI2A 0x40A8
+#define MIPI_RX_ANA00_CSI2B 0x5000
+#define MIPI_RX_ANA04_CSI2B 0x5004
+#define MIPI_RX_ANA08_CSI2B 0x5008
+#define MIPI_RX_ANA0C_CSI2B 0x500C
+#define MIPI_RX_ANA10_CSI2B 0x5010
+#define MIPI_RX_ANA18_CSI2B 0x5018
+#define MIPI_RX_ANA1C_CSI2B 0x501C
+#define MIPI_RX_ANA24_CSI2B 0x5024
+#define MIPI_RX_ANA48_CSI2B 0x5048
+#define MIPI_RX_WRAPPER80_CSI2B 0x5080
+#define MIPI_RX_WRAPPER84_CSI2B 0x5084
+#define MIPI_RX_WRAPPER88_CSI2B 0x5088
+#define MIPI_RX_WRAPPER8C_CSI2B 0x508C
+#define MIPI_RX_WRAPPER90_CSI2B 0x5090
+#define MIPI_RX_WRAPPER94_CSI2B 0x5094
+#define MIPI_RX_WRAPPER98_CSI2B 0x5098
+#define MIPI_RX_WRAPPER9C_CSI2B 0x509C
+#define MIPI_RX_ANAA4_CSI2B 0x50A4
+#define MIPI_RX_ANAA8_CSI2B 0x50A8
+
+/* 0x1a040000..0x1a047d40 */
+#define SENINF_TOP_CTRL 0x0000
+#define SENINF_TOP_CMODEL_PAR 0x0004
+#define SENINF_TOP_MUX_CTRL 0x0008
+#define SENINF_TOP_CAM_MUX_CTRL 0x0010
+#define SENINF_TOP_N3D_A_CTL 0x0014
+#define SENINF_TOP_N3D_B_CTL 0x0018
+#define SENINF_TOP_PHY_SENINF_CTL_CSI0 0x001C
+#define SENINF_TOP_PHY_SENINF_CTL_CSI1 0x0020
+#define SENINF_TOP_PHY_SENINF_CTL_CSI2 0x0024
+#define SENINF_N3D_A_CTL 0x0100
+#define SENINF_N3D_A_POS 0x0104
+#define SENINF_N3D_A_TRIG 0x0108
+#define SENINF_N3D_A_INT 0x010C
+#define SENINF_N3D_A_CNT0 0x0110
+#define SENINF_N3D_A_CNT1 0x0114
+#define SENINF_N3D_A_DBG 0x0118
+#define SENINF_N3D_A_DIFF_THR 0x011C
+#define SENINF_N3D_A_DIFF_CNT 0x0120
+#define SENINF_N3D_A_DBG_1 0x0124
+#define SENINF_N3D_A_VALID_TG_CNT 0x0128
+#define SENINF_N3D_A_SYNC_A_PERIOD 0x012C
+#define SENINF_N3D_A_SYNC_B_PERIOD 0x0130
+#define SENINF_N3D_A_SYNC_A_PULSE_LEN 0x0134
+#define SENINF_N3D_A_SYNC_B_PULSE_LEN 0x0138
+#define SENINF_N3D_A_SUB_CNT 0x013C
+#define SENINF_N3D_A_VSYNC_CNT 0x0140
+#define SENINF1_CTRL 0x0200
+#define SENINF1_CTRL_EXT 0x0204
+#define SENINF1_ASYNC_CTRL 0x0208
+#define SENINF_TG1_PH_CNT 0x0600
+#define SENINF_TG1_SEN_CK 0x0604
+#define SENINF_TG1_TM_CTL 0x0608
+#define SENINF_TG1_TM_SIZE 0x060C
+#define SENINF_TG1_TM_CLK 0x0610
+#define SENINF_TG1_TM_STP 0x0614
+#define MIPI_RX_CON24_CSI0 0x0824
+#define MIPI_RX_CON28_CSI0 0x0828
+#define MIPI_RX_CON34_CSI0 0x0834
+#define MIPI_RX_CON38_CSI0 0x0838
+#define MIPI_RX_CON3C_CSI0 0x083C
+#define MIPI_RX_CON7C_CSI0 0x087C
+#define MIPI_RX_CON80_CSI0 0x0880
+#define MIPI_RX_CON84_CSI0 0x0884
+#define MIPI_RX_CON88_CSI0 0x0888
+#define MIPI_RX_CON8C_CSI0 0x088C
+#define MIPI_RX_CON90_CSI0 0x0890
+#define MIPI_RX_CON94_CSI0 0x0894
+#define MIPI_RX_CON98_CSI0 0x0898
+#define MIPI_RX_CONA0_CSI0 0x08A0
+#define MIPI_RX_CONB0_CSI0 0x08B0
+#define MIPI_RX_CONB4_CSI0 0x08B4
+#define MIPI_RX_CONB8_CSI0 0x08B8
+#define MIPI_RX_CONBC_CSI0 0x08BC
+#define MIPI_RX_CONC0_CSI0 0x08C0
+#define MIPI_RX_CONC4_CSI0 0x08C4
+#define MIPI_RX_CONC8_CSI0 0x08C8
+#define MIPI_RX_CONCC_CSI0 0x08CC
+#define MIPI_RX_COND0_CSI0 0x08D0
+#define SENINF1_CSI2_CTL 0x0A00
+#define SENINF1_CSI2_LNRC_TIMING 0x0A04
+#define SENINF1_CSI2_LNRD_TIMING 0x0A08
+#define SENINF1_CSI2_DPCM 0x0A0C
+#define SENINF1_CSI2_INT_EN 0x0A10
+#define SENINF1_CSI2_INT_STATUS 0x0A14
+#define SENINF1_CSI2_DGB_SEL 0x0A18
+#define SENINF1_CSI2_DBG_PORT 0x0A1C
+#define SENINF1_CSI2_SPARE0 0x0A20
+#define SENINF1_CSI2_SPARE1 0x0A24
+#define SENINF1_CSI2_LNRC_FSM 0x0A28
+#define SENINF1_CSI2_LNRD_FSM 0x0A2C
+#define SENINF1_CSI2_FRAME_LINE_NUM 0x0A30
+#define SENINF1_CSI2_GENERIC_SHORT 0x0A34
+#define SENINF1_CSI2_HSRX_DBG 0x0A38
+#define SENINF1_CSI2_DI 0x0A3C
+#define SENINF1_CSI2_HS_TRAIL 0x0A40
+#define SENINF1_CSI2_DI_CTRL 0x0A44
+#define SENINF1_CSI2_DETECT_CON1 0x0A4C
+#define SENINF1_CSI2_DETECT_CON2 0x0A50
+#define SENINF1_CSI2_DETECT_CON3 0x0A54
+#define SENINF1_CSI2_RLR0_CON0 0x0A58
+#define SENINF1_CSI2_RLR1_CON0 0x0A5C
+#define SENINF1_CSI2_RLR2_CON0 0x0A60
+#define SENINF1_CSI2_RLR_CON0 0x0A64
+#define SENINF1_CSI2_MUX_CON 0x0A68
+#define SENINF1_CSI2_DETECT_DBG0 0x0A6C
+#define SENINF1_CSI2_DETECT_DBG1 0x0A70
+#define SENINF1_CSI2_RESYNC_MERGE_CTL 0x0A74
+#define SENINF1_CSI2_CTRL_TRIO_MUX 0x0A78
+#define SENINF1_CSI2_CTRL_TRIO_CON 0x0A7C
+#define SENINF1_FIX_ADDR_CPHY0_DBG 0x0A80
+#define SENINF1_FIX_ADDR_CPHY1_DBG 0x0A84
+#define SENINF1_FIX_ADDR_CPHY2_DBG 0x0A88
+#define SENINF1_FIX_ADDR_DBG 0x0A8C
+#define SENINF1_WIRE_STATE_DECODE_CPHY0_DBG0 0x0A90
+#define SENINF1_WIRE_STATE_DECODE_CPHY0_DBG1 0x0A94
+#define SENINF1_WIRE_STATE_DECODE_CPHY1_DBG0 0x0A98
+#define SENINF1_WIRE_STATE_DECODE_CPHY1_DBG1 0x0A9C
+#define SENINF1_WIRE_STATE_DECODE_CPHY2_DBG0 0x0AA0
+#define SENINF1_WIRE_STATE_DECODE_CPHY2_DBG1 0x0AA4
+#define SENINF1_SYNC_RESYNC_CTL 0x0AA8
+#define SENINF1_POST_DETECT_CTL 0x0AAC
+#define SENINF1_WIRE_STATE_DECODE_CONFIG 0x0AB0
+#define SENINF1_CSI2_CPHY_LNRD_FSM 0x0AB4
+#define SENINF1_FIX_ADDR_CPHY0_DBG0 0x0AB8
+#define SENINF1_FIX_ADDR_CPHY0_DBG1 0x0ABC
+#define SENINF1_FIX_ADDR_CPHY0_DBG2 0x0AC0
+#define SENINF1_FIX_ADDR_CPHY1_DBG0 0x0AC4
+#define SENINF1_FIX_ADDR_CPHY1_DBG1 0x0AC8
+#define SENINF1_FIX_ADDR_CPHY1_DBG2 0x0ACC
+#define SENINF1_FIX_ADDR_CPHY2_DBG0 0x0AD0
+#define SENINF1_FIX_ADDR_CPHY2_DBG1 0x0AD4
+#define SENINF1_FIX_ADDR_CPHY2_DBG2 0x0AD8
+#define SENINF1_FIX_ADDR_DBG0 0x0ADC
+#define SENINF1_FIX_ADDR_DBG1 0x0AE0
+#define SENINF1_FIX_ADDR_DBG2 0x0AE4
+#define SENINF1_CSI2_MODE 0x0AE8
+#define SENINF1_CSI2_DI_EXT 0x0AF0
+#define SENINF1_CSI2_DI_CTRL_EXT 0x0AF4
+#define SENINF1_CSI2_CPHY_LOOPBACK 0x0AF8
+#define SENINF1_CSI2_PROGSEQ_0 0x0B00
+#define SENINF1_CSI2_PROGSEQ_1 0x0B04
+#define SENINF1_CSI2_INT_EN_EXT 0x0B10
+#define SENINF1_CSI2_INT_STATUS_EXT 0x0B14
+#define SENINF1_CSI2_CPHY_FIX_POINT_RST 0x0B18
+#define SENINF1_CSI2_RLR3_CON0 0x0B1C
+#define SENINF1_CSI2_DPHY_SYNC 0x0B20
+#define SENINF1_CSI2_DESKEW_SYNC 0x0B24
+#define SENINF1_CSI2_DETECT_DBG2 0x0B28
+#define SENINF1_FIX_ADDR_CPHY3_DBG0 0x0B30
+#define SENINF1_FIX_ADDR_CPHY3_DBG1 0x0B34
+#define SENINF1_FIX_ADDR_CPHY3_DBG2 0x0B38
+#define SENINF1_CSI2_DI_EXT_2 0x0B3C
+#define SENINF1_CSI2_DI_CTRL_EXT_2 0x0B40
+#define SENINF1_WIRE_STATE_DECODE_CPHY3_DBG0 0x0B44
+#define SENINF1_WIRE_STATE_DECODE_CPHY3_DBG1 0x0B48
+#define SENINF1_MUX_CTRL 0x0D00
+#define SENINF1_MUX_INTEN 0x0D04
+#define SENINF1_MUX_INTSTA 0x0D08
+#define SENINF1_MUX_SIZE 0x0D0C
+#define SENINF1_MUX_DEBUG_1 0x0D10
+#define SENINF1_MUX_DEBUG_2 0x0D14
+#define SENINF1_MUX_DEBUG_3 0x0D18
+#define SENINF1_MUX_DEBUG_4 0x0D1C
+#define SENINF1_MUX_DEBUG_5 0x0D20
+#define SENINF1_MUX_DEBUG_6 0x0D24
+#define SENINF1_MUX_DEBUG_7 0x0D28
+#define SENINF1_MUX_SPARE 0x0D2C
+#define SENINF1_MUX_DATA 0x0D30
+#define SENINF1_MUX_DATA_CNT 0x0D34
+#define SENINF1_MUX_CROP 0x0D38
+#define SENINF1_MUX_CTRL_EXT 0x0D3C
+#define SENINF_N3D_B_CTL 0x1100
+#define SENINF_N3D_B_POS 0x1104
+#define SENINF_N3D_B_TRIG 0x1108
+#define SENINF_N3D_B_INT 0x110C
+#define SENINF_N3D_B_CNT0 0x1110
+#define SENINF_N3D_B_CNT1 0x1114
+#define SENINF_N3D_B_DBG 0x1118
+#define SENINF_N3D_B_DIFF_THR 0x111C
+#define SENINF_N3D_B_DIFF_CNT 0x1120
+#define SENINF_N3D_B_DBG_1 0x1124
+#define SENINF_N3D_B_VALID_TG_CNT 0x1128
+#define SENINF_N3D_B_SYNC_A_PERIOD 0x112C
+#define SENINF_N3D_B_SYNC_B_PERIOD 0x1130
+#define SENINF_N3D_B_SYNC_A_PULSE_LEN 0x1134
+#define SENINF_N3D_B_SYNC_B_PULSE_LEN 0x1138
+#define SENINF_N3D_B_SUB_CNT 0x113C
+#define SENINF_N3D_B_VSYNC_CNT 0x1140
+#define SENINF2_CTRL 0x1200
+#define SENINF2_CTRL_EXT 0x1204
+#define SENINF2_ASYNC_CTRL 0x1208
+#define SENINF_TG2_PH_CNT 0x1600
+#define SENINF_TG2_SEN_CK 0x1604
+#define SENINF_TG2_TM_CTL 0x1608
+#define SENINF_TG2_TM_SIZE 0x160C
+#define SENINF_TG2_TM_CLK 0x1610
+#define SENINF_TG2_TM_STP 0x1614
+#define MIPI_RX_CON24_CSI1 0x1824
+#define MIPI_RX_CON28_CSI1 0x1828
+#define MIPI_RX_CON34_CSI1 0x1834
+#define MIPI_RX_CON38_CSI1 0x1838
+#define MIPI_RX_CON3C_CSI1 0x183C
+#define MIPI_RX_CON7C_CSI1 0x187C
+#define MIPI_RX_CON80_CSI1 0x1880
+#define MIPI_RX_CON84_CSI1 0x1884
+#define MIPI_RX_CON88_CSI1 0x1888
+#define MIPI_RX_CON8C_CSI1 0x188C
+#define MIPI_RX_CON90_CSI1 0x1890
+#define MIPI_RX_CON94_CSI1 0x1894
+#define MIPI_RX_CON98_CSI1 0x1898
+#define MIPI_RX_CONA0_CSI1 0x18A0
+#define MIPI_RX_CONB0_CSI1 0x18B0
+#define MIPI_RX_CONB4_CSI1 0x18B4
+#define MIPI_RX_CONB8_CSI1 0x18B8
+#define MIPI_RX_CONBC_CSI1 0x18BC
+#define MIPI_RX_CONC0_CSI1 0x18C0
+#define MIPI_RX_CONC4_CSI1 0x18C4
+#define MIPI_RX_CONC8_CSI1 0x18C8
+#define MIPI_RX_CONCC_CSI1 0x18CC
+#define MIPI_RX_COND0_CSI1 0x18D0
+#define SENINF2_CSI2_CTL 0x1A00
+#define SENINF2_CSI2_LNRC_TIMING 0x1A04
+#define SENINF2_CSI2_LNRD_TIMING 0x1A08
+#define SENINF2_CSI2_DPCM 0x1A0C
+#define SENINF2_CSI2_INT_EN 0x1A10
+#define SENINF2_CSI2_INT_STATUS 0x1A14
+#define SENINF2_CSI2_DGB_SEL 0x1A18
+#define SENINF2_CSI2_DBG_PORT 0x1A1C
+#define SENINF2_CSI2_SPARE0 0x1A20
+#define SENINF2_CSI2_SPARE1 0x1A24
+#define SENINF2_CSI2_LNRC_FSM 0x1A28
+#define SENINF2_CSI2_LNRD_FSM 0x1A2C
+#define SENINF2_CSI2_FRAME_LINE_NUM 0x1A30
+#define SENINF2_CSI2_GENERIC_SHORT 0x1A34
+#define SENINF2_CSI2_HSRX_DBG 0x1A38
+#define SENINF2_CSI2_DI 0x1A3C
+#define SENINF2_CSI2_HS_TRAIL 0x1A40
+#define SENINF2_CSI2_DI_CTRL 0x1A44
+#define SENINF2_CSI2_DETECT_CON1 0x1A4C
+#define SENINF2_CSI2_DETECT_CON2 0x1A50
+#define SENINF2_CSI2_DETECT_CON3 0x1A54
+#define SENINF2_CSI2_RLR0_CON0 0x1A58
+#define SENINF2_CSI2_RLR1_CON0 0x1A5C
+#define SENINF2_CSI2_RLR2_CON0 0x1A60
+#define SENINF2_CSI2_RLR_CON0 0x1A64
+#define SENINF2_CSI2_MUX_CON 0x1A68
+#define SENINF2_CSI2_DETECT_DBG0 0x1A6C
+#define SENINF2_CSI2_DETECT_DBG1 0x1A70
+#define SENINF2_CSI2_RESYNC_MERGE_CTL 0x1A74
+#define SENINF2_CSI2_CTRL_TRIO_MUX 0x1A78
+#define SENINF2_CSI2_CTRL_TRIO_CON 0x1A7C
+#define SENINF2_FIX_ADDR_CPHY0_DBG 0x1A80
+#define SENINF2_FIX_ADDR_CPHY1_DBG 0x1A84
+#define SENINF2_FIX_ADDR_CPHY2_DBG 0x1A88
+#define SENINF2_FIX_ADDR_DBG 0x1A8C
+#define SENINF2_WIRE_STATE_DECODE_CPHY0_DBG0 0x1A90
+#define SENINF2_WIRE_STATE_DECODE_CPHY0_DBG1 0x1A94
+#define SENINF2_WIRE_STATE_DECODE_CPHY1_DBG0 0x1A98
+#define SENINF2_WIRE_STATE_DECODE_CPHY1_DBG1 0x1A9C
+#define SENINF2_WIRE_STATE_DECODE_CPHY2_DBG0 0x1AA0
+#define SENINF2_WIRE_STATE_DECODE_CPHY2_DBG1 0x1AA4
+#define SENINF2_SYNC_RESYNC_CTL 0x1AA8
+#define SENINF2_POST_DETECT_CTL 0x1AAC
+#define SENINF2_WIRE_STATE_DECODE_CONFIG 0x1AB0
+#define SENINF2_CSI2_CPHY_LNRD_FSM 0x1AB4
+#define SENINF2_FIX_ADDR_CPHY0_DBG0 0x1AB8
+#define SENINF2_FIX_ADDR_CPHY0_DBG1 0x1ABC
+#define SENINF2_FIX_ADDR_CPHY0_DBG2 0x1AC0
+#define SENINF2_FIX_ADDR_CPHY1_DBG0 0x1AC4
+#define SENINF2_FIX_ADDR_CPHY1_DBG1 0x1AC8
+#define SENINF2_FIX_ADDR_CPHY1_DBG2 0x1ACC
+#define SENINF2_FIX_ADDR_CPHY2_DBG0 0x1AD0
+#define SENINF2_FIX_ADDR_CPHY2_DBG1 0x1AD4
+#define SENINF2_FIX_ADDR_CPHY2_DBG2 0x1AD8
+#define SENINF2_FIX_ADDR_DBG0 0x1ADC
+#define SENINF2_FIX_ADDR_DBG1 0x1AE0
+#define SENINF2_FIX_ADDR_DBG2 0x1AE4
+#define SENINF2_CSI2_MODE 0x1AE8
+#define SENINF2_CSI2_DI_EXT 0x1AF0
+#define SENINF2_CSI2_DI_CTRL_EXT 0x1AF4
+#define SENINF2_CSI2_CPHY_LOOPBACK 0x1AF8
+#define SENINF2_CSI2_PROGSEQ_0 0x1B00
+#define SENINF2_CSI2_PROGSEQ_1 0x1B04
+#define SENINF2_CSI2_INT_EN_EXT 0x1B10
+#define SENINF2_CSI2_INT_STATUS_EXT 0x1B14
+#define SENINF2_CSI2_CPHY_FIX_POINT_RST 0x1B18
+#define SENINF2_CSI2_RLR3_CON0 0x1B1C
+#define SENINF2_CSI2_DPHY_SYNC 0x1B20
+#define SENINF2_CSI2_DESKEW_SYNC 0x1B24
+#define SENINF2_CSI2_DETECT_DBG2 0x1B28
+#define SENINF2_FIX_ADDR_CPHY3_DBG0 0x1B30
+#define SENINF2_FIX_ADDR_CPHY3_DBG1 0x1B34
+#define SENINF2_FIX_ADDR_CPHY3_DBG2 0x1B38
+#define SENINF2_CSI2_DI_EXT_2 0x1B3C
+#define SENINF2_CSI2_DI_CTRL_EXT_2 0x1B40
+#define SENINF2_WIRE_STATE_DECODE_CPHY3_DBG0 0x1B44
+#define SENINF2_WIRE_STATE_DECODE_CPHY3_DBG1 0x1B48
+#define SENINF2_MUX_CTRL 0x1D00
+#define SENINF2_MUX_INTEN 0x1D04
+#define SENINF2_MUX_INTSTA 0x1D08
+#define SENINF2_MUX_SIZE 0x1D0C
+#define SENINF2_MUX_DEBUG_1 0x1D10
+#define SENINF2_MUX_DEBUG_2 0x1D14
+#define SENINF2_MUX_DEBUG_3 0x1D18
+#define SENINF2_MUX_DEBUG_4 0x1D1C
+#define SENINF2_MUX_DEBUG_5 0x1D20
+#define SENINF2_MUX_DEBUG_6 0x1D24
+#define SENINF2_MUX_DEBUG_7 0x1D28
+#define SENINF2_MUX_SPARE 0x1D2C
+#define SENINF2_MUX_DATA 0x1D30
+#define SENINF2_MUX_DATA_CNT 0x1D34
+#define SENINF2_MUX_CROP 0x1D38
+#define SENINF2_MUX_CTRL_EXT 0x1D3C
+#define SENINF3_CTRL 0x2200
+#define SENINF3_CTRL_EXT 0x2204
+#define SENINF3_ASYNC_CTRL 0x2208
+#define SENINF_TG3_PH_CNT 0x2600
+#define SENINF_TG3_SEN_CK 0x2604
+#define SENINF_TG3_TM_CTL 0x2608
+#define SENINF_TG3_TM_SIZE 0x260C
+#define SENINF_TG3_TM_CLK 0x2610
+#define SENINF_TG3_TM_STP 0x2614
+#define MIPI_RX_CON24_CSI2 0x2824
+#define MIPI_RX_CON28_CSI2 0x2828
+#define MIPI_RX_CON34_CSI2 0x2834
+#define MIPI_RX_CON38_CSI2 0x2838
+#define MIPI_RX_CON3C_CSI2 0x283C
+#define MIPI_RX_CON7C_CSI2 0x287C
+#define MIPI_RX_CON80_CSI2 0x2880
+#define MIPI_RX_CON84_CSI2 0x2884
+#define MIPI_RX_CON88_CSI2 0x2888
+#define MIPI_RX_CON8C_CSI2 0x288C
+#define MIPI_RX_CON90_CSI2 0x2890
+#define MIPI_RX_CON94_CSI2 0x2894
+#define MIPI_RX_CON98_CSI2 0x2898
+#define MIPI_RX_CONA0_CSI2 0x28A0
+#define MIPI_RX_CONB0_CSI2 0x28B0
+#define MIPI_RX_CONB4_CSI2 0x28B4
+#define MIPI_RX_CONB8_CSI2 0x28B8
+#define MIPI_RX_CONBC_CSI2 0x28BC
+#define MIPI_RX_CONC0_CSI2 0x28C0
+#define MIPI_RX_CONC4_CSI2 0x28C4
+#define MIPI_RX_CONC8_CSI2 0x28C8
+#define MIPI_RX_CONCC_CSI2 0x28CC
+#define MIPI_RX_COND0_CSI2 0x28D0
+#define SENINF3_CSI2_CTL 0x2A00
+#define SENINF3_CSI2_LNRC_TIMING 0x2A04
+#define SENINF3_CSI2_LNRD_TIMING 0x2A08
+#define SENINF3_CSI2_DPCM 0x2A0C
+#define SENINF3_CSI2_INT_EN 0x2A10
+#define SENINF3_CSI2_INT_STATUS 0x2A14
+#define SENINF3_CSI2_DGB_SEL 0x2A18
+#define SENINF3_CSI2_DBG_PORT 0x2A1C
+#define SENINF3_CSI2_SPARE0 0x2A20
+#define SENINF3_CSI2_SPARE1 0x2A24
+#define SENINF3_CSI2_LNRC_FSM 0x2A28
+#define SENINF3_CSI2_LNRD_FSM 0x2A2C
+#define SENINF3_CSI2_FRAME_LINE_NUM 0x2A30
+#define SENINF3_CSI2_GENERIC_SHORT 0x2A34
+#define SENINF3_CSI2_HSRX_DBG 0x2A38
+#define SENINF3_CSI2_DI 0x2A3C
+#define SENINF3_CSI2_HS_TRAIL 0x2A40
+#define SENINF3_CSI2_DI_CTRL 0x2A44
+#define SENINF3_CSI2_DETECT_CON1 0x2A4C
+#define SENINF3_CSI2_DETECT_CON2 0x2A50
+#define SENINF3_CSI2_DETECT_CON3 0x2A54
+#define SENINF3_CSI2_RLR0_CON0 0x2A58
+#define SENINF3_CSI2_RLR1_CON0 0x2A5C
+#define SENINF3_CSI2_RLR2_CON0 0x2A60
+#define SENINF3_CSI2_RLR_CON0 0x2A64
+#define SENINF3_CSI2_MUX_CON 0x2A68
+#define SENINF3_CSI2_DETECT_DBG0 0x2A6C
+#define SENINF3_CSI2_DETECT_DBG1 0x2A70
+#define SENINF3_CSI2_RESYNC_MERGE_CTL 0x2A74
+#define SENINF3_CSI2_CTRL_TRIO_MUX 0x2A78
+#define SENINF3_CSI2_CTRL_TRIO_CON 0x2A7C
+#define SENINF3_FIX_ADDR_CPHY0_DBG 0x2A80
+#define SENINF3_FIX_ADDR_CPHY1_DBG 0x2A84
+#define SENINF3_FIX_ADDR_CPHY2_DBG 0x2A88
+#define SENINF3_FIX_ADDR_DBG 0x2A8C
+#define SENINF3_WIRE_STATE_DECODE_CPHY0_DBG0 0x2A90
+#define SENINF3_WIRE_STATE_DECODE_CPHY0_DBG1 0x2A94
+#define SENINF3_WIRE_STATE_DECODE_CPHY1_DBG0 0x2A98
+#define SENINF3_WIRE_STATE_DECODE_CPHY1_DBG1 0x2A9C
+#define SENINF3_WIRE_STATE_DECODE_CPHY2_DBG0 0x2AA0
+#define SENINF3_WIRE_STATE_DECODE_CPHY2_DBG1 0x2AA4
+#define SENINF3_SYNC_RESYNC_CTL 0x2AA8
+#define SENINF3_POST_DETECT_CTL 0x2AAC
+#define SENINF3_WIRE_STATE_DECODE_CONFIG 0x2AB0
+#define SENINF3_CSI2_CPHY_LNRD_FSM 0x2AB4
+#define SENINF3_FIX_ADDR_CPHY0_DBG0 0x2AB8
+#define SENINF3_FIX_ADDR_CPHY0_DBG1 0x2ABC
+#define SENINF3_FIX_ADDR_CPHY0_DBG2 0x2AC0
+#define SENINF3_FIX_ADDR_CPHY1_DBG0 0x2AC4
+#define SENINF3_FIX_ADDR_CPHY1_DBG1 0x2AC8
+#define SENINF3_FIX_ADDR_CPHY1_DBG2 0x2ACC
+#define SENINF3_FIX_ADDR_CPHY2_DBG0 0x2AD0
+#define SENINF3_FIX_ADDR_CPHY2_DBG1 0x2AD4
+#define SENINF3_FIX_ADDR_CPHY2_DBG2 0x2AD8
+#define SENINF3_FIX_ADDR_DBG0 0x2ADC
+#define SENINF3_FIX_ADDR_DBG1 0x2AE0
+#define SENINF3_FIX_ADDR_DBG2 0x2AE4
+#define SENINF3_CSI2_MODE 0x2AE8
+#define SENINF3_CSI2_DI_EXT 0x2AF0
+#define SENINF3_CSI2_DI_CTRL_EXT 0x2AF4
+#define SENINF3_CSI2_CPHY_LOOPBACK 0x2AF8
+#define SENINF3_CSI2_PROGSEQ_0 0x2B00
+#define SENINF3_CSI2_PROGSEQ_1 0x2B04
+#define SENINF3_CSI2_INT_EN_EXT 0x2B10
+#define SENINF3_CSI2_INT_STATUS_EXT 0x2B14
+#define SENINF3_CSI2_CPHY_FIX_POINT_RST 0x2B18
+#define SENINF3_CSI2_RLR3_CON0 0x2B1C
+#define SENINF3_CSI2_DPHY_SYNC 0x2B20
+#define SENINF3_CSI2_DESKEW_SYNC 0x2B24
+#define SENINF3_CSI2_DETECT_DBG2 0x2B28
+#define SENINF3_FIX_ADDR_CPHY3_DBG0 0x2B30
+#define SENINF3_FIX_ADDR_CPHY3_DBG1 0x2B34
+#define SENINF3_FIX_ADDR_CPHY3_DBG2 0x2B38
+#define SENINF3_CSI2_DI_EXT_2 0x2B3C
+#define SENINF3_CSI2_DI_CTRL_EXT_2 0x2B40
+#define SENINF3_WIRE_STATE_DECODE_CPHY3_DBG0 0x2B44
+#define SENINF3_WIRE_STATE_DECODE_CPHY3_DBG1 0x2B48
+#define SENINF3_MUX_CTRL 0x2D00
+#define SENINF3_MUX_INTEN 0x2D04
+#define SENINF3_MUX_INTSTA 0x2D08
+#define SENINF3_MUX_SIZE 0x2D0C
+#define SENINF3_MUX_DEBUG_1 0x2D10
+#define SENINF3_MUX_DEBUG_2 0x2D14
+#define SENINF3_MUX_DEBUG_3 0x2D18
+#define SENINF3_MUX_DEBUG_4 0x2D1C
+#define SENINF3_MUX_DEBUG_5 0x2D20
+#define SENINF3_MUX_DEBUG_6 0x2D24
+#define SENINF3_MUX_DEBUG_7 0x2D28
+#define SENINF3_MUX_SPARE 0x2D2C
+#define SENINF3_MUX_DATA 0x2D30
+#define SENINF3_MUX_DATA_CNT 0x2D34
+#define SENINF3_MUX_CROP 0x2D38
+#define SENINF3_MUX_CTRL_EXT 0x2D3C
+#define SENINF4_CTRL 0x3200
+#define SENINF4_CTRL_EXT 0x3204
+#define SENINF4_ASYNC_CTRL 0x3208
+#define SENINF_TG4_PH_CNT 0x3600
+#define SENINF_TG4_SEN_CK 0x3604
+#define SENINF_TG4_TM_CTL 0x3608
+#define SENINF_TG4_TM_SIZE 0x360C
+#define SENINF_TG4_TM_CLK 0x3610
+#define SENINF_TG4_TM_STP 0x3614
+#define MIPI_RX_CON24_CSI3 0x3824
+#define MIPI_RX_CON28_CSI3 0x3828
+#define MIPI_RX_CON34_CSI3 0x3834
+#define MIPI_RX_CON38_CSI3 0x3838
+#define MIPI_RX_CON3C_CSI3 0x383C
+#define MIPI_RX_CON7C_CSI3 0x387C
+#define MIPI_RX_CON80_CSI3 0x3880
+#define MIPI_RX_CON84_CSI3 0x3884
+#define MIPI_RX_CON88_CSI3 0x3888
+#define MIPI_RX_CON8C_CSI3 0x388C
+#define MIPI_RX_CON90_CSI3 0x3890
+#define MIPI_RX_CON94_CSI3 0x3894
+#define MIPI_RX_CON98_CSI3 0x3898
+#define MIPI_RX_CONA0_CSI3 0x38A0
+#define MIPI_RX_CONB0_CSI3 0x38B0
+#define MIPI_RX_CONB4_CSI3 0x38B4
+#define MIPI_RX_CONB8_CSI3 0x38B8
+#define MIPI_RX_CONBC_CSI3 0x38BC
+#define MIPI_RX_CONC0_CSI3 0x38C0
+#define MIPI_RX_CONC4_CSI3 0x38C4
+#define MIPI_RX_CONC8_CSI3 0x38C8
+#define MIPI_RX_CONCC_CSI3 0x38CC
+#define MIPI_RX_COND0_CSI3 0x38D0
+#define SENINF4_CSI2_CTL 0x3A00
+#define SENINF4_CSI2_LNRC_TIMING 0x3A04
+#define SENINF4_CSI2_LNRD_TIMING 0x3A08
+#define SENINF4_CSI2_DPCM 0x3A0C
+#define SENINF4_CSI2_INT_EN 0x3A10
+#define SENINF4_CSI2_INT_STATUS 0x3A14
+#define SENINF4_CSI2_DGB_SEL 0x3A18
+#define SENINF4_CSI2_DBG_PORT 0x3A1C
+#define SENINF4_CSI2_SPARE0 0x3A20
+#define SENINF4_CSI2_SPARE1 0x3A24
+#define SENINF4_CSI2_LNRC_FSM 0x3A28
+#define SENINF4_CSI2_LNRD_FSM 0x3A2C
+#define SENINF4_CSI2_FRAME_LINE_NUM 0x3A30
+#define SENINF4_CSI2_GENERIC_SHORT 0x3A34
+#define SENINF4_CSI2_HSRX_DBG 0x3A38
+#define SENINF4_CSI2_DI 0x3A3C
+#define SENINF4_CSI2_HS_TRAIL 0x3A40
+#define SENINF4_CSI2_DI_CTRL 0x3A44
+#define SENINF4_CSI2_DETECT_CON1 0x3A4C
+#define SENINF4_CSI2_DETECT_CON2 0x3A50
+#define SENINF4_CSI2_DETECT_CON3 0x3A54
+#define SENINF4_CSI2_RLR0_CON0 0x3A58
+#define SENINF4_CSI2_RLR1_CON0 0x3A5C
+#define SENINF4_CSI2_RLR2_CON0 0x3A60
+#define SENINF4_CSI2_RLR_CON0 0x3A64
+#define SENINF4_CSI2_MUX_CON 0x3A68
+#define SENINF4_CSI2_DETECT_DBG0 0x3A6C
+#define SENINF4_CSI2_DETECT_DBG1 0x3A70
+#define SENINF4_CSI2_RESYNC_MERGE_CTL 0x3A74
+#define SENINF4_CSI2_CTRL_TRIO_MUX 0x3A78
+#define SENINF4_CSI2_CTRL_TRIO_CON 0x3A7C
+#define SENINF4_FIX_ADDR_CPHY0_DBG 0x3A80
+#define SENINF4_FIX_ADDR_CPHY1_DBG 0x3A84
+#define SENINF4_FIX_ADDR_CPHY2_DBG 0x3A88
+#define SENINF4_FIX_ADDR_DBG 0x3A8C
+#define SENINF4_WIRE_STATE_DECODE_CPHY0_DBG0 0x3A90
+#define SENINF4_WIRE_STATE_DECODE_CPHY0_DBG1 0x3A94
+#define SENINF4_WIRE_STATE_DECODE_CPHY1_DBG0 0x3A98
+#define SENINF4_WIRE_STATE_DECODE_CPHY1_DBG1 0x3A9C
+#define SENINF4_WIRE_STATE_DECODE_CPHY2_DBG0 0x3AA0
+#define SENINF4_WIRE_STATE_DECODE_CPHY2_DBG1 0x3AA4
+#define SENINF4_SYNC_RESYNC_CTL 0x3AA8
+#define SENINF4_POST_DETECT_CTL 0x3AAC
+#define SENINF4_WIRE_STATE_DECODE_CONFIG 0x3AB0
+#define SENINF4_CSI2_CPHY_LNRD_FSM 0x3AB4
+#define SENINF4_FIX_ADDR_CPHY0_DBG0 0x3AB8
+#define SENINF4_FIX_ADDR_CPHY0_DBG1 0x3ABC
+#define SENINF4_FIX_ADDR_CPHY0_DBG2 0x3AC0
+#define SENINF4_FIX_ADDR_CPHY1_DBG0 0x3AC4
+#define SENINF4_FIX_ADDR_CPHY1_DBG1 0x3AC8
+#define SENINF4_FIX_ADDR_CPHY1_DBG2 0x3ACC
+#define SENINF4_FIX_ADDR_CPHY2_DBG0 0x3AD0
+#define SENINF4_FIX_ADDR_CPHY2_DBG1 0x3AD4
+#define SENINF4_FIX_ADDR_CPHY2_DBG2 0x3AD8
+#define SENINF4_FIX_ADDR_DBG0 0x3ADC
+#define SENINF4_FIX_ADDR_DBG1 0x3AE0
+#define SENINF4_FIX_ADDR_DBG2 0x3AE4
+#define SENINF4_CSI2_MODE 0x3AE8
+#define SENINF4_CSI2_DI_EXT 0x3AF0
+#define SENINF4_CSI2_DI_CTRL_EXT 0x3AF4
+#define SENINF4_CSI2_CPHY_LOOPBACK 0x3AF8
+#define SENINF4_CSI2_PROGSEQ_0 0x3B00
+#define SENINF4_CSI2_PROGSEQ_1 0x3B04
+#define SENINF4_CSI2_INT_EN_EXT 0x3B10
+#define SENINF4_CSI2_INT_STATUS_EXT 0x3B14
+#define SENINF4_CSI2_CPHY_FIX_POINT_RST 0x3B18
+#define SENINF4_CSI2_RLR3_CON0 0x3B1C
+#define SENINF4_CSI2_DPHY_SYNC 0x3B20
+#define SENINF4_CSI2_DESKEW_SYNC 0x3B24
+#define SENINF4_CSI2_DETECT_DBG2 0x3B28
+#define SENINF4_FIX_ADDR_CPHY3_DBG0 0x3B30
+#define SENINF4_FIX_ADDR_CPHY3_DBG1 0x3B34
+#define SENINF4_FIX_ADDR_CPHY3_DBG2 0x3B38
+#define SENINF4_CSI2_DI_EXT_2 0x3B3C
+#define SENINF4_CSI2_DI_CTRL_EXT_2 0x3B40
+#define SENINF4_WIRE_STATE_DECODE_CPHY3_DBG0 0x3B44
+#define SENINF4_WIRE_STATE_DECODE_CPHY3_DBG1 0x3B48
+#define SENINF4_MUX_CTRL 0x3D00
+#define SENINF4_MUX_INTEN 0x3D04
+#define SENINF4_MUX_INTSTA 0x3D08
+#define SENINF4_MUX_SIZE 0x3D0C
+#define SENINF4_MUX_DEBUG_1 0x3D10
+#define SENINF4_MUX_DEBUG_2 0x3D14
+#define SENINF4_MUX_DEBUG_3 0x3D18
+#define SENINF4_MUX_DEBUG_4 0x3D1C
+#define SENINF4_MUX_DEBUG_5 0x3D20
+#define SENINF4_MUX_DEBUG_6 0x3D24
+#define SENINF4_MUX_DEBUG_7 0x3D28
+#define SENINF4_MUX_SPARE 0x3D2C
+#define SENINF4_MUX_DATA 0x3D30
+#define SENINF4_MUX_DATA_CNT 0x3D34
+#define SENINF4_MUX_CROP 0x3D38
+#define SENINF4_MUX_CTRL_EXT 0x3D3C
+#define SENINF5_CTRL 0x4200
+#define SENINF5_CTRL_EXT 0x4204
+#define SENINF5_ASYNC_CTRL 0x4208
+#define SENINF_TG5_PH_CNT 0x4600
+#define SENINF_TG5_SEN_CK 0x4604
+#define SENINF_TG5_TM_CTL 0x4608
+#define SENINF_TG5_TM_SIZE 0x460C
+#define SENINF_TG5_TM_CLK 0x4610
+#define SENINF_TG5_TM_STP 0x4614
+#define MIPI_RX_CON24_CSI4 0x4824
+#define MIPI_RX_CON28_CSI4 0x4828
+#define MIPI_RX_CON34_CSI4 0x4834
+#define MIPI_RX_CON38_CSI4 0x4838
+#define MIPI_RX_CON3C_CSI4 0x483C
+#define MIPI_RX_CON7C_CSI4 0x487C
+#define MIPI_RX_CON80_CSI4 0x4880
+#define MIPI_RX_CON84_CSI4 0x4884
+#define MIPI_RX_CON88_CSI4 0x4888
+#define MIPI_RX_CON8C_CSI4 0x488C
+#define MIPI_RX_CON90_CSI4 0x4890
+#define MIPI_RX_CON94_CSI4 0x4894
+#define MIPI_RX_CON98_CSI4 0x4898
+#define MIPI_RX_CONA0_CSI4 0x48A0
+#define MIPI_RX_CONB0_CSI4 0x48B0
+#define MIPI_RX_CONB4_CSI4 0x48B4
+#define MIPI_RX_CONB8_CSI4 0x48B8
+#define MIPI_RX_CONBC_CSI4 0x48BC
+#define MIPI_RX_CONC0_CSI4 0x48C0
+#define MIPI_RX_CONC4_CSI4 0x48C4
+#define MIPI_RX_CONC8_CSI4 0x48C8
+#define MIPI_RX_CONCC_CSI4 0x48CC
+#define MIPI_RX_COND0_CSI4 0x48D0
+#define SENINF5_CSI2_CTL 0x4A00
+#define SENINF5_CSI2_LNRC_TIMING 0x4A04
+#define SENINF5_CSI2_LNRD_TIMING 0x4A08
+#define SENINF5_CSI2_DPCM 0x4A0C
+#define SENINF5_CSI2_INT_EN 0x4A10
+#define SENINF5_CSI2_INT_STATUS 0x4A14
+#define SENINF5_CSI2_DGB_SEL 0x4A18
+#define SENINF5_CSI2_DBG_PORT 0x4A1C
+#define SENINF5_CSI2_SPARE0 0x4A20
+#define SENINF5_CSI2_SPARE1 0x4A24
+#define SENINF5_CSI2_LNRC_FSM 0x4A28
+#define SENINF5_CSI2_LNRD_FSM 0x4A2C
+#define SENINF5_CSI2_FRAME_LINE_NUM 0x4A30
+#define SENINF5_CSI2_GENERIC_SHORT 0x4A34
+#define SENINF5_CSI2_HSRX_DBG 0x4A38
+#define SENINF5_CSI2_DI 0x4A3C
+#define SENINF5_CSI2_HS_TRAIL 0x4A40
+#define SENINF5_CSI2_DI_CTRL 0x4A44
+#define SENINF5_CSI2_DETECT_CON1 0x4A4C
+#define SENINF5_CSI2_DETECT_CON2 0x4A50
+#define SENINF5_CSI2_DETECT_CON3 0x4A54
+#define SENINF5_CSI2_RLR0_CON0 0x4A58
+#define SENINF5_CSI2_RLR1_CON0 0x4A5C
+#define SENINF5_CSI2_RLR2_CON0 0x4A60
+#define SENINF5_CSI2_RLR_CON0 0x4A64
+#define SENINF5_CSI2_MUX_CON 0x4A68
+#define SENINF5_CSI2_DETECT_DBG0 0x4A6C
+#define SENINF5_CSI2_DETECT_DBG1 0x4A70
+#define SENINF5_CSI2_RESYNC_MERGE_CTL 0x4A74
+#define SENINF5_CSI2_CTRL_TRIO_MUX 0x4A78
+#define SENINF5_CSI2_CTRL_TRIO_CON 0x4A7C
+#define SENINF5_FIX_ADDR_CPHY0_DBG 0x4A80
+#define SENINF5_FIX_ADDR_CPHY1_DBG 0x4A84
+#define SENINF5_FIX_ADDR_CPHY2_DBG 0x4A88
+#define SENINF5_FIX_ADDR_DBG 0x4A8C
+#define SENINF5_WIRE_STATE_DECODE_CPHY0_DBG0 0x4A90
+#define SENINF5_WIRE_STATE_DECODE_CPHY0_DBG1 0x4A94
+#define SENINF5_WIRE_STATE_DECODE_CPHY1_DBG0 0x4A98
+#define SENINF5_WIRE_STATE_DECODE_CPHY1_DBG1 0x4A9C
+#define SENINF5_WIRE_STATE_DECODE_CPHY2_DBG0 0x4AA0
+#define SENINF5_WIRE_STATE_DECODE_CPHY2_DBG1 0x4AA4
+#define SENINF5_SYNC_RESYNC_CTL 0x4AA8
+#define SENINF5_POST_DETECT_CTL 0x4AAC
+#define SENINF5_WIRE_STATE_DECODE_CONFIG 0x4AB0
+#define SENINF5_CSI2_CPHY_LNRD_FSM 0x4AB4
+#define SENINF5_FIX_ADDR_CPHY0_DBG0 0x4AB8
+#define SENINF5_FIX_ADDR_CPHY0_DBG1 0x4ABC
+#define SENINF5_FIX_ADDR_CPHY0_DBG2 0x4AC0
+#define SENINF5_FIX_ADDR_CPHY1_DBG0 0x4AC4
+#define SENINF5_FIX_ADDR_CPHY1_DBG1 0x4AC8
+#define SENINF5_FIX_ADDR_CPHY1_DBG2 0x4ACC
+#define SENINF5_FIX_ADDR_CPHY2_DBG0 0x4AD0
+#define SENINF5_FIX_ADDR_CPHY2_DBG1 0x4AD4
+#define SENINF5_FIX_ADDR_CPHY2_DBG2 0x4AD8
+#define SENINF5_FIX_ADDR_DBG0 0x4ADC
+#define SENINF5_FIX_ADDR_DBG1 0x4AE0
+#define SENINF5_FIX_ADDR_DBG2 0x4AE4
+#define SENINF5_CSI2_MODE 0x4AE8
+#define SENINF5_CSI2_DI_EXT 0x4AF0
+#define SENINF5_CSI2_DI_CTRL_EXT 0x4AF4
+#define SENINF5_CSI2_CPHY_LOOPBACK 0x4AF8
+#define SENINF5_CSI2_PROGSEQ_0 0x4B00
+#define SENINF5_CSI2_PROGSEQ_1 0x4B04
+#define SENINF5_CSI2_INT_EN_EXT 0x4B10
+#define SENINF5_CSI2_INT_STATUS_EXT 0x4B14
+#define SENINF5_CSI2_CPHY_FIX_POINT_RST 0x4B18
+#define SENINF5_CSI2_RLR3_CON0 0x4B1C
+#define SENINF5_CSI2_DPHY_SYNC 0x4B20
+#define SENINF5_CSI2_DESKEW_SYNC 0x4B24
+#define SENINF5_CSI2_DETECT_DBG2 0x4B28
+#define SENINF5_FIX_ADDR_CPHY3_DBG0 0x4B30
+#define SENINF5_FIX_ADDR_CPHY3_DBG1 0x4B34
+#define SENINF5_FIX_ADDR_CPHY3_DBG2 0x4B38
+#define SENINF5_CSI2_DI_EXT_2 0x4B3C
+#define SENINF5_CSI2_DI_CTRL_EXT_2 0x4B40
+#define SENINF5_WIRE_STATE_DECODE_CPHY3_DBG0 0x4B44
+#define SENINF5_WIRE_STATE_DECODE_CPHY3_DBG1 0x4B48
+#define SENINF5_MUX_CTRL 0x4D00
+#define SENINF5_MUX_INTEN 0x4D04
+#define SENINF5_MUX_INTSTA 0x4D08
+#define SENINF5_MUX_SIZE 0x4D0C
+#define SENINF5_MUX_DEBUG_1 0x4D10
+#define SENINF5_MUX_DEBUG_2 0x4D14
+#define SENINF5_MUX_DEBUG_3 0x4D18
+#define SENINF5_MUX_DEBUG_4 0x4D1C
+#define SENINF5_MUX_DEBUG_5 0x4D20
+#define SENINF5_MUX_DEBUG_6 0x4D24
+#define SENINF5_MUX_DEBUG_7 0x4D28
+#define SENINF5_MUX_SPARE 0x4D2C
+#define SENINF5_MUX_DATA 0x4D30
+#define SENINF5_MUX_DATA_CNT 0x4D34
+#define SENINF5_MUX_CROP 0x4D38
+#define SENINF5_MUX_CTRL_EXT 0x4D3C
+#define SENINF6_MUX_CTRL 0x5D00
+#define SENINF6_MUX_INTEN 0x5D04
+#define SENINF6_MUX_INTSTA 0x5D08
+#define SENINF6_MUX_SIZE 0x5D0C
+#define SENINF6_MUX_DEBUG_1 0x5D10
+#define SENINF6_MUX_DEBUG_2 0x5D14
+#define SENINF6_MUX_DEBUG_3 0x5D18
+#define SENINF6_MUX_DEBUG_4 0x5D1C
+#define SENINF6_MUX_DEBUG_5 0x5D20
+#define SENINF6_MUX_DEBUG_6 0x5D24
+#define SENINF6_MUX_DEBUG_7 0x5D28
+#define SENINF6_MUX_SPARE 0x5D2C
+#define SENINF6_MUX_DATA 0x5D30
+#define SENINF6_MUX_DATA_CNT 0x5D34
+#define SENINF6_MUX_CROP 0x5D38
+#define SENINF6_MUX_CTRL_EXT 0x5D3C
+#define SENINF7_MUX_CTRL 0x6D00
+#define SENINF7_MUX_INTEN 0x6D04
+#define SENINF7_MUX_INTSTA 0x6D08
+#define SENINF7_MUX_SIZE 0x6D0C
+#define SENINF7_MUX_DEBUG_1 0x6D10
+#define SENINF7_MUX_DEBUG_2 0x6D14
+#define SENINF7_MUX_DEBUG_3 0x6D18
+#define SENINF7_MUX_DEBUG_4 0x6D1C
+#define SENINF7_MUX_DEBUG_5 0x6D20
+#define SENINF7_MUX_DEBUG_6 0x6D24
+#define SENINF7_MUX_DEBUG_7 0x6D28
+#define SENINF7_MUX_SPARE 0x6D2C
+#define SENINF7_MUX_DATA 0x6D30
+#define SENINF7_MUX_DATA_CNT 0x6D34
+#define SENINF7_MUX_CROP 0x6D38
+#define SENINF7_MUX_CTRL_EXT 0x6D3C
+#define SENINF8_MUX_CTRL 0x7D00
+#define SENINF8_MUX_INTEN 0x7D04
+#define SENINF8_MUX_INTSTA 0x7D08
+#define SENINF8_MUX_SIZE 0x7D0C
+#define SENINF8_MUX_DEBUG_1 0x7D10
+#define SENINF8_MUX_DEBUG_2 0x7D14
+#define SENINF8_MUX_DEBUG_3 0x7D18
+#define SENINF8_MUX_DEBUG_4 0x7D1C
+#define SENINF8_MUX_DEBUG_5 0x7D20
+#define SENINF8_MUX_DEBUG_6 0x7D24
+#define SENINF8_MUX_DEBUG_7 0x7D28
+#define SENINF8_MUX_SPARE 0x7D2C
+#define SENINF8_MUX_DATA 0x7D30
+#define SENINF8_MUX_DATA_CNT 0x7D34
+#define SENINF8_MUX_CROP 0x7D38
+#define SENINF8_MUX_CTRL_EXT 0x7D3C
+
+#endif /* _SENINF_REG_H_ */
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 0/9] added helper macros to remove duplicate code from probe functions of the platform drivers
From: Satendra Singh Thakur @ 2019-09-15 7:00 UTC (permalink / raw)
To: dan.j.williams, vkoul, jun.nie, shawnguo, agross, sean.wang,
matthias.bgg, maxime.ripard, wens, lars, afaerber,
manivannan.sadhasivam
Cc: linux-kernel, linux-mediatek, satendrasingh.thakur, dmaengine,
Satendra Singh Thakur, linux-arm-kernel
1. For most of the platform drivers's probe include following steps
-memory allocation for driver's private structure
-getting io resources
-io remapping resources
-getting irq number
-registering irq
-setting driver's private data
-getting clock
-preparing and enabling clock
2. We have defined a set of macros to combine some or all of
the above mentioned steps. This will remove redundant/duplicate
code in drivers' probe functions of platform drivers.
devm_platform_probe_helper(pdev, priv, clk_name);
devm_platform_probe_helper_clk(pdev, priv, clk_name);
devm_platform_probe_helper_irq(pdev, priv, clk_name,
irq_hndlr, irq_flags, irq_name, irq_devid);
devm_platform_probe_helper_all(pdev, priv, clk_name,
irq_hndlr, irq_flags, irq_name, irq_devid);
devm_platform_probe_helper_all_data(pdev, priv, clk_name,
irq_hndlr, irq_flags, irq_name, irq_devid);
3. Code is made devres compatible (wherever required)
The functions: clk_get, request_irq, kzalloc, platform_get_resource
are replaced with their devm_* counterparts.
4. Few bugs are also fixed.
Satendra Singh Thakur (9):
probe/dma : added helper macros to remove redundant/duplicate code
from probe functions of the dma controller drivers
probe/dma/jz4740: removed redundant code from jz4740 dma controller's
probe function
probe/dma/zx: removed redundant code from zx dma controller's probe
function
probe/dma/qcom-bam: removed redundant code from qcom bam dma
controller's probe function
probe/dma/mtk-hs: removed redundant code from mediatek hs dma
controller's probe function
probe/dma/sun6i: removed redundant code from sun6i dma controller's
probe function
probe/dma/sun4i: removed redundant code from sun4i dma controller's
probe function
probe/dma/axi: removed redundant code from axi dma controller's probe
function
probe/dma/owl: removed redundant code from owl dma controller's probe
function
drivers/dma/dma-axi-dmac.c | 28 ++---
drivers/dma/dma-jz4740.c | 33 +++---
drivers/dma/mediatek/mtk-hsdma.c | 38 +++----
drivers/dma/owl-dma.c | 29 ++---
drivers/dma/qcom/bam_dma.c | 71 +++++-------
drivers/dma/sun4i-dma.c | 30 ++----
drivers/dma/sun6i-dma.c | 30 ++----
drivers/dma/zx_dma.c | 35 ++----
include/linux/probe-helper.h | 179 +++++++++++++++++++++++++++++++
9 files changed, 280 insertions(+), 193 deletions(-)
create mode 100644 include/linux/probe-helper.h
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 1/9] probe/dma : added helper macros to remove redundant/duplicate code from probe functions of the dma controller drivers
From: Satendra Singh Thakur @ 2019-09-15 7:26 UTC (permalink / raw)
To: dan.j.williams, vkoul, jun.nie, shawnguo, agross, sean.wang,
matthias.bgg, maxime.ripard, wens, lars, afaerber,
manivannan.sadhasivam
Cc: linux-kernel, linux-mediatek, satendrasingh.thakur, dmaengine,
Satendra Singh Thakur, linux-arm-kernel
In-Reply-To: <20190915070003.21260-1-sst2005@gmail.com>
1. For most of the drivers probe include following steps
a) memory allocation for driver's private structure
b) getting io resources
c) io remapping resources
d) getting clock
e) getting irq number
f) registering irq
g) preparing and enabling clock
i) setting platform's drv data
2. We have defined a set of macros to combine above mentioned
steps.
This will remove redundant/duplicate code in drivers' probe
functions.
3. This macro combines all the steps except f), g) and i).
devm_platform_probe_helper(pdev, priv, clk_name);
4. This macro combines all the steps except f) and i).
devm_platform_probe_helper_clk(pdev, priv, clk_name);
5. This macro combines all the steps except g) and i).
devm_platform_probe_helper_irq(pdev, priv, clk_name,
irq_hndlr, irq_flags, irq_name, irq_devid);
6. This is because, some drivers perform step f) and g)
after hw init or subsys registration at very different points
in the probe function. The step i) is called at the end of
probe function by several drivers; while other drivers call it at
different points in probe function.
7. This macro combines above mentioned steps a) to g).
devm_platform_probe_helper_all(pdev, priv, clk_name,
irq_hndlr, irq_flags, irq_name, irq_devid);
8. This macro combines all of the above mentioned steps a) to i).
devm_platform_probe_helper_all_data(pdev, priv, clk_name,
irq_hndlr, irq_flags, irq_name, irq_devid);
9. Above macros will be useful for wide variety of probe
functions of different drivers.
Signed-off-by: Satendra Singh Thakur <satendrasingh.thakur@hcl.com>
Signed-off-by: Satendra Singh Thakur <sst2005@gmail.com>
---
include/linux/probe-helper.h | 179 +++++++++++++++++++++++++++++++++++
1 file changed, 179 insertions(+)
create mode 100644 include/linux/probe-helper.h
diff --git a/include/linux/probe-helper.h b/include/linux/probe-helper.h
new file mode 100644
index 000000000000..7baa468509e3
--- /dev/null
+++ b/include/linux/probe-helper.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * probe_helper.h - helper functions for platform drivers' probe
+ * function
+ * Author: Satendra Singh Thakur <satendrasingh.thakur@hcl.com> Sep 2019
+ * <sst2005@gmail.com>
+ */
+#ifndef _PROBE_HELPER_H_
+#define _PROBE_HELPER_H_
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+/* devm_platform_probe_helper - Macro for helping probe method
+ * of platform drivers
+ * This macro combines the functions:
+ * devm_kzalloc, platform_get_resource, devm_ioremap_resource,
+ * devm_clk_get, platform_get_irq
+ * @pdev platform device
+ * @priv driver's private object for memory allocation
+ * @clk_name clock name as in DT
+ */
+#define devm_platform_probe_helper(pdev, priv, clk_name) \
+({ \
+ __label__ __out; \
+ int __ret = 0; \
+ priv = devm_kzalloc(&(pdev)->dev, sizeof(*priv), GFP_KERNEL); \
+ if (!(priv)) { \
+ dev_err(&(pdev)->dev, "devm_kzalloc failed\n"); \
+ __ret = -ENOMEM; \
+ goto __out; \
+ } \
+ (priv)->base = devm_platform_ioremap_resource(pdev, 0); \
+ if (IS_ERR((priv)->base)) { \
+ dev_err(&(pdev)->dev, \
+ "devm_platform_ioremap_resource failed\n"); \
+ __ret = PTR_ERR((priv)->base); \
+ goto __out; \
+ } \
+ (priv)->clk = devm_clk_get(&(pdev)->dev, clk_name); \
+ if (IS_ERR((priv)->clk)) { \
+ dev_err(&(pdev)->dev, "devm_clk_get failed\n"); \
+ __ret = PTR_ERR((priv)->clk); \
+ goto __out; \
+ } \
+ (priv)->irq = platform_get_irq(pdev, 0); \
+ if ((priv)->irq < 0) { \
+ dev_err(&(pdev)->dev, "platform_get_irq failed\n"); \
+ __ret = (priv)->irq; \
+ goto __out; \
+ } \
+__out: \
+ __ret; \
+})
+
+/* devm_platform_probe_helper_irq - Macro for helping probe method
+ * of platform drivers
+ * This macro combines the functions:
+ * devm_kzalloc, platform_get_resource, devm_ioremap_resource,
+ * devm_clk_get, platform_get_irq, devm_request_irq
+ * @pdev platform device
+ * @priv driver's private object for memory allocation
+ * @clk_name clock name as in DT
+ * @irq_hndlr interrupt handler function (isr)
+ * @irq_flags flags for interrupt registration
+ * @irq_name name of the interrupt handler
+ * @irq_devid device identifier for irq
+ */
+#define devm_platform_probe_helper_irq(pdev, priv, clk_name, \
+ irq_hndlr, irq_flags, irq_name, irq_devid) \
+({ \
+ __label__ __out; \
+ int __ret = 0; \
+ __ret = devm_platform_probe_helper(pdev, priv, clk_name); \
+ if (__ret < 0) \
+ goto __out; \
+ __ret = devm_request_irq(&(pdev)->dev, (priv)->irq, irq_hndlr, \
+ irq_flags, irq_name, irq_devid); \
+ if (__ret < 0) { \
+ dev_err(&(pdev)->dev, \
+ "devm_request_irq failed for irq num %d\n", \
+ (priv)->irq); \
+ goto __out; \
+ } \
+__out: \
+ __ret; \
+})
+
+/* devm_platform_probe_helper_clk Macro - for helping probe method
+ * of platform drivers
+ * This macro combines the functions:
+ * devm_kzalloc, platform_get_resource, devm_ioremap_resource,
+ * devm_clk_get, platform_get_irq, clk_prepare_enable
+ * @pdev platform device
+ * @priv driver's private object for memory allocation
+ * @clk_name clock name as in DT
+ */
+#define devm_platform_probe_helper_clk(pdev, priv, clk_name) \
+({ \
+ __label__ __out; \
+ int __ret = 0; \
+ __ret = devm_platform_probe_helper(pdev, priv, clk_name); \
+ if (__ret < 0) \
+ goto __out; \
+ __ret = clk_prepare_enable((priv)->clk); \
+ if (__ret < 0) { \
+ dev_err(&(pdev)->dev, "clk_prepare_enable failed\n"); \
+ goto __out; \
+ } \
+__out: \
+ __ret; \
+})
+
+/* devm_platform_probe_helper_all - Macro for helping probe method
+ * of platform drivers
+ * This macro combines the functions:
+ * devm_kzalloc, platform_get_resource, devm_ioremap_resource,
+ * devm_clk_get, platform_get_irq, devm_request_irq,
+ * clk_prepare_enable
+ * @pdev platform device
+ * @priv driver's private object for memory allocation
+ * @clk_name clock name as in DT
+ * @irq_hndlr interrupt handler function (isr)
+ * @irq_flags flags for interrupt registration
+ * @irq_name name of the interrupt handler
+ * @irq_devid device identifier for irq
+ */
+#define devm_platform_probe_helper_all(pdev, priv, clk_name, \
+ irq_hndlr, irq_flags, irq_name, irq_devid) \
+({ \
+ __label__ __out; \
+ int __ret = 0; \
+ __ret = devm_platform_probe_helper_clk(pdev, priv, clk_name); \
+ if (__ret < 0) \
+ goto __out; \
+ __ret = devm_request_irq(&(pdev)->dev, (priv)->irq, \
+ irq_hndlr, irq_flags, irq_name, irq_devid); \
+ if (__ret < 0) { \
+ dev_err(&(pdev)->dev, \
+ "devm_request_irq failed for irq num %d\n", \
+ (priv)->irq); \
+ if ((priv)->clk) \
+ clk_disable_unprepare((priv)->clk); \
+ goto __out; \
+ } \
+__out: \
+ __ret; \
+})
+
+/* devm_platform_probe_helper_all_data - Macro for helping probe method
+ * of platform drivers
+ * This macro combines the functions:
+ * devm_kzalloc, platform_get_resource, devm_ioremap_resource,
+ * devm_clk_get, platform_get_irq, devm_request_irq,
+ * clk_prepare_enable, platform_set_drvdata
+ * @pdev platform device
+ * @priv driver's private object for memory allocation
+ * @clk_name clock name as in DT
+ * @irq_hndlr interrupt handler function (isr)
+ * @irq_flags flags for interrupt registration
+ * @irq_name name of the interrupt handler
+ * @irq_devid device identifier for irq
+ */
+#define devm_platform_probe_helper_all_data(pdev, priv, clk_name, \
+ irq_hndlr, irq_flags, irq_name, irq_devid) \
+({ \
+ __label__ __out; \
+ int __ret = 0; \
+ __ret = devm_platform_probe_helper_all(pdev, priv, clk_name, \
+ irq_hndlr, irq_flags, irq_name, irq_devid); \
+ if (__ret < 0) \
+ goto __out; \
+ platform_set_drvdata(pdev, priv); \
+__out: \
+ __ret; \
+})
+
+#endif /*_PROBE_HELPER_H_*/
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 3/9] probe/dma/zx: removed redundant code from zx dma controller's probe function
From: Satendra Singh Thakur @ 2019-09-15 7:29 UTC (permalink / raw)
Cc: linux-kernel, Vinod Koul, satendrasingh.thakur, dmaengine,
Dan Williams, Satendra Singh Thakur, Shawn Guo, Jun Nie,
linux-arm-kernel
In-Reply-To: <20190915072644.23329-1-sst2005@gmail.com>
1. In order to remove duplicate code, following functions:
platform_get_resource
devm_kzalloc
devm_ioremap_resource
devm_clk_get
platform_get_irq
devm_request_irq
are replaced with a macro devm_platform_probe_helper_irq.
2. Removed dmam_pool_destroy from remove method as dmam_pool_create
is already used in probe function.
3. This patch depends on the file include/linux/probe-helper.h
which is pushed in previous patch [01/09].
Signed-off-by: Satendra Singh Thakur <satendrasingh.thakur@hcl.com>
Signed-off-by: Satendra Singh Thakur <sst2005@gmail.com>
---
drivers/dma/zx_dma.c | 35 ++++++++++-------------------------
1 file changed, 10 insertions(+), 25 deletions(-)
diff --git a/drivers/dma/zx_dma.c b/drivers/dma/zx_dma.c
index 9f4436f7c914..d8c2fbe9766c 100644
--- a/drivers/dma/zx_dma.c
+++ b/drivers/dma/zx_dma.c
@@ -18,6 +18,7 @@
#include <linux/of.h>
#include <linux/clk.h>
#include <linux/of_dma.h>
+#include <linux/probe-helper.h>
#include "virt-dma.h"
@@ -754,20 +755,17 @@ static struct dma_chan *zx_of_dma_simple_xlate(struct of_phandle_args *dma_spec,
static int zx_dma_probe(struct platform_device *op)
{
struct zx_dma_dev *d;
- struct resource *iores;
int i, ret = 0;
- iores = platform_get_resource(op, IORESOURCE_MEM, 0);
- if (!iores)
- return -EINVAL;
-
- d = devm_kzalloc(&op->dev, sizeof(*d), GFP_KERNEL);
- if (!d)
- return -ENOMEM;
-
- d->base = devm_ioremap_resource(&op->dev, iores);
- if (IS_ERR(d->base))
- return PTR_ERR(d->base);
+ /*
+ * This macro internally combines following functions:
+ * devm_kzalloc, platform_get_resource, devm_ioremap_resource,
+ * devm_clk_get, platform_get_irq, devm_request_irq,
+ */
+ ret = devm_platform_probe_helper_irq(op, d, NULL,
+ zx_dma_int_handler, 0, DRIVER_NAME, d);
+ if (ret < 0)
+ return ret;
of_property_read_u32((&op->dev)->of_node,
"dma-channels", &d->dma_channels);
@@ -776,18 +774,6 @@ static int zx_dma_probe(struct platform_device *op)
if (!d->dma_requests || !d->dma_channels)
return -EINVAL;
- d->clk = devm_clk_get(&op->dev, NULL);
- if (IS_ERR(d->clk)) {
- dev_err(&op->dev, "no dma clk\n");
- return PTR_ERR(d->clk);
- }
-
- d->irq = platform_get_irq(op, 0);
- ret = devm_request_irq(&op->dev, d->irq, zx_dma_int_handler,
- 0, DRIVER_NAME, d);
- if (ret)
- return ret;
-
/* A DMA memory pool for LLIs, align on 32-byte boundary */
d->pool = dmam_pool_create(DRIVER_NAME, &op->dev,
LLI_BLOCK_SIZE, 32, 0);
@@ -894,7 +880,6 @@ static int zx_dma_remove(struct platform_device *op)
list_del(&c->vc.chan.device_node);
}
clk_disable_unprepare(d->clk);
- dmam_pool_destroy(d->pool);
return 0;
}
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 5/9] probe/dma/mtk-hs: removed redundant code from mediatek hs dma controller's probe function
From: Satendra Singh Thakur @ 2019-09-15 7:30 UTC (permalink / raw)
Cc: Sean Wang, linux-kernel, dmaengine, Vinod Koul, linux-mediatek,
satendrasingh.thakur, Matthias Brugger, Dan Williams,
Satendra Singh Thakur, linux-arm-kernel
In-Reply-To: <20190915072644.23329-1-sst2005@gmail.com>
1. In order to remove duplicate code, following functions:
platform_get_resource
devm_kzalloc
devm_ioremap_resource
devm_clk_get
platform_get_irq
are replaced with a macro devm_platform_probe_helper.
2. Fixed a memory leak when devm_request_irq fails,
Called of_dma_controller_free in such case.
3. This patch depends on the file include/linux/probe-helper.h
which is pushed in previous patch [01/09].
Signed-off-by: Satendra Singh Thakur <satendrasingh.thakur@hcl.com>
Signed-off-by: Satendra Singh Thakur <sst2005@gmail.com>
---
drivers/dma/mediatek/mtk-hsdma.c | 38 ++++++++++----------------------
1 file changed, 12 insertions(+), 26 deletions(-)
diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c
index 1a2028e1c29e..6fc01093aeea 100644
--- a/drivers/dma/mediatek/mtk-hsdma.c
+++ b/drivers/dma/mediatek/mtk-hsdma.c
@@ -23,6 +23,7 @@
#include <linux/pm_runtime.h>
#include <linux/refcount.h>
#include <linux/slab.h>
+#include <linux/probe-helper.h>
#include "../virt-dma.h"
@@ -896,41 +897,24 @@ static int mtk_hsdma_probe(struct platform_device *pdev)
struct mtk_hsdma_device *hsdma;
struct mtk_hsdma_vchan *vc;
struct dma_device *dd;
- struct resource *res;
int i, err;
- hsdma = devm_kzalloc(&pdev->dev, sizeof(*hsdma), GFP_KERNEL);
- if (!hsdma)
- return -ENOMEM;
-
+ /*
+ * This macro internally combines following functions:
+ * devm_kzalloc, platform_get_resource, devm_ioremap_resource,
+ * devm_clk_get, platform_get_irq
+ */
+ err = devm_platform_probe_helper(pdev, hsdma, "hsdma");
+ if (err < 0)
+ return err;
dd = &hsdma->ddev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hsdma->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(hsdma->base))
- return PTR_ERR(hsdma->base);
-
hsdma->soc = of_device_get_match_data(&pdev->dev);
if (!hsdma->soc) {
dev_err(&pdev->dev, "No device match found\n");
return -ENODEV;
}
- hsdma->clk = devm_clk_get(&pdev->dev, "hsdma");
- if (IS_ERR(hsdma->clk)) {
- dev_err(&pdev->dev, "No clock for %s\n",
- dev_name(&pdev->dev));
- return PTR_ERR(hsdma->clk);
- }
-
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res) {
- dev_err(&pdev->dev, "No irq resource for %s\n",
- dev_name(&pdev->dev));
- return -EINVAL;
- }
- hsdma->irq = res->start;
-
refcount_set(&hsdma->pc_refcnt, 0);
spin_lock_init(&hsdma->lock);
@@ -997,7 +981,7 @@ static int mtk_hsdma_probe(struct platform_device *pdev)
if (err) {
dev_err(&pdev->dev,
"request_irq failed with err %d\n", err);
- goto err_unregister;
+ goto err_free;
}
platform_set_drvdata(pdev, hsdma);
@@ -1006,6 +990,8 @@ static int mtk_hsdma_probe(struct platform_device *pdev)
return 0;
+err_free:
+ of_dma_controller_free(pdev->dev.of_node);
err_unregister:
dma_async_device_unregister(dd);
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 6/9] probe/dma/sun6i: removed redundant code from sun6i dma controller's probe function
From: Satendra Singh Thakur @ 2019-09-15 7:31 UTC (permalink / raw)
Cc: Maxime Ripard, Chen-Yu Tsai, linux-kernel, Vinod Koul,
satendrasingh.thakur, dmaengine, Dan Williams,
Satendra Singh Thakur, linux-arm-kernel
In-Reply-To: <20190915072644.23329-1-sst2005@gmail.com>
1. In order to remove duplicate code, following functions:
platform_get_resource
devm_kzalloc
devm_ioremap_resource
devm_clk_get
platform_get_irq
are replaced with a macro devm_platform_probe_helper.
2. This patch depends on the file include/linux/probe-helper.h
which is pushed in previous patch [01/09].
Signed-off-by: Satendra Singh Thakur <satendrasingh.thakur@hcl.com>
Signed-off-by: Satendra Singh Thakur <sst2005@gmail.com>
---
drivers/dma/sun6i-dma.c | 30 +++++++++---------------------
1 file changed, 9 insertions(+), 21 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index ed5b68dcfe50..41ee054bbeeb 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -19,6 +19,7 @@
#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/probe-helper.h>
#include "virt-dma.h"
@@ -1234,34 +1235,21 @@ static int sun6i_dma_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct sun6i_dma_dev *sdc;
- struct resource *res;
int ret, i;
- sdc = devm_kzalloc(&pdev->dev, sizeof(*sdc), GFP_KERNEL);
- if (!sdc)
- return -ENOMEM;
+ /*
+ * This macro internally combines following functions:
+ * devm_kzalloc, platform_get_resource, devm_ioremap_resource,
+ * devm_clk_get, platform_get_irq
+ */
+ ret = devm_platform_probe_helper(pdev, sdc, NULL);
+ if (ret < 0)
+ return ret;
sdc->cfg = of_device_get_match_data(&pdev->dev);
if (!sdc->cfg)
return -ENODEV;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- sdc->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(sdc->base))
- return PTR_ERR(sdc->base);
-
- sdc->irq = platform_get_irq(pdev, 0);
- if (sdc->irq < 0) {
- dev_err(&pdev->dev, "Cannot claim IRQ\n");
- return sdc->irq;
- }
-
- sdc->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(sdc->clk)) {
- dev_err(&pdev->dev, "No clock specified\n");
- return PTR_ERR(sdc->clk);
- }
-
if (sdc->cfg->has_mbus_clk) {
sdc->clk_mbus = devm_clk_get(&pdev->dev, "mbus");
if (IS_ERR(sdc->clk_mbus)) {
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 7/9] probe/dma/sun4i: removed redundant code from sun4i dma controller's probe function
From: Satendra Singh Thakur @ 2019-09-15 7:32 UTC (permalink / raw)
Cc: Maxime Ripard, Chen-Yu Tsai, linux-kernel, Vinod Koul,
satendrasingh.thakur, dmaengine, Dan Williams,
Satendra Singh Thakur, linux-arm-kernel
In-Reply-To: <20190915072644.23329-1-sst2005@gmail.com>
1. In order to remove duplicate code, following functions:
platform_get_resource
devm_kzalloc
devm_ioremap_resource
devm_clk_get
platform_get_irq
are replaced with a macro devm_platform_probe_helper.
2. This patch depends on the file include/linux/probe-helper.h
which is pushed in previous patch [01/09].
Signed-off-by: Satendra Singh Thakur <satendrasingh.thakur@hcl.com>
Signed-off-by: Satendra Singh Thakur <sst2005@gmail.com>
---
drivers/dma/sun4i-dma.c | 30 +++++++++---------------------
1 file changed, 9 insertions(+), 21 deletions(-)
diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
index 1f80568b2613..5db139ff43ac 100644
--- a/drivers/dma/sun4i-dma.c
+++ b/drivers/dma/sun4i-dma.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/probe-helper.h>
#include "virt-dma.h"
@@ -1119,29 +1120,16 @@ static irqreturn_t sun4i_dma_interrupt(int irq, void *dev_id)
static int sun4i_dma_probe(struct platform_device *pdev)
{
struct sun4i_dma_dev *priv;
- struct resource *res;
int i, j, ret;
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(priv->base))
- return PTR_ERR(priv->base);
-
- priv->irq = platform_get_irq(pdev, 0);
- if (priv->irq < 0) {
- dev_err(&pdev->dev, "Cannot claim IRQ\n");
- return priv->irq;
- }
-
- priv->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(priv->clk)) {
- dev_err(&pdev->dev, "No clock specified\n");
- return PTR_ERR(priv->clk);
- }
+ /*
+ * This macro internally combines following functions:
+ * devm_kzalloc, platform_get_resource, devm_ioremap_resource,
+ * devm_clk_get, platform_get_irq
+ */
+ ret = devm_platform_probe_helper(pdev, priv, NULL);
+ if (ret < 0)
+ return ret;
platform_set_drvdata(pdev, priv);
spin_lock_init(&priv->lock);
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 9/9] probe/dma/owl: removed redundant code from owl dma controller's probe function
From: Satendra Singh Thakur @ 2019-09-15 7:32 UTC (permalink / raw)
Cc: linux-kernel, Vinod Koul, satendrasingh.thakur,
Manivannan Sadhasivam, dmaengine, Dan Williams,
Satendra Singh Thakur, Andreas Färber, linux-arm-kernel
In-Reply-To: <20190915072644.23329-1-sst2005@gmail.com>
1. In order to remove duplicate code, following functions:
platform_get_resource
devm_kzalloc
devm_ioremap_resource
devm_clk_get
platform_get_irq
are replaced with a macro devm_platform_probe_helper.
2. This patch depends on the file include/linux/probe-helper.h
which is pushed in previous patch [01/09].
Signed-off-by: Satendra Singh Thakur <satendrasingh.thakur@hcl.com>
Signed-off-by: Satendra Singh Thakur <sst2005@gmail.com>
---
drivers/dma/owl-dma.c | 29 +++++++++--------------------
1 file changed, 9 insertions(+), 20 deletions(-)
diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c
index 90bbcef99ef8..03e692fc25a1 100644
--- a/drivers/dma/owl-dma.c
+++ b/drivers/dma/owl-dma.c
@@ -23,6 +23,7 @@
#include <linux/of_device.h>
#include <linux/of_dma.h>
#include <linux/slab.h>
+#include <linux/probe-helper.h>
#include "virt-dma.h"
#define OWL_DMA_FRAME_MAX_LENGTH 0xfffff
@@ -1045,20 +1046,15 @@ static int owl_dma_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct owl_dma *od;
- struct resource *res;
int ret, i, nr_channels, nr_requests;
-
- od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
- if (!od)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
-
- od->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(od->base))
- return PTR_ERR(od->base);
+ /*
+ * This macro internally combines following functions:
+ * devm_kzalloc, platform_get_resource, devm_ioremap_resource,
+ * devm_clk_get, platform_get_irq
+ */
+ ret = devm_platform_probe_helper(pdev, od, NULL);
+ if (ret < 0)
+ return ret;
ret = of_property_read_u32(np, "dma-channels", &nr_channels);
if (ret) {
@@ -1105,18 +1101,11 @@ static int owl_dma_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&od->dma.channels);
- od->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(od->clk)) {
- dev_err(&pdev->dev, "unable to get clock\n");
- return PTR_ERR(od->clk);
- }
-
/*
* Eventhough the DMA controller is capable of generating 4
* IRQ's for DMA priority feature, we only use 1 IRQ for
* simplification.
*/
- od->irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(&pdev->dev, od->irq, owl_dma_interrupt, 0,
dev_name(&pdev->dev), od);
if (ret) {
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v6 1/5] dt-bindings: media: Add Allwinner A10 CSI binding
From: Chen-Yu Tsai @ 2019-09-15 8:54 UTC (permalink / raw)
To: Maxime Ripard
Cc: Mark Rutland, devicetree, linux-kernel, Rob Herring, Hans Verkuil,
Laurent Pinchart, Sakari Ailus, Mauro Carvalho Chehab,
linux-arm-kernel, Linux Media Mailing List
In-Reply-To: <CAGb2v64nx2AuWZN+RxCneE0pqvXr_d7u6mQ+=nCHv2VJ1MNtrQ@mail.gmail.com>
On Thu, Aug 15, 2019 at 4:34 PM Chen-Yu Tsai <wens@csie.org> wrote:
>
> Hi,
>
> Sorry for chiming in so late.
>
> On Thu, Jul 11, 2019 at 8:15 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> >
> > The Allwinner A10 CMOS Sensor Interface is a camera capture interface also
> > used in later (A10s, A13, A20, R8 and GR8) SoCs.
> >
> > On some SoCs, like the A10, there's multiple instances of that controller,
> > with one instance supporting more channels and having an ISP.
> >
> > Reviewed-by: Rob Herring <robh@kernel.org>
> > Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> > ---
> > Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 94 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml
> > new file mode 100644
> > index 000000000000..97c9fc3b5050
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml
> > @@ -0,0 +1,94 @@
> > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/arm/allwinner,sun4i-a10-csi.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Allwinner A10 CMOS Sensor Interface (CSI) Device Tree Bindings
> > +
> > +maintainers:
> > + - Chen-Yu Tsai <wens@csie.org>
> > + - Maxime Ripard <maxime.ripard@bootlin.com>
> > +
> > +description: |-
> > + The Allwinner A10 and later has a CMOS Sensor Interface to retrieve
> > + frames from a parallel or BT656 sensor.
> > +
> > +
> > +properties:
> > + compatible:
> > + oneOf:
> > + - items:
> > + - enum:
> > + - allwinner,sun7i-a20-csi0
> > + - const: allwinner,sun4i-a10-csi0
>
> CSI0 on the A10 has an ISP. Do we know if the one in the A20 does
> as well? It certainly doesn't say so in the user manual. If not,
> then we can't claim that A20 CSI0 is compatible with A10 CSI0.
>
> > +
> > + - items:
> > + - const: allwinner,sun4i-a10-csi0
> > +
> > + reg:
> > + maxItems: 1
> > +
> > + interrupts:
> > + maxItems: 1
> > +
> > + clocks:
> > + items:
> > + - description: The CSI interface clock
> > + - description: The CSI module clock
> > + - description: The CSI ISP clock
> > + - description: The CSI DRAM clock
> > +
> > + clock-names:
> > + items:
> > + - const: bus
> > + - const: mod
>
> I doubt this actually is a module clock. Based on the usage in your
> device tree patch, and the csi driver in the old linux-sunxi kernel,
> the clock rate is set to 24 MHz, or whatever the sensor requires for
> MCLK.
I'm working on adding support for this on the R40, and it seems with
this SoC the picture is much clearer. It has the same CSI interface
block, but the CCU has the clocks correctly named. We have:
- CSI_MCLK0
- CSI_MCLK1
- CSI_SCLK
in addition to the bus clocks.
The CSI section also explains the clock signals:
6.1.3.2. Clock Sources
Two Clocks need to be configured for CSI controller. CSI0/1_MCLK
provides the master clock for sensor and other devices. CSI_SCLK
is the top clock for the whole CSI module.
So it would seem the ISP clock we currently have in the DT is simply
the module clock shared by all CSI-related hardware blocks, and the
module clock is bogus.
ChenYu
> ChenYu
>
> > + - const: isp
> > + - const: ram
> > +
> > + resets:
> > + description: The reset line driver this IP
> > + maxItems: 1
> > +
> > + pinctrl-0:
> > + minItems: 1
> > +
> > + pinctrl-names:
> > + const: default
> > +
> > + port:
> > + type: object
> > + additionalProperties: false
> > +
> > + properties:
> > + endpoint:
> > + properties:
> > + bus-width:
> > + const: 8
> > + description: Number of data lines actively used.
> > +
> > + data-active: true
> > + hsync-active: true
> > + pclk-sample: true
> > + remote-endpoint: true
> > + vsync-active: true
> > +
> > + required:
> > + - bus-width
> > + - data-active
> > + - hsync-active
> > + - pclk-sample
> > + - remote-endpoint
> > + - vsync-active
> > +
> > + required:
> > + - endpoint
> > +
> > +required:
> > + - compatible
> > + - reg
> > + - interrupts
> > + - clocks
> > +
> > +additionalProperties: false
> > +...
> > --
> > git-series 0.9.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] iio: adc: stm32-adc: fix a race when using several adcs with dma and irq
From: Jonathan Cameron @ 2019-09-15 10:05 UTC (permalink / raw)
To: Fabrice Gasnier
Cc: lars, alexandre.torgue, linux-iio, pmeerw, linux-kernel,
mcoquelin.stm32, knaack.h, linux-stm32, linux-arm-kernel
In-Reply-To: <1568380890-313-1-git-send-email-fabrice.gasnier@st.com>
On Fri, 13 Sep 2019 15:21:30 +0200
Fabrice Gasnier <fabrice.gasnier@st.com> wrote:
> End of conversion may be handled by using IRQ or DMA. There may be a
> race when two conversions complete at the same time on several ADCs.
> EOC can be read as 'set' for several ADCs, with:
> - an ADC configured to use IRQs. EOCIE bit is set. The handler is normally
> called in this case.
> - an ADC configured to use DMA. EOCIE bit isn't set. EOC triggers the DMA
> request instead. It's then automatically cleared by DMA read. But the
> handler gets called due to status bit is temporarily set (IRQ triggered
> by the other ADC).
> So both EOC status bit in CSR and EOCIE control bit must be checked
> before invoking the interrupt handler (e.g. call ISR only for
> IRQ-enabled ADCs).
>
> Fixes: 2763ea0585c9 ("iio: adc: stm32: add optional dma support")
>
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Fix looks fine to me, but I'm not keen on splitting out individual bits from
register defines. That's a long term readability nightmare.
See below,
Jonathan
> ---
> drivers/iio/adc/stm32-adc-core.c | 43 +++++++++++++++++++++++++++++++++++++---
> drivers/iio/adc/stm32-adc-core.h | 13 ++++++++++++
> drivers/iio/adc/stm32-adc.c | 6 ------
> 3 files changed, 53 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
> index 9b85fef..7297396 100644
> --- a/drivers/iio/adc/stm32-adc-core.c
> +++ b/drivers/iio/adc/stm32-adc-core.c
> @@ -71,6 +71,8 @@
> * @eoc1: adc1 end of conversion flag in @csr
> * @eoc2: adc2 end of conversion flag in @csr
> * @eoc3: adc3 end of conversion flag in @csr
> + * @ier: interrupt enable register offset for each adc
> + * @eocie_msk: end of conversion interrupt enable mask in @ier
> */
> struct stm32_adc_common_regs {
> u32 csr;
> @@ -78,6 +80,8 @@ struct stm32_adc_common_regs {
> u32 eoc1_msk;
> u32 eoc2_msk;
> u32 eoc3_msk;
> + u32 ier;
> + u32 eocie_msk;
> };
>
> struct stm32_adc_priv;
> @@ -303,6 +307,8 @@ static const struct stm32_adc_common_regs stm32f4_adc_common_regs = {
> .eoc1_msk = STM32F4_EOC1,
> .eoc2_msk = STM32F4_EOC2,
> .eoc3_msk = STM32F4_EOC3,
> + .ier = STM32F4_ADC_CR1,
> + .eocie_msk = STM32F4_EOCIE,
> };
>
> /* STM32H7 common registers definitions */
> @@ -311,8 +317,24 @@ static const struct stm32_adc_common_regs stm32h7_adc_common_regs = {
> .ccr = STM32H7_ADC_CCR,
> .eoc1_msk = STM32H7_EOC_MST,
> .eoc2_msk = STM32H7_EOC_SLV,
> + .ier = STM32H7_ADC_IER,
> + .eocie_msk = STM32H7_EOCIE,
> };
>
> +static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = {
> + 0, STM32_ADC_OFFSET, STM32_ADC_OFFSET * 2,
> +};
> +
> +static unsigned int stm32_adc_eoc_enabled(struct stm32_adc_priv *priv,
> + unsigned int adc)
> +{
> + u32 ier, offset = stm32_adc_offset[adc];
> +
> + ier = readl_relaxed(priv->common.base + offset + priv->cfg->regs->ier);
> +
> + return ier & priv->cfg->regs->eocie_msk;
> +}
> +
> /* ADC common interrupt for all instances */
> static void stm32_adc_irq_handler(struct irq_desc *desc)
> {
> @@ -323,13 +345,28 @@ static void stm32_adc_irq_handler(struct irq_desc *desc)
> chained_irq_enter(chip, desc);
> status = readl_relaxed(priv->common.base + priv->cfg->regs->csr);
>
> - if (status & priv->cfg->regs->eoc1_msk)
> + /*
> + * End of conversion may be handled by using IRQ or DMA. There may be a
> + * race here when two conversions complete at the same time on several
> + * ADCs. EOC may be read 'set' for several ADCs, with:
> + * - an ADC configured to use DMA (EOC triggers the DMA request, and
> + * is then automatically cleared by DR read in hardware)
> + * - an ADC configured to use IRQs (EOCIE bit is set. The handler must
> + * be called in this case)
> + * So both EOC status bit in CSR and EOCIE control bit must be checked
> + * before invoking the interrupt handler (e.g. call ISR only for
> + * IRQ-enabled ADCs).
> + */
> + if (status & priv->cfg->regs->eoc1_msk &&
> + stm32_adc_eoc_enabled(priv, 0))
> generic_handle_irq(irq_find_mapping(priv->domain, 0));
>
> - if (status & priv->cfg->regs->eoc2_msk)
> + if (status & priv->cfg->regs->eoc2_msk &&
> + stm32_adc_eoc_enabled(priv, 1))
> generic_handle_irq(irq_find_mapping(priv->domain, 1));
>
> - if (status & priv->cfg->regs->eoc3_msk)
> + if (status & priv->cfg->regs->eoc3_msk &&
> + stm32_adc_eoc_enabled(priv, 2))
> generic_handle_irq(irq_find_mapping(priv->domain, 2));
>
> chained_irq_exit(chip, desc);
> diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h
> index 8af507b..8dc936b 100644
> --- a/drivers/iio/adc/stm32-adc-core.h
> +++ b/drivers/iio/adc/stm32-adc-core.h
> @@ -25,8 +25,21 @@
> * --------------------------------------------------------
> */
> #define STM32_ADC_MAX_ADCS 3
> +#define STM32_ADC_OFFSET 0x100
> #define STM32_ADCX_COMN_OFFSET 0x300
>
> +/* STM32F4 - registers for each ADC instance */
> +#define STM32F4_ADC_CR1 0x04
> +
> +/* STM32F4_ADC_CR1 - bit fields */
> +#define STM32F4_EOCIE BIT(5)
> +
> +/* STM32H7 - registers for each instance */
> +#define STM32H7_ADC_IER 0x04
> +
> +/* STM32H7_ADC_IER - bit fields */
> +#define STM32H7_EOCIE BIT(2)
> +
> /**
> * struct stm32_adc_common - stm32 ADC driver common data (for all instances)
> * @base: control registers base cpu addr
> diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
> index 6a7dd08..3c9f456 100644
> --- a/drivers/iio/adc/stm32-adc.c
> +++ b/drivers/iio/adc/stm32-adc.c
> @@ -30,7 +30,6 @@
>
> /* STM32F4 - Registers for each ADC instance */
> #define STM32F4_ADC_SR 0x00
> -#define STM32F4_ADC_CR1 0x04
> #define STM32F4_ADC_CR2 0x08
> #define STM32F4_ADC_SMPR1 0x0C
> #define STM32F4_ADC_SMPR2 0x10
> @@ -54,7 +53,6 @@
> #define STM32F4_RES_SHIFT 24
> #define STM32F4_RES_MASK GENMASK(25, 24)
> #define STM32F4_SCAN BIT(8)
> -#define STM32F4_EOCIE BIT(5)
Hmm. This is breaking up the definitions of bits in a single register.
That is rather nasty from a code readability point of view.
I am as keen as the next person on only exposing definitions where
we need to, but in this case we either need to provide an access path
to it here, or we need to move the whole block to the header.
>
> /* STM32F4_ADC_CR2 - bit fields */
> #define STM32F4_SWSTART BIT(30)
> @@ -69,7 +67,6 @@
>
> /* STM32H7 - Registers for each ADC instance */
> #define STM32H7_ADC_ISR 0x00
> -#define STM32H7_ADC_IER 0x04
> #define STM32H7_ADC_CR 0x08
> #define STM32H7_ADC_CFGR 0x0C
> #define STM32H7_ADC_SMPR1 0x14
> @@ -89,9 +86,6 @@
> #define STM32H7_EOC BIT(2)
> #define STM32H7_ADRDY BIT(0)
>
> -/* STM32H7_ADC_IER - bit fields */
> -#define STM32H7_EOCIE STM32H7_EOC
> -
> /* STM32H7_ADC_CR - bit fields */
> #define STM32H7_ADCAL BIT(31)
> #define STM32H7_ADCALDIF BIT(30)
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay`
From: Jonathan Cameron @ 2019-09-15 10:22 UTC (permalink / raw)
To: Alexandru Ardelean
Cc: f.fainelli, baolin.wang, linux-iio, zhang.lyra, linus.walleij,
linux-kernel, linux-spi, broonie, bcm-kernel-feedback-list,
linux-tegra, orsonzhai, linux-arm-kernel
In-Reply-To: <20190913114550.956-1-alexandru.ardelean@analog.com>
On Fri, 13 Sep 2019 14:45:35 +0300
Alexandru Ardelean <alexandru.ardelean@analog.com> wrote:
> Initially, I started this patchset thinking: "we need a new delay for
> something-something" (in case someone is curios, we need a CS-hold-time for
> the first transfer, because the CS wakes a chip from sleep-mode).
>
> Then I added the delay, and felt a bit dirty-inside about adding a new one
> (just like that), and decided to look at maybe cleaning things up a bit,
> and a few days later, I got here.
>
> Full disclaimer: this patchset is not complete. It's an RFC.
> It's based on top of Jonathan's `iio/togreg` branch which also includes the
> ADIS driver library changes and also includes `cs_change_delay`.
>
> I'll send a V2 patchset, which just the first 4 patches, since I feel that
> those are a bit more complete.
>
> I thought about just sending the first 4 patches on-their-own, but I
> figured that the whole series (even if not complete) serves as a better
> explanation about the whole "why?".
>
> Hopefully, this can sort-of-explain things.
> I'll reference this RFC on the next series.
General approach looks sensible to me. Over to SPI specialists on
whether this is a sensible bit of unification to do.
Jonathan
>
> Thanks
>
> Alexandru Ardelean (15):
> spi: move `cs_change_delay` backwards compat logic outside switch
> spi: introduce spi_delay struct as "value + unit" & spi_delay_exec()
> spi: make `cs_change_delay` the first user of the `spi_delay` logic
> iio: imu: adis: convert cs_change_delay to spi_delay struct
> spi: sprd: convert transfer word delay to spi_delay struct
> spi: orion: use new `word_delay` field for SPI transfers
> spi: spidev: use new `word_delay` field for spi transfers
> spi: core,atmel: convert `word_delay_usecs` -> `word_delay` for
> spi_device
> spi: introduce `delay` field for `spi_transfer` + spi_transfer_exec()
> spi: use new `spi_transfer_delay` helper where straightforward
> spi: tegra114: use `spi_transfer_delay` helper
> spi: spi-loopback-test: use new `delay` field
> spi: spidev: use new `delay` field for spi transfers
> spi: tegra114: change format for `spi_set_cs_timing()` function
> spi: implement SW control for CS times
>
> drivers/iio/imu/adis.c | 24 ++---
> drivers/spi/spi-atmel.c | 29 +++++-
> drivers/spi/spi-bcm63xx-hsspi.c | 3 +-
> drivers/spi/spi-cavium.c | 3 +-
> drivers/spi/spi-fsl-dspi.c | 3 +-
> drivers/spi/spi-fsl-espi.c | 3 +-
> drivers/spi/spi-fsl-spi.c | 3 +-
> drivers/spi/spi-loopback-test.c | 12 ++-
> drivers/spi/spi-mpc512x-psc.c | 3 +-
> drivers/spi/spi-mpc52xx-psc.c | 3 +-
> drivers/spi/spi-omap-100k.c | 3 +-
> drivers/spi/spi-orion.c | 6 +-
> drivers/spi/spi-pl022.c | 25 +++--
> drivers/spi/spi-sc18is602.c | 3 +-
> drivers/spi/spi-sh-hspi.c | 3 +-
> drivers/spi/spi-sprd.c | 11 ++-
> drivers/spi/spi-tegra114.c | 39 +++++---
> drivers/spi/spi-tegra20-sflash.c | 2 +-
> drivers/spi/spi-topcliff-pch.c | 7 +-
> drivers/spi/spi-txx9.c | 3 +-
> drivers/spi/spi-xcomm.c | 3 +-
> drivers/spi/spi.c | 162 +++++++++++++++++++++++++------
> drivers/spi/spidev.c | 6 +-
> include/linux/spi/spi.h | 65 ++++++++++---
> 24 files changed, 293 insertions(+), 131 deletions(-)
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] ARM: dts: imx6dl: SolidRun: add phy node with 100Mb/s max-speed
From: Russell King - ARM Linux admin @ 2019-09-15 12:29 UTC (permalink / raw)
To: Baruch Siach
Cc: Mark Rutland, Andrew Lunn,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Fabio Estevam, Sascha Hauer, tinywrkb, open list, Rob Herring,
NXP Linux Team, Pengutronix Kernel Team, Shawn Guo,
linux-arm-kernel
In-Reply-To: <87muf6oyvr.fsf@tarshish>
On Sun, Sep 15, 2019 at 09:30:00AM +0300, Baruch Siach wrote:
> Hi Andrew,
>
> On Tue, Sep 10 2019, Andrew Lunn wrote:
> > On Tue, Sep 10, 2019 at 06:55:07PM +0300, tinywrkb wrote:
> >> Cubox-i Solo/DualLite carrier board has 100Mb/s magnetics while the
> >> Atheros AR8035 PHY on the MicroSoM v1.3 CPU module is a 1GbE PHY device.
> >>
> >> Since commit 5502b218e001 ("net: phy: use phy_resolve_aneg_linkmode in
> >> genphy_read_status") ethernet is broken on Cubox-i Solo/DualLite devices.
> >
> > Hi Tinywrkb
> >
> > You emailed lots of people, but missed the PHY maintainers :-(
> >
> > Are you sure this is the patch which broken it? Did you do a git
> > bisect.
>
> Tinywrkb confirmed to me in private communication that revert of
> 5502b218e001 fixes Ethernet for him on effected system.
>
> He also referred me to an old Cubox-i spec that lists 10/100 Ethernet
> only for i.MX6 Solo/DualLite variants of Cubox-i. It turns out that
> there was a plan to use a different 10/100 PHY for Solo/DualLite
> SOMs. This plan never materialized. All SolidRun i.MX6 SOMs use the same
> AR8035 PHY that supports 1Gb.
>
> Commit 5502b218e001 might be triggering a hardware issue on the affected
> Cubox-i. I could not reproduce the issue here with Cubox-i and a Dual
> SOM variant running v5.3-rc8. I have no Solo/DualLite variant handy at
> the moment.
With 5.3 due out today, I'll be updating my systems to that, which will
include quite a few variants of the Hummingboard.
It looks like one of my Solo Hummingboards (running a fully up to date
Fedora 28) has encountered a problem, so needs a reboot...
systemd-journald[436]: Failed to retrieve credentials for PID 17906, ignoring: Cannot allocate memory
systemd-journald[436]: Failed to open runtime journal: Cannot allocate memory
# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
...
root 436 0.0 5.2 3128140 26392 ? Ss Aug03 1:20 /usr/lib/systemd/systemd-journald
# uptime
13:28:41 up 42 days, 19:13, 1 user, load average: 0.00, 0.03, 0.00
Looks like systemd-journald has a rather bad memory leak...
#include <std-complaints-about-systemd>
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] ARM: dts: dir685: Drop spi-cpol from the display
From: Linus Walleij @ 2019-09-15 13:54 UTC (permalink / raw)
To: arm, soc; +Cc: Linus Walleij, Mark Brown, linux-arm-kernel
The D-Link DIR-685 had its clock polarity set as active
low using the special SPI "spi-cpol" property.
This is not correct: the datasheet clearly states:
"Fix SCL to GND level when not in use" which is
indicative that this line is active high.
After a recent fix making the GPIO-based SPI driver
force the clock line de-asserted at the beginning of
each SPI transaction this reared its ugly head: now
de-asserted was taken to mean the line should be
driven high, but it should be driven low.
Fix this up in the DTS file and the display works again.
Cc: Mark Brown <broonie@kernel.org>
Fixes: 2922d1cc1696 ("spi: gpio: Add SPI_MASTER_GPIO_SS flag")
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ARM SoC folks: please apply this directly to fixes if
you're OK with the patch.
---
arch/arm/boot/dts/gemini-dlink-dir-685.dts | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/arm/boot/dts/gemini-dlink-dir-685.dts b/arch/arm/boot/dts/gemini-dlink-dir-685.dts
index bfaa2de63a10..e2030ba16512 100644
--- a/arch/arm/boot/dts/gemini-dlink-dir-685.dts
+++ b/arch/arm/boot/dts/gemini-dlink-dir-685.dts
@@ -72,7 +72,6 @@
reg = <0>;
/* 50 ns min period = 20 MHz */
spi-max-frequency = <20000000>;
- spi-cpol; /* Clock active low */
vcc-supply = <&vdisp>;
iovcc-supply = <&vdisp>;
vci-supply = <&vdisp>;
--
2.21.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH] ARM: dts: imx6dl: SolidRun: add phy node with 100Mb/s max-speed
From: Andrew Lunn @ 2019-09-15 13:56 UTC (permalink / raw)
To: Baruch Siach
Cc: Mark Rutland,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Fabio Estevam, Sascha Hauer, tinywrkb, Russell King, open list,
Rob Herring, NXP Linux Team, Pengutronix Kernel Team, Shawn Guo,
linux-arm-kernel
In-Reply-To: <87muf6oyvr.fsf@tarshish>
> Tinywrkb confirmed to me in private communication that revert of
> 5502b218e001 fixes Ethernet for him on effected system.
>
> He also referred me to an old Cubox-i spec that lists 10/100 Ethernet
> only for i.MX6 Solo/DualLite variants of Cubox-i. It turns out that
> there was a plan to use a different 10/100 PHY for Solo/DualLite
> SOMs. This plan never materialized. All SolidRun i.MX6 SOMs use the same
> AR8035 PHY that supports 1Gb.
>
> Commit 5502b218e001 might be triggering a hardware issue on the affected
> Cubox-i. I could not reproduce the issue here with Cubox-i and a Dual
> SOM variant running v5.3-rc8. I have no Solo/DualLite variant handy at
> the moment.
Could somebody with an affected device show us the output of ethtool
with and without 5502b218e001. Does one show 1G has been negotiated,
and the other 100Mbps? If this is true, how does it get 100Mbps
without that patch? We are missing a piece of the puzzle.
Andrew
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] ARM: dts: imx6dl: SolidRun: add phy node with 100Mb/s max-speed
From: Russell King - ARM Linux admin @ 2019-09-15 14:06 UTC (permalink / raw)
To: Andrew Lunn
Cc: Mark Rutland,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Baruch Siach, Fabio Estevam, Sascha Hauer, tinywrkb, open list,
Rob Herring, NXP Linux Team, Pengutronix Kernel Team, Shawn Guo,
linux-arm-kernel
In-Reply-To: <20190915135652.GC3427@lunn.ch>
On Sun, Sep 15, 2019 at 03:56:52PM +0200, Andrew Lunn wrote:
> > Tinywrkb confirmed to me in private communication that revert of
> > 5502b218e001 fixes Ethernet for him on effected system.
> >
> > He also referred me to an old Cubox-i spec that lists 10/100 Ethernet
> > only for i.MX6 Solo/DualLite variants of Cubox-i. It turns out that
> > there was a plan to use a different 10/100 PHY for Solo/DualLite
> > SOMs. This plan never materialized. All SolidRun i.MX6 SOMs use the same
> > AR8035 PHY that supports 1Gb.
> >
> > Commit 5502b218e001 might be triggering a hardware issue on the affected
> > Cubox-i. I could not reproduce the issue here with Cubox-i and a Dual
> > SOM variant running v5.3-rc8. I have no Solo/DualLite variant handy at
> > the moment.
>
> Could somebody with an affected device show us the output of ethtool
> with and without 5502b218e001. Does one show 1G has been negotiated,
> and the other 100Mbps? If this is true, how does it get 100Mbps
> without that patch? We are missing a piece of the puzzle.
Hang on. 5502b218e001 is in 5.2 already - it was merged as part of the
v5.1 merge window. That means my imx6 Solo Hummingboard is already
running it with the AR8035 PHY, and it works fine.
# dmesg
...
OF: fdt: Machine model: SolidRun HummingBoard Solo/DualLite
...
# ethtool eth0
Settings for eth0:
Supported ports: [ TP MII ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supported pause frame use: Symmetric
Supports auto-negotiation: Yes
Supported FEC modes: Not reported
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Advertised pause frame use: Symmetric
Advertised auto-negotiation: Yes
Advertised FEC modes: Not reported
Link partner advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Link partner advertised pause frame use: Symmetric
Link partner advertised auto-negotiation: Yes
Link partner advertised FEC modes: Not reported
Speed: 1000Mb/s
Duplex: Full
Port: MII
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Supports Wake-on: d
Wake-on: d
Link detected: yes
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] ARM: dts: imx6dl: SolidRun: add phy node with 100Mb/s max-speed
From: Russell King - ARM Linux admin @ 2019-09-15 14:15 UTC (permalink / raw)
To: Andrew Lunn
Cc: Mark Rutland,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Baruch Siach, Shawn Guo, Sascha Hauer, tinywrkb, open list,
Rob Herring, NXP Linux Team, Pengutronix Kernel Team,
Fabio Estevam, linux-arm-kernel
In-Reply-To: <20190915140639.GC25745@shell.armlinux.org.uk>
On Sun, Sep 15, 2019 at 03:06:39PM +0100, Russell King - ARM Linux admin wrote:
> On Sun, Sep 15, 2019 at 03:56:52PM +0200, Andrew Lunn wrote:
> > > Tinywrkb confirmed to me in private communication that revert of
> > > 5502b218e001 fixes Ethernet for him on effected system.
> > >
> > > He also referred me to an old Cubox-i spec that lists 10/100 Ethernet
> > > only for i.MX6 Solo/DualLite variants of Cubox-i. It turns out that
> > > there was a plan to use a different 10/100 PHY for Solo/DualLite
> > > SOMs. This plan never materialized. All SolidRun i.MX6 SOMs use the same
> > > AR8035 PHY that supports 1Gb.
> > >
> > > Commit 5502b218e001 might be triggering a hardware issue on the affected
> > > Cubox-i. I could not reproduce the issue here with Cubox-i and a Dual
> > > SOM variant running v5.3-rc8. I have no Solo/DualLite variant handy at
> > > the moment.
> >
> > Could somebody with an affected device show us the output of ethtool
> > with and without 5502b218e001. Does one show 1G has been negotiated,
> > and the other 100Mbps? If this is true, how does it get 100Mbps
> > without that patch? We are missing a piece of the puzzle.
>
> Hang on. 5502b218e001 is in 5.2 already - it was merged as part of the
> v5.1 merge window. That means my imx6 Solo Hummingboard is already
> running it with the AR8035 PHY, and it works fine.
>
> # dmesg
> ...
> OF: fdt: Machine model: SolidRun HummingBoard Solo/DualLite
> ...
> # ethtool eth0
> Settings for eth0:
> Supported ports: [ TP MII ]
> Supported link modes: 10baseT/Half 10baseT/Full
> 100baseT/Half 100baseT/Full
> 1000baseT/Full
> Supported pause frame use: Symmetric
> Supports auto-negotiation: Yes
> Supported FEC modes: Not reported
> Advertised link modes: 10baseT/Half 10baseT/Full
> 100baseT/Half 100baseT/Full
> 1000baseT/Full
> Advertised pause frame use: Symmetric
> Advertised auto-negotiation: Yes
> Advertised FEC modes: Not reported
> Link partner advertised link modes: 10baseT/Half 10baseT/Full
> 100baseT/Half 100baseT/Full
> 1000baseT/Full
> Link partner advertised pause frame use: Symmetric
> Link partner advertised auto-negotiation: Yes
> Link partner advertised FEC modes: Not reported
> Speed: 1000Mb/s
> Duplex: Full
> Port: MII
> PHYAD: 0
> Transceiver: internal
> Auto-negotiation: on
> Supports Wake-on: d
> Wake-on: d
> Link detected: yes
For some further testing, by changing the advertisment on the DSA
switch (other end of this platform's link):
Link partner advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
...
Speed: 100Mb/s
Duplex: Full
===============
Link partner advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half
...
Speed: 100Mb/s
Duplex: Half
===============
Link partner advertised link modes: 10baseT/Half 10baseT/Full
...
Speed: 10Mb/s
Duplex: Full
===============
Link partner advertised link modes: 10baseT/Half
...
Speed: 10Mb/s
Duplex: Half
So it looks like the commit works as it should. So there's something
else going on.
Note that the FEC does *not* support 1000baseT/Half.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox