From 5a413dfbaf3f446a154d65d1d9811a6d311482a5 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Fri, 2 Jan 2015 21:55:02 +0100 Subject: [PATCH 0001/3798] drm/armada: armada_output: Remove some unused functions Removes some functions that are not used anywhere: armada_drm_encoder_mode_fixup() armada_drm_encoder_commit() armada_drm_encoder_prepare() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_output.c | 16 ---------------- drivers/gpu/drm/armada/armada_output.h | 6 ------ 2 files changed, 22 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_output.c b/drivers/gpu/drm/armada/armada_output.c index abbc309fe539e9..5a9823178291f1 100644 --- a/drivers/gpu/drm/armada/armada_output.c +++ b/drivers/gpu/drm/armada/armada_output.c @@ -72,22 +72,6 @@ static const struct drm_connector_funcs armada_drm_conn_funcs = { .set_property = armada_drm_connector_set_property, }; -void armada_drm_encoder_prepare(struct drm_encoder *encoder) -{ - encoder_helper_funcs(encoder)->dpms(encoder, DRM_MODE_DPMS_OFF); -} - -void armada_drm_encoder_commit(struct drm_encoder *encoder) -{ - encoder_helper_funcs(encoder)->dpms(encoder, DRM_MODE_DPMS_ON); -} - -bool armada_drm_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, struct drm_display_mode *adjusted) -{ - return true; -} - /* Shouldn't this be a generic helper function? */ int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn, struct drm_display_mode *mode) diff --git a/drivers/gpu/drm/armada/armada_output.h b/drivers/gpu/drm/armada/armada_output.h index 4126d43b5057a0..d3a6ce79d0945a 100644 --- a/drivers/gpu/drm/armada/armada_output.h +++ b/drivers/gpu/drm/armada/armada_output.h @@ -21,12 +21,6 @@ struct armada_output_type { struct drm_encoder *armada_drm_connector_encoder(struct drm_connector *conn); -void armada_drm_encoder_prepare(struct drm_encoder *encoder); -void armada_drm_encoder_commit(struct drm_encoder *encoder); - -bool armada_drm_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, struct drm_display_mode *adj); - int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn, struct drm_display_mode *mode); From 38bf3aee3ec7b5b264b701da14114a618cddd1a1 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Fri, 2 Jan 2015 22:04:25 +0100 Subject: [PATCH 0002/3798] drm/armada: armada_drv: Remove unused function Remove the function armada_drm_vbl_event_remove_unlocked() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_drm.h | 2 -- drivers/gpu/drm/armada/armada_drv.c | 10 ---------- 2 files changed, 12 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h index ea63c6c7c66f61..5f6aef0dca59e5 100644 --- a/drivers/gpu/drm/armada/armada_drm.h +++ b/drivers/gpu/drm/armada/armada_drm.h @@ -46,8 +46,6 @@ void armada_drm_vbl_event_add(struct armada_crtc *, struct armada_vbl_event *); void armada_drm_vbl_event_remove(struct armada_crtc *, struct armada_vbl_event *); -void armada_drm_vbl_event_remove_unlocked(struct armada_crtc *, - struct armada_vbl_event *); #define armada_drm_vbl_event_init(_e, _f, _d) do { \ struct armada_vbl_event *__e = _e; \ INIT_LIST_HEAD(&__e->node); \ diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index f672e6ad8afae0..7c00a90997794f 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -252,16 +252,6 @@ void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc, } } -void armada_drm_vbl_event_remove_unlocked(struct armada_crtc *dcrtc, - struct armada_vbl_event *evt) -{ - unsigned long flags; - - spin_lock_irqsave(&dcrtc->irq_lock, flags); - armada_drm_vbl_event_remove(dcrtc, evt); - spin_unlock_irqrestore(&dcrtc->irq_lock, flags); -} - /* These are called under the vbl_lock. */ static int armada_drm_enable_vblank(struct drm_device *dev, int crtc) { From 6d293983d4d2d1c233fff94f7b2c4603bdab0170 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 30 Mar 2015 08:33:12 +0300 Subject: [PATCH 0003/3798] drm/i915: Check lane sharing between pipes B & C using atomic state Makes that code atomic ready. v2: Acquire crtc_state for the "other" pipe only when needed. (Daniel) v3: Really only acquire the other state if necessary. (Daniel) Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 69 +++++++++++++++++----------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 75955fee6d24b1..cfe34c316d77a2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5667,65 +5667,80 @@ bool intel_connector_get_hw_state(struct intel_connector *connector) return encoder->get_hw_state(encoder, &pipe); } -static int pipe_required_fdi_lanes(struct drm_device *dev, enum pipe pipe) +static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = - to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); - - if (crtc->base.state->enable && - crtc->config->has_pch_encoder) - return crtc->config->fdi_lanes; + if (crtc_state->base.enable && crtc_state->has_pch_encoder) + return crtc_state->fdi_lanes; return 0; } -static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, +static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, struct intel_crtc_state *pipe_config) { + struct drm_atomic_state *state = pipe_config->base.state; + struct intel_crtc *other_crtc; + struct intel_crtc_state *other_crtc_state; + DRM_DEBUG_KMS("checking fdi config on pipe %c, lanes %i\n", pipe_name(pipe), pipe_config->fdi_lanes); if (pipe_config->fdi_lanes > 4) { DRM_DEBUG_KMS("invalid fdi lane config on pipe %c: %i lanes\n", pipe_name(pipe), pipe_config->fdi_lanes); - return false; + return -EINVAL; } if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { if (pipe_config->fdi_lanes > 2) { DRM_DEBUG_KMS("only 2 lanes on haswell, required: %i lanes\n", pipe_config->fdi_lanes); - return false; + return -EINVAL; } else { - return true; + return 0; } } if (INTEL_INFO(dev)->num_pipes == 2) - return true; + return 0; /* Ivybridge 3 pipe is really complicated */ switch (pipe) { case PIPE_A: - return true; + return 0; case PIPE_B: - if (pipe_config->fdi_lanes > 2 && - pipe_required_fdi_lanes(dev, PIPE_C) > 0) { + if (pipe_config->fdi_lanes <= 2) + return 0; + + other_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, PIPE_C)); + other_crtc_state = + intel_atomic_get_crtc_state(state, other_crtc); + if (IS_ERR(other_crtc_state)) + return PTR_ERR(other_crtc_state); + + if (pipe_required_fdi_lanes(other_crtc_state) > 0) { DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n", pipe_name(pipe), pipe_config->fdi_lanes); - return false; + return -EINVAL; } - return true; + return 0; case PIPE_C: if (pipe_config->fdi_lanes > 2) { DRM_DEBUG_KMS("only 2 lanes on pipe %c: required %i lanes\n", pipe_name(pipe), pipe_config->fdi_lanes); - return false; + return -EINVAL; } - if (pipe_required_fdi_lanes(dev, PIPE_B) > 2) { + + other_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, PIPE_B)); + other_crtc_state = + intel_atomic_get_crtc_state(state, other_crtc); + if (IS_ERR(other_crtc_state)) + return PTR_ERR(other_crtc_state); + + if (pipe_required_fdi_lanes(other_crtc_state) > 2) { DRM_DEBUG_KMS("fdi link B uses too many lanes to enable link C\n"); - return false; + return -EINVAL; } - return true; + return 0; default: BUG(); } @@ -5737,8 +5752,8 @@ static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc, { struct drm_device *dev = intel_crtc->base.dev; struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; - int lane, link_bw, fdi_dotclock; - bool setup_ok, needs_recompute = false; + int lane, link_bw, fdi_dotclock, ret; + bool needs_recompute = false; retry: /* FDI is a binary signal running at ~2.7GHz, encoding @@ -5760,9 +5775,9 @@ static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc, intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock, link_bw, &pipe_config->fdi_m_n); - setup_ok = ironlake_check_fdi_lanes(intel_crtc->base.dev, - intel_crtc->pipe, pipe_config); - if (!setup_ok && pipe_config->pipe_bpp > 6*3) { + ret = ironlake_check_fdi_lanes(intel_crtc->base.dev, + intel_crtc->pipe, pipe_config); + if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) { pipe_config->pipe_bpp -= 2*3; DRM_DEBUG_KMS("fdi link bw constraint, reducing pipe bpp to %i\n", pipe_config->pipe_bpp); @@ -5775,7 +5790,7 @@ static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc, if (needs_recompute) return RETRY; - return setup_ok ? 0 : -EINVAL; + return ret; } static void hsw_compute_ips_config(struct intel_crtc *crtc, From 41037f9f0e299f72e062cb508371906810fcedde Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 27 Mar 2015 11:01:36 +0000 Subject: [PATCH 0004/3798] drm/i915: Add i915_gem_request_unreference__unlocked We were missing a convenience stub to aquire the right mutex whilst dropping the request, so add it. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 13 +++++++++++++ drivers/gpu/drm/i915/i915_gem.c | 8 ++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e326ac9730cf9c..4ef320c17b63ee 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2142,6 +2142,19 @@ i915_gem_request_unreference(struct drm_i915_gem_request *req) kref_put(&req->ref, i915_gem_request_free); } +static inline void +i915_gem_request_unreference__unlocked(struct drm_i915_gem_request *req) +{ + if (req && !atomic_add_unless(&req->ref.refcount, -1, 1)) { + struct drm_device *dev = req->ring->dev; + + mutex_lock(&dev->struct_mutex); + if (likely(atomic_dec_and_test(&req->ref.refcount))) + i915_gem_request_free(&req->ref); + mutex_unlock(&dev->struct_mutex); + } +} + static inline void i915_gem_request_assign(struct drm_i915_gem_request **pdst, struct drm_i915_gem_request *src) { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d07c0b1fb49826..3a913658483386 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2866,9 +2866,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) ret = __i915_wait_request(req, reset_counter, true, args->timeout_ns > 0 ? &args->timeout_ns : NULL, file->driver_priv); - mutex_lock(&dev->struct_mutex); - i915_gem_request_unreference(req); - mutex_unlock(&dev->struct_mutex); + i915_gem_request_unreference__unlocked(req); return ret; out: @@ -4071,9 +4069,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) if (ret == 0) queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); - mutex_lock(&dev->struct_mutex); - i915_gem_request_unreference(target); - mutex_unlock(&dev->struct_mutex); + i915_gem_request_unreference__unlocked(target); return ret; } From b728d7265bfaf125604c48a54d2932add7aebf31 Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Sat, 28 Mar 2015 10:57:46 +0100 Subject: [PATCH 0005/3798] Enabled dithering in the intel VCH DVO for 18bpp pipelines. Signed-off-by: Thomas Richter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/dvo_ivch.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c index 0f2587ff347c95..89b08a896d20ca 100644 --- a/drivers/gpu/drm/i915/dvo_ivch.c +++ b/drivers/gpu/drm/i915/dvo_ivch.c @@ -23,6 +23,9 @@ * Authors: * Eric Anholt * + * Minor modifications (Dithering enable): + * Thomas Richter + * */ #include "dvo.h" @@ -59,6 +62,8 @@ # define VR01_DVO_BYPASS_ENABLE (1 << 1) /** Enables the DVO clock */ # define VR01_DVO_ENABLE (1 << 0) +/** Enable dithering for 18bpp panels. Not documented. */ +# define VR01_DITHER_ENABLE (1 << 4) /* * LCD Interface Format @@ -74,6 +79,8 @@ # define VR10_INTERFACE_2X18 (2 << 2) /** Enables 2x24-bit LVDS output */ # define VR10_INTERFACE_2X24 (3 << 2) +/** Mask that defines the depth of the pipeline */ +# define VR10_INTERFACE_DEPTH_MASK (3 << 2) /* * VR20 LCD Horizontal Display Size @@ -342,9 +349,15 @@ static void ivch_mode_set(struct intel_dvo_device *dvo, struct drm_display_mode *adjusted_mode) { uint16_t vr40 = 0; - uint16_t vr01; + uint16_t vr01 = 0; + uint16_t vr10; + + ivch_read(dvo, VR10, &vr10); + /* Enable dithering for 18 bpp pipelines */ + vr10 &= VR10_INTERFACE_DEPTH_MASK; + if (vr10 == VR10_INTERFACE_2X18 || vr10 == VR10_INTERFACE_1X18) + vr01 = VR01_DITHER_ENABLE; - vr01 = 0; vr40 = (VR40_STALL_ENABLE | VR40_VERTICAL_INTERP_ENABLE | VR40_HORIZONTAL_INTERP_ENABLE); @@ -353,7 +366,7 @@ static void ivch_mode_set(struct intel_dvo_device *dvo, uint16_t x_ratio, y_ratio; vr01 |= VR01_PANEL_FIT_ENABLE; - vr40 |= VR40_CLOCK_GATING_ENABLE; + vr40 |= VR40_CLOCK_GATING_ENABLE | VR40_ENHANCED_PANEL_FITTING; x_ratio = (((mode->hdisplay - 1) << 16) / (adjusted_mode->hdisplay - 1)) >> 2; y_ratio = (((mode->vdisplay - 1) << 16) / @@ -380,6 +393,8 @@ static void ivch_dump_regs(struct intel_dvo_device *dvo) DRM_DEBUG_KMS("VR00: 0x%04x\n", val); ivch_read(dvo, VR01, &val); DRM_DEBUG_KMS("VR01: 0x%04x\n", val); + ivch_read(dvo, VR10, &val); + DRM_DEBUG_KMS("VR10: 0x%04x\n", val); ivch_read(dvo, VR30, &val); DRM_DEBUG_KMS("VR30: 0x%04x\n", val); ivch_read(dvo, VR40, &val); From 670b90d20a5d71a2f430e0c4b97dac2d17a659b5 Mon Sep 17 00:00:00 2001 From: Durgadoss R Date: Fri, 27 Mar 2015 17:21:32 +0530 Subject: [PATCH 0006/3798] drm/i915: PSR: Keep sink state consistent with source BSpec recommends to keep the main link state consistent between the source and the sink. As per that, update the main link state in sink DPCD register to 'active', for Valleyview based platforms. Signed-off-by: Durgadoss R Reviewed-by: Rodrigo Vivi Tested-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_psr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index a8f9348259ae58..9668735fce523a 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -133,7 +133,7 @@ static void hsw_psr_setup_vsc(struct intel_dp *intel_dp) static void vlv_psr_enable_sink(struct intel_dp *intel_dp) { drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, - DP_PSR_ENABLE); + DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE); } static void hsw_psr_enable_sink(struct intel_dp *intel_dp) From 8c7a075da9f7980cc95ffcd7e6621d4a87f20f40 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 30 Mar 2015 16:20:44 +0100 Subject: [PATCH 0007/3798] drm/i2c: tda998x: use drm_hdmi_avi_infoframe_from_display_mode() Make use of the DRM HDMI AVI infoframe helper to construct the AVI infoframe, rather than coding this up ourselves. This allows DRM to supply proper aspect ratio information derived from the DRM display mode structure. Signed-off-by: Russell King --- drivers/gpu/drm/i2c/tda998x_drv.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 43d5d91fe8806f..fbc9c1facdfe21 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -610,19 +610,21 @@ tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p) static void tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode) { - u8 buf[PB(HDMI_AVI_INFOFRAME_SIZE) + 1]; + struct hdmi_avi_infoframe frame; + u8 buf[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; + ssize_t len; - memset(buf, 0, sizeof(buf)); - buf[HB(0)] = HDMI_INFOFRAME_TYPE_AVI; - buf[HB(1)] = 0x02; - buf[HB(2)] = HDMI_AVI_INFOFRAME_SIZE; - buf[PB(1)] = HDMI_SCAN_MODE_UNDERSCAN; - buf[PB(2)] = HDMI_ACTIVE_ASPECT_PICTURE; - buf[PB(3)] = HDMI_QUANTIZATION_RANGE_FULL << 2; - buf[PB(4)] = drm_match_cea_mode(mode); - - tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf, - sizeof(buf)); + drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + + frame.quantization_range = HDMI_QUANTIZATION_RANGE_FULL; + + len = hdmi_avi_infoframe_pack(&frame, buf, sizeof(buf)); + if (len < 0) { + dev_err(&priv->hdmi->dev, "hdmi_avi_infoframe_pack() failed: %d\n", len); + return; + } + + tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf, len); } static void tda998x_audio_mute(struct tda998x_priv *priv, bool on) From 85250ddff7a603dfe0ec0503a9e6395f79424f61 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Sat, 28 Mar 2015 15:23:34 +0530 Subject: [PATCH 0008/3798] drm/i915/chv: Remove Wait for a previous gfx force-off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On CHV, PUNIT team confirmed that 'VLV_GFX_CLK_STATUS_BIT' is not a sticky bit and it will always be set. So ignore Check for previous Gfx force off during suspend and allow the force clk as part S0ix Sequence Signed-off-by: Deepak S Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 82f8be4b674596..182d6a74277834 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1194,11 +1194,13 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on) int err; val = I915_READ(VLV_GTLC_SURVIVABILITY_REG); - WARN_ON(!!(val & VLV_GFX_CLK_FORCE_ON_BIT) == force_on); #define COND (I915_READ(VLV_GTLC_SURVIVABILITY_REG) & VLV_GFX_CLK_STATUS_BIT) /* Wait for a previous force-off to settle */ - if (force_on) { + if (force_on && !IS_CHERRYVIEW(dev_priv->dev)) { + /* WARN_ON only for the Valleyview */ + WARN_ON(!!(val & VLV_GFX_CLK_FORCE_ON_BIT) == force_on); + err = wait_for(!COND, 20); if (err) { DRM_ERROR("timeout waiting for GFX clock force-off (%08x)\n", From 77589f561bce75e6799e2bc05551486bbef3954a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2015 10:37:22 +0300 Subject: [PATCH 0009/3798] drm/i915: Convert BUGs to WARNs in the video overlay code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG is bad, just use WARN. Also drop one BUG(!overlay) since we'd oops anyway when dereferencing it. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_overlay.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index dd92122ed95c87..730ee46563c850 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -216,7 +216,7 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, struct intel_engine_cs *ring = &dev_priv->ring[RCS]; int ret; - BUG_ON(overlay->last_flip_req); + WARN_ON(overlay->last_flip_req); i915_gem_request_assign(&overlay->last_flip_req, ring->outstanding_lazy_request); ret = i915_add_request(ring); @@ -241,7 +241,7 @@ static int intel_overlay_on(struct intel_overlay *overlay) struct intel_engine_cs *ring = &dev_priv->ring[RCS]; int ret; - BUG_ON(overlay->active); + WARN_ON(overlay->active); overlay->active = 1; WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE)); @@ -270,7 +270,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay, u32 tmp; int ret; - BUG_ON(!overlay->active); + WARN_ON(!overlay->active); if (load_polyphase_filter) flip_addr |= OFC_UPDATE; @@ -309,7 +309,8 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay) struct drm_i915_gem_object *obj = overlay->vid_bo; /* never have the overlay hw on without showing a frame */ - BUG_ON(!overlay->vid_bo); + if (WARN_ON(!obj)) + return; i915_gem_object_ggtt_unpin(obj); drm_gem_object_unreference(&obj->base); @@ -329,7 +330,7 @@ static int intel_overlay_off(struct intel_overlay *overlay) u32 flip_addr = overlay->flip_addr; int ret; - BUG_ON(!overlay->active); + WARN_ON(!overlay->active); /* According to intel docs the overlay hw may hang (when switching * off) without loading the filter coeffs. It is however unclear whether @@ -712,9 +713,8 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, u32 swidth, swidthsw, sheight, ostride; enum pipe pipe = overlay->crtc->pipe; - BUG_ON(!mutex_is_locked(&dev->struct_mutex)); - BUG_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); - BUG_ON(!overlay); + WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); ret = intel_overlay_release_old_vid(overlay); if (ret != 0) @@ -824,8 +824,8 @@ int intel_overlay_switch_off(struct intel_overlay *overlay) struct drm_device *dev = overlay->dev; int ret; - BUG_ON(!mutex_is_locked(&dev->struct_mutex)); - BUG_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); + WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); ret = intel_overlay_recover_from_interrupt(overlay); if (ret != 0) @@ -1432,7 +1432,7 @@ void intel_cleanup_overlay(struct drm_device *dev) /* The bo's should be free'd by the generic code already. * Furthermore modesetting teardown happens beforehand so the * hardware should be off already */ - BUG_ON(dev_priv->overlay->active); + WARN_ON(dev_priv->overlay->active); drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base); kfree(dev_priv->overlay); From 209c2a5ec1c9b59f1f43ecd882a2b04d8a6b65de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2015 10:37:23 +0300 Subject: [PATCH 0010/3798] drm/i915: Convert overlay->{active, pfit_active} to bools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit overlay.{active,pfit_active} are just on/off flags, so make them bool. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_overlay.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 730ee46563c850..fd9ded771d0152 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -172,8 +172,8 @@ struct intel_overlay { struct intel_crtc *crtc; struct drm_i915_gem_object *vid_bo; struct drm_i915_gem_object *old_vid_bo; - int active; - int pfit_active; + bool active; + bool pfit_active; u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */ u32 color_key; u32 brightness, contrast, saturation; @@ -242,7 +242,7 @@ static int intel_overlay_on(struct intel_overlay *overlay) int ret; WARN_ON(overlay->active); - overlay->active = 1; + overlay->active = true; WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE)); @@ -318,7 +318,7 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay) overlay->crtc->overlay = NULL; overlay->crtc = NULL; - overlay->active = 0; + overlay->active = false; } /* overlay needs to be disabled in OCMD reg */ @@ -1131,10 +1131,10 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, /* line too wide, i.e. one-line-mode */ if (mode->hdisplay > 1024 && intel_panel_fitter_pipe(dev) == crtc->pipe) { - overlay->pfit_active = 1; + overlay->pfit_active = true; update_pfit_vscale_ratio(overlay); } else - overlay->pfit_active = 0; + overlay->pfit_active = false; } ret = check_overlay_dst(overlay, put_image_rec); From 1c7c4301eeeff9af7e5009785aa721b0da6c9198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2015 10:37:24 +0300 Subject: [PATCH 0011/3798] drm/i915: Mark the overlay active only if we got ring space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the GPU has wedged we can't turn on the overlay anymore. Only mark it as active if we succeed in allocating ring space. This prevents a WARN (previous;y a BUG) during driver unload if we attempted to use the overlay after the GPU had already wedged. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_overlay.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index fd9ded771d0152..b291f1301c9386 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -242,14 +242,14 @@ static int intel_overlay_on(struct intel_overlay *overlay) int ret; WARN_ON(overlay->active); - overlay->active = true; - WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE)); ret = intel_ring_begin(ring, 4); if (ret) return ret; + overlay->active = true; + intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON); intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE); intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); From 46509475a817ed099829be2a8d03cdbc355a284e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2015 10:37:21 +0300 Subject: [PATCH 0012/3798] drm/i915: Enable DVO 2x clock around DVO encoder init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ns2501 requires the DVO 2x clock before it will respond to i2c access, so make sure the clock is enabled when we try to initialize the encoder. Fixes the display getting lost on module reload on my Fujitsu/Siemens Lifebook S6010. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dvo.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 4ccd6c3f133d3d..f2ed122615ae7f 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -495,6 +495,8 @@ void intel_dvo_init(struct drm_device *dev) struct i2c_adapter *i2c; int gpio; bool dvoinit; + enum pipe pipe; + uint32_t dpll[2]; /* Allow the I2C driver info to specify the GPIO to be used in * special cases, but otherwise default to what's defined @@ -520,8 +522,23 @@ void intel_dvo_init(struct drm_device *dev) */ intel_gmbus_force_bit(i2c, true); + /* ns2501 requires the DVO 2x clock before it will + * respond to i2c accesses, so make sure we have + * have the clock enabled before we attempt to + * initialize the device. + */ + for_each_pipe(dev_priv, pipe) { + dpll[pipe] = I915_READ(DPLL(pipe)); + I915_WRITE(DPLL(pipe), dpll[pipe] | DPLL_DVO_2X_MODE); + } + dvoinit = dvo->dev_ops->init(&intel_dvo->dev, i2c); + /* restore the DVO 2x clock state to original */ + for_each_pipe(dev_priv, pipe) { + I915_WRITE(DPLL(pipe), dpll[pipe]); + } + intel_gmbus_force_bit(i2c, false); if (!dvoinit) From e907f1704c402122b0c0a206d8064e19b79ed1c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2015 14:09:47 +0300 Subject: [PATCH 0013/3798] drm/i915: Return more precise cdclk for gen2/3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fill out the lower three digits for gen2 and gen3 cdclk frqeuncy. It's not clear if these are accurate frquencies or just in the ballpark, but without docs this is the best we can do. Signed-off-by: Ville Syrjälä Signed-off-by: Mika Kahola Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cfe34c316d77a2..2ce097fa4418d4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5893,7 +5893,7 @@ static int i945_get_display_clock_speed(struct drm_device *dev) static int i915_get_display_clock_speed(struct drm_device *dev) { - return 333000; + return 333333; } static int i9xx_misc_get_display_clock_speed(struct drm_device *dev) @@ -5909,19 +5909,19 @@ static int pnv_get_display_clock_speed(struct drm_device *dev) switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { case GC_DISPLAY_CLOCK_267_MHZ_PNV: - return 267000; + return 266667; case GC_DISPLAY_CLOCK_333_MHZ_PNV: - return 333000; + return 333333; case GC_DISPLAY_CLOCK_444_MHZ_PNV: - return 444000; + return 444444; case GC_DISPLAY_CLOCK_200_MHZ_PNV: return 200000; default: DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc); case GC_DISPLAY_CLOCK_133_MHZ_PNV: - return 133000; + return 133333; case GC_DISPLAY_CLOCK_167_MHZ_PNV: - return 167000; + return 166667; } } @@ -5932,11 +5932,11 @@ static int i915gm_get_display_clock_speed(struct drm_device *dev) pci_read_config_word(dev->pdev, GCFGC, &gcfgc); if (gcfgc & GC_LOW_FREQUENCY_ENABLE) - return 133000; + return 133333; else { switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { case GC_DISPLAY_CLOCK_333_MHZ: - return 333000; + return 333333; default: case GC_DISPLAY_CLOCK_190_200_MHZ: return 190000; @@ -5946,7 +5946,7 @@ static int i915gm_get_display_clock_speed(struct drm_device *dev) static int i865_get_display_clock_speed(struct drm_device *dev) { - return 266000; + return 266667; } static int i855_get_display_clock_speed(struct drm_device *dev) @@ -5962,7 +5962,7 @@ static int i855_get_display_clock_speed(struct drm_device *dev) case GC_CLOCK_166_250: return 250000; case GC_CLOCK_100_133: - return 133000; + return 133333; } /* Shouldn't happen */ @@ -5971,7 +5971,7 @@ static int i855_get_display_clock_speed(struct drm_device *dev) static int i830_get_display_clock_speed(struct drm_device *dev) { - return 133000; + return 133333; } static void From b37a6434cfa9477e6e5cb386e7e3d135073aef63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2015 14:11:54 +0300 Subject: [PATCH 0014/3798] drm/i915: ILK cdclk seems to be 450MHz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on the BIOS DP A AUX 2x clock divider the cdclk frequency on ILK is 450Mhz. At least that holds on my ILK and it matches how we program the divider. Supposedly cdclk is 400MHz on SNB and IVB, again based on the AUX 2x clock divider. Note that I don't have a SNB or IVB machine with eDP so I couldn't verify what the BIOS used, so this notion is purely based on our current code, Signed-off-by: Ville Syrjälä Signed-off-by: Mika Kahola Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2ce097fa4418d4..c43716a3ad2e10 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5886,6 +5886,11 @@ static int valleyview_get_display_clock_speed(struct drm_device *dev) return DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, divider + 1); } +static int ilk_get_display_clock_speed(struct drm_device *dev) +{ + return 450000; +} + static int i945_get_display_clock_speed(struct drm_device *dev) { return 400000; @@ -13498,6 +13503,9 @@ static void intel_init_display(struct drm_device *dev) if (IS_VALLEYVIEW(dev)) dev_priv->display.get_display_clock_speed = valleyview_get_display_clock_speed; + else if (IS_GEN5(dev)) + dev_priv->display.get_display_clock_speed = + ilk_get_display_clock_speed; else if (IS_I945G(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev))) dev_priv->display.get_display_clock_speed = i945_get_display_clock_speed; From a7c66cd86ae0a2377b6efda56b93b26ce1f4322e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2015 14:11:56 +0300 Subject: [PATCH 0015/3798] drm/i915: Assume 400MHz cdclk for the rest of gen4-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't currently have cdclk extraction code for 965g,snb,ivb. Let's assume 400 MHz until we know better. That seems to match hints in various vague documents. Whether that's good enough is not entirely clear. Signed-off-by: Ville Syrjälä Signed-off-by: Mika Kahola Acked-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c43716a3ad2e10..44a146b27c2fc6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13506,7 +13506,8 @@ static void intel_init_display(struct drm_device *dev) else if (IS_GEN5(dev)) dev_priv->display.get_display_clock_speed = ilk_get_display_clock_speed; - else if (IS_I945G(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev))) + else if (IS_I945G(dev) || IS_BROADWATER(dev) || + IS_GEN6(dev) || IS_IVYBRIDGE(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev))) dev_priv->display.get_display_clock_speed = i945_get_display_clock_speed; else if (IS_I915G(dev)) From 469d4b2a4ed7a255ffef31fad9d56bb6f7ac1213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2015 14:11:59 +0300 Subject: [PATCH 0016/3798] drm/i915: Simplify ilk_get_aux_clock_divider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we are "extracting" the cdclk frequency on ILK-IVB we can also simplify ilk_get_aux_clock_divider() to calculate the divider based on cdclk instead of hardcoding the values. Signed-off-by: Ville Syrjälä Signed-off-by: Mika Kahola Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b70e635ccaf4f2..fd9fc3c6a72cc0 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -696,15 +696,13 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; if (index) return 0; if (intel_dig_port->port == PORT_A) { - if (IS_GEN6(dev) || IS_GEN7(dev)) - return 200; /* SNB & IVB eDP input clock at 400Mhz */ - else - return 225; /* eDP input clock at 450Mhz */ + return DIV_ROUND_UP(dev_priv->display.get_display_clock_speed(dev), 2000); } else { return DIV_ROUND_UP(intel_pch_rawclk(dev), 2); } From 1652d19e66c2dd118bd263ccba2a951b7946a2bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2015 14:12:01 +0300 Subject: [PATCH 0017/3798] drm/i915: Convert the ddi cdclk code to get_display_clock_speed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify the HSW/BDW/SKL cdclk extraction code to conform to the same .get_display_clock_speed() mold that all the other platforms use. v2: Update due to SKL code getting added v3: Rebase on top of -nightly (introduction of intel_audio.c) (Mika Kahola) Signed-off-by: Ville Syrjälä Signed-off-by: Mika Kahola Reviewed-by: Damien Lespiau [danvet: Add v3 note as suggested by Damien.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_audio.c | 3 +- drivers/gpu/drm/i915/intel_ddi.c | 101 +-------------------------- drivers/gpu/drm/i915/intel_display.c | 98 +++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 1 - drivers/gpu/drm/i915/intel_pm.c | 2 +- 6 files changed, 102 insertions(+), 105 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 2396cc702d18b3..0d5b1cea47156c 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -485,7 +485,8 @@ static int i915_audio_component_get_cdclk_freq(struct device *dev) return -ENODEV; intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO); - ret = intel_ddi_get_cdclk_freq(dev_priv); + ret = dev_priv->display.get_display_clock_speed(dev_priv->dev); + intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); return ret; diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 47b9307da24b23..8c692d8a3ef60b 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1689,105 +1689,6 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder) } } -static int skl_get_cdclk_freq(struct drm_i915_private *dev_priv) -{ - uint32_t lcpll1 = I915_READ(LCPLL1_CTL); - uint32_t cdctl = I915_READ(CDCLK_CTL); - uint32_t linkrate; - - if (!(lcpll1 & LCPLL_PLL_ENABLE)) { - WARN(1, "LCPLL1 not enabled\n"); - return 24000; /* 24MHz is the cd freq with NSSC ref */ - } - - if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540) - return 540000; - - linkrate = (I915_READ(DPLL_CTRL1) & - DPLL_CRTL1_LINK_RATE_MASK(SKL_DPLL0)) >> 1; - - if (linkrate == DPLL_CRTL1_LINK_RATE_2160 || - linkrate == DPLL_CRTL1_LINK_RATE_1080) { - /* vco 8640 */ - switch (cdctl & CDCLK_FREQ_SEL_MASK) { - case CDCLK_FREQ_450_432: - return 432000; - case CDCLK_FREQ_337_308: - return 308570; - case CDCLK_FREQ_675_617: - return 617140; - default: - WARN(1, "Unknown cd freq selection\n"); - } - } else { - /* vco 8100 */ - switch (cdctl & CDCLK_FREQ_SEL_MASK) { - case CDCLK_FREQ_450_432: - return 450000; - case CDCLK_FREQ_337_308: - return 337500; - case CDCLK_FREQ_675_617: - return 675000; - default: - WARN(1, "Unknown cd freq selection\n"); - } - } - - /* error case, do as if DPLL0 isn't enabled */ - return 24000; -} - -static int bdw_get_cdclk_freq(struct drm_i915_private *dev_priv) -{ - uint32_t lcpll = I915_READ(LCPLL_CTL); - uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; - - if (lcpll & LCPLL_CD_SOURCE_FCLK) - return 800000; - else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) - return 450000; - else if (freq == LCPLL_CLK_FREQ_450) - return 450000; - else if (freq == LCPLL_CLK_FREQ_54O_BDW) - return 540000; - else if (freq == LCPLL_CLK_FREQ_337_5_BDW) - return 337500; - else - return 675000; -} - -static int hsw_get_cdclk_freq(struct drm_i915_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - uint32_t lcpll = I915_READ(LCPLL_CTL); - uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; - - if (lcpll & LCPLL_CD_SOURCE_FCLK) - return 800000; - else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) - return 450000; - else if (freq == LCPLL_CLK_FREQ_450) - return 450000; - else if (IS_HSW_ULT(dev)) - return 337500; - else - return 540000; -} - -int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - - if (IS_SKYLAKE(dev)) - return skl_get_cdclk_freq(dev_priv); - - if (IS_BROADWELL(dev)) - return bdw_get_cdclk_freq(dev_priv); - - /* Haswell */ - return hsw_get_cdclk_freq(dev_priv); -} - static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll) { @@ -1974,7 +1875,7 @@ void intel_ddi_pll_init(struct drm_device *dev) hsw_shared_dplls_init(dev_priv); DRM_DEBUG_KMS("CDCLK running at %dKHz\n", - intel_ddi_get_cdclk_freq(dev_priv)); + dev_priv->display.get_display_clock_speed(dev)); if (IS_SKYLAKE(dev)) { if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 44a146b27c2fc6..d3cdc12a6330c6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5864,6 +5864,93 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, return 0; } +static int skylake_get_display_clock_speed(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + uint32_t lcpll1 = I915_READ(LCPLL1_CTL); + uint32_t cdctl = I915_READ(CDCLK_CTL); + uint32_t linkrate; + + if (!(lcpll1 & LCPLL_PLL_ENABLE)) { + WARN(1, "LCPLL1 not enabled\n"); + return 24000; /* 24MHz is the cd freq with NSSC ref */ + } + + if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540) + return 540000; + + linkrate = (I915_READ(DPLL_CTRL1) & + DPLL_CRTL1_LINK_RATE_MASK(SKL_DPLL0)) >> 1; + + if (linkrate == DPLL_CRTL1_LINK_RATE_2160 || + linkrate == DPLL_CRTL1_LINK_RATE_1080) { + /* vco 8640 */ + switch (cdctl & CDCLK_FREQ_SEL_MASK) { + case CDCLK_FREQ_450_432: + return 432000; + case CDCLK_FREQ_337_308: + return 308570; + case CDCLK_FREQ_675_617: + return 617140; + default: + WARN(1, "Unknown cd freq selection\n"); + } + } else { + /* vco 8100 */ + switch (cdctl & CDCLK_FREQ_SEL_MASK) { + case CDCLK_FREQ_450_432: + return 450000; + case CDCLK_FREQ_337_308: + return 337500; + case CDCLK_FREQ_675_617: + return 675000; + default: + WARN(1, "Unknown cd freq selection\n"); + } + } + + /* error case, do as if DPLL0 isn't enabled */ + return 24000; +} + +static int broadwell_get_display_clock_speed(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t lcpll = I915_READ(LCPLL_CTL); + uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; + + if (lcpll & LCPLL_CD_SOURCE_FCLK) + return 800000; + else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) + return 450000; + else if (freq == LCPLL_CLK_FREQ_450) + return 450000; + else if (freq == LCPLL_CLK_FREQ_54O_BDW) + return 540000; + else if (freq == LCPLL_CLK_FREQ_337_5_BDW) + return 337500; + else + return 675000; +} + +static int haswell_get_display_clock_speed(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t lcpll = I915_READ(LCPLL_CTL); + uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; + + if (lcpll & LCPLL_CD_SOURCE_FCLK) + return 800000; + else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) + return 450000; + else if (freq == LCPLL_CLK_FREQ_450) + return 450000; + else if (IS_HSW_ULT(dev)) + return 337500; + else + return 540000; +} + static int valleyview_get_display_clock_speed(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -13500,7 +13587,16 @@ static void intel_init_display(struct drm_device *dev) } /* Returns the core display clock speed */ - if (IS_VALLEYVIEW(dev)) + if (IS_SKYLAKE(dev)) + dev_priv->display.get_display_clock_speed = + skylake_get_display_clock_speed; + else if (IS_BROADWELL(dev)) + dev_priv->display.get_display_clock_speed = + broadwell_get_display_clock_speed; + else if (IS_HASWELL(dev)) + dev_priv->display.get_display_clock_speed = + haswell_get_display_clock_speed; + else if (IS_VALLEYVIEW(dev)) dev_priv->display.get_display_clock_speed = valleyview_get_display_clock_speed; else if (IS_GEN5(dev)) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index fd9fc3c6a72cc0..7936155acbe809 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -717,7 +717,7 @@ static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index) if (intel_dig_port->port == PORT_A) { if (index) return 0; - return DIV_ROUND_CLOSEST(intel_ddi_get_cdclk_freq(dev_priv), 2000); + return DIV_ROUND_CLOSEST(dev_priv->display.get_display_clock_speed(dev), 2000); } else if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { /* Workaround for non-ULT HSW */ switch (index) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6036e3b73b7b9d..4799b11f30c54e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -855,7 +855,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc); void intel_ddi_init(struct drm_device *dev, enum port port); enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder); bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe); -int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv); void intel_ddi_pll_init(struct drm_device *dev); void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc); void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index fa4ccb346389e2..e1392e79c5c4b8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1792,7 +1792,7 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc) linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8, mode->crtc_clock); ips_linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8, - intel_ddi_get_cdclk_freq(dev_priv)); + dev_priv->display.get_display_clock_speed(dev_priv->dev)); return PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) | PIPE_WM_LINETIME_TIME(linetime); From f3dc74c0e17b712cbcb4688a28d27df3fa8644a9 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Thu, 19 Mar 2015 12:30:06 +0000 Subject: [PATCH 0018/3798] drm/i915: Rename 'do_execbuf' to 'execbuf_submit' The submission portion of the execbuffer code path was abstracted into a function pointer indirection as part of the legacy vs execlist work. The two implementation functions are called 'i915_gem_ringbuffer_submission' and 'intel_execlists_submission' but the pointer was called 'do_execbuf'. There is already a 'i915_gem_do_execbuffer' function (which is what calls the pointer indirection). The name of the pointer is therefore considered to be backwards and should be changed. This patch renames it to 'execbuf_submit' which is hopefully a bit clearer. For: VIZ-5115 Signed-off-by: John Harrison Reviewed-by: Tomas Elf Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 14 +++++++------- drivers/gpu/drm/i915/i915_gem.c | 4 ++-- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4ef320c17b63ee..727fc544852090 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1814,13 +1814,13 @@ struct drm_i915_private { /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ struct { - int (*do_execbuf)(struct drm_device *dev, struct drm_file *file, - struct intel_engine_cs *ring, - struct intel_context *ctx, - struct drm_i915_gem_execbuffer2 *args, - struct list_head *vmas, - struct drm_i915_gem_object *batch_obj, - u64 exec_start, u32 flags); + int (*execbuf_submit)(struct drm_device *dev, struct drm_file *file, + struct intel_engine_cs *ring, + struct intel_context *ctx, + struct drm_i915_gem_execbuffer2 *args, + struct list_head *vmas, + struct drm_i915_gem_object *batch_obj, + u64 exec_start, u32 flags); int (*init_rings)(struct drm_device *dev); void (*cleanup_ring)(struct intel_engine_cs *ring); void (*stop_ring)(struct intel_engine_cs *ring); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 3a913658483386..815223694f3292 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4859,12 +4859,12 @@ int i915_gem_init(struct drm_device *dev) } if (!i915.enable_execlists) { - dev_priv->gt.do_execbuf = i915_gem_ringbuffer_submission; + dev_priv->gt.execbuf_submit = i915_gem_ringbuffer_submission; dev_priv->gt.init_rings = i915_gem_init_rings; dev_priv->gt.cleanup_ring = intel_cleanup_ring_buffer; dev_priv->gt.stop_ring = intel_stop_ring_buffer; } else { - dev_priv->gt.do_execbuf = intel_execlists_submission; + dev_priv->gt.execbuf_submit = intel_execlists_submission; dev_priv->gt.init_rings = intel_logical_rings_init; dev_priv->gt.cleanup_ring = intel_logical_ring_cleanup; dev_priv->gt.stop_ring = intel_logical_ring_stop; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index a3190e793ed437..2522f325e0e6d0 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1601,9 +1601,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, } else exec_start += i915_gem_obj_offset(batch_obj, vm); - ret = dev_priv->gt.do_execbuf(dev, file, ring, ctx, args, - &eb->vmas, batch_obj, exec_start, - dispatch_flags); + ret = dev_priv->gt.execbuf_submit(dev, file, ring, ctx, args, + &eb->vmas, batch_obj, exec_start, + dispatch_flags); /* * FIXME: We crucially rely upon the active tracking for the (ppgtt) From bc0dce3fd0526215aa781c28069519d126d50129 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Thu, 19 Mar 2015 12:30:07 +0000 Subject: [PATCH 0019/3798] drm/i915: Make intel_logical_ring_begin() static The only usage of intel_logical_ring_begin() is within intel_lrc.c so it can be made static. To avoid a forward declaration at the top of the file, it and bunch of other functions have been shuffled upwards. For: VIZ-5115 Signed-off-by: John Harrison Reviewed-by: Tomas Elf Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 474 +++++++++++++++---------------- drivers/gpu/drm/i915/intel_lrc.h | 3 - 2 files changed, 237 insertions(+), 240 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index fcb074bd55dcb0..cad4300dd55cc3 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -611,6 +611,243 @@ static int execlists_move_to_gpu(struct intel_ringbuffer *ringbuf, return logical_ring_invalidate_all_caches(ringbuf, ctx); } +static int logical_ring_alloc_request(struct intel_engine_cs *ring, + struct intel_context *ctx) +{ + struct drm_i915_gem_request *request; + struct drm_i915_private *dev_private = ring->dev->dev_private; + int ret; + + if (ring->outstanding_lazy_request) + return 0; + + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) + return -ENOMEM; + + if (ctx != ring->default_context) { + ret = intel_lr_context_pin(ring, ctx); + if (ret) { + kfree(request); + return ret; + } + } + + kref_init(&request->ref); + request->ring = ring; + request->uniq = dev_private->request_uniq++; + + ret = i915_gem_get_seqno(ring->dev, &request->seqno); + if (ret) { + intel_lr_context_unpin(ring, ctx); + kfree(request); + return ret; + } + + request->ctx = ctx; + i915_gem_context_reference(request->ctx); + request->ringbuf = ctx->engine[ring->id].ringbuf; + + ring->outstanding_lazy_request = request; + return 0; +} + +static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, + int bytes) +{ + struct intel_engine_cs *ring = ringbuf->ring; + struct drm_i915_gem_request *request; + int ret; + + if (intel_ring_space(ringbuf) >= bytes) + return 0; + + list_for_each_entry(request, &ring->request_list, list) { + /* + * The request queue is per-engine, so can contain requests + * from multiple ringbuffers. Here, we must ignore any that + * aren't from the ringbuffer we're considering. + */ + struct intel_context *ctx = request->ctx; + if (ctx->engine[ring->id].ringbuf != ringbuf) + continue; + + /* Would completion of this request free enough space? */ + if (__intel_ring_space(request->tail, ringbuf->tail, + ringbuf->size) >= bytes) { + break; + } + } + + if (&request->list == &ring->request_list) + return -ENOSPC; + + ret = i915_wait_request(request); + if (ret) + return ret; + + i915_gem_retire_requests_ring(ring); + + return intel_ring_space(ringbuf) >= bytes ? 0 : -ENOSPC; +} + +/* + * intel_logical_ring_advance_and_submit() - advance the tail and submit the workload + * @ringbuf: Logical Ringbuffer to advance. + * + * The tail is updated in our logical ringbuffer struct, not in the actual context. What + * really happens during submission is that the context and current tail will be placed + * on a queue waiting for the ELSP to be ready to accept a new context submission. At that + * point, the tail *inside* the context is updated and the ELSP written to. + */ +static void +intel_logical_ring_advance_and_submit(struct intel_ringbuffer *ringbuf, + struct intel_context *ctx, + struct drm_i915_gem_request *request) +{ + struct intel_engine_cs *ring = ringbuf->ring; + + intel_logical_ring_advance(ringbuf); + + if (intel_ring_stopped(ring)) + return; + + execlists_context_queue(ring, ctx, ringbuf->tail, request); +} + +static int logical_ring_wait_for_space(struct intel_ringbuffer *ringbuf, + struct intel_context *ctx, + int bytes) +{ + struct intel_engine_cs *ring = ringbuf->ring; + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long end; + int ret; + + ret = logical_ring_wait_request(ringbuf, bytes); + if (ret != -ENOSPC) + return ret; + + /* Force the context submission in case we have been skipping it */ + intel_logical_ring_advance_and_submit(ringbuf, ctx, NULL); + + /* With GEM the hangcheck timer should kick us out of the loop, + * leaving it early runs the risk of corrupting GEM state (due + * to running on almost untested codepaths). But on resume + * timers don't work yet, so prevent a complete hang in that + * case by choosing an insanely large timeout. */ + end = jiffies + 60 * HZ; + + ret = 0; + do { + if (intel_ring_space(ringbuf) >= bytes) + break; + + msleep(1); + + if (dev_priv->mm.interruptible && signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + + ret = i915_gem_check_wedge(&dev_priv->gpu_error, + dev_priv->mm.interruptible); + if (ret) + break; + + if (time_after(jiffies, end)) { + ret = -EBUSY; + break; + } + } while (1); + + return ret; +} + +static int logical_ring_wrap_buffer(struct intel_ringbuffer *ringbuf, + struct intel_context *ctx) +{ + uint32_t __iomem *virt; + int rem = ringbuf->size - ringbuf->tail; + + if (ringbuf->space < rem) { + int ret = logical_ring_wait_for_space(ringbuf, ctx, rem); + + if (ret) + return ret; + } + + virt = ringbuf->virtual_start + ringbuf->tail; + rem /= 4; + while (rem--) + iowrite32(MI_NOOP, virt++); + + ringbuf->tail = 0; + intel_ring_update_space(ringbuf); + + return 0; +} + +static int logical_ring_prepare(struct intel_ringbuffer *ringbuf, + struct intel_context *ctx, int bytes) +{ + int ret; + + if (unlikely(ringbuf->tail + bytes > ringbuf->effective_size)) { + ret = logical_ring_wrap_buffer(ringbuf, ctx); + if (unlikely(ret)) + return ret; + } + + if (unlikely(ringbuf->space < bytes)) { + ret = logical_ring_wait_for_space(ringbuf, ctx, bytes); + if (unlikely(ret)) + return ret; + } + + return 0; +} + +/** + * intel_logical_ring_begin() - prepare the logical ringbuffer to accept some commands + * + * @ringbuf: Logical ringbuffer. + * @num_dwords: number of DWORDs that we plan to write to the ringbuffer. + * + * The ringbuffer might not be ready to accept the commands right away (maybe it needs to + * be wrapped, or wait a bit for the tail to be updated). This function takes care of that + * and also preallocates a request (every workload submission is still mediated through + * requests, same as it did with legacy ringbuffer submission). + * + * Return: non-zero if the ringbuffer is not ready to be written to. + */ +static int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf, + struct intel_context *ctx, int num_dwords) +{ + struct intel_engine_cs *ring = ringbuf->ring; + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int ret; + + ret = i915_gem_check_wedge(&dev_priv->gpu_error, + dev_priv->mm.interruptible); + if (ret) + return ret; + + ret = logical_ring_prepare(ringbuf, ctx, num_dwords * sizeof(uint32_t)); + if (ret) + return ret; + + /* Preallocate the olr before touching the ring */ + ret = logical_ring_alloc_request(ring, ctx); + if (ret) + return ret; + + ringbuf->space -= num_dwords * sizeof(uint32_t); + return 0; +} + /** * execlists_submission() - submit a batchbuffer for execution, Execlists style * @dev: DRM device. @@ -787,30 +1024,6 @@ int logical_ring_flush_all_caches(struct intel_ringbuffer *ringbuf, return 0; } -/* - * intel_logical_ring_advance_and_submit() - advance the tail and submit the workload - * @ringbuf: Logical Ringbuffer to advance. - * - * The tail is updated in our logical ringbuffer struct, not in the actual context. What - * really happens during submission is that the context and current tail will be placed - * on a queue waiting for the ELSP to be ready to accept a new context submission. At that - * point, the tail *inside* the context is updated and the ELSP written to. - */ -static void -intel_logical_ring_advance_and_submit(struct intel_ringbuffer *ringbuf, - struct intel_context *ctx, - struct drm_i915_gem_request *request) -{ - struct intel_engine_cs *ring = ringbuf->ring; - - intel_logical_ring_advance(ringbuf); - - if (intel_ring_stopped(ring)) - return; - - execlists_context_queue(ring, ctx, ringbuf->tail, request); -} - static int intel_lr_context_pin(struct intel_engine_cs *ring, struct intel_context *ctx) { @@ -855,219 +1068,6 @@ void intel_lr_context_unpin(struct intel_engine_cs *ring, } } -static int logical_ring_alloc_request(struct intel_engine_cs *ring, - struct intel_context *ctx) -{ - struct drm_i915_gem_request *request; - struct drm_i915_private *dev_private = ring->dev->dev_private; - int ret; - - if (ring->outstanding_lazy_request) - return 0; - - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; - - if (ctx != ring->default_context) { - ret = intel_lr_context_pin(ring, ctx); - if (ret) { - kfree(request); - return ret; - } - } - - kref_init(&request->ref); - request->ring = ring; - request->uniq = dev_private->request_uniq++; - - ret = i915_gem_get_seqno(ring->dev, &request->seqno); - if (ret) { - intel_lr_context_unpin(ring, ctx); - kfree(request); - return ret; - } - - request->ctx = ctx; - i915_gem_context_reference(request->ctx); - request->ringbuf = ctx->engine[ring->id].ringbuf; - - ring->outstanding_lazy_request = request; - return 0; -} - -static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, - int bytes) -{ - struct intel_engine_cs *ring = ringbuf->ring; - struct drm_i915_gem_request *request; - int ret; - - if (intel_ring_space(ringbuf) >= bytes) - return 0; - - list_for_each_entry(request, &ring->request_list, list) { - /* - * The request queue is per-engine, so can contain requests - * from multiple ringbuffers. Here, we must ignore any that - * aren't from the ringbuffer we're considering. - */ - struct intel_context *ctx = request->ctx; - if (ctx->engine[ring->id].ringbuf != ringbuf) - continue; - - /* Would completion of this request free enough space? */ - if (__intel_ring_space(request->tail, ringbuf->tail, - ringbuf->size) >= bytes) { - break; - } - } - - if (&request->list == &ring->request_list) - return -ENOSPC; - - ret = i915_wait_request(request); - if (ret) - return ret; - - i915_gem_retire_requests_ring(ring); - - return intel_ring_space(ringbuf) >= bytes ? 0 : -ENOSPC; -} - -static int logical_ring_wait_for_space(struct intel_ringbuffer *ringbuf, - struct intel_context *ctx, - int bytes) -{ - struct intel_engine_cs *ring = ringbuf->ring; - struct drm_device *dev = ring->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long end; - int ret; - - ret = logical_ring_wait_request(ringbuf, bytes); - if (ret != -ENOSPC) - return ret; - - /* Force the context submission in case we have been skipping it */ - intel_logical_ring_advance_and_submit(ringbuf, ctx, NULL); - - /* With GEM the hangcheck timer should kick us out of the loop, - * leaving it early runs the risk of corrupting GEM state (due - * to running on almost untested codepaths). But on resume - * timers don't work yet, so prevent a complete hang in that - * case by choosing an insanely large timeout. */ - end = jiffies + 60 * HZ; - - ret = 0; - do { - if (intel_ring_space(ringbuf) >= bytes) - break; - - msleep(1); - - if (dev_priv->mm.interruptible && signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - ret = i915_gem_check_wedge(&dev_priv->gpu_error, - dev_priv->mm.interruptible); - if (ret) - break; - - if (time_after(jiffies, end)) { - ret = -EBUSY; - break; - } - } while (1); - - return ret; -} - -static int logical_ring_wrap_buffer(struct intel_ringbuffer *ringbuf, - struct intel_context *ctx) -{ - uint32_t __iomem *virt; - int rem = ringbuf->size - ringbuf->tail; - - if (ringbuf->space < rem) { - int ret = logical_ring_wait_for_space(ringbuf, ctx, rem); - - if (ret) - return ret; - } - - virt = ringbuf->virtual_start + ringbuf->tail; - rem /= 4; - while (rem--) - iowrite32(MI_NOOP, virt++); - - ringbuf->tail = 0; - intel_ring_update_space(ringbuf); - - return 0; -} - -static int logical_ring_prepare(struct intel_ringbuffer *ringbuf, - struct intel_context *ctx, int bytes) -{ - int ret; - - if (unlikely(ringbuf->tail + bytes > ringbuf->effective_size)) { - ret = logical_ring_wrap_buffer(ringbuf, ctx); - if (unlikely(ret)) - return ret; - } - - if (unlikely(ringbuf->space < bytes)) { - ret = logical_ring_wait_for_space(ringbuf, ctx, bytes); - if (unlikely(ret)) - return ret; - } - - return 0; -} - -/** - * intel_logical_ring_begin() - prepare the logical ringbuffer to accept some commands - * - * @ringbuf: Logical ringbuffer. - * @num_dwords: number of DWORDs that we plan to write to the ringbuffer. - * - * The ringbuffer might not be ready to accept the commands right away (maybe it needs to - * be wrapped, or wait a bit for the tail to be updated). This function takes care of that - * and also preallocates a request (every workload submission is still mediated through - * requests, same as it did with legacy ringbuffer submission). - * - * Return: non-zero if the ringbuffer is not ready to be written to. - */ -int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf, - struct intel_context *ctx, int num_dwords) -{ - struct intel_engine_cs *ring = ringbuf->ring; - struct drm_device *dev = ring->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int ret; - - ret = i915_gem_check_wedge(&dev_priv->gpu_error, - dev_priv->mm.interruptible); - if (ret) - return ret; - - ret = logical_ring_prepare(ringbuf, ctx, num_dwords * sizeof(uint32_t)); - if (ret) - return ret; - - /* Preallocate the olr before touching the ring */ - ret = logical_ring_alloc_request(ring, ctx); - if (ret) - return ret; - - ringbuf->space -= num_dwords * sizeof(uint32_t); - return 0; -} - static int intel_logical_ring_workarounds_emit(struct intel_engine_cs *ring, struct intel_context *ctx) { diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index adb731e49c5773..ac8f81a99feae2 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -63,9 +63,6 @@ static inline void intel_logical_ring_emit(struct intel_ringbuffer *ringbuf, iowrite32(data, ringbuf->virtual_start + ringbuf->tail); ringbuf->tail += 4; } -int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf, - struct intel_context *ctx, - int num_dwords); /* Logical Ring Contexts */ void intel_lr_context_free(struct intel_context *ctx); From 6689cb2b62065b5417aeda13d57d61b437b2126e Mon Sep 17 00:00:00 2001 From: John Harrison Date: Thu, 19 Mar 2015 12:30:08 +0000 Subject: [PATCH 0020/3798] drm/i915: Move common request allocation code into a common function The request allocation code is largely duplicated between legacy mode and execlist mode. The actual difference between the two versions of the code is pretty minimal. This patch moves the common code out into a separate function. This is then called by the execution specific version prior to setting up the one different value. For: VIZ-5190 Signed-off-by: John Harrison Reviewed-by: Tomas Elf Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_gem.c | 37 +++++++++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.c | 39 +++++-------------------- drivers/gpu/drm/i915/intel_lrc.h | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 28 ++---------------- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 ++ 6 files changed, 54 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 727fc544852090..83cda2786e556f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2115,6 +2115,8 @@ struct drm_i915_gem_request { }; +int i915_gem_request_alloc(struct intel_engine_cs *ring, + struct intel_context *ctx); void i915_gem_request_free(struct kref *req_ref); static inline uint32_t diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 815223694f3292..267fdf0f46ae7b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2518,6 +2518,43 @@ void i915_gem_request_free(struct kref *req_ref) kfree(req); } +int i915_gem_request_alloc(struct intel_engine_cs *ring, + struct intel_context *ctx) +{ + int ret; + struct drm_i915_gem_request *request; + struct drm_i915_private *dev_private = ring->dev->dev_private; + + if (ring->outstanding_lazy_request) + return 0; + + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) + return -ENOMEM; + + ret = i915_gem_get_seqno(ring->dev, &request->seqno); + if (ret) { + kfree(request); + return ret; + } + + kref_init(&request->ref); + request->ring = ring; + request->uniq = dev_private->request_uniq++; + + if (i915.enable_execlists) + ret = intel_logical_ring_alloc_request_extras(request, ctx); + else + ret = intel_ring_alloc_request_extras(request); + if (ret) { + kfree(request); + return ret; + } + + ring->outstanding_lazy_request = request; + return 0; +} + struct drm_i915_gem_request * i915_gem_find_active_request(struct intel_engine_cs *ring) { diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index cad4300dd55cc3..6504689467b15f 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -611,44 +611,21 @@ static int execlists_move_to_gpu(struct intel_ringbuffer *ringbuf, return logical_ring_invalidate_all_caches(ringbuf, ctx); } -static int logical_ring_alloc_request(struct intel_engine_cs *ring, - struct intel_context *ctx) +int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request, + struct intel_context *ctx) { - struct drm_i915_gem_request *request; - struct drm_i915_private *dev_private = ring->dev->dev_private; int ret; - if (ring->outstanding_lazy_request) - return 0; - - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; - - if (ctx != ring->default_context) { - ret = intel_lr_context_pin(ring, ctx); - if (ret) { - kfree(request); + if (ctx != request->ring->default_context) { + ret = intel_lr_context_pin(request->ring, ctx); + if (ret) return ret; - } - } - - kref_init(&request->ref); - request->ring = ring; - request->uniq = dev_private->request_uniq++; - - ret = i915_gem_get_seqno(ring->dev, &request->seqno); - if (ret) { - intel_lr_context_unpin(ring, ctx); - kfree(request); - return ret; } - request->ctx = ctx; + request->ringbuf = ctx->engine[request->ring->id].ringbuf; + request->ctx = ctx; i915_gem_context_reference(request->ctx); - request->ringbuf = ctx->engine[ring->id].ringbuf; - ring->outstanding_lazy_request = request; return 0; } @@ -840,7 +817,7 @@ static int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf, return ret; /* Preallocate the olr before touching the ring */ - ret = logical_ring_alloc_request(ring, ctx); + ret = i915_gem_request_alloc(ring, ctx); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index ac8f81a99feae2..04d3a6d8b207e2 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -36,6 +36,8 @@ #define RING_CONTEXT_STATUS_PTR(ring) ((ring)->mmio_base+0x3a0) /* Logical Rings */ +int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request, + struct intel_context *ctx); void intel_logical_ring_stop(struct intel_engine_cs *ring); void intel_logical_ring_cleanup(struct intel_engine_cs *ring); int intel_logical_rings_init(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 441e2502b88946..99fb2f06710ac4 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2181,32 +2181,10 @@ int intel_ring_idle(struct intel_engine_cs *ring) return i915_wait_request(req); } -static int -intel_ring_alloc_request(struct intel_engine_cs *ring) +int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) { - int ret; - struct drm_i915_gem_request *request; - struct drm_i915_private *dev_private = ring->dev->dev_private; - - if (ring->outstanding_lazy_request) - return 0; - - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; - - kref_init(&request->ref); - request->ring = ring; - request->ringbuf = ring->buffer; - request->uniq = dev_private->request_uniq++; - - ret = i915_gem_get_seqno(ring->dev, &request->seqno); - if (ret) { - kfree(request); - return ret; - } + request->ringbuf = request->ring->buffer; - ring->outstanding_lazy_request = request; return 0; } @@ -2247,7 +2225,7 @@ int intel_ring_begin(struct intel_engine_cs *ring, return ret; /* Preallocate the olr before touching the ring */ - ret = intel_ring_alloc_request(ring); + ret = i915_gem_request_alloc(ring, ring->default_context); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index c761fe05ad6fd9..6566dd4474985e 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -390,6 +390,8 @@ int intel_alloc_ringbuffer_obj(struct drm_device *dev, void intel_stop_ring_buffer(struct intel_engine_cs *ring); void intel_cleanup_ring_buffer(struct intel_engine_cs *ring); +int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request); + int __must_check intel_ring_begin(struct intel_engine_cs *ring, int n); int __must_check intel_ring_cacheline_align(struct intel_engine_cs *ring); static inline void intel_ring_emit(struct intel_engine_cs *ring, From dbe4646d6e3467adbe2ec8dbe6b7ceea57dee2ec Mon Sep 17 00:00:00 2001 From: John Harrison Date: Thu, 19 Mar 2015 12:30:09 +0000 Subject: [PATCH 0021/3798] drm/i915: Fix for ringbuf space wait in LRC mode The legacy and LRC code paths have an almost identical procedure for waiting for space in the ring buffer. They both search for a request in the free list that will advance the tail to a point where sufficient space is available. They then wait for that request, retire it and recalculate the free space value. Unfortunately, a bug in the LRC side meant that the resulting free space might not be as large as expected and indeed, might not be sufficient. This is because it was testing against the value of request->tail not request->postfix. Whereas, when a request is retired, ringbuf->tail is updated to req->postfix not req->tail. Another significant difference between the two is that the LRC one did not trust the wait for request to work! It redid the is there enough space available test and would fail the call if insufficient. Whereas, the legacy version just said 'return 0' - it assumed the preceeding code works. This difference meant that the LRC version still worked even with the bug - it just fell back to the polling wait path. For: VIZ-5115 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Reviewed-by: Tomas Elf Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 10 ++++++---- drivers/gpu/drm/i915/intel_ringbuffer.c | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 6504689467b15f..1c3834fc5608e2 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -634,7 +634,7 @@ static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, { struct intel_engine_cs *ring = ringbuf->ring; struct drm_i915_gem_request *request; - int ret; + int ret, new_space; if (intel_ring_space(ringbuf) >= bytes) return 0; @@ -650,10 +650,10 @@ static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, continue; /* Would completion of this request free enough space? */ - if (__intel_ring_space(request->tail, ringbuf->tail, - ringbuf->size) >= bytes) { + new_space = __intel_ring_space(request->postfix, ringbuf->tail, + ringbuf->size); + if (new_space >= bytes) break; - } } if (&request->list == &ring->request_list) @@ -665,6 +665,8 @@ static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, i915_gem_retire_requests_ring(ring); + WARN_ON(intel_ring_space(ringbuf) < new_space); + return intel_ring_space(ringbuf) >= bytes ? 0 : -ENOSPC; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 99fb2f06710ac4..a26bdf89e270a7 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2059,16 +2059,16 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) { struct intel_ringbuffer *ringbuf = ring->buffer; struct drm_i915_gem_request *request; - int ret; + int ret, new_space; if (intel_ring_space(ringbuf) >= n) return 0; list_for_each_entry(request, &ring->request_list, list) { - if (__intel_ring_space(request->postfix, ringbuf->tail, - ringbuf->size) >= n) { + new_space = __intel_ring_space(request->postfix, ringbuf->tail, + ringbuf->size); + if (new_space >= n) break; - } } if (&request->list == &ring->request_list) @@ -2080,6 +2080,8 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) i915_gem_retire_requests_ring(ring); + WARN_ON(intel_ring_space(ringbuf) < new_space); + return 0; } From 988c70156ce1ae146e4105a3d21ec16c5894162b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 27 Mar 2015 00:20:19 +0200 Subject: [PATCH 0022/3798] drm/i915: rename GMBUS_PORT_* macros as GMBUS_PIN_* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The specs refer to pin pairs. Start moving towards using pin rather than port all around to avoid confusion. No functional changes. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_reg.h | 20 ++++++++++---------- drivers/gpu/drm/i915/intel_bios.c | 2 +- drivers/gpu/drm/i915/intel_crt.c | 2 +- drivers/gpu/drm/i915/intel_dvo.c | 8 ++++---- drivers/gpu/drm/i915/intel_hdmi.c | 8 ++++---- drivers/gpu/drm/i915/intel_lvds.c | 2 +- drivers/gpu/drm/i915/intel_sdvo.c | 2 +- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 83cda2786e556f..dca3a4d32a11e8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3067,7 +3067,7 @@ extern int intel_setup_gmbus(struct drm_device *dev); extern void intel_teardown_gmbus(struct drm_device *dev); static inline bool intel_gmbus_is_port_valid(unsigned port) { - return (port >= GMBUS_PORT_SSC && port <= GMBUS_PORT_DPD); + return (port >= GMBUS_PIN_SSC && port <= GMBUS_PIN_DPD); } extern struct i2c_adapter *intel_gmbus_get_adapter( diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b522eb6e59a486..b6113c9a803b02 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1788,16 +1788,16 @@ enum skl_disp_power_wells { #define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */ #define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */ #define GMBUS_HOLD_EXT (1<<7) /* 300ns hold time, rsvd on Pineview */ -#define GMBUS_PORT_DISABLED 0 -#define GMBUS_PORT_SSC 1 -#define GMBUS_PORT_VGADDC 2 -#define GMBUS_PORT_PANEL 3 -#define GMBUS_PORT_DPD_CHV 3 /* HDMID_CHV */ -#define GMBUS_PORT_DPC 4 /* HDMIC */ -#define GMBUS_PORT_DPB 5 /* SDVO, HDMIB */ -#define GMBUS_PORT_DPD 6 /* HDMID */ -#define GMBUS_PORT_RESERVED 7 /* 7 reserved */ -#define GMBUS_NUM_PORTS (GMBUS_PORT_DPD - GMBUS_PORT_SSC + 1) +#define GMBUS_PIN_DISABLED 0 +#define GMBUS_PIN_SSC 1 +#define GMBUS_PIN_VGADDC 2 +#define GMBUS_PIN_PANEL 3 +#define GMBUS_PIN_DPD_CHV 3 /* HDMID_CHV */ +#define GMBUS_PIN_DPC 4 /* HDMIC */ +#define GMBUS_PIN_DPB 5 /* SDVO, HDMIB */ +#define GMBUS_PIN_DPD 6 /* HDMID */ +#define GMBUS_PIN_RESERVED 7 /* 7 reserved */ +#define GMBUS_NUM_PORTS (GMBUS_PIN_DPD - GMBUS_PIN_SSC + 1) #define GMBUS1 0x5104 /* command/status */ #define GMBUS_SW_CLR_INT (1<<31) #define GMBUS_SW_RDY (1<<30) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index c684085cb56ac0..40c8375a447718 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1133,7 +1133,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) struct drm_device *dev = dev_priv->dev; enum port port; - dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC; + dev_priv->vbt.crt_ddc_pin = GMBUS_PIN_VGADDC; /* Default to having backlight */ dev_priv->vbt.backlight.present = true; diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 6095a998bdac38..fa5699c8452b0a 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -747,7 +747,7 @@ static int intel_crt_get_modes(struct drm_connector *connector) goto out; /* Try to probe digital port for output in DVI-I -> VGA mode. */ - i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB); + i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPB); ret = intel_crt_ddc_get_modes(connector, i2c); out: diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index f2ed122615ae7f..447cdc76c960e7 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -80,7 +80,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = { .name = "ch7017", .dvo_reg = DVOC, .slave_addr = 0x75, - .gpio = GMBUS_PORT_DPB, + .gpio = GMBUS_PIN_DPB, .dev_ops = &ch7017_ops, }, { @@ -364,7 +364,7 @@ static int intel_dvo_get_modes(struct drm_connector *connector) * that's not the case. */ intel_ddc_get_modes(connector, - intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPC)); + intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPC)); if (!list_empty(&connector->probed_modes)) return 1; @@ -505,9 +505,9 @@ void intel_dvo_init(struct drm_device *dev) if (intel_gmbus_is_port_valid(dvo->gpio)) gpio = dvo->gpio; else if (dvo->type == INTEL_DVO_CHIP_LVDS) - gpio = GMBUS_PORT_SSC; + gpio = GMBUS_PIN_SSC; else - gpio = GMBUS_PORT_DPB; + gpio = GMBUS_PIN_DPB; /* Set up the I2C bus necessary for the chip we're probing. * It appears that everything is on GPIOE except for panels diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index cacbafdad3abd3..26222e6c1ff343 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1681,18 +1681,18 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, switch (port) { case PORT_B: - intel_hdmi->ddc_bus = GMBUS_PORT_DPB; + intel_hdmi->ddc_bus = GMBUS_PIN_DPB; intel_encoder->hpd_pin = HPD_PORT_B; break; case PORT_C: - intel_hdmi->ddc_bus = GMBUS_PORT_DPC; + intel_hdmi->ddc_bus = GMBUS_PIN_DPC; intel_encoder->hpd_pin = HPD_PORT_C; break; case PORT_D: if (IS_CHERRYVIEW(dev)) - intel_hdmi->ddc_bus = GMBUS_PORT_DPD_CHV; + intel_hdmi->ddc_bus = GMBUS_PIN_DPD_CHV; else - intel_hdmi->ddc_bus = GMBUS_PORT_DPD; + intel_hdmi->ddc_bus = GMBUS_PIN_DPD; intel_encoder->hpd_pin = HPD_PORT_D; break; case PORT_A: diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 06d2da336f7c86..87591615264569 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -921,7 +921,7 @@ void intel_lvds_init(struct drm_device *dev) if (dmi_check_system(intel_no_lvds)) return; - pin = GMBUS_PORT_PANEL; + pin = GMBUS_PIN_PANEL; if (!lvds_is_present_in_vbt(dev, &pin)) { DRM_DEBUG_KMS("LVDS is not present in VBT\n"); return; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index f5b7e1e7c5e039..3e0e9b0e350342 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2294,7 +2294,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, if (mapping->initialized && intel_gmbus_is_port_valid(mapping->i2c_pin)) pin = mapping->i2c_pin; else - pin = GMBUS_PORT_DPB; + pin = GMBUS_PIN_DPB; sdvo->i2c = intel_gmbus_get_adapter(dev_priv, pin); From 0184df465efc3b0a09e6999437ca4925567acf28 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 27 Mar 2015 00:20:20 +0200 Subject: [PATCH 0023/3798] drm/i915: refer to pin instead of port in the intel_i2c.c interfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename intel_gmbus_is_port_valid to intel_gmbus_is_valid_pin, and rename port parameters to pin as well. This matches usage all around, as usually a pin is passed to the validity check function. No functional changes. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 8 ++++---- drivers/gpu/drm/i915/intel_bios.c | 2 +- drivers/gpu/drm/i915/intel_dvo.c | 2 +- drivers/gpu/drm/i915/intel_i2c.c | 8 ++++---- drivers/gpu/drm/i915/intel_lvds.c | 2 +- drivers/gpu/drm/i915/intel_sdvo.c | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index dca3a4d32a11e8..b0390c8c959507 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3065,13 +3065,13 @@ void i915_teardown_sysfs(struct drm_device *dev_priv); /* intel_i2c.c */ extern int intel_setup_gmbus(struct drm_device *dev); extern void intel_teardown_gmbus(struct drm_device *dev); -static inline bool intel_gmbus_is_port_valid(unsigned port) +static inline bool intel_gmbus_is_valid_pin(unsigned int pin) { - return (port >= GMBUS_PIN_SSC && port <= GMBUS_PIN_DPD); + return (pin >= GMBUS_PIN_SSC && pin <= GMBUS_PIN_DPD); } -extern struct i2c_adapter *intel_gmbus_get_adapter( - struct drm_i915_private *dev_priv, unsigned port); +extern struct i2c_adapter * +intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin); extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed); extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit); static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 40c8375a447718..333f4079343528 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -438,7 +438,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv, if (block_size >= sizeof(*general)) { int bus_pin = general->crt_ddc_gmbus_pin; DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); - if (intel_gmbus_is_port_valid(bus_pin)) + if (intel_gmbus_is_valid_pin(bus_pin)) dev_priv->vbt.crt_ddc_pin = bus_pin; } else { DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 447cdc76c960e7..bfedea3826d763 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -502,7 +502,7 @@ void intel_dvo_init(struct drm_device *dev) * special cases, but otherwise default to what's defined * in the spec. */ - if (intel_gmbus_is_port_valid(dvo->gpio)) + if (intel_gmbus_is_valid_pin(dvo->gpio)) gpio = dvo->gpio; else if (dvo->type == INTEL_DVO_CHIP_LVDS) gpio = GMBUS_PIN_SSC; diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index b31088a551f20f..b0003a2bd854b4 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -574,12 +574,12 @@ int intel_setup_gmbus(struct drm_device *dev) } struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, - unsigned port) + unsigned int pin) { - WARN_ON(!intel_gmbus_is_port_valid(port)); + WARN_ON(!intel_gmbus_is_valid_pin(pin)); /* -1 to map pin pair to gmbus index */ - return (intel_gmbus_is_port_valid(port)) ? - &dev_priv->gmbus[port - 1].adapter : NULL; + return (intel_gmbus_is_valid_pin(pin)) ? + &dev_priv->gmbus[pin - 1].adapter : NULL; } void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 87591615264569..d61aa78ed7e3bc 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -781,7 +781,7 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev, child->device_type != DEVICE_TYPE_LFP) continue; - if (intel_gmbus_is_port_valid(child->i2c_pin)) + if (intel_gmbus_is_valid_pin(child->i2c_pin)) *i2c_pin = child->i2c_pin; /* However, we cannot trust the BIOS writers to populate diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 3e0e9b0e350342..124992e48abd39 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2291,7 +2291,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, else mapping = &dev_priv->sdvo_mappings[1]; - if (mapping->initialized && intel_gmbus_is_port_valid(mapping->i2c_pin)) + if (mapping->initialized && intel_gmbus_is_valid_pin(mapping->i2c_pin)) pin = mapping->i2c_pin; else pin = GMBUS_PIN_DPB; From 5ea6e5e36ee54a83dfef9739f006a6a91d00e7fe Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 1 Apr 2015 10:55:04 +0300 Subject: [PATCH 0024/3798] drm/i915: index gmbus tables using the pin pair number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Index the gmbus tables directly using the pin instead of having a confusing "port = i + 1" mapping. This finishes off removing the "gmbus port" as a notion, and leaves us with just the "gmbus pin". As pin 0 is invalid by definition and the gmbus tables will have a gap at that index, add pin validity check to all the loops. This will be benefitial for supporting platforms that have different numbers of pins, or gaps. v2: s/GMBUS_PIN_MAX/GMBUS_NUM_PINS/ (Ville, Daniel) Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/i915_reg.h | 2 +- drivers/gpu/drm/i915/intel_i2c.c | 65 +++++++++++++++++++------------- 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b0390c8c959507..0ad11d9c123fc8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1574,8 +1574,7 @@ struct drm_i915_private { struct i915_virtual_gpu vgpu; - struct intel_gmbus gmbus[GMBUS_NUM_PORTS]; - + struct intel_gmbus gmbus[GMBUS_NUM_PINS]; /** gmbus_mutex protects against concurrent usage of the single hw gmbus * controller on different i2c buses. */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b6113c9a803b02..49fbed9c35cd94 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1797,7 +1797,7 @@ enum skl_disp_power_wells { #define GMBUS_PIN_DPB 5 /* SDVO, HDMIB */ #define GMBUS_PIN_DPD 6 /* HDMID */ #define GMBUS_PIN_RESERVED 7 /* 7 reserved */ -#define GMBUS_NUM_PORTS (GMBUS_PIN_DPD - GMBUS_PIN_SSC + 1) +#define GMBUS_NUM_PINS 7 /* including 0 */ #define GMBUS1 0x5104 /* command/status */ #define GMBUS_SW_CLR_INT (1<<31) #define GMBUS_SW_RDY (1<<30) diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index b0003a2bd854b4..ff47a8fdcb6d9a 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -34,18 +34,19 @@ #include #include "i915_drv.h" -struct gmbus_port { +struct gmbus_pin { const char *name; int reg; }; -static const struct gmbus_port gmbus_ports[] = { - { "ssc", GPIOB }, - { "vga", GPIOA }, - { "panel", GPIOC }, - { "dpc", GPIOD }, - { "dpb", GPIOE }, - { "dpd", GPIOF }, +/* Map gmbus pin pairs to names and registers. */ +static const struct gmbus_pin gmbus_pins[] = { + [GMBUS_PIN_SSC] = { "ssc", GPIOB }, + [GMBUS_PIN_VGADDC] = { "vga", GPIOA }, + [GMBUS_PIN_PANEL] = { "panel", GPIOC }, + [GMBUS_PIN_DPC] = { "dpc", GPIOD }, + [GMBUS_PIN_DPB] = { "dpb", GPIOE }, + [GMBUS_PIN_DPD] = { "dpd", GPIOF }, }; /* Intel GPIO access functions */ @@ -182,15 +183,14 @@ intel_gpio_post_xfer(struct i2c_adapter *adapter) } static void -intel_gpio_setup(struct intel_gmbus *bus, u32 pin) +intel_gpio_setup(struct intel_gmbus *bus, unsigned int pin) { struct drm_i915_private *dev_priv = bus->dev_priv; struct i2c_algo_bit_data *algo; algo = &bus->bit_algo; - /* -1 to map pin pair to gmbus index */ - bus->gpio_reg = dev_priv->gpio_mmio_base + gmbus_ports[pin - 1].reg; + bus->gpio_reg = dev_priv->gpio_mmio_base + gmbus_pins[pin].reg; bus->adapter.algo_data = algo; algo->setsda = set_data; @@ -517,7 +517,9 @@ static const struct i2c_algorithm gmbus_algorithm = { int intel_setup_gmbus(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - int ret, i; + struct intel_gmbus *bus; + unsigned int pin; + int ret; if (HAS_PCH_NOP(dev)) return 0; @@ -531,16 +533,18 @@ int intel_setup_gmbus(struct drm_device *dev) mutex_init(&dev_priv->gmbus_mutex); init_waitqueue_head(&dev_priv->gmbus_wait_queue); - for (i = 0; i < GMBUS_NUM_PORTS; i++) { - struct intel_gmbus *bus = &dev_priv->gmbus[i]; - u32 port = i + 1; /* +1 to map gmbus index to pin pair */ + for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) { + if (!intel_gmbus_is_valid_pin(pin)) + continue; + + bus = &dev_priv->gmbus[pin]; bus->adapter.owner = THIS_MODULE; bus->adapter.class = I2C_CLASS_DDC; snprintf(bus->adapter.name, sizeof(bus->adapter.name), "i915 gmbus %s", - gmbus_ports[i].name); + gmbus_pins[pin].name); bus->adapter.dev.parent = &dev->pdev->dev; bus->dev_priv = dev_priv; @@ -548,13 +552,13 @@ int intel_setup_gmbus(struct drm_device *dev) bus->adapter.algo = &gmbus_algorithm; /* By default use a conservative clock rate */ - bus->reg0 = port | GMBUS_RATE_100KHZ; + bus->reg0 = pin | GMBUS_RATE_100KHZ; /* gmbus seems to be broken on i830 */ if (IS_I830(dev)) bus->force_bit = 1; - intel_gpio_setup(bus, port); + intel_gpio_setup(bus, pin); ret = i2c_add_adapter(&bus->adapter); if (ret) @@ -566,8 +570,11 @@ int intel_setup_gmbus(struct drm_device *dev) return 0; err: - while (--i) { - struct intel_gmbus *bus = &dev_priv->gmbus[i]; + while (--pin) { + if (!intel_gmbus_is_valid_pin(pin)) + continue; + + bus = &dev_priv->gmbus[pin]; i2c_del_adapter(&bus->adapter); } return ret; @@ -576,10 +583,10 @@ int intel_setup_gmbus(struct drm_device *dev) struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin) { - WARN_ON(!intel_gmbus_is_valid_pin(pin)); - /* -1 to map pin pair to gmbus index */ - return (intel_gmbus_is_valid_pin(pin)) ? - &dev_priv->gmbus[pin - 1].adapter : NULL; + if (WARN_ON(!intel_gmbus_is_valid_pin(pin))) + return NULL; + + return &dev_priv->gmbus[pin].adapter; } void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed) @@ -602,10 +609,14 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) void intel_teardown_gmbus(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - int i; + struct intel_gmbus *bus; + unsigned int pin; + + for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) { + if (!intel_gmbus_is_valid_pin(pin)) + continue; - for (i = 0; i < GMBUS_NUM_PORTS; i++) { - struct intel_gmbus *bus = &dev_priv->gmbus[i]; + bus = &dev_priv->gmbus[pin]; i2c_del_adapter(&bus->adapter); } } From 88ac7939d2a6cb67e338e72cf6aaff2ae526b026 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 27 Mar 2015 00:20:22 +0200 Subject: [PATCH 0025/3798] drm/i915: base gmbus pin validity check on the gmbus pin map array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will be helpful for adding future platforms. It is better to keep the information in the single point of truth (the table) instead of duplicating it into the validity function. While at it, add dev_priv parameter to the function, also to prepare for adding future platform support. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 6 ++---- drivers/gpu/drm/i915/intel_bios.c | 2 +- drivers/gpu/drm/i915/intel_dvo.c | 2 +- drivers/gpu/drm/i915/intel_i2c.c | 14 ++++++++++---- drivers/gpu/drm/i915/intel_lvds.c | 2 +- drivers/gpu/drm/i915/intel_sdvo.c | 3 ++- 6 files changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0ad11d9c123fc8..d63997bc80e4a7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3064,10 +3064,8 @@ void i915_teardown_sysfs(struct drm_device *dev_priv); /* intel_i2c.c */ extern int intel_setup_gmbus(struct drm_device *dev); extern void intel_teardown_gmbus(struct drm_device *dev); -static inline bool intel_gmbus_is_valid_pin(unsigned int pin) -{ - return (pin >= GMBUS_PIN_SSC && pin <= GMBUS_PIN_DPD); -} +extern bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv, + unsigned int pin); extern struct i2c_adapter * intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin); diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 333f4079343528..ad2f3b0d922f11 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -438,7 +438,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv, if (block_size >= sizeof(*general)) { int bus_pin = general->crt_ddc_gmbus_pin; DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); - if (intel_gmbus_is_valid_pin(bus_pin)) + if (intel_gmbus_is_valid_pin(dev_priv, bus_pin)) dev_priv->vbt.crt_ddc_pin = bus_pin; } else { DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index bfedea3826d763..9a27ec7100efa0 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -502,7 +502,7 @@ void intel_dvo_init(struct drm_device *dev) * special cases, but otherwise default to what's defined * in the spec. */ - if (intel_gmbus_is_valid_pin(dvo->gpio)) + if (intel_gmbus_is_valid_pin(dev_priv, dvo->gpio)) gpio = dvo->gpio; else if (dvo->type == INTEL_DVO_CHIP_LVDS) gpio = GMBUS_PIN_SSC; diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index ff47a8fdcb6d9a..ec9cc8cf642e62 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -49,6 +49,12 @@ static const struct gmbus_pin gmbus_pins[] = { [GMBUS_PIN_DPD] = { "dpd", GPIOF }, }; +bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv, + unsigned int pin) +{ + return pin < ARRAY_SIZE(gmbus_pins) && gmbus_pins[pin].reg; +} + /* Intel GPIO access functions */ #define I2C_RISEFALL_TIME 10 @@ -534,7 +540,7 @@ int intel_setup_gmbus(struct drm_device *dev) init_waitqueue_head(&dev_priv->gmbus_wait_queue); for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) { - if (!intel_gmbus_is_valid_pin(pin)) + if (!intel_gmbus_is_valid_pin(dev_priv, pin)) continue; bus = &dev_priv->gmbus[pin]; @@ -571,7 +577,7 @@ int intel_setup_gmbus(struct drm_device *dev) err: while (--pin) { - if (!intel_gmbus_is_valid_pin(pin)) + if (!intel_gmbus_is_valid_pin(dev_priv, pin)) continue; bus = &dev_priv->gmbus[pin]; @@ -583,7 +589,7 @@ int intel_setup_gmbus(struct drm_device *dev) struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin) { - if (WARN_ON(!intel_gmbus_is_valid_pin(pin))) + if (WARN_ON(!intel_gmbus_is_valid_pin(dev_priv, pin))) return NULL; return &dev_priv->gmbus[pin].adapter; @@ -613,7 +619,7 @@ void intel_teardown_gmbus(struct drm_device *dev) unsigned int pin; for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) { - if (!intel_gmbus_is_valid_pin(pin)) + if (!intel_gmbus_is_valid_pin(dev_priv, pin)) continue; bus = &dev_priv->gmbus[pin]; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index d61aa78ed7e3bc..314a5d56ace25c 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -781,7 +781,7 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev, child->device_type != DEVICE_TYPE_LFP) continue; - if (intel_gmbus_is_valid_pin(child->i2c_pin)) + if (intel_gmbus_is_valid_pin(dev_priv, child->i2c_pin)) *i2c_pin = child->i2c_pin; /* However, we cannot trust the BIOS writers to populate diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 124992e48abd39..b121796c86aa91 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2291,7 +2291,8 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, else mapping = &dev_priv->sdvo_mappings[1]; - if (mapping->initialized && intel_gmbus_is_valid_pin(mapping->i2c_pin)) + if (mapping->initialized && + intel_gmbus_is_valid_pin(dev_priv, mapping->i2c_pin)) pin = mapping->i2c_pin; else pin = GMBUS_PIN_DPB; From f61cccf3e9a4f7deae633b6c073a6e40ef8e86f3 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 31 Mar 2015 11:35:00 +0300 Subject: [PATCH 0026/3798] drm/i915: Set best_encoder field of connector_state also when disabling The best_encoder field of connector_state wasn't properly set when a connector was being disabled, leading to an incosistent atomic state. For now, this doesn't cause anything to blow up, because everywhere we're using connector_state->best_encoder there is a check for connector_state->crtc which is properly initialized. I reached the issue while testing some patches I haven't sent out yet, that remove the usage of intel_connector->new_encoder from check_digital_port_conflicts(). In that case, it would be possible to trigger the converted version of the WARN in that function. Signed-off-by: Ander Conselvan de Oliveira [danvet: Add commit message augmentation Ander supplied.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d3cdc12a6330c6..84f5b417ad3cb9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12100,6 +12100,7 @@ intel_modeset_stage_output_state(struct drm_device *dev, connector->encoder = connector->new_encoder; } else { connector_state->crtc = NULL; + connector_state->best_encoder = NULL; } } for_each_intel_crtc(dev, crtc) { From 2d1070b21e004609a5bebafdb4303bb021f5477c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 1 Apr 2015 10:36:56 +0100 Subject: [PATCH 0027/3798] drm/i915: Make debugfs/i915_gem_request more friendly Count the number of requests in a ring for the user and show who submitted them. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 39 +++++++++++++++++++---------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 007c7d7d82950f..91c945b6a76241 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -643,31 +643,44 @@ static int i915_gem_request_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring; - struct drm_i915_gem_request *gem_request; - int ret, count, i; + struct drm_i915_gem_request *rq; + int ret, any, i; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; - count = 0; + any = 0; for_each_ring(ring, dev_priv, i) { - if (list_empty(&ring->request_list)) + int count; + + count = 0; + list_for_each_entry(rq, &ring->request_list, list) + count++; + if (count == 0) continue; - seq_printf(m, "%s requests:\n", ring->name); - list_for_each_entry(gem_request, - &ring->request_list, - list) { - seq_printf(m, " %x @ %d\n", - gem_request->seqno, - (int) (jiffies - gem_request->emitted_jiffies)); + seq_printf(m, "%s requests: %d\n", ring->name, count); + list_for_each_entry(rq, &ring->request_list, list) { + struct task_struct *task; + + rcu_read_lock(); + task = NULL; + if (rq->pid) + task = pid_task(rq->pid, PIDTYPE_PID); + seq_printf(m, " %x @ %d: %s [%d]\n", + rq->seqno, + (int) (jiffies - rq->emitted_jiffies), + task ? task->comm : "", + task ? task->pid : -1); + rcu_read_unlock(); } - count++; + + any++; } mutex_unlock(&dev->struct_mutex); - if (count == 0) + if (any == 0) seq_puts(m, "No requests\n"); return 0; From 474d1ec4a3d7775b071e60fdbe431cae37b84ff3 Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Thu, 2 Apr 2015 11:02:44 +0530 Subject: [PATCH 0028/3798] drm/i915/skl: Enabling PSR2 SU with frame sync We make use of HW tracking for Selective update region and enable frame sync on sink. We use hardware's hardcoded data values for frame sync and GTC. v2: Add 3200x2000 resolution restriction with PSR2, move psr2_support to i915_psr struct, add aux_frame_sync to independently control aux frame sync, rename the TP2 TIME macro for 2500us (Rodrigo, Siva) v3: Moving the resolution restriction to intel_psr_enable so that we check it only once(Durga) Cc: Durgadoss R Cc: Rodrigo Vivi Signed-off-by: Sonika Jindal Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_reg.h | 14 ++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 15 +++++++++++++ drivers/gpu/drm/i915/intel_psr.c | 38 +++++++++++++++++++++++++++++++- 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d63997bc80e4a7..1d62fbe3fcc0c6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -881,6 +881,8 @@ struct i915_psr { struct delayed_work work; unsigned busy_frontbuffer_bits; bool link_standby; + bool psr2_support; + bool aux_frame_sync; }; enum intel_pch { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 49fbed9c35cd94..8db2a91692667e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2748,6 +2748,20 @@ enum skl_disp_power_wells { #define EDP_PSR_DEBUG_MASK_MEMUP (1<<26) #define EDP_PSR_DEBUG_MASK_HPD (1<<25) +#define EDP_PSR2_CTL 0x6f900 +#define EDP_PSR2_ENABLE (1<<31) +#define EDP_SU_TRACK_ENABLE (1<<30) +#define EDP_MAX_SU_DISABLE_TIME(t) ((t)<<20) +#define EDP_MAX_SU_DISABLE_TIME_MASK (0x1f<<20) +#define EDP_PSR2_TP2_TIME_500 (0<<8) +#define EDP_PSR2_TP2_TIME_100 (1<<8) +#define EDP_PSR2_TP2_TIME_2500 (2<<8) +#define EDP_PSR2_TP2_TIME_50 (3<<8) +#define EDP_PSR2_TP2_TIME_MASK (3<<8) +#define EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4 +#define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4) +#define EDP_PSR2_IDLE_MASK 0xf + /* VGA port control */ #define ADPA 0x61100 #define PCH_ADPA 0xe1100 diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 7936155acbe809..a651dba7fb5a8b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3785,6 +3785,21 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) dev_priv->psr.sink_support = true; DRM_DEBUG_KMS("Detected EDP PSR Panel.\n"); } + + if (INTEL_INFO(dev)->gen >= 9 && + (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) { + uint8_t frame_sync_cap; + + dev_priv->psr.sink_support = true; + intel_dp_dpcd_read_wake(&intel_dp->aux, + DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP, + &frame_sync_cap, 1); + dev_priv->psr.aux_frame_sync = frame_sync_cap ? true : false; + /* PSR2 needs frame sync as well */ + dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync; + DRM_DEBUG_KMS("PSR2 %s on sink", + dev_priv->psr.psr2_support ? "supported" : "not supported"); + } } /* Training Pattern 3 support, both source and sink */ diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 9668735fce523a..27608ce19b1cf6 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -117,6 +117,19 @@ static void vlv_psr_setup_vsc(struct intel_dp *intel_dp) I915_WRITE(VLV_VSCSDP(pipe), val); } +static void skl_psr_setup_su_vsc(struct intel_dp *intel_dp) +{ + struct edp_vsc_psr psr_vsc; + + /* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */ + memset(&psr_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.HB1 = 0x7; + psr_vsc.sdp_header.HB2 = 0x3; + psr_vsc.sdp_header.HB3 = 0xb; + intel_psr_write_vsc(intel_dp, &psr_vsc); +} + static void hsw_psr_setup_vsc(struct intel_dp *intel_dp) { struct edp_vsc_psr psr_vsc; @@ -165,6 +178,12 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE); + /* Enable AUX frame sync at sink */ + if (dev_priv->psr.aux_frame_sync) + drm_dp_dpcd_writeb(&intel_dp->aux, + DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF, + DP_AUX_FRAME_SYNC_ENABLE); + aux_data_reg = (INTEL_INFO(dev)->gen >= 9) ? DPA_AUX_CH_DATA1 : EDP_PSR_AUX_DATA1(dev); aux_ctl_reg = (INTEL_INFO(dev)->gen >= 9) ? @@ -183,8 +202,10 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) val |= DP_AUX_CH_CTL_TIME_OUT_1600us; val &= ~DP_AUX_CH_CTL_MESSAGE_SIZE_MASK; val |= (sizeof(aux_msg) << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); - /* Use hardcoded data values for PSR */ + /* Use hardcoded data values for PSR, frame sync and GTC */ val &= ~DP_AUX_CH_CTL_PSR_DATA_AUX_REG_SKL; + val &= ~DP_AUX_CH_CTL_FS_DATA_AUX_REG_SKL; + val &= ~DP_AUX_CH_CTL_GTC_DATA_AUX_REG_SKL; I915_WRITE(aux_ctl_reg, val); } else { I915_WRITE(aux_ctl_reg, @@ -232,6 +253,7 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t max_sleep_time = 0x1f; /* Lately it was identified that depending on panel idle frame count * calculated at HW can be off by 1. So let's use what came @@ -255,6 +277,10 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT | idle_frames << EDP_PSR_IDLE_FRAME_SHIFT | EDP_PSR_ENABLE); + + if (dev_priv->psr.psr2_support) + I915_WRITE(EDP_PSR2_CTL, EDP_PSR2_ENABLE | + EDP_SU_TRACK_ENABLE | EDP_PSR2_TP2_TIME_100); } static bool intel_psr_match_conditions(struct intel_dp *intel_dp) @@ -332,6 +358,7 @@ void intel_psr_enable(struct intel_dp *intel_dp) struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc); if (!HAS_PSR(dev)) { DRM_DEBUG_KMS("PSR not supported on this platform\n"); @@ -364,6 +391,15 @@ void intel_psr_enable(struct intel_dp *intel_dp) if (HAS_DDI(dev)) { hsw_psr_setup_vsc(intel_dp); + if (dev_priv->psr.psr2_support) { + /* PSR2 is restricted to work with panel resolutions upto 3200x2000 */ + if (crtc->config->pipe_src_w > 3200 || + crtc->config->pipe_src_h > 2000) + dev_priv->psr.psr2_support = false; + else + skl_psr_setup_su_vsc(intel_dp); + } + /* Avoid continuous PSR exit by masking memup and hpd */ I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP | EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP); From 51ce4db1749028b89a1f4a70bfa78b77df8795e7 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Tue, 31 Mar 2015 16:03:21 -0700 Subject: [PATCH 0029/3798] drm/i915/bdw: WaProgramL3SqcReg1Default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Program the default initial value of the L3SqcReg1 on BDW for performance v2: Default confirmed and using intel_ring_emit_wa as Mika pointed out. v3: Spec shows now a different value. It tells us to set to 0x784000 instead the 0x610000 that is there already. Also rebased after a long time so using WA_WRITE now. Cc: Mika Kuoppala Signed-off-by: Rodrigo Vivi Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_ringbuffer.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8db2a91692667e..9966d3294a02ec 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5336,6 +5336,9 @@ enum skl_disp_power_wells { #define GEN7_L3SQCREG1 0xB010 #define VLV_B0_WA_L3SQCREG1_VALUE 0x00D30000 +#define GEN8_L3SQCREG1 0xB100 +#define BDW_WA_L3SQCREG1_DEFAULT 0x784000 + #define GEN7_L3CNTLREG1 0xB01C #define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C47FF8C #define GEN7_L3AGDIS (1<<19) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index a26bdf89e270a7..b5af9b121ce1f9 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -853,6 +853,9 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring) GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4); + /* WaProgramL3SqcReg1Default:bdw */ + WA_WRITE(GEN8_L3SQCREG1, BDW_WA_L3SQCREG1_DEFAULT); + return 0; } From aa7471d228eb6dfddd0d201ea9746d6a2020972a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 1 Apr 2015 11:15:21 +0300 Subject: [PATCH 0030/3798] drm/i915: add i915 specific connector debugfs file for DPCD Occasionally it would be interesting to read some of the DPCD registers for debug purposes, without having to resort to logging. Add an i915 specific i915_dpcd debugfs file for DP and eDP connectors to dump parts of the DPCD. Currently the DPCD addresses to be dumped are statically configured, and more can be added trivially. The implementation also makes it relatively easy to add other i915 and connector specific debugfs files in the future, as necessary. This is currently i915 specific just because there's no generic way to do AUX transactions given just a drm_connector. However it's all pretty straightforward to port to other drivers. v2: Add more DPCD registers to dump. Signed-off-by: Jani Nikula Reviewed-by: Bob Paauwe Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 96 +++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_dp.c | 2 + 3 files changed, 99 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 91c945b6a76241..10ca5117fceeee 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4793,3 +4793,99 @@ void i915_debugfs_cleanup(struct drm_minor *minor) drm_debugfs_remove_files(info_list, 1, minor); } } + +struct dpcd_block { + /* DPCD dump start address. */ + unsigned int offset; + /* DPCD dump end address, inclusive. If unset, .size will be used. */ + unsigned int end; + /* DPCD dump size. Used if .end is unset. If unset, defaults to 1. */ + size_t size; + /* Only valid for eDP. */ + bool edp; +}; + +static const struct dpcd_block i915_dpcd_debug[] = { + { .offset = DP_DPCD_REV, .size = DP_RECEIVER_CAP_SIZE }, + { .offset = DP_PSR_SUPPORT, .end = DP_PSR_CAPS }, + { .offset = DP_DOWNSTREAM_PORT_0, .size = 16 }, + { .offset = DP_LINK_BW_SET, .end = DP_EDP_CONFIGURATION_SET }, + { .offset = DP_SINK_COUNT, .end = DP_ADJUST_REQUEST_LANE2_3 }, + { .offset = DP_SET_POWER }, + { .offset = DP_EDP_DPCD_REV }, + { .offset = DP_EDP_GENERAL_CAP_1, .end = DP_EDP_GENERAL_CAP_3 }, + { .offset = DP_EDP_DISPLAY_CONTROL_REGISTER, .end = DP_EDP_BACKLIGHT_FREQ_CAP_MAX_LSB }, + { .offset = DP_EDP_DBC_MINIMUM_BRIGHTNESS_SET, .end = DP_EDP_DBC_MAXIMUM_BRIGHTNESS_SET }, +}; + +static int i915_dpcd_show(struct seq_file *m, void *data) +{ + struct drm_connector *connector = m->private; + struct intel_dp *intel_dp = + enc_to_intel_dp(&intel_attached_encoder(connector)->base); + uint8_t buf[16]; + ssize_t err; + int i; + + for (i = 0; i < ARRAY_SIZE(i915_dpcd_debug); i++) { + const struct dpcd_block *b = &i915_dpcd_debug[i]; + size_t size = b->end ? b->end - b->offset + 1 : (b->size ?: 1); + + if (b->edp && + connector->connector_type != DRM_MODE_CONNECTOR_eDP) + continue; + + /* low tech for now */ + if (WARN_ON(size > sizeof(buf))) + continue; + + err = drm_dp_dpcd_read(&intel_dp->aux, b->offset, buf, size); + if (err <= 0) { + DRM_ERROR("dpcd read (%zu bytes at %u) failed (%zd)\n", + size, b->offset, err); + continue; + } + + seq_printf(m, "%04x: %*ph\n", b->offset, (int) size, buf); + }; + + return 0; +} + +static int i915_dpcd_open(struct inode *inode, struct file *file) +{ + return single_open(file, i915_dpcd_show, inode->i_private); +} + +static const struct file_operations i915_dpcd_fops = { + .owner = THIS_MODULE, + .open = i915_dpcd_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/** + * i915_debugfs_connector_add - add i915 specific connector debugfs files + * @connector: pointer to a registered drm_connector + * + * Cleanup will be done by drm_connector_unregister() through a call to + * drm_debugfs_connector_remove(). + * + * Returns 0 on success, negative error codes on error. + */ +int i915_debugfs_connector_add(struct drm_connector *connector) +{ + struct dentry *root = connector->debugfs_entry; + + /* The connector must have been registered beforehands. */ + if (!root) + return -ENODEV; + + if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort || + connector->connector_type == DRM_MODE_CONNECTOR_eDP) + debugfs_create_file("i915_dpcd", S_IRUGO, root, connector, + &i915_dpcd_fops); + + return 0; +} diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1d62fbe3fcc0c6..4fd38f2e6e623b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3007,6 +3007,7 @@ int i915_verify_lists(struct drm_device *dev); /* i915_debugfs.c */ int i915_debugfs_init(struct drm_minor *minor); void i915_debugfs_cleanup(struct drm_minor *minor); +int i915_debugfs_connector_add(struct drm_connector *connector); #ifdef CONFIG_DEBUG_FS void intel_display_crc_init(struct drm_device *dev); #else diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a651dba7fb5a8b..1b87969536ffc8 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5584,6 +5584,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); } + i915_debugfs_connector_add(connector); + return true; } From 53375103eae8dd6b717b170c69b72ac50fa01985 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Sat, 28 Mar 2015 21:43:08 +0200 Subject: [PATCH 0031/3798] tools: iio: Add iio targets in tools Makefile This patch adds targets for building and cleaning iio tools to tools/Makefile. To build iio tools from the toplevel kernel directory one should call: $ make -C tools iio and for cleaning it $ make -C tools iio_clean Signed-off-by: Roberta Dobrescu Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- tools/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/Makefile b/tools/Makefile index 9a617adc6675dc..79463b00b81e0d 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -8,6 +8,7 @@ help: @echo ' cpupower - a tool for all things x86 CPU power' @echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer' @echo ' hv - tools used when in Hyper-V clients' + @echo ' iio - IIO tools' @echo ' lguest - a minimal 32-bit x86 hypervisor' @echo ' perf - Linux performance measurement and analysis tool' @echo ' selftests - various kernel selftests' @@ -41,7 +42,7 @@ acpi: FORCE cpupower: FORCE $(call descend,power/$@) -cgroup firewire hv guest usb virtio vm net: FORCE +cgroup firewire hv guest usb virtio vm net iio: FORCE $(call descend,$@) liblockdep: FORCE @@ -91,7 +92,7 @@ acpi_clean: cpupower_clean: $(call descend,power/cpupower,clean) -cgroup_clean hv_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean: +cgroup_clean hv_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean iio_clean: $(call descend,$(@:_clean=),clean) liblockdep_clean: @@ -114,6 +115,6 @@ tmon_clean: clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_clean \ perf_clean selftests_clean turbostat_clean usb_clean virtio_clean \ - vm_clean net_clean x86_energy_perf_policy_clean tmon_clean + vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean .PHONY: FORCE From a25691c1f9674090fb66586cf4c5d60d3efdf339 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Fri, 3 Apr 2015 15:03:02 +0300 Subject: [PATCH 0032/3798] iio: accel: kxcjk1013: allow using an external trigger In its present state, the driver mandates that its buffer only be triggered by one of the device's own triggers (data ready or any motion). This is not always desirable, for example because the interrupt pins may not be wired in. Patch the driver to be able to accept using an external trigger, such as one based on hrtimer. When using such a trigger, we need to ensure that the device is powered on when the buffer is started. We do that by setting setup_ops for the buffer. Signed-off-by: Vlad Dogaru Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/accel/kxcjk-1013.c | 38 ++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 51da3692d56137..df6f5d70fa3b4b 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -875,15 +875,18 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev, return 0; } -static int kxcjk1013_validate_trigger(struct iio_dev *indio_dev, - struct iio_trigger *trig) +static int kxcjk1013_buffer_preenable(struct iio_dev *indio_dev) { struct kxcjk1013_data *data = iio_priv(indio_dev); - if (data->dready_trig != trig && data->motion_trig != trig) - return -EINVAL; + return kxcjk1013_set_power_state(data, true); +} - return 0; +static int kxcjk1013_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct kxcjk1013_data *data = iio_priv(indio_dev); + + return kxcjk1013_set_power_state(data, false); } static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( @@ -935,6 +938,13 @@ static const struct iio_chan_spec kxcjk1013_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(3), }; +static const struct iio_buffer_setup_ops kxcjk1013_buffer_setup_ops = { + .preenable = kxcjk1013_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .postdisable = kxcjk1013_buffer_postdisable, + .predisable = iio_triggered_buffer_predisable, +}; + static const struct iio_info kxcjk1013_info = { .attrs = &kxcjk1013_attrs_group, .read_raw = kxcjk1013_read_raw, @@ -943,7 +953,6 @@ static const struct iio_info kxcjk1013_info = { .write_event_value = kxcjk1013_write_event, .write_event_config = kxcjk1013_write_event_config, .read_event_config = kxcjk1013_read_event_config, - .validate_trigger = kxcjk1013_validate_trigger, .driver_module = THIS_MODULE, }; @@ -1276,16 +1285,15 @@ static int kxcjk1013_probe(struct i2c_client *client, data->motion_trig = NULL; goto err_trigger_unregister; } + } - ret = iio_triggered_buffer_setup(indio_dev, - &iio_pollfunc_store_time, - kxcjk1013_trigger_handler, - NULL); - if (ret < 0) { - dev_err(&client->dev, - "iio triggered buffer setup failed\n"); - goto err_trigger_unregister; - } + ret = iio_triggered_buffer_setup(indio_dev, + &iio_pollfunc_store_time, + kxcjk1013_trigger_handler, + &kxcjk1013_buffer_setup_ops); + if (ret < 0) { + dev_err(&client->dev, "iio triggered buffer setup failed\n"); + goto err_trigger_unregister; } ret = iio_device_register(indio_dev); From 1347f5b46a270db1991625f9f57af91e23a4b512 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Tue, 17 Mar 2015 11:39:27 +0200 Subject: [PATCH 0033/3798] drm/i915/bxt: Add BXT PCI ids MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: Switch to info->ring_mask and add VEBOX support. v3: Fold in update from Damien. v4: Add GEN_DEFAULT_PIPEOFFSETS and IVB_CURSOR_OFFSETS v5: set no-LLC (imre) Signed-off-by: Damien Lespiau (v1,v4) Signed-off-by: Daniel Vetter (v4) Signed-off-by: Imre Deak Reviewed-by: Antti Koskipää Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 14 +++++++++++++- include/drm/i915_pciids.h | 6 ++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 82f8be4b674596..4d5078550e0b67 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -381,6 +381,17 @@ static const struct intel_device_info intel_skylake_gt3_info = { IVB_CURSOR_OFFSETS, }; +static const struct intel_device_info intel_broxton_info = { + .is_preliminary = 1, + .gen = 9, + .need_gfx_hws = 1, .has_hotplug = 1, + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, + .num_pipes = 3, + .has_ddi = 1, + GEN_DEFAULT_PIPEOFFSETS, + IVB_CURSOR_OFFSETS, +}; + /* * Make sure any device matches here are from most specific to most * general. For example, since the Quanta match is based on the subsystem @@ -420,7 +431,8 @@ static const struct intel_device_info intel_skylake_gt3_info = { INTEL_CHV_IDS(&intel_cherryview_info), \ INTEL_SKL_GT1_IDS(&intel_skylake_info), \ INTEL_SKL_GT2_IDS(&intel_skylake_info), \ - INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info) \ + INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info), \ + INTEL_BXT_IDS(&intel_broxton_info) static const struct pci_device_id pciidlist[] = { /* aka */ INTEL_PCI_IDS, diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 613372375adac0..bd0d644d2a038f 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -287,4 +287,10 @@ INTEL_SKL_GT3_IDS(info) +#define INTEL_BXT_IDS(info) \ + INTEL_VGA_DEVICE(0x0A84, info), \ + INTEL_VGA_DEVICE(0x0A85, info), \ + INTEL_VGA_DEVICE(0x0A86, info), \ + INTEL_VGA_DEVICE(0x0A87, info) + #endif /* _I915_PCIIDS_H */ From ce89db2eabb0979e823aed38d5f5b22512d06392 Mon Sep 17 00:00:00 2001 From: Daisy Sun Date: Tue, 17 Mar 2015 11:39:28 +0200 Subject: [PATCH 0034/3798] drm/i915/bxt: BXT FBC enablement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable FBC feature on Broxton Issue: VIZ-3784 Signed-off-by: Daisy Sun Signed-off-by: Damien Lespiau Reviewed-by: Antti Koskipää Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 4d5078550e0b67..48434cb6898d25 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -388,6 +388,7 @@ static const struct intel_device_info intel_broxton_info = { .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, .num_pipes = 3, .has_ddi = 1, + .has_fbc = 1, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, }; From 46ec15f2662b48103751ea059d2cb4e2571bad5e Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 26 Mar 2015 17:35:40 +0200 Subject: [PATCH 0035/3798] drm/i915: use proper FBC base register on all new platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starting from GEN5 the FBC base register is the same on all platforms. GEN>=5 is the same condition as HAS_PCH_SPLIT except on BXT, so make things work on BXT as well. Motivated by Rodrigo's request to check FBC support on BXT. Signed-off-by: Imre Deak Reviewed-by: Antti Koskipää Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_stolen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index f8da71682c9657..348ed5abcdbf6d 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -209,7 +209,7 @@ static int i915_setup_compression(struct drm_device *dev, int size, int fb_cpp) dev_priv->fbc.threshold = ret; - if (HAS_PCH_SPLIT(dev)) + if (INTEL_INFO(dev_priv)->gen >= 5) I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->fbc.compressed_fb.start); else if (IS_GM45(dev)) { I915_WRITE(DPFC_CB_BASE, dev_priv->fbc.compressed_fb.start); From 1feed8855d168482bb9e6faa0ba0f1f257e62514 Mon Sep 17 00:00:00 2001 From: Satheeshakrishna M Date: Tue, 17 Mar 2015 11:39:29 +0200 Subject: [PATCH 0036/3798] drm/i915/bxt: Add IS_BROXTON macro Adding IS_BROXTON macro for broxton specific implementation. Signed-off-by: Satheeshakrishna M Signed-off-by: Damien Lespiau Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e326ac9730cf9c..8341f0f2299f12 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2306,6 +2306,7 @@ struct drm_i915_cmd_table { #define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell) #define IS_BROADWELL(dev) (!INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev)) #define IS_SKYLAKE(dev) (INTEL_INFO(dev)->is_skylake) +#define IS_BROXTON(dev) (!INTEL_INFO(dev)->is_skylake && IS_GEN9(dev)) #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) #define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \ (INTEL_DEVID(dev) & 0xFF00) == 0x0C00) From 31d4dcf705c33da28e3688bfb1f11889cf8b29f9 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Tue, 17 Mar 2015 11:39:30 +0200 Subject: [PATCH 0037/3798] drm/i915/bxt: Broxton uses the same GMS values as Skylake v2: Rebase on top of the early-quirks rework from Ville. Signed-off-by: Damien Lespiau (v1) Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter --- arch/x86/kernel/early-quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index fe9f0b79a18b32..ab470e47519980 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -546,6 +546,7 @@ static const struct pci_device_id intel_stolen_ids[] __initconst = { INTEL_BDW_D_IDS(&gen8_stolen_funcs), INTEL_CHV_IDS(&chv_stolen_funcs), INTEL_SKL_IDS(&gen9_stolen_funcs), + INTEL_BXT_IDS(&gen9_stolen_funcs), }; static void __init intel_graphics_stolen(int num, int slot, int func) From 5a4e33a34fc27d6b54200bde187766e049ae876b Mon Sep 17 00:00:00 2001 From: Sumit Singh Date: Tue, 17 Mar 2015 11:39:31 +0200 Subject: [PATCH 0038/3798] drm/i915/bxt: Enable PTE encoding The caching options for page table entries have remained the same as Cherryview. This patch fixes it so the right code path is taken on BXT. v2: Fix up commit message (Mike) Signed-off-by: Sumit Singh Signed-off-by: Damien Lespiau Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 0239fbff7bf728..22ad9c38812143 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1687,7 +1687,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) if (INTEL_INFO(dev)->gen >= 8) { - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) chv_setup_private_ppat(dev_priv); else bdw_setup_private_ppat(dev_priv); @@ -2375,7 +2375,7 @@ static int gen8_gmch_probe(struct drm_device *dev, *gtt_total = (gtt_size / sizeof(gen8_pte_t)) << PAGE_SHIFT; - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) chv_setup_private_ppat(dev_priv); else bdw_setup_private_ppat(dev_priv); From 8fb9397dafadacd8d3ae21a3f5ac3c473adfe6d4 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Tue, 17 Mar 2015 11:39:32 +0200 Subject: [PATCH 0039/3798] drm/i915/bxt: Broxton has 3 sprite planes on pipe A/B, 2 on pipe C v2: Rebase on top of the for_each_pipe() change adding dev_priv as first argument. Signed-off-by: Damien Lespiau Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 68e0c85a17cfcd..ec661fe44e709e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -585,7 +585,11 @@ static void intel_device_info_runtime_init(struct drm_device *dev) info = (struct intel_device_info *)&dev_priv->info; - if (IS_VALLEYVIEW(dev) || INTEL_INFO(dev)->gen == 9) + if (IS_BROXTON(dev)) { + info->num_sprites[PIPE_A] = 3; + info->num_sprites[PIPE_B] = 3; + info->num_sprites[PIPE_C] = 2; + } else if (IS_VALLEYVIEW(dev) || INTEL_INFO(dev)->gen == 9) for_each_pipe(dev_priv, pipe) info->num_sprites[pipe] = 2; else From b21249c90e7ad8fce2234df98555c80c5f828c4f Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Tue, 17 Mar 2015 11:39:33 +0200 Subject: [PATCH 0040/3798] drm/i915/bxt: Add the plane4 related interrupt definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Damien Lespiau Reviewed-by: Antti Koskipää Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b522eb6e59a486..7e1a0fd9333f45 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5218,9 +5218,11 @@ enum skl_disp_power_wells { #define GEN8_PIPE_VSYNC (1 << 1) #define GEN8_PIPE_VBLANK (1 << 0) #define GEN9_PIPE_CURSOR_FAULT (1 << 11) +#define GEN9_PIPE_PLANE4_FAULT (1 << 10) #define GEN9_PIPE_PLANE3_FAULT (1 << 9) #define GEN9_PIPE_PLANE2_FAULT (1 << 8) #define GEN9_PIPE_PLANE1_FAULT (1 << 7) +#define GEN9_PIPE_PLANE4_FLIP_DONE (1 << 6) #define GEN9_PIPE_PLANE3_FLIP_DONE (1 << 5) #define GEN9_PIPE_PLANE2_FLIP_DONE (1 << 4) #define GEN9_PIPE_PLANE1_FLIP_DONE (1 << 3) @@ -5231,6 +5233,7 @@ enum skl_disp_power_wells { GEN8_PIPE_PRIMARY_FAULT) #define GEN9_DE_PIPE_IRQ_FAULT_ERRORS \ (GEN9_PIPE_CURSOR_FAULT | \ + GEN9_PIPE_PLANE4_FAULT | \ GEN9_PIPE_PLANE3_FAULT | \ GEN9_PIPE_PLANE2_FAULT | \ GEN9_PIPE_PLANE1_FAULT) From 43d735a686d03033599187c276071eceb32d52dd Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Tue, 17 Mar 2015 11:39:34 +0200 Subject: [PATCH 0041/3798] drm/i915/bxt: Broxton DDB is 512 blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Damien Lespiau Reviewed-by: Antti Koskipää Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index fa4ccb346389e2..1e25e3e26a6787 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2538,6 +2538,7 @@ static bool ilk_disable_lp_wm(struct drm_device *dev) */ #define SKL_DDB_SIZE 896 /* in blocks */ +#define BXT_DDB_SIZE 512 static void skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, @@ -2556,7 +2557,10 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, return; } - ddb_size = SKL_DDB_SIZE; + if (IS_BROXTON(dev)) + ddb_size = BXT_DDB_SIZE; + else + ddb_size = SKL_DDB_SIZE; ddb_size -= 4; /* 4 blocks for bypass path allocation */ From 8232edb5f74af0f4664362fefab165e891a7fa68 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Tue, 17 Mar 2015 11:39:35 +0200 Subject: [PATCH 0042/3798] drm/i915/bxt: Broxton raises the maximum number of planes to 4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pipe A and b have 4 planes. Signed-off-by: Damien Lespiau Reviewed-by: Antti Koskipää Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8341f0f2299f12..2d402e49f7fd31 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -130,7 +130,7 @@ enum transcoder { * * This value doesn't count the cursor plane. */ -#define I915_MAX_PLANES 3 +#define I915_MAX_PLANES 4 enum plane { PLANE_A = 0, From 2a073f89435771409a21930b78f182d8cb5c5941 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 27 Mar 2015 13:07:33 +0200 Subject: [PATCH 0043/3798] drm/i915/bxt: map GTT as uncached MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Broxton per specification the GTT has to be mapped as uncached. This was caught by the PTE write readback warning, which showed a corrupted PTE value with using the current write-combine mapping. v2: - add comment explaining how the problem with WC mapping manifests (Daniel) Signed-off-by: Imre Deak Reviewed-by: Antti Koskipää Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 22ad9c38812143..f48d8454f0efb0 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2253,7 +2253,17 @@ static int ggtt_probe_common(struct drm_device *dev, gtt_phys_addr = pci_resource_start(dev->pdev, 0) + (pci_resource_len(dev->pdev, 0) / 2); - dev_priv->gtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size); + /* + * On BXT writes larger than 64 bit to the GTT pagetable range will be + * dropped. For WC mappings in general we have 64 byte burst writes + * when the WC buffer is flushed, so we can't use it, but have to + * resort to an uncached mapping. The WC issue is easily caught by the + * readback check when writing GTT PTE entries. + */ + if (IS_BROXTON(dev)) + dev_priv->gtt.gsm = ioremap_nocache(gtt_phys_addr, gtt_size); + else + dev_priv->gtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size); if (!dev_priv->gtt.gsm) { DRM_ERROR("Failed to map the gtt page table\n"); return -ENOMEM; From cae0437f7a367594cb0abc17ddf337c6b2669fab Mon Sep 17 00:00:00 2001 From: Nick Hoath Date: Tue, 17 Mar 2015 11:39:38 +0200 Subject: [PATCH 0044/3798] drm/i915/bxt: HardWare WorkAround ring initialisation for Broxton Adds framework for Broxton HW WAs Signed-off-by: Nick Hoath Signed-off-by: Imre Deak Reviewed-by: Nick Hoath Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 441e2502b88946..abe062a95be8b5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1027,6 +1027,13 @@ static int skl_init_workarounds(struct intel_engine_cs *ring) return skl_tune_iz_hashing(ring); } +static int bxt_init_workarounds(struct intel_engine_cs *ring) +{ + gen9_init_workarounds(ring); + + return 0; +} + int init_workarounds_ring(struct intel_engine_cs *ring) { struct drm_device *dev = ring->dev; @@ -1044,8 +1051,9 @@ int init_workarounds_ring(struct intel_engine_cs *ring) if (IS_SKYLAKE(dev)) return skl_init_workarounds(ring); - else if (IS_GEN9(dev)) - return gen9_init_workarounds(ring); + + if (IS_BROXTON(dev)) + return bxt_init_workarounds(ring); return 0; } From 6c74c87f7cc94e71960e5a1044c1b26f68f7d3c8 Mon Sep 17 00:00:00 2001 From: Nick Hoath Date: Fri, 20 Mar 2015 09:03:52 +0000 Subject: [PATCH 0045/3798] drm/i915/bxt: Add Broxton steppings Signed-off-by: Nick Hoath Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2d402e49f7fd31..99facbf86043bc 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2331,6 +2331,10 @@ struct drm_i915_cmd_table { #define SKL_REVID_D0 (0x3) #define SKL_REVID_E0 (0x4) +#define BXT_REVID_A0 (0x0) +#define BXT_REVID_B0 (0x3) +#define BXT_REVID_C0 (0x6) + /* * The genX designation typically refers to the render engine, so render * capability related checks should use IS_GEN, while display and other checks From 3449ca859a2ea8466b58794b256892508ea0c1b0 Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Fri, 27 Mar 2015 14:19:09 +0200 Subject: [PATCH 0046/3798] drm/i915/bxt: Increase DDI buf idle timeout For BXT, DDI buf idle timeout delay needs to be increased to 16us. Since this is a timeout value and we return as soon as the condition is realized, no penalty incurred for other platforms. v2: - remove TIMEOUT macro used only at a single place (Daniel) Suggested-by: Satheeshakrishna M Cc: Satheeshakrishna M Cc: Damien Lespiau Signed-off-by: Vandana Kannan Signed-off-by: Damien Lespiau (v1) Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 47b9307da24b23..1c9d439e864af4 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -322,7 +322,7 @@ static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, uint32_t reg = DDI_BUF_CTL(port); int i; - for (i = 0; i < 8; i++) { + for (i = 0; i < 16; i++) { udelay(1); if (I915_READ(reg) & DDI_BUF_IS_IDLE) return; From 9705ad8a9684c5b4952263821e07929ca3856fd1 Mon Sep 17 00:00:00 2001 From: Jeff McGee Date: Fri, 3 Apr 2015 18:13:15 -0700 Subject: [PATCH 0047/3798] drm/i915: Split SSEU init into functions by platform Signed-off-by: Jeff McGee Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 234 +++++++++++++++++--------------- 1 file changed, 125 insertions(+), 109 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ec661fe44e709e..9691f0fc0918bb 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -564,6 +564,127 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv) #undef SEP_COMMA } +static void cherryview_sseu_info_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_device_info *info; + u32 fuse, eu_dis; + + info = (struct intel_device_info *)&dev_priv->info; + fuse = I915_READ(CHV_FUSE_GT); + + info->slice_total = 1; + + if (!(fuse & CHV_FGT_DISABLE_SS0)) { + info->subslice_per_slice++; + eu_dis = fuse & (CHV_FGT_EU_DIS_SS0_R0_MASK | + CHV_FGT_EU_DIS_SS0_R1_MASK); + info->eu_total += 8 - hweight32(eu_dis); + } + + if (!(fuse & CHV_FGT_DISABLE_SS1)) { + info->subslice_per_slice++; + eu_dis = fuse & (CHV_FGT_EU_DIS_SS1_R0_MASK | + CHV_FGT_EU_DIS_SS1_R1_MASK); + info->eu_total += 8 - hweight32(eu_dis); + } + + info->subslice_total = info->subslice_per_slice; + /* + * CHV expected to always have a uniform distribution of EU + * across subslices. + */ + info->eu_per_subslice = info->subslice_total ? + info->eu_total / info->subslice_total : + 0; + /* + * CHV supports subslice power gating on devices with more than + * one subslice, and supports EU power gating on devices with + * more than one EU pair per subslice. + */ + info->has_slice_pg = 0; + info->has_subslice_pg = (info->subslice_total > 1); + info->has_eu_pg = (info->eu_per_subslice > 2); +} + +static void gen9_sseu_info_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_device_info *info; + const int s_max = 3, ss_max = 4, eu_max = 8; + int s, ss; + u32 fuse2, eu_disable[s_max], s_enable, ss_disable; + + info = (struct intel_device_info *)&dev_priv->info; + fuse2 = I915_READ(GEN8_FUSE2); + s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> + GEN8_F2_S_ENA_SHIFT; + ss_disable = (fuse2 & GEN9_F2_SS_DIS_MASK) >> + GEN9_F2_SS_DIS_SHIFT; + + eu_disable[0] = I915_READ(GEN8_EU_DISABLE0); + eu_disable[1] = I915_READ(GEN8_EU_DISABLE1); + eu_disable[2] = I915_READ(GEN8_EU_DISABLE2); + + info->slice_total = hweight32(s_enable); + /* + * The subslice disable field is global, i.e. it applies + * to each of the enabled slices. + */ + info->subslice_per_slice = ss_max - hweight32(ss_disable); + info->subslice_total = info->slice_total * + info->subslice_per_slice; + + /* + * Iterate through enabled slices and subslices to + * count the total enabled EU. + */ + for (s = 0; s < s_max; s++) { + if (!(s_enable & (0x1 << s))) + /* skip disabled slice */ + continue; + + for (ss = 0; ss < ss_max; ss++) { + u32 n_disabled; + + if (ss_disable & (0x1 << ss)) + /* skip disabled subslice */ + continue; + + n_disabled = hweight8(eu_disable[s] >> + (ss * eu_max)); + + /* + * Record which subslice(s) has(have) 7 EUs. we + * can tune the hash used to spread work among + * subslices if they are unbalanced. + */ + if (eu_max - n_disabled == 7) + info->subslice_7eu[s] |= 1 << ss; + + info->eu_total += eu_max - n_disabled; + } + } + + /* + * SKL is expected to always have a uniform distribution + * of EU across subslices with the exception that any one + * EU in any one subslice may be fused off for die + * recovery. + */ + info->eu_per_subslice = info->subslice_total ? + DIV_ROUND_UP(info->eu_total, + info->subslice_total) : 0; + /* + * SKL supports slice power gating on devices with more than + * one slice, and supports EU power gating on devices with + * more than one EU pair per subslice. + */ + info->has_slice_pg = (info->slice_total > 1) ? 1 : 0; + info->has_subslice_pg = 0; + info->has_eu_pg = (info->eu_per_subslice > 2) ? 1 : 0; +} + /* * Determine various intel_device_info fields at runtime. * @@ -624,116 +745,11 @@ static void intel_device_info_runtime_init(struct drm_device *dev) } /* Initialize slice/subslice/EU info */ - if (IS_CHERRYVIEW(dev)) { - u32 fuse, eu_dis; - - fuse = I915_READ(CHV_FUSE_GT); + if (IS_CHERRYVIEW(dev)) + cherryview_sseu_info_init(dev); + else if (IS_SKYLAKE(dev)) + gen9_sseu_info_init(dev); - info->slice_total = 1; - - if (!(fuse & CHV_FGT_DISABLE_SS0)) { - info->subslice_per_slice++; - eu_dis = fuse & (CHV_FGT_EU_DIS_SS0_R0_MASK | - CHV_FGT_EU_DIS_SS0_R1_MASK); - info->eu_total += 8 - hweight32(eu_dis); - } - - if (!(fuse & CHV_FGT_DISABLE_SS1)) { - info->subslice_per_slice++; - eu_dis = fuse & (CHV_FGT_EU_DIS_SS1_R0_MASK | - CHV_FGT_EU_DIS_SS1_R1_MASK); - info->eu_total += 8 - hweight32(eu_dis); - } - - info->subslice_total = info->subslice_per_slice; - /* - * CHV expected to always have a uniform distribution of EU - * across subslices. - */ - info->eu_per_subslice = info->subslice_total ? - info->eu_total / info->subslice_total : - 0; - /* - * CHV supports subslice power gating on devices with more than - * one subslice, and supports EU power gating on devices with - * more than one EU pair per subslice. - */ - info->has_slice_pg = 0; - info->has_subslice_pg = (info->subslice_total > 1); - info->has_eu_pg = (info->eu_per_subslice > 2); - } else if (IS_SKYLAKE(dev)) { - const int s_max = 3, ss_max = 4, eu_max = 8; - int s, ss; - u32 fuse2, eu_disable[s_max], s_enable, ss_disable; - - fuse2 = I915_READ(GEN8_FUSE2); - s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> - GEN8_F2_S_ENA_SHIFT; - ss_disable = (fuse2 & GEN9_F2_SS_DIS_MASK) >> - GEN9_F2_SS_DIS_SHIFT; - - eu_disable[0] = I915_READ(GEN8_EU_DISABLE0); - eu_disable[1] = I915_READ(GEN8_EU_DISABLE1); - eu_disable[2] = I915_READ(GEN8_EU_DISABLE2); - - info->slice_total = hweight32(s_enable); - /* - * The subslice disable field is global, i.e. it applies - * to each of the enabled slices. - */ - info->subslice_per_slice = ss_max - hweight32(ss_disable); - info->subslice_total = info->slice_total * - info->subslice_per_slice; - - /* - * Iterate through enabled slices and subslices to - * count the total enabled EU. - */ - for (s = 0; s < s_max; s++) { - if (!(s_enable & (0x1 << s))) - /* skip disabled slice */ - continue; - - for (ss = 0; ss < ss_max; ss++) { - u32 n_disabled; - - if (ss_disable & (0x1 << ss)) - /* skip disabled subslice */ - continue; - - n_disabled = hweight8(eu_disable[s] >> - (ss * eu_max)); - - /* - * Record which subslice(s) has(have) 7 EUs. we - * can tune the hash used to spread work among - * subslices if they are unbalanced. - */ - if (eu_max - n_disabled == 7) - info->subslice_7eu[s] |= 1 << ss; - - info->eu_total += eu_max - n_disabled; - } - } - - /* - * SKL is expected to always have a uniform distribution - * of EU across subslices with the exception that any one - * EU in any one subslice may be fused off for die - * recovery. - */ - info->eu_per_subslice = info->subslice_total ? - DIV_ROUND_UP(info->eu_total, - info->subslice_total) : 0; - /* - * SKL supports slice power gating on devices with more than - * one slice, and supports EU power gating on devices with - * more than one EU pair per subslice. - */ - info->has_slice_pg = (info->slice_total > 1) ? 1 : 0; - info->has_subslice_pg = 0; - info->has_eu_pg = (info->eu_per_subslice > 2) ? 1 : 0; - } DRM_DEBUG_DRIVER("slice total: %u\n", info->slice_total); DRM_DEBUG_DRIVER("subslice total: %u\n", info->subslice_total); DRM_DEBUG_DRIVER("subslice per slice: %u\n", info->subslice_per_slice); From dead16e2c34343f0e12ee71cd50c9398440e2556 Mon Sep 17 00:00:00 2001 From: Jeff McGee Date: Fri, 3 Apr 2015 18:13:16 -0700 Subject: [PATCH 0048/3798] drm/i915/bxt: Determine BXT slice/subslice/EU info Modify the Gen9 SSEU info initialization logic to support Broxton. Broxton reuses the SKL fuse registers but has at most 1 slice and 6 EU per subslice. Signed-off-by: Jeff McGee Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 47 +++++++++++++++++++++------------ drivers/gpu/drm/i915/i915_reg.h | 4 +-- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 9691f0fc0918bb..a9b7770dc4801d 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -611,9 +611,21 @@ static void gen9_sseu_info_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_device_info *info; - const int s_max = 3, ss_max = 4, eu_max = 8; + int s_max = 3, ss_max = 4, eu_max = 8; int s, ss; - u32 fuse2, eu_disable[s_max], s_enable, ss_disable; + u32 fuse2, s_enable, ss_disable, eu_disable; + u8 eu_mask = 0xff; + + /* + * BXT has a single slice. BXT also has at most 6 EU per subslice, + * and therefore only the lowest 6 bits of the 8-bit EU disable + * fields are valid. + */ + if (IS_BROXTON(dev)) { + s_max = 1; + eu_max = 6; + eu_mask = 0x3f; + } info = (struct intel_device_info *)&dev_priv->info; fuse2 = I915_READ(GEN8_FUSE2); @@ -622,10 +634,6 @@ static void gen9_sseu_info_init(struct drm_device *dev) ss_disable = (fuse2 & GEN9_F2_SS_DIS_MASK) >> GEN9_F2_SS_DIS_SHIFT; - eu_disable[0] = I915_READ(GEN8_EU_DISABLE0); - eu_disable[1] = I915_READ(GEN8_EU_DISABLE1); - eu_disable[2] = I915_READ(GEN8_EU_DISABLE2); - info->slice_total = hweight32(s_enable); /* * The subslice disable field is global, i.e. it applies @@ -644,25 +652,26 @@ static void gen9_sseu_info_init(struct drm_device *dev) /* skip disabled slice */ continue; + eu_disable = I915_READ(GEN9_EU_DISABLE(s)); for (ss = 0; ss < ss_max; ss++) { - u32 n_disabled; + int eu_per_ss; if (ss_disable & (0x1 << ss)) /* skip disabled subslice */ continue; - n_disabled = hweight8(eu_disable[s] >> - (ss * eu_max)); + eu_per_ss = eu_max - hweight8((eu_disable >> (ss*8)) & + eu_mask); /* * Record which subslice(s) has(have) 7 EUs. we * can tune the hash used to spread work among * subslices if they are unbalanced. */ - if (eu_max - n_disabled == 7) + if (eu_per_ss == 7) info->subslice_7eu[s] |= 1 << ss; - info->eu_total += eu_max - n_disabled; + info->eu_total += eu_per_ss; } } @@ -670,7 +679,8 @@ static void gen9_sseu_info_init(struct drm_device *dev) * SKL is expected to always have a uniform distribution * of EU across subslices with the exception that any one * EU in any one subslice may be fused off for die - * recovery. + * recovery. BXT is expected to be perfectly uniform in EU + * distribution. */ info->eu_per_subslice = info->subslice_total ? DIV_ROUND_UP(info->eu_total, @@ -678,11 +688,14 @@ static void gen9_sseu_info_init(struct drm_device *dev) /* * SKL supports slice power gating on devices with more than * one slice, and supports EU power gating on devices with - * more than one EU pair per subslice. + * more than one EU pair per subslice. BXT supports subslice + * power gating on devices with more than one subslice, and + * supports EU power gating on devices with more than one EU + * pair per subslice. */ - info->has_slice_pg = (info->slice_total > 1) ? 1 : 0; - info->has_subslice_pg = 0; - info->has_eu_pg = (info->eu_per_subslice > 2) ? 1 : 0; + info->has_slice_pg = (IS_SKYLAKE(dev) && (info->slice_total > 1)); + info->has_subslice_pg = (IS_BROXTON(dev) && (info->subslice_total > 1)); + info->has_eu_pg = (info->eu_per_subslice > 2); } /* @@ -747,7 +760,7 @@ static void intel_device_info_runtime_init(struct drm_device *dev) /* Initialize slice/subslice/EU info */ if (IS_CHERRYVIEW(dev)) cherryview_sseu_info_init(dev); - else if (IS_SKYLAKE(dev)) + else if (INTEL_INFO(dev)->gen >= 9) gen9_sseu_info_init(dev); DRM_DEBUG_DRIVER("slice total: %u\n", info->slice_total); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7e1a0fd9333f45..7eda205d5e87aa 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1554,9 +1554,7 @@ enum skl_disp_power_wells { #define GEN9_F2_SS_DIS_SHIFT 20 #define GEN9_F2_SS_DIS_MASK (0xf << GEN9_F2_SS_DIS_SHIFT) -#define GEN8_EU_DISABLE0 0x9134 -#define GEN8_EU_DISABLE1 0x9138 -#define GEN8_EU_DISABLE2 0x913c +#define GEN9_EU_DISABLE(slice) (0x9134 + (slice)*0x4) #define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050 #define GEN6_BSD_SLEEP_MSG_DISABLE (1 << 0) From 5d39525a1f2551a33f7f7380a038837e648ed511 Mon Sep 17 00:00:00 2001 From: Jeff McGee Date: Fri, 3 Apr 2015 18:13:17 -0700 Subject: [PATCH 0049/3798] drm/i915: Split-up SSEU device status by platform Signed-off-by: Jeff McGee Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 172 ++++++++++++++++------------ 1 file changed, 100 insertions(+), 72 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 007c7d7d82950f..8facc0045f95ea 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4470,12 +4470,97 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_cache_sharing_fops, i915_cache_sharing_get, i915_cache_sharing_set, "%llu\n"); +struct sseu_dev_status { + unsigned int slice_total; + unsigned int subslice_total; + unsigned int subslice_per_slice; + unsigned int eu_total; + unsigned int eu_per_subslice; +}; + +static void cherryview_sseu_device_status(struct drm_device *dev, + struct sseu_dev_status *stat) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + const int ss_max = 2; + int ss; + u32 sig1[ss_max], sig2[ss_max]; + + sig1[0] = I915_READ(CHV_POWER_SS0_SIG1); + sig1[1] = I915_READ(CHV_POWER_SS1_SIG1); + sig2[0] = I915_READ(CHV_POWER_SS0_SIG2); + sig2[1] = I915_READ(CHV_POWER_SS1_SIG2); + + for (ss = 0; ss < ss_max; ss++) { + unsigned int eu_cnt; + + if (sig1[ss] & CHV_SS_PG_ENABLE) + /* skip disabled subslice */ + continue; + + stat->slice_total = 1; + stat->subslice_per_slice++; + eu_cnt = ((sig1[ss] & CHV_EU08_PG_ENABLE) ? 0 : 2) + + ((sig1[ss] & CHV_EU19_PG_ENABLE) ? 0 : 2) + + ((sig1[ss] & CHV_EU210_PG_ENABLE) ? 0 : 2) + + ((sig2[ss] & CHV_EU311_PG_ENABLE) ? 0 : 2); + stat->eu_total += eu_cnt; + stat->eu_per_subslice = max(stat->eu_per_subslice, eu_cnt); + } + stat->subslice_total = stat->subslice_per_slice; +} + +static void gen9_sseu_device_status(struct drm_device *dev, + struct sseu_dev_status *stat) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + const int s_max = 3, ss_max = 4; + int s, ss; + u32 s_reg[s_max], eu_reg[2*s_max], eu_mask[2]; + + s_reg[0] = I915_READ(GEN9_SLICE0_PGCTL_ACK); + s_reg[1] = I915_READ(GEN9_SLICE1_PGCTL_ACK); + s_reg[2] = I915_READ(GEN9_SLICE2_PGCTL_ACK); + eu_reg[0] = I915_READ(GEN9_SLICE0_SS01_EU_PGCTL_ACK); + eu_reg[1] = I915_READ(GEN9_SLICE0_SS23_EU_PGCTL_ACK); + eu_reg[2] = I915_READ(GEN9_SLICE1_SS01_EU_PGCTL_ACK); + eu_reg[3] = I915_READ(GEN9_SLICE1_SS23_EU_PGCTL_ACK); + eu_reg[4] = I915_READ(GEN9_SLICE2_SS01_EU_PGCTL_ACK); + eu_reg[5] = I915_READ(GEN9_SLICE2_SS23_EU_PGCTL_ACK); + eu_mask[0] = GEN9_PGCTL_SSA_EU08_ACK | + GEN9_PGCTL_SSA_EU19_ACK | + GEN9_PGCTL_SSA_EU210_ACK | + GEN9_PGCTL_SSA_EU311_ACK; + eu_mask[1] = GEN9_PGCTL_SSB_EU08_ACK | + GEN9_PGCTL_SSB_EU19_ACK | + GEN9_PGCTL_SSB_EU210_ACK | + GEN9_PGCTL_SSB_EU311_ACK; + + for (s = 0; s < s_max; s++) { + if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0) + /* skip disabled slice */ + continue; + + stat->slice_total++; + stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice; + stat->subslice_total += stat->subslice_per_slice; + for (ss = 0; ss < ss_max; ss++) { + unsigned int eu_cnt; + + eu_cnt = 2 * hweight32(eu_reg[2*s + ss/2] & + eu_mask[ss%2]); + stat->eu_total += eu_cnt; + stat->eu_per_subslice = max(stat->eu_per_subslice, + eu_cnt); + } + } +} + static int i915_sseu_status(struct seq_file *m, void *unused) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned int s_tot = 0, ss_tot = 0, ss_per = 0, eu_tot = 0, eu_per = 0; + struct sseu_dev_status stat; if ((INTEL_INFO(dev)->gen < 8) || IS_BROADWELL(dev)) return -ENODEV; @@ -4499,79 +4584,22 @@ static int i915_sseu_status(struct seq_file *m, void *unused) yesno(INTEL_INFO(dev)->has_eu_pg)); seq_puts(m, "SSEU Device Status\n"); + memset(&stat, 0, sizeof(stat)); if (IS_CHERRYVIEW(dev)) { - const int ss_max = 2; - int ss; - u32 sig1[ss_max], sig2[ss_max]; - - sig1[0] = I915_READ(CHV_POWER_SS0_SIG1); - sig1[1] = I915_READ(CHV_POWER_SS1_SIG1); - sig2[0] = I915_READ(CHV_POWER_SS0_SIG2); - sig2[1] = I915_READ(CHV_POWER_SS1_SIG2); - - for (ss = 0; ss < ss_max; ss++) { - unsigned int eu_cnt; - - if (sig1[ss] & CHV_SS_PG_ENABLE) - /* skip disabled subslice */ - continue; - - s_tot = 1; - ss_per++; - eu_cnt = ((sig1[ss] & CHV_EU08_PG_ENABLE) ? 0 : 2) + - ((sig1[ss] & CHV_EU19_PG_ENABLE) ? 0 : 2) + - ((sig1[ss] & CHV_EU210_PG_ENABLE) ? 0 : 2) + - ((sig2[ss] & CHV_EU311_PG_ENABLE) ? 0 : 2); - eu_tot += eu_cnt; - eu_per = max(eu_per, eu_cnt); - } - ss_tot = ss_per; + cherryview_sseu_device_status(dev, &stat); } else if (IS_SKYLAKE(dev)) { - const int s_max = 3, ss_max = 4; - int s, ss; - u32 s_reg[s_max], eu_reg[2*s_max], eu_mask[2]; - - s_reg[0] = I915_READ(GEN9_SLICE0_PGCTL_ACK); - s_reg[1] = I915_READ(GEN9_SLICE1_PGCTL_ACK); - s_reg[2] = I915_READ(GEN9_SLICE2_PGCTL_ACK); - eu_reg[0] = I915_READ(GEN9_SLICE0_SS01_EU_PGCTL_ACK); - eu_reg[1] = I915_READ(GEN9_SLICE0_SS23_EU_PGCTL_ACK); - eu_reg[2] = I915_READ(GEN9_SLICE1_SS01_EU_PGCTL_ACK); - eu_reg[3] = I915_READ(GEN9_SLICE1_SS23_EU_PGCTL_ACK); - eu_reg[4] = I915_READ(GEN9_SLICE2_SS01_EU_PGCTL_ACK); - eu_reg[5] = I915_READ(GEN9_SLICE2_SS23_EU_PGCTL_ACK); - eu_mask[0] = GEN9_PGCTL_SSA_EU08_ACK | - GEN9_PGCTL_SSA_EU19_ACK | - GEN9_PGCTL_SSA_EU210_ACK | - GEN9_PGCTL_SSA_EU311_ACK; - eu_mask[1] = GEN9_PGCTL_SSB_EU08_ACK | - GEN9_PGCTL_SSB_EU19_ACK | - GEN9_PGCTL_SSB_EU210_ACK | - GEN9_PGCTL_SSB_EU311_ACK; - - for (s = 0; s < s_max; s++) { - if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0) - /* skip disabled slice */ - continue; - - s_tot++; - ss_per = INTEL_INFO(dev)->subslice_per_slice; - ss_tot += ss_per; - for (ss = 0; ss < ss_max; ss++) { - unsigned int eu_cnt; - - eu_cnt = 2 * hweight32(eu_reg[2*s + ss/2] & - eu_mask[ss%2]); - eu_tot += eu_cnt; - eu_per = max(eu_per, eu_cnt); - } - } + gen9_sseu_device_status(dev, &stat); } - seq_printf(m, " Enabled Slice Total: %u\n", s_tot); - seq_printf(m, " Enabled Subslice Total: %u\n", ss_tot); - seq_printf(m, " Enabled Subslice Per Slice: %u\n", ss_per); - seq_printf(m, " Enabled EU Total: %u\n", eu_tot); - seq_printf(m, " Enabled EU Per Subslice: %u\n", eu_per); + seq_printf(m, " Enabled Slice Total: %u\n", + stat.slice_total); + seq_printf(m, " Enabled Subslice Total: %u\n", + stat.subslice_total); + seq_printf(m, " Enabled Subslice Per Slice: %u\n", + stat.subslice_per_slice); + seq_printf(m, " Enabled EU Total: %u\n", + stat.eu_total); + seq_printf(m, " Enabled EU Per Subslice: %u\n", + stat.eu_per_subslice); return 0; } From 1c046bc1db49e5a42e5c4167ac42cee4c1725a37 Mon Sep 17 00:00:00 2001 From: Jeff McGee Date: Fri, 3 Apr 2015 18:13:18 -0700 Subject: [PATCH 0050/3798] drm/i915/bxt: Support BXT in SSEU device status dump Modify the Gen9 SSEU device status logic to support Broxton. Broxton reuses the Skylake power gate acknowledgment registers but has at most 1 slice and 3 subslices. Broxton supports subslice power gating within its single slice. Signed-off-by: Jeff McGee Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 45 ++++++++++++++++++++--------- drivers/gpu/drm/i915/i915_reg.h | 13 +++------ 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 8facc0045f95ea..effb7fc1428476 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4514,19 +4514,22 @@ static void gen9_sseu_device_status(struct drm_device *dev, struct sseu_dev_status *stat) { struct drm_i915_private *dev_priv = dev->dev_private; - const int s_max = 3, ss_max = 4; + int s_max = 3, ss_max = 4; int s, ss; u32 s_reg[s_max], eu_reg[2*s_max], eu_mask[2]; - s_reg[0] = I915_READ(GEN9_SLICE0_PGCTL_ACK); - s_reg[1] = I915_READ(GEN9_SLICE1_PGCTL_ACK); - s_reg[2] = I915_READ(GEN9_SLICE2_PGCTL_ACK); - eu_reg[0] = I915_READ(GEN9_SLICE0_SS01_EU_PGCTL_ACK); - eu_reg[1] = I915_READ(GEN9_SLICE0_SS23_EU_PGCTL_ACK); - eu_reg[2] = I915_READ(GEN9_SLICE1_SS01_EU_PGCTL_ACK); - eu_reg[3] = I915_READ(GEN9_SLICE1_SS23_EU_PGCTL_ACK); - eu_reg[4] = I915_READ(GEN9_SLICE2_SS01_EU_PGCTL_ACK); - eu_reg[5] = I915_READ(GEN9_SLICE2_SS23_EU_PGCTL_ACK); + /* BXT has a single slice and at most 3 subslices. */ + if (IS_BROXTON(dev)) { + s_max = 1; + ss_max = 3; + } + + for (s = 0; s < s_max; s++) { + s_reg[s] = I915_READ(GEN9_SLICE_PGCTL_ACK(s)); + eu_reg[2*s] = I915_READ(GEN9_SS01_EU_PGCTL_ACK(s)); + eu_reg[2*s + 1] = I915_READ(GEN9_SS23_EU_PGCTL_ACK(s)); + } + eu_mask[0] = GEN9_PGCTL_SSA_EU08_ACK | GEN9_PGCTL_SSA_EU19_ACK | GEN9_PGCTL_SSA_EU210_ACK | @@ -4537,22 +4540,38 @@ static void gen9_sseu_device_status(struct drm_device *dev, GEN9_PGCTL_SSB_EU311_ACK; for (s = 0; s < s_max; s++) { + unsigned int ss_cnt = 0; + if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0) /* skip disabled slice */ continue; stat->slice_total++; - stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice; - stat->subslice_total += stat->subslice_per_slice; + + if (IS_SKYLAKE(dev)) + ss_cnt = INTEL_INFO(dev)->subslice_per_slice; + for (ss = 0; ss < ss_max; ss++) { unsigned int eu_cnt; + if (IS_BROXTON(dev) && + !(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss)))) + /* skip disabled subslice */ + continue; + + if (IS_BROXTON(dev)) + ss_cnt++; + eu_cnt = 2 * hweight32(eu_reg[2*s + ss/2] & eu_mask[ss%2]); stat->eu_total += eu_cnt; stat->eu_per_subslice = max(stat->eu_per_subslice, eu_cnt); } + + stat->subslice_total += ss_cnt; + stat->subslice_per_slice = max(stat->subslice_per_slice, + ss_cnt); } } @@ -4587,7 +4606,7 @@ static int i915_sseu_status(struct seq_file *m, void *unused) memset(&stat, 0, sizeof(stat)); if (IS_CHERRYVIEW(dev)) { cherryview_sseu_device_status(dev, &stat); - } else if (IS_SKYLAKE(dev)) { + } else if (INTEL_INFO(dev)->gen >= 9) { gen9_sseu_device_status(dev, &stat); } seq_printf(m, " Enabled Slice Total: %u\n", diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7eda205d5e87aa..6c1ec72e94c464 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6269,17 +6269,12 @@ enum skl_disp_power_wells { #define CHV_POWER_SS1_SIG2 0xa72c #define CHV_EU311_PG_ENABLE (1<<1) -#define GEN9_SLICE0_PGCTL_ACK 0x804c -#define GEN9_SLICE1_PGCTL_ACK 0x8050 -#define GEN9_SLICE2_PGCTL_ACK 0x8054 +#define GEN9_SLICE_PGCTL_ACK(slice) (0x804c + (slice)*0x4) #define GEN9_PGCTL_SLICE_ACK (1 << 0) +#define GEN9_PGCTL_SS_ACK(subslice) (1 << (2 + (subslice)*2)) -#define GEN9_SLICE0_SS01_EU_PGCTL_ACK 0x805c -#define GEN9_SLICE0_SS23_EU_PGCTL_ACK 0x8060 -#define GEN9_SLICE1_SS01_EU_PGCTL_ACK 0x8064 -#define GEN9_SLICE1_SS23_EU_PGCTL_ACK 0x8068 -#define GEN9_SLICE2_SS01_EU_PGCTL_ACK 0x806c -#define GEN9_SLICE2_SS23_EU_PGCTL_ACK 0x8070 +#define GEN9_SS01_EU_PGCTL_ACK(slice) (0x805c + (slice)*0x8) +#define GEN9_SS23_EU_PGCTL_ACK(slice) (0x8060 + (slice)*0x8) #define GEN9_PGCTL_SSA_EU08_ACK (1 << 0) #define GEN9_PGCTL_SSA_EU19_ACK (1 << 2) #define GEN9_PGCTL_SSA_EU210_ACK (1 << 4) From c8a8585431efba0faaf41167f8f7c27c48307ca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vianney=20le=20Cl=C3=A9ment=20de=20Saint-Marcq?= Date: Mon, 30 Mar 2015 10:34:58 +0200 Subject: [PATCH 0051/3798] iio: core: Introduce IIO_CHAN_INFO_CALIBEMISSIVITY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contact-less IR temperature sensors measure the temperature of an object by using its thermal radiation. Surfaces with different emissivity ratios emit different amounts of energy at the same temperature. IIO_CHAN_INFO_CALIBEMISSIVITY allows the user to inform the sensor of the emissivity of the object in front of it, in order to effectively measure its temperature. A device providing such setting is Melexis's MLX90614: http://melexis.com/Assets/IR-sensor-thermometer-MLX90614-Datasheet-5152.aspx. Signed-off-by: Vianney le Clément de Saint-Marcq Cc: Arnout Vandecappelle (Essensium/Mind) Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 11 +++++++++++ drivers/iio/industrialio-core.c | 1 + include/linux/iio/iio.h | 1 + 3 files changed, 13 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 3befcb19f41415..866b4ec4aab698 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1364,3 +1364,14 @@ Description: hwfifo_watermak_min but not equal to any of the values in this list, the driver will chose an appropriate value for the hardware fifo watermark level. + +What: /sys/bus/iio/devices/iio:deviceX/in_temp_calibemissivity +What: /sys/bus/iio/devices/iio:deviceX/in_tempX_calibemissivity +What: /sys/bus/iio/devices/iio:deviceX/in_temp_object_calibemissivity +What: /sys/bus/iio/devices/iio:deviceX/in_tempX_object_calibemissivity +KernelVersion: 4.1 +Contact: linux-iio@vger.kernel.org +Description: + The emissivity ratio of the surface in the field of view of the + contactless temperature sensor. Emissivity varies from 0 to 1, + with 1 being the emissivity of a black body. diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 4df97f650e448e..7c98bc1504e60c 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -128,6 +128,7 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_CALIBWEIGHT] = "calibweight", [IIO_CHAN_INFO_DEBOUNCE_COUNT] = "debounce_count", [IIO_CHAN_INFO_DEBOUNCE_TIME] = "debounce_time", + [IIO_CHAN_INFO_CALIBEMISSIVITY] = "calibemissivity", }; /** diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index d86b753e9b3016..b1e46ae89aa7da 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -43,6 +43,7 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_CALIBWEIGHT, IIO_CHAN_INFO_DEBOUNCE_COUNT, IIO_CHAN_INFO_DEBOUNCE_TIME, + IIO_CHAN_INFO_CALIBEMISSIVITY, }; enum iio_shared_by { From 5147b21a61806b0ff2c29ccb3f8bc37495d5c2ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vianney=20le=20Cl=C3=A9ment=20de=20Saint-Marcq?= Date: Mon, 30 Mar 2015 10:34:59 +0200 Subject: [PATCH 0052/3798] iio: mlx90614: Add devicetree bindings documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also introduce "melexis" as a vendor prefix for device tree bindings. Signed-off-by: Vianney le Clément de Saint-Marcq Cc: Arnout Vandecappelle (Essensium/Mind) Signed-off-by: Jonathan Cameron --- .../bindings/iio/temperature/mlx90614.txt | 15 +++++++++++++++ .../devicetree/bindings/vendor-prefixes.txt | 1 + 2 files changed, 16 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/temperature/mlx90614.txt diff --git a/Documentation/devicetree/bindings/iio/temperature/mlx90614.txt b/Documentation/devicetree/bindings/iio/temperature/mlx90614.txt new file mode 100644 index 00000000000000..4c959f3b8663d6 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/temperature/mlx90614.txt @@ -0,0 +1,15 @@ +* Melexis MLX90614 contactless IR temperature sensor + +http://melexis.com/Infrared-Thermometer-Sensors/Infrared-Thermometer-Sensors/MLX90614-615.aspx + +Required properties: + + - compatible: should be "melexis,mlx90614" + - reg: the I2C address of the sensor + +Example: + +mlx90614@5a { + compatible = "melexis,mlx90614"; + reg = <0x5a>; +}; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index fae26d014aaf25..c8db30cc59a335 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -110,6 +110,7 @@ lltc Linear Technology Corporation marvell Marvell Technology Group Ltd. maxim Maxim Integrated Products mediatek MediaTek Inc. +melexis Melexis N.V. merrii Merrii Technology Co., Ltd. micrel Micrel Inc. microchip Microchip Technology Inc. From fad65a8fe5b85b5039b316258c2790e773cc3502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vianney=20le=20Cl=C3=A9ment=20de=20Saint-Marcq?= Date: Mon, 30 Mar 2015 10:35:00 +0200 Subject: [PATCH 0053/3798] iio: mlx90614: Add emissivity setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mapping from the 16-bit EEPROM value to the decimal 0-1 range is approximate. A special case ensures 0xFFFF shows as 1.0 instead of 0.999998565. Writing to EEPROM requires an explicit erase by writing zero. In addition, it takes 20ms for the erase/write to complete. During this time no EEPROM register should be accessed. Therefore, two msleep()s are added to the write function and a mutex protects against concurrent access. Signed-off-by: Vianney le Clément de Saint-Marcq Cc: Arnout Vandecappelle (Essensium/Mind) Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/mlx90614.c | 106 ++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 3 deletions(-) diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c index a112fc9abf4346..a307d8c9da899b 100644 --- a/drivers/iio/temperature/mlx90614.c +++ b/drivers/iio/temperature/mlx90614.c @@ -12,12 +12,13 @@ * * (7-bit I2C slave address 0x5a, 100KHz bus speed only!) * - * TODO: sleep mode, configuration EEPROM + * TODO: sleep mode, filter configuration */ #include #include #include +#include #include @@ -53,8 +54,47 @@ struct mlx90614_data { struct i2c_client *client; + struct mutex lock; /* for EEPROM access only */ }; +/* + * Erase an address and write word. + * The mutex must be locked before calling. + */ +static s32 mlx90614_write_word(const struct i2c_client *client, u8 command, + u16 value) +{ + /* + * Note: The mlx90614 requires a PEC on writing but does not send us a + * valid PEC on reading. Hence, we cannot set I2C_CLIENT_PEC in + * i2c_client.flags. As a workaround, we use i2c_smbus_xfer here. + */ + union i2c_smbus_data data; + s32 ret; + + dev_dbg(&client->dev, "Writing 0x%x to address 0x%x", value, command); + + data.word = 0x0000; /* erase command */ + ret = i2c_smbus_xfer(client->adapter, client->addr, + client->flags | I2C_CLIENT_PEC, + I2C_SMBUS_WRITE, command, + I2C_SMBUS_WORD_DATA, &data); + if (ret < 0) + return ret; + + msleep(MLX90614_TIMING_EEPROM); + + data.word = value; /* actual write */ + ret = i2c_smbus_xfer(client->adapter, client->addr, + client->flags | I2C_CLIENT_PEC, + I2C_SMBUS_WRITE, command, + I2C_SMBUS_WORD_DATA, &data); + + msleep(MLX90614_TIMING_EEPROM); + + return ret; +} + static int mlx90614_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *channel, int *val, int *val2, long mask) @@ -97,6 +137,61 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: *val = 20; return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */ + mutex_lock(&data->lock); + ret = i2c_smbus_read_word_data(data->client, + MLX90614_EMISSIVITY); + mutex_unlock(&data->lock); + + if (ret < 0) + return ret; + + if (ret == 65535) { + *val = 1; + *val2 = 0; + } else { + *val = 0; + *val2 = ret * 15259; /* 1/65535 ~ 0.000015259 */ + } + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } +} + +static int mlx90614_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *channel, int val, + int val2, long mask) +{ + struct mlx90614_data *data = iio_priv(indio_dev); + s32 ret; + + switch (mask) { + case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */ + if (val < 0 || val2 < 0 || val > 1 || (val == 1 && val2 != 0)) + return -EINVAL; + val = val * 65535 + val2 / 15259; /* 1/65535 ~ 0.000015259 */ + + mutex_lock(&data->lock); + ret = mlx90614_write_word(data->client, MLX90614_EMISSIVITY, + val); + mutex_unlock(&data->lock); + + if (ret < 0) + return ret; + return 0; + default: + return -EINVAL; + } +} + +static int mlx90614_write_raw_get_fmt(struct iio_dev *indio_dev, + const struct iio_chan_spec const *channel, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_CALIBEMISSIVITY: + return IIO_VAL_INT_PLUS_NANO; default: return -EINVAL; } @@ -115,7 +210,8 @@ static const struct iio_chan_spec mlx90614_channels[] = { .type = IIO_TEMP, .modified = 1, .channel2 = IIO_MOD_TEMP_OBJECT, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBEMISSIVITY), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), }, @@ -125,7 +221,8 @@ static const struct iio_chan_spec mlx90614_channels[] = { .modified = 1, .channel = 1, .channel2 = IIO_MOD_TEMP_OBJECT, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBEMISSIVITY), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), }, @@ -133,6 +230,8 @@ static const struct iio_chan_spec mlx90614_channels[] = { static const struct iio_info mlx90614_info = { .read_raw = mlx90614_read_raw, + .write_raw = mlx90614_write_raw, + .write_raw_get_fmt = mlx90614_write_raw_get_fmt, .driver_module = THIS_MODULE, }; @@ -166,6 +265,7 @@ static int mlx90614_probe(struct i2c_client *client, data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; + mutex_init(&data->lock); indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; From eb4b07dae4d4b7915333f687675209f677f72fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vianney=20le=20Cl=C3=A9ment=20de=20Saint-Marcq?= Date: Mon, 30 Mar 2015 10:35:01 +0200 Subject: [PATCH 0054/3798] iio: mlx90614: Add power management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for system sleep and runtime power management. To wake up the device, the SDA line should be held low for at least 33ms while SCL is high. As this is not possible using the i2c API (and not supported by all i2c adapters), a GPIO connected to the SDA line is needed. The GPIO is named "wakeup" and can be specified in a device tree with the "wakeup-gpios" binding. If the wake-up GPIO is not given, disable power management for the device. Entering sleep requires an SMBus byte access, hence power management is also disabled if byte access is not supported by the adapter. Signed-off-by: Vianney le Clément de Saint-Marcq Cc: Arnout Vandecappelle (Essensium/Mind) Signed-off-by: Jonathan Cameron --- .../bindings/iio/temperature/mlx90614.txt | 9 + drivers/iio/temperature/mlx90614.c | 246 +++++++++++++++++- 2 files changed, 253 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/temperature/mlx90614.txt b/Documentation/devicetree/bindings/iio/temperature/mlx90614.txt index 4c959f3b8663d6..9be57b036092cb 100644 --- a/Documentation/devicetree/bindings/iio/temperature/mlx90614.txt +++ b/Documentation/devicetree/bindings/iio/temperature/mlx90614.txt @@ -7,9 +7,18 @@ Required properties: - compatible: should be "melexis,mlx90614" - reg: the I2C address of the sensor +Optional properties: + + - wakeup-gpios: device tree identifier of the GPIO connected to the SDA line + to hold low in order to wake up the device. In normal operation, the + GPIO is set as input and will not interfere in I2C communication. There + is no need for a GPIO driving the SCL line. If no GPIO is given, power + management is disabled. + Example: mlx90614@5a { compatible = "melexis,mlx90614"; reg = <0x5a>; + wakeup-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; }; diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c index a307d8c9da899b..73ec7677496f9f 100644 --- a/drivers/iio/temperature/mlx90614.c +++ b/drivers/iio/temperature/mlx90614.c @@ -12,13 +12,24 @@ * * (7-bit I2C slave address 0x5a, 100KHz bus speed only!) * - * TODO: sleep mode, filter configuration + * To wake up from sleep mode, the SDA line must be held low while SCL is high + * for at least 33ms. This is achieved with an extra GPIO that can be connected + * directly to the SDA line. In normal operation, the GPIO is set as input and + * will not interfere in I2C communication. While the GPIO is driven low, the + * i2c adapter is locked since it cannot be used by other clients. The SCL line + * always has a pull-up so we do not need an extra GPIO to drive it high. If + * the "wakeup" GPIO is not given, power management will be disabled. + * + * TODO: filter configuration */ #include #include #include #include +#include +#include +#include #include @@ -52,9 +63,13 @@ #define MLX90614_TIMING_WAKEUP 34 /* time to hold SDA low for wake-up */ #define MLX90614_TIMING_STARTUP 250 /* time before first data after wake-up */ +#define MLX90614_AUTOSLEEP_DELAY 5000 /* default autosleep delay */ + struct mlx90614_data { struct i2c_client *client; struct mutex lock; /* for EEPROM access only */ + struct gpio_desc *wakeup_gpio; /* NULL to disable sleep/wake-up */ + unsigned long ready_timestamp; /* in jiffies */ }; /* @@ -95,6 +110,54 @@ static s32 mlx90614_write_word(const struct i2c_client *client, u8 command, return ret; } +#ifdef CONFIG_PM +/* + * If @startup is true, make sure MLX90614_TIMING_STARTUP ms have elapsed since + * the last wake-up. This is normally only needed to get a valid temperature + * reading. EEPROM access does not need such delay. + * Return 0 on success, <0 on error. + */ +static int mlx90614_power_get(struct mlx90614_data *data, bool startup) +{ + unsigned long now; + + if (!data->wakeup_gpio) + return 0; + + pm_runtime_get_sync(&data->client->dev); + + if (startup) { + now = jiffies; + if (time_before(now, data->ready_timestamp) && + msleep_interruptible(jiffies_to_msecs( + data->ready_timestamp - now)) != 0) { + pm_runtime_put_autosuspend(&data->client->dev); + return -EINTR; + } + } + + return 0; +} + +static void mlx90614_power_put(struct mlx90614_data *data) +{ + if (!data->wakeup_gpio) + return; + + pm_runtime_mark_last_busy(&data->client->dev); + pm_runtime_put_autosuspend(&data->client->dev); +} +#else +static inline int mlx90614_power_get(struct mlx90614_data *data, bool startup) +{ + return 0; +} + +static inline void mlx90614_power_put(struct mlx90614_data *data) +{ +} +#endif + static int mlx90614_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *channel, int *val, int *val2, long mask) @@ -125,7 +188,12 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, return -EINVAL; } + ret = mlx90614_power_get(data, true); + if (ret < 0) + return ret; ret = i2c_smbus_read_word_data(data->client, cmd); + mlx90614_power_put(data); + if (ret < 0) return ret; *val = ret; @@ -138,10 +206,12 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, *val = 20; return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */ + mlx90614_power_get(data, false); mutex_lock(&data->lock); ret = i2c_smbus_read_word_data(data->client, MLX90614_EMISSIVITY); mutex_unlock(&data->lock); + mlx90614_power_put(data); if (ret < 0) return ret; @@ -172,10 +242,12 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev, return -EINVAL; val = val * 65535 + val2 / 15259; /* 1/65535 ~ 0.000015259 */ + mlx90614_power_get(data, false); mutex_lock(&data->lock); ret = mlx90614_write_word(data->client, MLX90614_EMISSIVITY, val); mutex_unlock(&data->lock); + mlx90614_power_put(data); if (ret < 0) return ret; @@ -235,6 +307,98 @@ static const struct iio_info mlx90614_info = { .driver_module = THIS_MODULE, }; +#ifdef CONFIG_PM +static int mlx90614_sleep(struct mlx90614_data *data) +{ + s32 ret; + + if (!data->wakeup_gpio) { + dev_dbg(&data->client->dev, "Sleep disabled"); + return -ENOSYS; + } + + dev_dbg(&data->client->dev, "Requesting sleep"); + + mutex_lock(&data->lock); + ret = i2c_smbus_xfer(data->client->adapter, data->client->addr, + data->client->flags | I2C_CLIENT_PEC, + I2C_SMBUS_WRITE, MLX90614_OP_SLEEP, + I2C_SMBUS_BYTE, NULL); + mutex_unlock(&data->lock); + + return ret; +} + +static int mlx90614_wakeup(struct mlx90614_data *data) +{ + if (!data->wakeup_gpio) { + dev_dbg(&data->client->dev, "Wake-up disabled"); + return -ENOSYS; + } + + dev_dbg(&data->client->dev, "Requesting wake-up"); + + i2c_lock_adapter(data->client->adapter); + gpiod_direction_output(data->wakeup_gpio, 0); + msleep(MLX90614_TIMING_WAKEUP); + gpiod_direction_input(data->wakeup_gpio); + i2c_unlock_adapter(data->client->adapter); + + data->ready_timestamp = jiffies + + msecs_to_jiffies(MLX90614_TIMING_STARTUP); + + /* + * Quirk: the i2c controller may get confused right after the + * wake-up signal has been sent. As a workaround, do a dummy read. + * If the read fails, the controller will probably be reset so that + * further reads will work. + */ + i2c_smbus_read_word_data(data->client, MLX90614_CONFIG); + + return 0; +} + +/* Return wake-up GPIO or NULL if sleep functionality should be disabled. */ +static struct gpio_desc *mlx90614_probe_wakeup(struct i2c_client *client) +{ + struct gpio_desc *gpio; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE)) { + dev_info(&client->dev, + "i2c adapter does not support SMBUS_WRITE_BYTE, sleep disabled"); + return NULL; + } + + gpio = devm_gpiod_get_optional(&client->dev, "wakeup", GPIOD_IN); + + if (IS_ERR(gpio)) { + dev_warn(&client->dev, + "gpio acquisition failed with error %ld, sleep disabled", + PTR_ERR(gpio)); + return NULL; + } else if (!gpio) { + dev_info(&client->dev, + "wakeup-gpio not found, sleep disabled"); + } + + return gpio; +} +#else +static inline int mlx90614_sleep(struct mlx90614_data *data) +{ + return -ENOSYS; +} +static inline int mlx90614_wakeup(struct mlx90614_data *data) +{ + return -ENOSYS; +} +static inline struct gpio_desc *mlx90614_probe_wakeup(struct i2c_client *client) +{ + return NULL; +} +#endif + /* Return 0 for single sensor, 1 for dual sensor, <0 on error. */ static int mlx90614_probe_num_ir_sensors(struct i2c_client *client) { @@ -266,6 +430,9 @@ static int mlx90614_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; mutex_init(&data->lock); + data->wakeup_gpio = mlx90614_probe_wakeup(client); + + mlx90614_wakeup(data); indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; @@ -288,12 +455,30 @@ static int mlx90614_probe(struct i2c_client *client, return ret; } + if (data->wakeup_gpio) { + pm_runtime_set_autosuspend_delay(&client->dev, + MLX90614_AUTOSLEEP_DELAY); + pm_runtime_use_autosuspend(&client->dev); + pm_runtime_set_active(&client->dev); + pm_runtime_enable(&client->dev); + } + return iio_device_register(indio_dev); } static int mlx90614_remove(struct i2c_client *client) { - iio_device_unregister(i2c_get_clientdata(client)); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct mlx90614_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + if (data->wakeup_gpio) { + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + mlx90614_sleep(data); + pm_runtime_set_suspended(&client->dev); + } return 0; } @@ -304,10 +489,67 @@ static const struct i2c_device_id mlx90614_id[] = { }; MODULE_DEVICE_TABLE(i2c, mlx90614_id); +#ifdef CONFIG_PM_SLEEP +static int mlx90614_pm_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mlx90614_data *data = iio_priv(indio_dev); + + if (data->wakeup_gpio && pm_runtime_active(dev)) + return mlx90614_sleep(data); + + return 0; +} + +static int mlx90614_pm_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mlx90614_data *data = iio_priv(indio_dev); + int err; + + if (data->wakeup_gpio) { + err = mlx90614_wakeup(data); + if (err < 0) + return err; + + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + } + + return 0; +} +#endif + +#ifdef CONFIG_PM +static int mlx90614_pm_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mlx90614_data *data = iio_priv(indio_dev); + + return mlx90614_sleep(data); +} + +static int mlx90614_pm_runtime_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mlx90614_data *data = iio_priv(indio_dev); + + return mlx90614_wakeup(data); +} +#endif + +static const struct dev_pm_ops mlx90614_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(mlx90614_pm_suspend, mlx90614_pm_resume) + SET_RUNTIME_PM_OPS(mlx90614_pm_runtime_suspend, + mlx90614_pm_runtime_resume, NULL) +}; + static struct i2c_driver mlx90614_driver = { .driver = { .name = "mlx90614", .owner = THIS_MODULE, + .pm = &mlx90614_pm_ops, }, .probe = mlx90614_probe, .remove = mlx90614_remove, From d02e0f8f62f786e9291caf4633e20724c2ab7f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vianney=20le=20Cl=C3=A9ment=20de=20Saint-Marcq?= Date: Mon, 30 Mar 2015 10:35:02 +0200 Subject: [PATCH 0055/3798] iio: mlx90614: Check for errors in read values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The device uses the MSB of the returned temperature value as an error flag. Return a read error when this bit is set. Signed-off-by: Vianney le Clément de Saint-Marcq Cc: Arnout Vandecappelle (Essensium/Mind) Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/mlx90614.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c index 73ec7677496f9f..06b7b967798233 100644 --- a/drivers/iio/temperature/mlx90614.c +++ b/drivers/iio/temperature/mlx90614.c @@ -196,6 +196,11 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; + + /* MSB is an error flag */ + if (ret & 0x8000) + return -EIO; + *val = ret; return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: From dee1f55057aeb61839f985b2cf7fff82789335d5 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 31 Mar 2015 16:42:36 +0530 Subject: [PATCH 0056/3798] iio: adc: ti_am335x_adc: refactor DT parsing into a function Refactor DT parsing into a separate function from probe() to help addition of more DT parameters later. No functional changes. Signed-off-by: Vignesh R Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti_am335x_adc.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index a0e7161f040c91..42e444044ea5b1 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -395,16 +395,30 @@ static const struct iio_info tiadc_info = { .driver_module = THIS_MODULE, }; +static int tiadc_parse_dt(struct platform_device *pdev, + struct tiadc_device *adc_dev) +{ + struct device_node *node = pdev->dev.of_node; + struct property *prop; + const __be32 *cur; + int channels = 0; + u32 val; + + of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { + adc_dev->channel_line[channels] = val; + channels++; + } + + adc_dev->channels = channels; + return 0; +} + static int tiadc_probe(struct platform_device *pdev) { struct iio_dev *indio_dev; struct tiadc_device *adc_dev; struct device_node *node = pdev->dev.of_node; - struct property *prop; - const __be32 *cur; int err; - u32 val; - int channels = 0; if (!node) { dev_err(&pdev->dev, "Could not find valid DT data.\n"); @@ -420,12 +434,7 @@ static int tiadc_probe(struct platform_device *pdev) adc_dev = iio_priv(indio_dev); adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev); - - of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { - adc_dev->channel_line[channels] = val; - channels++; - } - adc_dev->channels = channels; + tiadc_parse_dt(pdev, adc_dev); indio_dev->dev.parent = &pdev->dev; indio_dev->name = dev_name(&pdev->dev); From abda2b4f21249a079b83ed3356937fa6d9faa789 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 9 Apr 2015 17:17:47 +0300 Subject: [PATCH 0057/3798] iio: light: ltr501: Fix alignment to match open parenthesis This makes ltr501 code consistent with the coding style adopted for the new drivers added to IIO. We prepare the path for adding support for LTR559 chip. Reported by checkpatch.pl Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/light/ltr501.c | 42 +++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index 78b87839c4b958..f208c9871107b1 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -58,7 +58,7 @@ static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) while (tries--) { ret = i2c_smbus_read_byte_data(data->client, - LTR501_ALS_PS_STATUS); + LTR501_ALS_PS_STATUS); if (ret < 0) return ret; if ((ret & drdy_mask) == drdy_mask) @@ -77,7 +77,8 @@ static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2]) return ret; /* always read both ALS channels in given order */ return i2c_smbus_read_i2c_block_data(data->client, - LTR501_ALS_DATA1, 2 * sizeof(__le16), (u8 *) buf); + LTR501_ALS_DATA1, + 2 * sizeof(__le16), (u8 *)buf); } static int ltr501_read_ps(struct ltr501_data *data) @@ -107,7 +108,7 @@ static int ltr501_read_ps(struct ltr501_data *data) static const struct iio_chan_spec ltr501_channels[] = { LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0), LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR, - BIT(IIO_CHAN_INFO_SCALE)), + BIT(IIO_CHAN_INFO_SCALE)), { .type = IIO_PROXIMITY, .address = LTR501_PS_DATA, @@ -129,8 +130,8 @@ static const int ltr501_ps_gain[4][2] = { }; static int ltr501_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, long mask) + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) { struct ltr501_data *data = iio_priv(indio_dev); __le16 buf[2]; @@ -149,7 +150,7 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; *val = le16_to_cpu(chan->address == LTR501_ALS_DATA1 ? - buf[0] : buf[1]); + buf[0] : buf[1]); return IIO_VAL_INT; case IIO_PROXIMITY: mutex_lock(&data->lock_ps); @@ -199,8 +200,8 @@ static int ltr501_get_ps_gain_index(int val, int val2) } static int ltr501_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) + struct iio_chan_spec const *chan, + int val, int val2, long mask) { struct ltr501_data *data = iio_priv(indio_dev); int i; @@ -219,7 +220,8 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, else return -EINVAL; return i2c_smbus_write_byte_data(data->client, - LTR501_ALS_CONTR, data->als_contr); + LTR501_ALS_CONTR, + data->als_contr); case IIO_PROXIMITY: i = ltr501_get_ps_gain_index(val, val2); if (i < 0) @@ -227,7 +229,8 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, data->ps_contr &= ~LTR501_CONTR_PS_GAIN_MASK; data->ps_contr |= i << LTR501_CONTR_PS_GAIN_SHIFT; return i2c_smbus_write_byte_data(data->client, - LTR501_PS_CONTR, data->ps_contr); + LTR501_PS_CONTR, + data->ps_contr); default: return -EINVAL; } @@ -279,7 +282,7 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) /* figure out which data needs to be ready */ if (test_bit(0, indio_dev->active_scan_mask) || - test_bit(1, indio_dev->active_scan_mask)) + test_bit(1, indio_dev->active_scan_mask)) mask |= LTR501_STATUS_ALS_RDY; if (test_bit(2, indio_dev->active_scan_mask)) mask |= LTR501_STATUS_PS_RDY; @@ -290,7 +293,9 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) if (mask & LTR501_STATUS_ALS_RDY) { ret = i2c_smbus_read_i2c_block_data(data->client, - LTR501_ALS_DATA1, sizeof(als_buf), (u8 *) als_buf); + LTR501_ALS_DATA1, + sizeof(als_buf), + (u8 *)als_buf); if (ret < 0) return ret; if (test_bit(0, indio_dev->active_scan_mask)) @@ -306,8 +311,7 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) buf[j++] = ret & LTR501_PS_DATA_MASK; } - iio_push_to_buffers_with_timestamp(indio_dev, buf, - iio_get_time_ns()); + iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); done: iio_trigger_notify_done(indio_dev->trig); @@ -330,7 +334,7 @@ static int ltr501_init(struct ltr501_data *data) data->ps_contr = ret | LTR501_CONTR_ACTIVE; return ltr501_write_contr(data->client, data->als_contr, - data->ps_contr); + data->ps_contr); } static int ltr501_powerdown(struct ltr501_data *data) @@ -341,7 +345,7 @@ static int ltr501_powerdown(struct ltr501_data *data) } static int ltr501_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct ltr501_data *data; struct iio_dev *indio_dev; @@ -375,7 +379,7 @@ static int ltr501_probe(struct i2c_client *client, return ret; ret = iio_triggered_buffer_setup(indio_dev, NULL, - ltr501_trigger_handler, NULL); + ltr501_trigger_handler, NULL); if (ret) goto powerdown_on_error; @@ -407,14 +411,14 @@ static int ltr501_remove(struct i2c_client *client) static int ltr501_suspend(struct device *dev) { struct ltr501_data *data = iio_priv(i2c_get_clientdata( - to_i2c_client(dev))); + to_i2c_client(dev))); return ltr501_powerdown(data); } static int ltr501_resume(struct device *dev) { struct ltr501_data *data = iio_priv(i2c_get_clientdata( - to_i2c_client(dev))); + to_i2c_client(dev))); return ltr501_write_contr(data->client, data->als_contr, data->ps_contr); From 7840ffee97842132f6a7f170ca609764551f7de2 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Fri, 3 Apr 2015 15:47:29 +0300 Subject: [PATCH 0058/3798] iio: sx9500: add power management Signed-off-by: Vlad Dogaru Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9500.c | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index fa40f6d0ca394f..d2c52f9da937f2 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -89,6 +90,8 @@ struct sx9500_data { bool event_enabled[SX9500_NUM_CHANNELS]; bool trigger_enabled; u16 *buffer; + /* Remember enabled channels and sample rate during suspend. */ + unsigned int suspend_ctrl0; }; static const struct iio_event_spec sx9500_events[] = { @@ -720,6 +723,49 @@ static int sx9500_remove(struct i2c_client *client) return 0; } +#ifdef CONFIG_PM_SLEEP +static int sx9500_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct sx9500_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->mutex); + ret = regmap_read(data->regmap, SX9500_REG_PROX_CTRL0, + &data->suspend_ctrl0); + if (ret < 0) + goto out; + + /* + * Scan period doesn't matter because when all the sensors are + * deactivated the device is in sleep mode. + */ + ret = regmap_write(data->regmap, SX9500_REG_PROX_CTRL0, 0); + +out: + mutex_unlock(&data->mutex); + return ret; +} + +static int sx9500_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct sx9500_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->mutex); + ret = regmap_write(data->regmap, SX9500_REG_PROX_CTRL0, + data->suspend_ctrl0); + mutex_unlock(&data->mutex); + + return ret; +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct dev_pm_ops sx9500_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(sx9500_suspend, sx9500_resume) +}; + static const struct acpi_device_id sx9500_acpi_match[] = { {"SSX9500", 0}, { }, @@ -736,6 +782,7 @@ static struct i2c_driver sx9500_driver = { .driver = { .name = SX9500_DRIVER_NAME, .acpi_match_table = ACPI_PTR(sx9500_acpi_match), + .pm = &sx9500_pm_ops, }, .probe = sx9500_probe, .remove = sx9500_remove, From ea9da4e4608104108c6d5eca7b178cec2720ab22 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 2 Apr 2015 10:35:08 +0100 Subject: [PATCH 0059/3798] drm/i915: Allow disabling the destination colorkey for overlay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sometimes userspace wants a true overlay that is never clipped. In such cases, we need to disable the destination colorkey. However, it is currently unconditionally enabled in the overlay with no means of disabling. So rectify that by always default to on, and extending the UPDATE_ATTR ioctl to support explicit disabling of the colorkey. This is contrast to the spite code which requires explicit enabling of either the destination or source colorkey. Handling source colorkey is still todo for the overlay. (Of course it may be worth migrating overlay to sprite before then.) Signed-off-by: Chris Wilson Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_overlay.c | 30 ++++++++++++++++++---------- include/uapi/drm/i915_drm.h | 1 + 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index b291f1301c9386..5fd2d5ac02e2dc 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -175,7 +175,8 @@ struct intel_overlay { bool active; bool pfit_active; u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */ - u32 color_key; + u32 color_key:24; + u32 color_key_enabled:1; u32 brightness, contrast, saturation; u32 old_xscale, old_yscale; /* register access */ @@ -630,31 +631,36 @@ static void update_colorkey(struct intel_overlay *overlay, struct overlay_registers __iomem *regs) { u32 key = overlay->color_key; + u32 flags; + + flags = 0; + if (overlay->color_key_enabled) + flags |= DST_KEY_ENABLE; switch (overlay->crtc->base.primary->fb->bits_per_pixel) { case 8: - iowrite32(0, ®s->DCLRKV); - iowrite32(CLK_RGB8I_MASK | DST_KEY_ENABLE, ®s->DCLRKM); + key = 0; + flags |= CLK_RGB8I_MASK; break; case 16: if (overlay->crtc->base.primary->fb->depth == 15) { - iowrite32(RGB15_TO_COLORKEY(key), ®s->DCLRKV); - iowrite32(CLK_RGB15_MASK | DST_KEY_ENABLE, - ®s->DCLRKM); + key = RGB15_TO_COLORKEY(key); + flags |= CLK_RGB15_MASK; } else { - iowrite32(RGB16_TO_COLORKEY(key), ®s->DCLRKV); - iowrite32(CLK_RGB16_MASK | DST_KEY_ENABLE, - ®s->DCLRKM); + key = RGB16_TO_COLORKEY(key); + flags |= CLK_RGB16_MASK; } break; case 24: case 32: - iowrite32(key, ®s->DCLRKV); - iowrite32(CLK_RGB24_MASK | DST_KEY_ENABLE, ®s->DCLRKM); + flags |= CLK_RGB24_MASK; break; } + + iowrite32(key, ®s->DCLRKV); + iowrite32(flags, ®s->DCLRKM); } static u32 overlay_cmd_reg(struct put_image_params *params) @@ -1329,6 +1335,7 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, I915_WRITE(OGAMC5, attrs->gamma5); } } + overlay->color_key_enabled = (attrs->flags & I915_OVERLAY_DISABLE_DEST_COLORKEY) == 0; ret = 0; out_unlock: @@ -1392,6 +1399,7 @@ void intel_setup_overlay(struct drm_device *dev) /* init all values */ overlay->color_key = 0x0101fe; + overlay->color_key_enabled = true; overlay->brightness = -19; overlay->contrast = 75; overlay->saturation = 146; diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 551b6737f5df69..4851d660243cee 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -996,6 +996,7 @@ struct drm_intel_overlay_put_image { /* flags */ #define I915_OVERLAY_UPDATE_ATTRS (1<<0) #define I915_OVERLAY_UPDATE_GAMMA (1<<1) +#define I915_OVERLAY_DISABLE_DEST_COLORKEY (1<<2) struct drm_intel_overlay_attrs { __u32 flags; __u32 color_key; From c929cb4524a304cb366854836ef7baf501ef6d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 2 Apr 2015 18:28:07 +0300 Subject: [PATCH 0060/3798] drm/i915: Silence a sparse warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ../drivers/gpu/drm/i915/intel_pm.c:3185:45: warning: Initializer entry defined twice ../drivers/gpu/drm/i915/intel_pm.c:3185:52: also defined here Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e1392e79c5c4b8..cd91407e1f932c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3178,7 +3178,7 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv, { struct drm_device *dev = dev_priv->dev; struct skl_ddb_allocation *cur_ddb, *new_ddb; - bool reallocated[I915_MAX_PIPES] = {false, false, false}; + bool reallocated[I915_MAX_PIPES] = {}; struct intel_crtc *crtc; enum pipe pipe; From 304603f47a7487309d5c450f438c59e92af2d93a Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 2 Apr 2015 14:47:56 +0300 Subject: [PATCH 0061/3798] drm/i915: Don't use staged config for VLV cdclk calculations Now that we use a drm atomic state for the legacy modeset, it is possible to get rid of the usage of intel_crtc->new_config in the function intel_mode_max_pixclk(). Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 55 +++++++++++++++++++++------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 84f5b417ad3cb9..a6cd8c7a64e974 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5160,36 +5160,48 @@ static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv, } /* compute the max pixel clock for new configuration */ -static int intel_mode_max_pixclk(struct drm_i915_private *dev_priv) +static int intel_mode_max_pixclk(struct drm_atomic_state *state) { - struct drm_device *dev = dev_priv->dev; + struct drm_device *dev = state->dev; struct intel_crtc *intel_crtc; + struct intel_crtc_state *crtc_state; int max_pixclk = 0; for_each_intel_crtc(dev, intel_crtc) { - if (intel_crtc->new_enabled) - max_pixclk = max(max_pixclk, - intel_crtc->new_config->base.adjusted_mode.crtc_clock); + crtc_state = intel_atomic_get_crtc_state(state, intel_crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + if (!crtc_state->base.enable) + continue; + + max_pixclk = max(max_pixclk, + crtc_state->base.adjusted_mode.crtc_clock); } return max_pixclk; } -static void valleyview_modeset_global_pipes(struct drm_device *dev, +static int valleyview_modeset_global_pipes(struct drm_atomic_state *state, unsigned *prepare_pipes) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(state->dev); struct intel_crtc *intel_crtc; - int max_pixclk = intel_mode_max_pixclk(dev_priv); + int max_pixclk = intel_mode_max_pixclk(state); + + if (max_pixclk < 0) + return max_pixclk; if (valleyview_calc_cdclk(dev_priv, max_pixclk) == dev_priv->vlv_cdclk_freq) - return; + return 0; /* disable/enable all currently active pipes while we change cdclk */ - for_each_intel_crtc(dev, intel_crtc) + for_each_intel_crtc(state->dev, intel_crtc) if (intel_crtc->base.state->enable) *prepare_pipes |= (1 << intel_crtc->pipe); + + return 0; } static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv) @@ -5232,8 +5244,18 @@ static void valleyview_modeset_global_resources(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; struct drm_i915_private *dev_priv = dev->dev_private; - int max_pixclk = intel_mode_max_pixclk(dev_priv); - int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk); + int max_pixclk = intel_mode_max_pixclk(state); + int req_cdclk; + + /* The only reason this can fail is if we fail to add the crtc_state + * to the atomic state. But that can't happen since the call to + * intel_mode_max_pixclk() in valleyview_modeset_global_pipes() (which + * can't have failed otherwise the mode set would be aborted) added all + * the states already. */ + if (WARN_ON(max_pixclk < 0)) + return; + + req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk); if (req_cdclk != dev_priv->vlv_cdclk_freq) { /* @@ -11550,6 +11572,8 @@ intel_modeset_compute_config(struct drm_crtc *crtc, if (IS_ERR(pipe_config)) return pipe_config; + pipe_config->base.enable = true; + intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config, "[modeset]"); } @@ -11598,6 +11622,7 @@ static int __intel_set_mode(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_display_mode *saved_mode; + struct drm_atomic_state *state = pipe_config->base.state; struct intel_crtc_state *crtc_state_copy = NULL; struct intel_crtc *intel_crtc; int ret = 0; @@ -11625,7 +11650,9 @@ static int __intel_set_mode(struct drm_crtc *crtc, * adjusted_mode bits in the crtc directly. */ if (IS_VALLEYVIEW(dev)) { - valleyview_modeset_global_pipes(dev, &prepare_pipes); + ret = valleyview_modeset_global_pipes(state, &prepare_pipes); + if (ret) + goto done; /* may have added more to prepare_pipes than we should */ prepare_pipes &= ~disable_pipes; @@ -11669,7 +11696,7 @@ static int __intel_set_mode(struct drm_crtc *crtc, * update the the output configuration. */ intel_modeset_update_state(dev, prepare_pipes); - modeset_update_crtc_power_domains(pipe_config->base.state); + modeset_update_crtc_power_domains(state); /* Set up the DPLL and any encoders state that needs to adjust or depend * on the DPLL. From 225da59b540a92c8f8bbeb4c69c9139da06b061a Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 2 Apr 2015 14:47:57 +0300 Subject: [PATCH 0062/3798] drm/i915: Don't use intel_crtc->new_config in pll calculation code Move towards atomic by using the atomic state instead. Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a6cd8c7a64e974..0b7ddeee681a70 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11581,10 +11581,11 @@ intel_modeset_compute_config(struct drm_crtc *crtc, return intel_atomic_get_crtc_state(state, to_intel_crtc(crtc));; } -static int __intel_set_mode_setup_plls(struct drm_device *dev, +static int __intel_set_mode_setup_plls(struct drm_atomic_state *state, unsigned modeset_pipes, unsigned disable_pipes) { + struct drm_device *dev = state->dev; struct drm_i915_private *dev_priv = to_i915(dev); unsigned clear_pipes = modeset_pipes | disable_pipes; struct intel_crtc *intel_crtc; @@ -11598,9 +11599,15 @@ static int __intel_set_mode_setup_plls(struct drm_device *dev, goto done; for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) { - struct intel_crtc_state *state = intel_crtc->new_config; + struct intel_crtc_state *crtc_state = + intel_atomic_get_crtc_state(state, intel_crtc); + + /* Modeset pipes should have a new state by now */ + if (WARN_ON(IS_ERR(crtc_state))) + continue; + ret = dev_priv->display.crtc_compute_clock(intel_crtc, - state); + crtc_state); if (ret) { intel_shared_dpll_abort_config(dev_priv); goto done; @@ -11658,7 +11665,7 @@ static int __intel_set_mode(struct drm_crtc *crtc, prepare_pipes &= ~disable_pipes; } - ret = __intel_set_mode_setup_plls(dev, modeset_pipes, disable_pipes); + ret = __intel_set_mode_setup_plls(state, modeset_pipes, disable_pipes); if (ret) goto done; From d69ba09b68ff779877dbbc3be2958a80151ae91b Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 2 Apr 2015 14:47:58 +0300 Subject: [PATCH 0063/3798] drm/i915: Remove intel_crtc->new_config It's not needed anymore, now that all the users were converted to using an atomic state. Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 31 ---------------------------- drivers/gpu/drm/i915/intel_drv.h | 1 - 2 files changed, 32 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0b7ddeee681a70..207c713dd574ba 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9171,7 +9171,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector, intel_crtc = to_intel_crtc(crtc); intel_crtc->new_enabled = true; - intel_crtc->new_config = intel_crtc->config; old->dpms_mode = connector->dpms; old->load_detect_temp = true; old->release_fb = NULL; @@ -9227,10 +9226,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector, fail: intel_crtc->new_enabled = crtc->state->enable; - if (intel_crtc->new_enabled) - intel_crtc->new_config = intel_crtc->config; - else - intel_crtc->new_config = NULL; fail_unlock: if (state) { drm_atomic_state_free(state); @@ -9276,7 +9271,6 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, to_intel_connector(connector)->new_encoder = NULL; intel_encoder->new_crtc = NULL; intel_crtc->new_enabled = false; - intel_crtc->new_config = NULL; connector_state->best_encoder = NULL; connector_state->crtc = NULL; @@ -10416,11 +10410,6 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev) for_each_intel_crtc(dev, crtc) { crtc->new_enabled = crtc->base.state->enable; - - if (crtc->new_enabled) - crtc->new_config = crtc->config; - else - crtc->new_config = NULL; } } @@ -10981,9 +10970,6 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes) /* Double check state. */ for_each_intel_crtc(dev, intel_crtc) { WARN_ON(intel_crtc->base.state->enable != intel_crtc_in_use(&intel_crtc->base)); - WARN_ON(intel_crtc->new_config && - intel_crtc->new_config != intel_crtc->config); - WARN_ON(intel_crtc->base.state->enable != !!intel_crtc->new_config); } list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -11646,9 +11632,6 @@ static int __intel_set_mode(struct drm_crtc *crtc, *saved_mode = crtc->mode; - if (modeset_pipes) - to_intel_crtc(crtc)->new_config = pipe_config; - /* * See if the config requires any additional preparation, e.g. * to adjust global state with pipes off. We need to do this @@ -11741,9 +11724,6 @@ static int __intel_set_mode(struct drm_crtc *crtc, sizeof *crtc_state_copy); intel_crtc->config = crtc_state_copy; intel_crtc->base.state = &crtc_state_copy->base; - - if (modeset_pipes) - intel_crtc->new_config = intel_crtc->config; } else { kfree(crtc_state_copy); } @@ -11922,11 +11902,6 @@ static void intel_set_config_restore_state(struct drm_device *dev, count = 0; for_each_intel_crtc(dev, crtc) { crtc->new_enabled = config->save_crtc_enabled[count++]; - - if (crtc->new_enabled) - crtc->new_config = crtc->config; - else - crtc->new_config = NULL; } count = 0; @@ -12153,11 +12128,6 @@ intel_modeset_stage_output_state(struct drm_device *dev, crtc->new_enabled ? "en" : "dis"); config->mode_changed = true; } - - if (crtc->new_enabled) - crtc->new_config = crtc->config; - else - crtc->new_config = NULL; } return 0; @@ -12184,7 +12154,6 @@ static void disable_crtc_nofb(struct intel_crtc *crtc) } crtc->new_enabled = false; - crtc->new_config = NULL; } static int intel_crtc_set_config(struct drm_mode_set *set) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4799b11f30c54e..686014bd5ec035 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -471,7 +471,6 @@ struct intel_crtc { struct intel_initial_plane_config plane_config; struct intel_crtc_state *config; - struct intel_crtc_state *new_config; bool new_enabled; /* reset counter value when the last flip was submitted */ From 5448a00d3f0640949c2a9a4d16e163b0b40a3b2e Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 2 Apr 2015 14:47:59 +0300 Subject: [PATCH 0064/3798] drm/i915: Don't use staged config in check_digital_port_conflicts() Reduce dependency on the staged config by using the atomic state instead. Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 207c713dd574ba..b1fbe9d994ffc7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10658,23 +10658,30 @@ static bool check_encoder_cloning(struct intel_crtc *crtc) return true; } -static bool check_digital_port_conflicts(struct drm_device *dev) +static bool check_digital_port_conflicts(struct drm_atomic_state *state) { - struct intel_connector *connector; + struct drm_device *dev = state->dev; + struct intel_encoder *encoder; + struct drm_connector_state *connector_state; unsigned int used_ports = 0; + int i; /* * Walk the connector list instead of the encoder * list to detect the problem on ddi platforms * where there's just one encoder per digital port. */ - for_each_intel_connector(dev, connector) { - struct intel_encoder *encoder = connector->new_encoder; + for (i = 0; i < state->num_connector; i++) { + if (!state->connectors[i]) + continue; - if (!encoder) + connector_state = state->connector_states[i]; + if (!connector_state->best_encoder) continue; - WARN_ON(!encoder->new_crtc); + encoder = to_intel_encoder(connector_state->best_encoder); + + WARN_ON(!connector_state->crtc); switch (encoder->type) { unsigned int port_mask; @@ -10716,7 +10723,6 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_atomic_state *state) { - struct drm_device *dev = crtc->dev; struct intel_encoder *encoder; struct intel_connector *connector; struct drm_connector_state *connector_state; @@ -10730,7 +10736,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, return ERR_PTR(-EINVAL); } - if (!check_digital_port_conflicts(dev)) { + if (!check_digital_port_conflicts(state)) { DRM_DEBUG_KMS("rejecting conflicting digital port configuration\n"); return ERR_PTR(-EINVAL); } From 98a221da4aeb18b2b68b08359666230c1febafe0 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 2 Apr 2015 14:48:00 +0300 Subject: [PATCH 0065/3798] drm/i915: Don't use staged config in check_encoder_cloning() Reduce dependency on the staged config by using the atomic state instead. Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 35 ++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b1fbe9d994ffc7..bc8e221a30d175 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10625,16 +10625,24 @@ static bool encoders_cloneable(const struct intel_encoder *a, b->cloneable & (1 << a->type)); } -static bool check_single_encoder_cloning(struct intel_crtc *crtc, +static bool check_single_encoder_cloning(struct drm_atomic_state *state, + struct intel_crtc *crtc, struct intel_encoder *encoder) { - struct drm_device *dev = crtc->base.dev; struct intel_encoder *source_encoder; + struct drm_connector_state *connector_state; + int i; - for_each_intel_encoder(dev, source_encoder) { - if (source_encoder->new_crtc != crtc) + for (i = 0; i < state->num_connector; i++) { + if (!state->connectors[i]) continue; + connector_state = state->connector_states[i]; + if (connector_state->crtc != &crtc->base) + continue; + + source_encoder = + to_intel_encoder(connector_state->best_encoder); if (!encoders_cloneable(encoder, source_encoder)) return false; } @@ -10642,16 +10650,23 @@ static bool check_single_encoder_cloning(struct intel_crtc *crtc, return true; } -static bool check_encoder_cloning(struct intel_crtc *crtc) +static bool check_encoder_cloning(struct drm_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_device *dev = crtc->base.dev; struct intel_encoder *encoder; + struct drm_connector_state *connector_state; + int i; - for_each_intel_encoder(dev, encoder) { - if (encoder->new_crtc != crtc) + for (i = 0; i < state->num_connector; i++) { + if (!state->connectors[i]) continue; - if (!check_single_encoder_cloning(crtc, encoder)) + connector_state = state->connector_states[i]; + if (connector_state->crtc != &crtc->base) + continue; + + encoder = to_intel_encoder(connector_state->best_encoder); + if (!check_single_encoder_cloning(state, crtc, encoder)) return false; } @@ -10731,7 +10746,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, int i; bool retry = true; - if (!check_encoder_cloning(to_intel_crtc(crtc))) { + if (!check_encoder_cloning(state, to_intel_crtc(crtc))) { DRM_DEBUG_KMS("rejecting invalid cloning configuration\n"); return ERR_PTR(-EINVAL); } From 9b4fd8f250e08d8f22a31d947ac3ca16383df1e1 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 2 Apr 2015 14:48:01 +0300 Subject: [PATCH 0066/3798] drm/i915: Don't use staged config in intel_mst_pre_enable_dp() For the conversion to atomic. The pre_enable() hooks are called as part of the crtc enable sequence, at which point the staged config was already made effective. Furthermore, the function actually changes hardware state, so it should anyway deal with current and not staged config. Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp_mst.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 5329c855acce71..adcc5e641347db 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -150,14 +150,14 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder) enum port port = intel_dig_port->port; int ret; uint32_t temp; - struct intel_connector *found = NULL, *intel_connector; + struct intel_connector *found = NULL, *connector; int slots; struct drm_crtc *crtc = encoder->base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - for_each_intel_connector(dev, intel_connector) { - if (intel_connector->new_encoder == encoder) { - found = intel_connector; + for_each_intel_connector(dev, connector) { + if (connector->base.state->best_encoder == &encoder->base) { + found = connector; break; } } From b833bb61fd905a8d2c7392d1bc5fedf34921e251 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 7 Apr 2015 11:32:02 +0200 Subject: [PATCH 0067/3798] drm/i915: use kref_put_mutex in i915_gem_request_unreference__unlocked Signed-off-by: Maarten Lankhorst Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4fd38f2e6e623b..d5b21153f200c6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2148,14 +2148,14 @@ i915_gem_request_unreference(struct drm_i915_gem_request *req) static inline void i915_gem_request_unreference__unlocked(struct drm_i915_gem_request *req) { - if (req && !atomic_add_unless(&req->ref.refcount, -1, 1)) { - struct drm_device *dev = req->ring->dev; + struct drm_device *dev; + + if (!req) + return; - mutex_lock(&dev->struct_mutex); - if (likely(atomic_dec_and_test(&req->ref.refcount))) - i915_gem_request_free(&req->ref); + dev = req->ring->dev; + if (kref_put_mutex(&req->ref, i915_gem_request_free, &dev->struct_mutex)) mutex_unlock(&dev->struct_mutex); - } } static inline void i915_gem_request_assign(struct drm_i915_gem_request **pdst, From 51847fb99f25fe1bf4bc6739f9d8ac85fa2c2a65 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Tue, 7 Apr 2015 14:01:33 +0100 Subject: [PATCH 0068/3798] drm/i915: Do not set L3-LLC Coherency bit in ctx descriptor According to Spec this is a reserved bit for Gen9+ and should not be set. Change-Id: I0215fb7057b94139b7a2f90ecc7a0201c0c93ad4 Signed-off-by: Arun Siluvery Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 1c3834fc5608e2..cfc73ea59804e6 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -265,7 +265,8 @@ static uint64_t execlists_ctx_descriptor(struct intel_engine_cs *ring, desc = GEN8_CTX_VALID; desc |= LEGACY_CONTEXT << GEN8_CTX_MODE_SHIFT; - desc |= GEN8_CTX_L3LLC_COHERENT; + if (IS_GEN8(ctx_obj->base.dev)) + desc |= GEN8_CTX_L3LLC_COHERENT; desc |= GEN8_CTX_PRIVILEGE; desc |= lrca; desc |= (u64)intel_execlists_ctx_id(ctx_obj) << GEN8_CTX_ID_SHIFT; From 669506e781d12939ad270b4c281189de119d1319 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 26 Feb 2015 18:20:38 +0000 Subject: [PATCH 0069/3798] drm/i915/skl: Fix stepping check for a couple of W/As Both WaDisableSDEUnitClockGating and WaSetGAPSunitClckGateDisable are needed on B0 as well. Signed-off-by: Damien Lespiau Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index cd91407e1f932c..d76d6ab3775fab 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -67,7 +67,7 @@ static void skl_init_clock_gating(struct drm_device *dev) gen9_init_clock_gating(dev); - if (INTEL_REVID(dev) == SKL_REVID_A0) { + if (INTEL_REVID(dev) <= SKL_REVID_B0) { /* * WaDisableSDEUnitClockGating:skl * WaSetGAPSunitClckGateDisable:skl From f9fc42f4bd9a6b9d63f8587325c7f53a6b788d8e Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 26 Feb 2015 18:20:39 +0000 Subject: [PATCH 0070/3798] drm/i915/skl: Implement WaDisableVFUnitClockGating Signed-off-by: Damien Lespiau Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9966d3294a02ec..b01da4ebcebe17 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6102,6 +6102,7 @@ enum skl_disp_power_wells { # define GEN6_CSUNIT_CLOCK_GATE_DISABLE (1 << 7) #define GEN6_UCGCTL2 0x9404 +# define GEN6_VFUNIT_CLOCK_GATE_DISABLE (1 << 31) # define GEN7_VDSUNIT_CLOCK_GATE_DISABLE (1 << 30) # define GEN7_TDLUNIT_CLOCK_GATE_DISABLE (1 << 22) # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d76d6ab3775fab..67e1e61c50e7d3 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -75,6 +75,10 @@ static void skl_init_clock_gating(struct drm_device *dev) I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) | GEN8_GAPSUNIT_CLOCK_GATE_DISABLE | GEN8_SDEUNIT_CLOCK_GATE_DISABLE); + + /* WaDisableVFUnitClockGating:skl */ + I915_WRITE(GEN6_UCGCTL2, I915_READ(GEN6_UCGCTL2) | + GEN6_VFUNIT_CLOCK_GATE_DISABLE); } if (INTEL_REVID(dev) <= SKL_REVID_D0) { From ee286370d6233da01788c942c2dd7e450078eb27 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:25 +0100 Subject: [PATCH 0071/3798] drm/i915: Cache last obj->pages location for i915_gem_object_get_page() The biggest user of i915_gem_object_get_page() is the relocation processing during execbuffer. Typically userspace passes in a set of relocations in sorted order. Sadly, we alternate between relocations increasing from the start of the buffers, and relocations decreasing from the end. However the majority of consecutive lookups will still be in the same page. We could cache the start of the last sg chain, however for most callers, the entire sgl is inside a single chain and so we see no improve from the extra layer of caching. v2: Avoid the double increment inside unlikely() References: https://bugs.freedesktop.org/show_bug.cgi?id=88308 Signed-off-by: Chris Wilson Cc: John Harrison Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 31 ++++++++++++++++++++++++++----- drivers/gpu/drm/i915/i915_gem.c | 4 ++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d5b21153f200c6..924676fdb26f1e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1986,6 +1986,10 @@ struct drm_i915_gem_object { struct sg_table *pages; int pages_pin_count; + struct get_page { + struct scatterlist *sg; + int last; + } get_page; /* prime dma-buf support */ void *dma_buf_vmapping; @@ -2656,15 +2660,32 @@ int i915_gem_obj_prepare_shmem_read(struct drm_i915_gem_object *obj, int *needs_clflush); int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj); -static inline struct page *i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n) + +static inline int __sg_page_count(struct scatterlist *sg) +{ + return sg->length >> PAGE_SHIFT; +} + +static inline struct page * +i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n) { - struct sg_page_iter sg_iter; + if (WARN_ON(n >= obj->base.size >> PAGE_SHIFT)) + return NULL; - for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, n) - return sg_page_iter_page(&sg_iter); + if (n < obj->get_page.last) { + obj->get_page.sg = obj->pages->sgl; + obj->get_page.last = 0; + } + + while (obj->get_page.last + __sg_page_count(obj->get_page.sg) <= n) { + obj->get_page.last += __sg_page_count(obj->get_page.sg++); + if (unlikely(sg_is_chain(obj->get_page.sg))) + obj->get_page.sg = sg_chain_ptr(obj->get_page.sg); + } - return NULL; + return nth_page(sg_page(obj->get_page.sg), n - obj->get_page.last); } + static inline void i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) { BUG_ON(obj->pages == NULL); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 267fdf0f46ae7b..976d27a191925d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2178,6 +2178,10 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj) return ret; list_add_tail(&obj->global_list, &dev_priv->mm.unbound_list); + + obj->get_page.sg = obj->pages->sgl; + obj->get_page.last = 0; + return 0; } From cf5d8a46a001c9421c7397699db55f962e0410fc Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:26 +0100 Subject: [PATCH 0072/3798] drm/i915: Fix the flip synchronisation to consider mmioflips Currently we emit semaphore synchronisation as if we were going to flip using the target CS engine, but we then change our minds and do the flip using the CPU. Consequently we write instructions to the ring but never use them - even to the point of filling that ring up entirely and never submitting a request. The wrinkle in the ointment is that we have to tell a white lie to pin-to-display for it to skip the synchronisation for mmioflips as we will create a task specifically for that slow synchronisation. An oddity of note is the discrepancy in requests that we tell to pin-display to serialise to and that we then eventually wait upon. This is due to a limitation in the i915_gem_object_sync() routine that will be lifted later. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bc8e221a30d175..6256e6157845c1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10210,6 +10210,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, enum pipe pipe = intel_crtc->pipe; struct intel_unpin_work *work; struct intel_engine_cs *ring; + bool mmio_flip; int ret; /* @@ -10307,15 +10308,23 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, ring = &dev_priv->ring[RCS]; } + mmio_flip = use_mmio_flip(ring, obj); + + /* When using CS flips, we want to emit semaphores between rings. + * However, when using mmio flips we will create a task to do the + * synchronisation, so all we want here is to pin the framebuffer + * into the display plane and skip any waits. + */ ret = intel_pin_and_fence_fb_obj(crtc->primary, fb, - crtc->primary->state, ring); + crtc->primary->state, + mmio_flip ? i915_gem_request_get_ring(obj->last_read_req) : ring); if (ret) goto cleanup_pending; work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary), obj) + intel_crtc->dspaddr_offset; - if (use_mmio_flip(ring, obj)) { + if (mmio_flip) { ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring, page_flip_flags); if (ret) From 8fb55197e64d5988ec57b54e973daeea72c3f2ff Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:28 +0100 Subject: [PATCH 0073/3798] drm/i915: Agressive downclocking on Baytrail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reuse the same reclocking strategy for Baytail as on its bigger brethren, Sandybridge and Ivybridge. In particular, this makes the device quicker to reclock (both up and down) though the tendency now is to downclock more aggressively to compensate for the RPS boosts. v2: Rebase v3: Exclude Cherrytrail as Deepak was concerned that the increased number of register writes would wake the common powerwell too often. Signed-off-by: Chris Wilson Cc: Deepak S Cc: Ville Syrjälä Cc: Rodrigo Vivi Cc: Daniel Vetter Reviewed-by: Deepak S Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/i915_irq.c | 4 ++-- drivers/gpu/drm/i915/i915_reg.h | 2 -- drivers/gpu/drm/i915/intel_pm.c | 8 +++++++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 924676fdb26f1e..b4501647795ea2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1035,6 +1035,9 @@ struct intel_gen6_power_mgmt { u8 rp0_freq; /* Non-overclocked max frequency. */ u32 cz_freq; + u8 up_threshold; /* Current %busy required to uplock */ + u8 down_threshold; /* Current %busy required to downclock */ + int last_adj; enum { LOW_POWER, BETWEEN, HIGH_POWER } power; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 14ecb4d13a1aa2..128a6f40b45093 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1049,7 +1049,7 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) if (pm_iir & GEN6_PM_RP_DOWN_EI_EXPIRED) { if (!vlv_c0_above(dev_priv, &dev_priv->rps.down_ei, &now, - VLV_RP_DOWN_EI_THRESHOLD)) + dev_priv->rps.down_threshold)) events |= GEN6_PM_RP_DOWN_THRESHOLD; dev_priv->rps.down_ei = now; } @@ -1057,7 +1057,7 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) { if (vlv_c0_above(dev_priv, &dev_priv->rps.up_ei, &now, - VLV_RP_UP_EI_THRESHOLD)) + dev_priv->rps.up_threshold)) events |= GEN6_PM_RP_UP_THRESHOLD; dev_priv->rps.up_ei = now; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b01da4ebcebe17..77d8874c2fc37c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -671,8 +671,6 @@ enum skl_disp_power_wells { #define FB_FMAX_VMIN_FREQ_LO_MASK 0xf8000000 #define VLV_CZ_CLOCK_TO_MILLI_SEC 100000 -#define VLV_RP_UP_EI_THRESHOLD 90 -#define VLV_RP_DOWN_EI_THRESHOLD 70 /* vlv2 north clock has */ #define CCK_FUSE_REG 0x8 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 67e1e61c50e7d3..9c705dec853eff 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3934,6 +3934,8 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val) GEN6_RP_DOWN_IDLE_AVG); dev_priv->rps.power = new_power; + dev_priv->rps.up_threshold = threshold_up; + dev_priv->rps.down_threshold = threshold_down; dev_priv->rps.last_adj = 0; } @@ -4005,8 +4007,11 @@ static void valleyview_set_rps(struct drm_device *dev, u8 val) "Odd GPU freq value\n")) val &= ~1; - if (val != dev_priv->rps.cur_freq) + if (val != dev_priv->rps.cur_freq) { vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val); + if (!IS_CHERRYVIEW(dev_priv)) + gen6_set_rps_thresholds(dev_priv, val); + } I915_WRITE(GEN6_PMINTRMSK, gen6_rps_pm_mask(dev_priv, val)); @@ -4055,6 +4060,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) & GENFREQSTATUS) == 0, 100)) DRM_ERROR("timed out waiting for Punit\n"); + gen6_set_rps_thresholds(dev_priv, val); vlv_force_gfx_clock(dev_priv, false); I915_WRITE(GEN6_PMINTRMSK, gen6_rps_pm_mask(dev_priv, val)); From edcf284bfe9c94eab2923b13cfff7456c0dc7dc6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:29 +0100 Subject: [PATCH 0074/3798] drm/i915: Fix computation of last_adjustment for RPS autotuning The issue is that by computing the last_adj value after applying the clamping, we can end up with a bogus value for feeding into the next RPS autotuning step. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Deepak S Reviewed-by: Deepak S Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 128a6f40b45093..8b5e0358c59287 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1095,21 +1095,20 @@ static void gen6_pm_rps_work(struct work_struct *work) pm_iir |= vlv_wa_c0_ei(dev_priv, pm_iir); adj = dev_priv->rps.last_adj; + new_delay = dev_priv->rps.cur_freq; if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) { if (adj > 0) adj *= 2; - else { - /* CHV needs even encode values */ - adj = IS_CHERRYVIEW(dev_priv->dev) ? 2 : 1; - } - new_delay = dev_priv->rps.cur_freq + adj; - + else /* CHV needs even encode values */ + adj = IS_CHERRYVIEW(dev_priv) ? 2 : 1; /* * For better performance, jump directly * to RPe if we're below it. */ - if (new_delay < dev_priv->rps.efficient_freq) + if (new_delay < dev_priv->rps.efficient_freq - adj) { new_delay = dev_priv->rps.efficient_freq; + adj = 0; + } } else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) { if (dev_priv->rps.cur_freq > dev_priv->rps.efficient_freq) new_delay = dev_priv->rps.efficient_freq; @@ -1119,24 +1118,22 @@ static void gen6_pm_rps_work(struct work_struct *work) } else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) { if (adj < 0) adj *= 2; - else { - /* CHV needs even encode values */ - adj = IS_CHERRYVIEW(dev_priv->dev) ? -2 : -1; - } - new_delay = dev_priv->rps.cur_freq + adj; + else /* CHV needs even encode values */ + adj = IS_CHERRYVIEW(dev_priv) ? -2 : -1; } else { /* unknown event */ - new_delay = dev_priv->rps.cur_freq; + adj = 0; } + dev_priv->rps.last_adj = adj; + /* sysfs frequency interfaces may have snuck in while servicing the * interrupt */ + new_delay += adj; new_delay = clamp_t(int, new_delay, dev_priv->rps.min_freq_softlimit, dev_priv->rps.max_freq_softlimit); - dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_freq; - intel_set_rps(dev_priv->dev, new_delay); mutex_unlock(&dev_priv->rps.hw_lock); From 6ad790c0f5ac55fd13f322c23519f0d6f0721864 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:31 +0100 Subject: [PATCH 0075/3798] drm/i915: Boost GPU frequency if we detect outstanding pageflips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we hit a vblank and see that have a pageflip queue but not yet processed, ensure that the GPU is running at maximum in order to clear the backlog. Pageflips are only queued for the following vblank, if we miss it, there will be a visible stutter. Boosting the GPU frequency doesn't prevent us from missing the target vblank, but it should help the subsequent frames hitting theirs. v2: Reorder vblank vs flip-complete so that we only check for a missed flip after processing the completion events, and avoid spurious boosts. v3: Rename missed_vblank v4: Rebase v5: Cancel the outstanding work in runtime suspend v6: Rebase v7: Rebase required fixing Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Ville Syrjälä Cc: Deepak S Reviewed-by: Deepak S Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 11 ++++++--- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 35 ++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6256e6157845c1..7bfe2af42030f9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10180,6 +10180,7 @@ void intel_check_page_flip(struct drm_device *dev, int pipe) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_unpin_work *work; WARN_ON(!in_interrupt()); @@ -10187,12 +10188,16 @@ void intel_check_page_flip(struct drm_device *dev, int pipe) return; spin_lock(&dev->event_lock); - if (intel_crtc->unpin_work && __intel_pageflip_stall_check(dev, crtc)) { + work = intel_crtc->unpin_work; + if (work != NULL && __intel_pageflip_stall_check(dev, crtc)) { WARN_ONCE(1, "Kicking stuck page flip: queued at %d, now %d\n", - intel_crtc->unpin_work->flip_queued_vblank, - drm_vblank_count(dev, pipe)); + work->flip_queued_vblank, drm_vblank_count(dev, pipe)); page_flip_completed(intel_crtc); + work = NULL; } + if (work != NULL && + drm_vblank_count(dev, pipe) - work->flip_queued_vblank > 1) + intel_queue_rps_boost_for_request(dev, work->flip_queued_req); spin_unlock(&dev->event_lock); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 686014bd5ec035..4771d319ac7bc5 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1263,6 +1263,8 @@ void gen6_rps_busy(struct drm_i915_private *dev_priv); void gen6_rps_reset_ei(struct drm_i915_private *dev_priv); void gen6_rps_idle(struct drm_i915_private *dev_priv); void gen6_rps_boost(struct drm_i915_private *dev_priv); +void intel_queue_rps_boost_for_request(struct drm_device *dev, + struct drm_i915_gem_request *rq); void ilk_wm_get_hw_state(struct drm_device *dev); void skl_wm_get_hw_state(struct drm_device *dev); void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9c705dec853eff..acf1a318fda900 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6772,6 +6772,41 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val) return val / GT_FREQUENCY_MULTIPLIER; } +struct request_boost { + struct work_struct work; + struct drm_i915_gem_request *rq; +}; + +static void __intel_rps_boost_work(struct work_struct *work) +{ + struct request_boost *boost = container_of(work, struct request_boost, work); + + if (!i915_gem_request_completed(boost->rq, true)) + gen6_rps_boost(to_i915(boost->rq->ring->dev)); + + i915_gem_request_unreference__unlocked(boost->rq); + kfree(boost); +} + +void intel_queue_rps_boost_for_request(struct drm_device *dev, + struct drm_i915_gem_request *rq) +{ + struct request_boost *boost; + + if (rq == NULL || INTEL_INFO(dev)->gen < 6) + return; + + boost = kmalloc(sizeof(*boost), GFP_ATOMIC); + if (boost == NULL) + return; + + i915_gem_request_reference(rq); + boost->rq = rq; + + INIT_WORK(&boost->work, __intel_rps_boost_work); + queue_work(to_i915(dev)->wq, &boost->work); +} + void intel_pm_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; From 1854d5ca0dd7a9fc11243ff220a3e93fce2b4d3e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:32 +0100 Subject: [PATCH 0076/3798] drm/i915: Deminish contribution of wait-boosting from clients With boosting for missed pageflips, we have a much stronger indication of when we need to (temporarily) boost GPU frequency to ensure smooth delivery of frames. So now only allow each client to perform one RPS boost in each period of GPU activity due to stalling on results. Signed-off-by: Chris Wilson Cc: Deepak S Reviewed-by: Deepak S Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 39 +++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 9 ++++--- drivers/gpu/drm/i915/i915_gem.c | 35 ++++++-------------------- drivers/gpu/drm/i915/intel_drv.h | 3 ++- drivers/gpu/drm/i915/intel_pm.c | 18 ++++++++++--- 5 files changed, 70 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 10ca5117fceeee..9c23eec3277e2a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2239,6 +2239,44 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) return 0; } +static int i915_rps_boost_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_file *file; + int ret; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; + + ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock); + if (ret) + goto unlock; + + list_for_each_entry_reverse(file, &dev->filelist, lhead) { + struct drm_i915_file_private *file_priv = file->driver_priv; + struct task_struct *task; + + rcu_read_lock(); + task = pid_task(file->pid, PIDTYPE_PID); + seq_printf(m, "%s [%d]: %d boosts%s\n", + task ? task->comm : "", + task ? task->pid : -1, + file_priv->rps_boosts, + list_empty(&file_priv->rps_boost) ? "" : ", active"); + rcu_read_unlock(); + } + seq_printf(m, "Kernel boosts: %d\n", dev_priv->rps.boosts); + + mutex_unlock(&dev_priv->rps.hw_lock); +unlock: + mutex_unlock(&dev->struct_mutex); + + return ret; +} + static int i915_llc(struct seq_file *m, void *data) { struct drm_info_node *node = m->private; @@ -4704,6 +4742,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_ddb_info", i915_ddb_info, 0}, {"i915_sseu_status", i915_sseu_status, 0}, {"i915_drrs_status", i915_drrs_status, 0}, + {"i915_rps_boost_info", i915_rps_boost_info, 0}, }; #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b4501647795ea2..3b6ddd74cd6971 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1043,6 +1043,8 @@ struct intel_gen6_power_mgmt { bool enabled; struct delayed_work delayed_resume_work; + struct list_head clients; + unsigned boosts; /* manual wa residency calculations */ struct intel_rps_ei up_ei, down_ei; @@ -2190,12 +2192,13 @@ struct drm_i915_file_private { struct { spinlock_t lock; struct list_head request_list; - struct delayed_work idle_work; } mm; struct idr context_idr; - atomic_t rps_wait_boost; - struct intel_engine_cs *bsd_ring; + struct list_head rps_boost; + struct intel_engine_cs *bsd_ring; + + unsigned rps_boosts; }; /* diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 976d27a191925d..4061b4ffe81504 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1181,14 +1181,6 @@ static bool missed_irq(struct drm_i915_private *dev_priv, return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings); } -static bool can_wait_boost(struct drm_i915_file_private *file_priv) -{ - if (file_priv == NULL) - return true; - - return !atomic_xchg(&file_priv->rps_wait_boost, true); -} - /** * __i915_wait_request - wait until execution of request has finished * @req: duh! @@ -1230,13 +1222,8 @@ int __i915_wait_request(struct drm_i915_gem_request *req, timeout_expire = timeout ? jiffies + nsecs_to_jiffies_timeout((u64)*timeout) : 0; - if (INTEL_INFO(dev)->gen >= 6 && ring->id == RCS && can_wait_boost(file_priv)) { - gen6_rps_boost(dev_priv); - if (file_priv) - mod_delayed_work(dev_priv->wq, - &file_priv->mm.idle_work, - msecs_to_jiffies(100)); - } + if (ring->id == RCS && INTEL_INFO(dev)->gen >= 6) + gen6_rps_boost(dev_priv, file_priv); if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring))) return -ENODEV; @@ -5043,8 +5030,6 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; - cancel_delayed_work_sync(&file_priv->mm.idle_work); - /* Clean up our request list when the client is going away, so that * later retire_requests won't dereference our soon-to-be-gone * file_priv. @@ -5060,15 +5045,12 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file) request->file_priv = NULL; } spin_unlock(&file_priv->mm.lock); -} - -static void -i915_gem_file_idle_work_handler(struct work_struct *work) -{ - struct drm_i915_file_private *file_priv = - container_of(work, typeof(*file_priv), mm.idle_work.work); - atomic_set(&file_priv->rps_wait_boost, false); + if (!list_empty(&file_priv->rps_boost)) { + mutex_lock(&to_i915(dev)->rps.hw_lock); + list_del(&file_priv->rps_boost); + mutex_unlock(&to_i915(dev)->rps.hw_lock); + } } int i915_gem_open(struct drm_device *dev, struct drm_file *file) @@ -5085,11 +5067,10 @@ int i915_gem_open(struct drm_device *dev, struct drm_file *file) file->driver_priv = file_priv; file_priv->dev_priv = dev->dev_private; file_priv->file = file; + INIT_LIST_HEAD(&file_priv->rps_boost); spin_lock_init(&file_priv->mm.lock); INIT_LIST_HEAD(&file_priv->mm.request_list); - INIT_DELAYED_WORK(&file_priv->mm.idle_work, - i915_gem_file_idle_work_handler); ret = i915_gem_context_open(dev, file); if (ret) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4771d319ac7bc5..efa53d57dd37a9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1262,7 +1262,8 @@ void gen6_update_ring_freq(struct drm_device *dev); void gen6_rps_busy(struct drm_i915_private *dev_priv); void gen6_rps_reset_ei(struct drm_i915_private *dev_priv); void gen6_rps_idle(struct drm_i915_private *dev_priv); -void gen6_rps_boost(struct drm_i915_private *dev_priv); +void gen6_rps_boost(struct drm_i915_private *dev_priv, + struct drm_i915_file_private *file_priv); void intel_queue_rps_boost_for_request(struct drm_device *dev, struct drm_i915_gem_request *rq); void ilk_wm_get_hw_state(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index acf1a318fda900..1ab9e897994aa5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4091,10 +4091,14 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv) dev_priv->rps.last_adj = 0; I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); } + + while (!list_empty(&dev_priv->rps.clients)) + list_del_init(dev_priv->rps.clients.next); mutex_unlock(&dev_priv->rps.hw_lock); } -void gen6_rps_boost(struct drm_i915_private *dev_priv) +void gen6_rps_boost(struct drm_i915_private *dev_priv, + struct drm_i915_file_private *file_priv) { u32 val; @@ -4102,9 +4106,16 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv) val = dev_priv->rps.max_freq_softlimit; if (dev_priv->rps.enabled && dev_priv->mm.busy && - dev_priv->rps.cur_freq < val) { + dev_priv->rps.cur_freq < val && + (file_priv == NULL || list_empty(&file_priv->rps_boost))) { intel_set_rps(dev_priv->dev, val); dev_priv->rps.last_adj = 0; + + if (file_priv != NULL) { + list_add(&file_priv->rps_boost, &dev_priv->rps.clients); + file_priv->rps_boosts++; + } else + dev_priv->rps.boosts++; } mutex_unlock(&dev_priv->rps.hw_lock); } @@ -6782,7 +6793,7 @@ static void __intel_rps_boost_work(struct work_struct *work) struct request_boost *boost = container_of(work, struct request_boost, work); if (!i915_gem_request_completed(boost->rq, true)) - gen6_rps_boost(to_i915(boost->rq->ring->dev)); + gen6_rps_boost(to_i915(boost->rq->ring->dev), NULL); i915_gem_request_unreference__unlocked(boost->rq); kfree(boost); @@ -6815,6 +6826,7 @@ void intel_pm_setup(struct drm_device *dev) INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, intel_gen6_powersave_work); + INIT_LIST_HEAD(&dev_priv->rps.clients); dev_priv->pm.suspended = false; } From 7c27f52509994a874371a0756bee35facf51858b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:33 +0100 Subject: [PATCH 0077/3798] drm/i915: Re-enable RPS wait-boosting for all engines This reverts commit ec5cc0f9b019af95e4571a9fa162d94294c8d90b Author: Chris Wilson Date: Thu Jun 12 10:28:55 2014 +0100 drm/i915: Restrict GPU boost to the RCS engine The premise that media/blitter workloads are not affected by boosting is patently false with a trip through igt. The question that remains is what exactly is going wrong with the media workload that prompted this? Hopefully that would be fixed by the missing agressive downclocking, in addition to the extra restrictions imposed on how frequent a process is allowed to boost. Signed-off-by: Chris Wilson Cc: Deepak S Cc: Daniel Vetter Acked-by: Deepak S Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4061b4ffe81504..35edc8f9309d1f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1222,7 +1222,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req, timeout_expire = timeout ? jiffies + nsecs_to_jiffies_timeout((u64)*timeout) : 0; - if (ring->id == RCS && INTEL_INFO(dev)->gen >= 6) + if (INTEL_INFO(dev)->gen >= 6) gen6_rps_boost(dev_priv, file_priv); if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring))) From ed9ddd25b2055d29e2106da2a6340e2614d71e86 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:34 +0100 Subject: [PATCH 0078/3798] drm/i915: Split i915_gem_batch_pool into its own header In the next patch, I want to use the structure elsewhere and so require it defined earlier. Rather than move the definition to an earlier location where it feels very odd, place it in its own header file. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 13 +------ drivers/gpu/drm/i915/i915_gem_batch_pool.c | 1 + drivers/gpu/drm/i915/i915_gem_batch_pool.h | 42 ++++++++++++++++++++++ 3 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gem_batch_pool.h diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3b6ddd74cd6971..5edacad1a6e00d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -37,6 +37,7 @@ #include "intel_bios.h" #include "intel_ringbuffer.h" #include "intel_lrc.h" +#include "i915_gem_batch_pool.h" #include "i915_gem_gtt.h" #include "i915_gem_render_state.h" #include @@ -1142,11 +1143,6 @@ struct intel_l3_parity { int which_slice; }; -struct i915_gem_batch_pool { - struct drm_device *dev; - struct list_head cache_list; -}; - struct i915_gem_mm { /** Memory allocator for GTT stolen memory */ struct drm_mm stolen; @@ -3064,13 +3060,6 @@ void i915_destroy_error_state(struct drm_device *dev); void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone); const char *i915_cache_level_str(struct drm_i915_private *i915, int type); -/* i915_gem_batch_pool.c */ -void i915_gem_batch_pool_init(struct drm_device *dev, - struct i915_gem_batch_pool *pool); -void i915_gem_batch_pool_fini(struct i915_gem_batch_pool *pool); -struct drm_i915_gem_object* -i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, size_t size); - /* i915_cmd_parser.c */ int i915_cmd_parser_get_version(void); int i915_cmd_parser_init_ring(struct intel_engine_cs *ring); diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c index c690170a1c4fba..564be7c5ea7ea9 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c @@ -23,6 +23,7 @@ */ #include "i915_drv.h" +#include "i915_gem_batch_pool.h" /** * DOC: batch pool diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.h b/drivers/gpu/drm/i915/i915_gem_batch_pool.h new file mode 100644 index 00000000000000..5ed70ef6a88752 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.h @@ -0,0 +1,42 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef I915_GEM_BATCH_POOL_H +#define I915_GEM_BATCH_POOL_H + +#include "i915_drv.h" + +struct i915_gem_batch_pool { + struct drm_device *dev; + struct list_head cache_list; +}; + +/* i915_gem_batch_pool.c */ +void i915_gem_batch_pool_init(struct drm_device *dev, + struct i915_gem_batch_pool *pool); +void i915_gem_batch_pool_fini(struct i915_gem_batch_pool *pool); +struct drm_i915_gem_object* +i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, size_t size); + +#endif /* I915_GEM_BATCH_POOL_H */ From de4e783a3f86f63b03303b463cd7ef885e14b476 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:35 +0100 Subject: [PATCH 0079/3798] drm/i915: Tidy batch pool logic Move the madvise logic out of the execbuffer main path into the relatively rare allocation path, making the execbuffer manipulation less fragile. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_cmd_parser.c | 12 ++----- drivers/gpu/drm/i915/i915_gem_batch_pool.c | 39 +++++++++++----------- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 13 +++----- 3 files changed, 27 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 61ae8ff4eaed99..9605ff8f2fcdf4 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -869,6 +869,9 @@ static u32 *copy_batch(struct drm_i915_gem_object *dest_obj, batch_len + batch_start_offset > src_obj->base.size) return ERR_PTR(-E2BIG); + if (WARN_ON(dest_obj->pages_pin_count == 0)) + return ERR_PTR(-ENODEV); + ret = i915_gem_obj_prepare_shmem_read(src_obj, &needs_clflush); if (ret) { DRM_DEBUG_DRIVER("CMD: failed to prepare shadow batch\n"); @@ -882,13 +885,6 @@ static u32 *copy_batch(struct drm_i915_gem_object *dest_obj, goto unpin_src; } - ret = i915_gem_object_get_pages(dest_obj); - if (ret) { - DRM_DEBUG_DRIVER("CMD: Failed to get pages for shadow batch\n"); - goto unmap_src; - } - i915_gem_object_pin_pages(dest_obj); - ret = i915_gem_object_set_to_cpu_domain(dest_obj, true); if (ret) { DRM_DEBUG_DRIVER("CMD: Failed to set shadow batch to CPU\n"); @@ -898,7 +894,6 @@ static u32 *copy_batch(struct drm_i915_gem_object *dest_obj, dst = vmap_batch(dest_obj, 0, batch_len); if (!dst) { DRM_DEBUG_DRIVER("CMD: Failed to vmap shadow batch\n"); - i915_gem_object_unpin_pages(dest_obj); ret = -ENOMEM; goto unmap_src; } @@ -1129,7 +1124,6 @@ int i915_parse_cmds(struct intel_engine_cs *ring, } vunmap(batch_base); - i915_gem_object_unpin_pages(shadow_batch_obj); return ret; } diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c index 564be7c5ea7ea9..21f3356cc0aba7 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c @@ -67,25 +67,23 @@ void i915_gem_batch_pool_fini(struct i915_gem_batch_pool *pool) struct drm_i915_gem_object, batch_pool_list); - WARN_ON(obj->active); - - list_del_init(&obj->batch_pool_list); + list_del(&obj->batch_pool_list); drm_gem_object_unreference(&obj->base); } } /** - * i915_gem_batch_pool_get() - select a buffer from the pool + * i915_gem_batch_pool_get() - allocate a buffer from the pool * @pool: the batch buffer pool * @size: the minimum desired size of the returned buffer * - * Finds or allocates a batch buffer in the pool with at least the requested - * size. The caller is responsible for any domain, active/inactive, or - * purgeability management for the returned buffer. + * Returns an inactive buffer from @pool with at least @size bytes, + * with the pages pinned. The caller must i915_gem_object_unpin_pages() + * on the returned object. * * Note: Callers must hold the struct_mutex * - * Return: the selected batch buffer object + * Return: the buffer object or an error pointer */ struct drm_i915_gem_object * i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, @@ -97,8 +95,7 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, WARN_ON(!mutex_is_locked(&pool->dev->struct_mutex)); list_for_each_entry_safe(tmp, next, - &pool->cache_list, batch_pool_list) { - + &pool->cache_list, batch_pool_list) { if (tmp->active) continue; @@ -114,25 +111,27 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, * but not 'too much' bigger. A better way to do this * might be to bucket the pool objects based on size. */ - if (tmp->base.size >= size && - tmp->base.size <= (2 * size)) { + if (tmp->base.size >= size && tmp->base.size <= 2 * size) { obj = tmp; break; } } - if (!obj) { + if (obj == NULL) { + int ret; + obj = i915_gem_alloc_object(pool->dev, size); - if (!obj) + if (obj == NULL) return ERR_PTR(-ENOMEM); - list_add_tail(&obj->batch_pool_list, &pool->cache_list); - } - else - /* Keep list in LRU order */ - list_move_tail(&obj->batch_pool_list, &pool->cache_list); + ret = i915_gem_object_get_pages(obj); + if (ret) + return ERR_PTR(ret); - obj->madv = I915_MADV_WILLNEED; + obj->madv = I915_MADV_DONTNEED; + } + list_move_tail(&obj->batch_pool_list, &pool->cache_list); + i915_gem_object_pin_pages(obj); return obj; } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 2522f325e0e6d0..166d53330ee467 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -37,7 +37,6 @@ #define __EXEC_OBJECT_HAS_FENCE (1<<30) #define __EXEC_OBJECT_NEEDS_MAP (1<<29) #define __EXEC_OBJECT_NEEDS_BIAS (1<<28) -#define __EXEC_OBJECT_PURGEABLE (1<<27) #define BATCH_OFFSET_BIAS (256*1024) @@ -224,12 +223,7 @@ i915_gem_execbuffer_unreserve_vma(struct i915_vma *vma) if (entry->flags & __EXEC_OBJECT_HAS_PIN) vma->pin_count--; - if (entry->flags & __EXEC_OBJECT_PURGEABLE) - obj->madv = I915_MADV_DONTNEED; - - entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | - __EXEC_OBJECT_HAS_PIN | - __EXEC_OBJECT_PURGEABLE); + entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN); } static void eb_destroy(struct eb_vmas *eb) @@ -1165,11 +1159,13 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *ring, if (ret) goto err; + i915_gem_object_unpin_pages(shadow_batch_obj); + memset(shadow_exec_entry, 0, sizeof(*shadow_exec_entry)); vma = i915_gem_obj_to_ggtt(shadow_batch_obj); vma->exec_entry = shadow_exec_entry; - vma->exec_entry->flags = __EXEC_OBJECT_PURGEABLE | __EXEC_OBJECT_HAS_PIN; + vma->exec_entry->flags = __EXEC_OBJECT_HAS_PIN; drm_gem_object_reference(&shadow_batch_obj->base); list_add_tail(&vma->exec_list, &eb->vmas); @@ -1178,6 +1174,7 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *ring, return shadow_batch_obj; err: + i915_gem_object_unpin_pages(shadow_batch_obj); if (ret == -EACCES) /* unhandled chained batch */ return batch_obj; else From 06fbca713e8e4a04c3506a64978969be580cd077 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:36 +0100 Subject: [PATCH 0080/3798] drm/i915: Split the batch pool by engine I woke up one morning and found 50k objects sitting in the batch pool and every search seemed to iterate the entire list... Painting the screen in oils would provide a more fluid display. One issue with the current design is that we only check for retirements on the current ring when preparing to submit a new batch. This means that we can have thousands of "active" batches on another ring that we have to walk over. The simplest way to avoid that is to split the pools per ring and then our LRU execution ordering will also ensure that the inactive buffers remain at the front. v2: execlists still requires duplicate code. v3: execlists requires more duplicate code Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 33 +++++++++++++--------- drivers/gpu/drm/i915/i915_dma.c | 1 - drivers/gpu/drm/i915/i915_drv.h | 8 ------ drivers/gpu/drm/i915/i915_gem.c | 2 -- drivers/gpu/drm/i915/i915_gem_batch_pool.c | 3 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 +- drivers/gpu/drm/i915/intel_lrc.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 8 ++++++ 9 files changed, 35 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 9c23eec3277e2a..f610a2cd208810 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -377,13 +377,17 @@ static void print_batch_pool_stats(struct seq_file *m, { struct drm_i915_gem_object *obj; struct file_stats stats; + struct intel_engine_cs *ring; + int i; memset(&stats, 0, sizeof(stats)); - list_for_each_entry(obj, - &dev_priv->mm.batch_pool.cache_list, - batch_pool_list) - per_file_stats(0, obj, &stats); + for_each_ring(ring, dev_priv, i) { + list_for_each_entry(obj, + &ring->batch_pool.cache_list, + batch_pool_list) + per_file_stats(0, obj, &stats); + } print_file_stats(m, "batch pool", stats); } @@ -613,21 +617,24 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj; + struct intel_engine_cs *ring; int count = 0; - int ret; + int ret, i; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; - seq_puts(m, "cache:\n"); - list_for_each_entry(obj, - &dev_priv->mm.batch_pool.cache_list, - batch_pool_list) { - seq_puts(m, " "); - describe_obj(m, obj); - seq_putc(m, '\n'); - count++; + for_each_ring(ring, dev_priv, i) { + seq_printf(m, "%s cache:\n", ring->name); + list_for_each_entry(obj, + &ring->batch_pool.cache_list, + batch_pool_list) { + seq_puts(m, " "); + describe_obj(m, obj); + seq_putc(m, '\n'); + count++; + } } seq_printf(m, "total: %d\n", count); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 68e0c85a17cfcd..8f5428b46a2730 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1072,7 +1072,6 @@ int i915_driver_unload(struct drm_device *dev) mutex_lock(&dev->struct_mutex); i915_gem_cleanup_ringbuffer(dev); - i915_gem_batch_pool_fini(&dev_priv->mm.batch_pool); i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); i915_gem_cleanup_stolen(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5edacad1a6e00d..c839b5771a837e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -37,7 +37,6 @@ #include "intel_bios.h" #include "intel_ringbuffer.h" #include "intel_lrc.h" -#include "i915_gem_batch_pool.h" #include "i915_gem_gtt.h" #include "i915_gem_render_state.h" #include @@ -1156,13 +1155,6 @@ struct i915_gem_mm { */ struct list_head unbound_list; - /* - * A pool of objects to use as shadow copies of client batch buffers - * when the command parser is enabled. Prevents the client from - * modifying the batch contents after software parsing. - */ - struct i915_gem_batch_pool batch_pool; - /** Usable portion of the GTT for GEM */ unsigned long stolen_base; /* limited to low memory (32-bit) */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 35edc8f9309d1f..d1ca192afaccb6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5021,8 +5021,6 @@ i915_gem_load(struct drm_device *dev) i915_gem_shrinker_init(dev_priv); - i915_gem_batch_pool_init(dev, &dev_priv->mm.batch_pool); - mutex_init(&dev_priv->fb_tracking.lock); } diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c index 21f3356cc0aba7..1287abf55b8447 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c @@ -96,8 +96,9 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, list_for_each_entry_safe(tmp, next, &pool->cache_list, batch_pool_list) { + /* The batches are strictly LRU ordered */ if (tmp->active) - continue; + break; /* While we're looping, do some clean up */ if (tmp->madv == __I915_MADV_PURGED) { diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 166d53330ee467..48ac5608481e4b 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1136,12 +1136,11 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *ring, u32 batch_len, bool is_master) { - struct drm_i915_private *dev_priv = to_i915(batch_obj->base.dev); struct drm_i915_gem_object *shadow_batch_obj; struct i915_vma *vma; int ret; - shadow_batch_obj = i915_gem_batch_pool_get(&dev_priv->mm.batch_pool, + shadow_batch_obj = i915_gem_batch_pool_get(&ring->batch_pool, PAGE_ALIGN(batch_len)); if (IS_ERR(shadow_batch_obj)) return shadow_batch_obj; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index cfc73ea59804e6..580248d927105f 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1384,6 +1384,7 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *ring) ring->cleanup(ring); i915_cmd_parser_fini_ring(ring); + i915_gem_batch_pool_fini(&ring->batch_pool); if (ring->status_page.obj) { kunmap(sg_page(ring->status_page.obj->pages->sgl)); @@ -1401,6 +1402,7 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin ring->dev = dev; INIT_LIST_HEAD(&ring->active_list); INIT_LIST_HEAD(&ring->request_list); + i915_gem_batch_pool_init(dev, &ring->batch_pool); init_waitqueue_head(&ring->irq_queue); INIT_LIST_HEAD(&ring->execlist_queue); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b5af9b121ce1f9..1f9463a295a561 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1975,6 +1975,7 @@ static int intel_init_ring_buffer(struct drm_device *dev, INIT_LIST_HEAD(&ring->active_list); INIT_LIST_HEAD(&ring->request_list); INIT_LIST_HEAD(&ring->execlist_queue); + i915_gem_batch_pool_init(dev, &ring->batch_pool); ringbuf->size = 32 * PAGE_SIZE; ringbuf->ring = ring; memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno)); @@ -2053,6 +2054,7 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) cleanup_status_page(ring); i915_cmd_parser_fini_ring(ring); + i915_gem_batch_pool_fini(&ring->batch_pool); kfree(ringbuf); ring->buffer = NULL; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 6566dd4474985e..39f6dfc0ee5491 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -2,6 +2,7 @@ #define _INTEL_RINGBUFFER_H_ #include +#include "i915_gem_batch_pool.h" #define I915_CMD_HASH_ORDER 9 @@ -133,6 +134,13 @@ struct intel_engine_cs { struct drm_device *dev; struct intel_ringbuffer *buffer; + /* + * A pool of objects to use as shadow copies of client batch buffers + * when the command parser is enabled. Prevents the client from + * modifying the batch contents after software parsing. + */ + struct i915_gem_batch_pool batch_pool; + struct intel_hw_status_page status_page; unsigned irq_refcount; /* protected by dev_priv->irq_lock */ From 35c94185c56de950110a09efd5d176292a21360b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:37 +0100 Subject: [PATCH 0081/3798] drm/i915: Free batch pool when idle At runtime, this helps ensure that the batch pools are kept trim and fast. Then at suspend, this releases memory that we do not need to restore. It also ties into the oom-notifier to ensure that we recover as much kernel memory as possible during OOM. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d1ca192afaccb6..4ec5d7e010db90 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2795,8 +2795,19 @@ i915_gem_idle_work_handler(struct work_struct *work) { struct drm_i915_private *dev_priv = container_of(work, typeof(*dev_priv), mm.idle_work.work); + struct drm_device *dev = dev_priv->dev; + + intel_mark_idle(dev); - intel_mark_idle(dev_priv->dev); + if (mutex_trylock(&dev->struct_mutex)) { + struct intel_engine_cs *ring; + int i; + + for_each_ring(ring, dev_priv, i) + i915_gem_batch_pool_fini(&ring->batch_pool); + + mutex_unlock(&dev->struct_mutex); + } } /** From 8d9d5744c6bc861dbd379fee6dd5633a62f85be4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:38 +0100 Subject: [PATCH 0082/3798] drm/i915: Split batch pool into size buckets Now with the trimmed memcpy before the command parser, we try to allocate many different sizes of batches, predominantly one or two pages. We can therefore speed up searching for a good sized batch by keeping the objects of buckets of roughly the same size. v2: Add a comment about bucket sizes Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_debugfs.c | 46 +++++++++++++------- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_batch_pool.c | 49 ++++++++++++++-------- drivers/gpu/drm/i915/i915_gem_batch_pool.h | 2 +- 5 files changed, 64 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index f610a2cd208810..11eebc28775ae6 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -378,15 +378,17 @@ static void print_batch_pool_stats(struct seq_file *m, struct drm_i915_gem_object *obj; struct file_stats stats; struct intel_engine_cs *ring; - int i; + int i, j; memset(&stats, 0, sizeof(stats)); for_each_ring(ring, dev_priv, i) { - list_for_each_entry(obj, - &ring->batch_pool.cache_list, - batch_pool_list) - per_file_stats(0, obj, &stats); + for (j = 0; j < ARRAY_SIZE(ring->batch_pool.cache_list); j++) { + list_for_each_entry(obj, + &ring->batch_pool.cache_list[j], + batch_pool_link) + per_file_stats(0, obj, &stats); + } } print_file_stats(m, "batch pool", stats); @@ -618,26 +620,38 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj; struct intel_engine_cs *ring; - int count = 0; - int ret, i; + int total = 0; + int ret, i, j; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; for_each_ring(ring, dev_priv, i) { - seq_printf(m, "%s cache:\n", ring->name); - list_for_each_entry(obj, - &ring->batch_pool.cache_list, - batch_pool_list) { - seq_puts(m, " "); - describe_obj(m, obj); - seq_putc(m, '\n'); - count++; + for (j = 0; j < ARRAY_SIZE(ring->batch_pool.cache_list); j++) { + int count; + + count = 0; + list_for_each_entry(obj, + &ring->batch_pool.cache_list[j], + batch_pool_link) + count++; + seq_printf(m, "%s cache[%d]: %d objects\n", + ring->name, j, count); + + list_for_each_entry(obj, + &ring->batch_pool.cache_list[j], + batch_pool_link) { + seq_puts(m, " "); + describe_obj(m, obj); + seq_putc(m, '\n'); + } + + total += count; } } - seq_printf(m, "total: %d\n", count); + seq_printf(m, "total: %d\n", total); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c839b5771a837e..6e0a0ae34a3fee 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1910,7 +1910,7 @@ struct drm_i915_gem_object { /** Used in execbuf to temporarily hold a ref */ struct list_head obj_exec_link; - struct list_head batch_pool_list; + struct list_head batch_pool_link; /** * This is set if the object is on the active lists (has pending diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4ec5d7e010db90..8feafe9be1f08c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4409,7 +4409,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, INIT_LIST_HEAD(&obj->ring_list); INIT_LIST_HEAD(&obj->obj_exec_link); INIT_LIST_HEAD(&obj->vma_list); - INIT_LIST_HEAD(&obj->batch_pool_list); + INIT_LIST_HEAD(&obj->batch_pool_link); obj->ops = ops; diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c index 1287abf55b8447..7bf2f3f2968e64 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c @@ -47,8 +47,12 @@ void i915_gem_batch_pool_init(struct drm_device *dev, struct i915_gem_batch_pool *pool) { + int n; + pool->dev = dev; - INIT_LIST_HEAD(&pool->cache_list); + + for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++) + INIT_LIST_HEAD(&pool->cache_list[n]); } /** @@ -59,16 +63,20 @@ void i915_gem_batch_pool_init(struct drm_device *dev, */ void i915_gem_batch_pool_fini(struct i915_gem_batch_pool *pool) { + int n; + WARN_ON(!mutex_is_locked(&pool->dev->struct_mutex)); - while (!list_empty(&pool->cache_list)) { - struct drm_i915_gem_object *obj = - list_first_entry(&pool->cache_list, - struct drm_i915_gem_object, - batch_pool_list); + for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++) { + while (!list_empty(&pool->cache_list[n])) { + struct drm_i915_gem_object *obj = + list_first_entry(&pool->cache_list[n], + struct drm_i915_gem_object, + batch_pool_link); - list_del(&obj->batch_pool_list); - drm_gem_object_unreference(&obj->base); + list_del(&obj->batch_pool_link); + drm_gem_object_unreference(&obj->base); + } } } @@ -91,28 +99,33 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, { struct drm_i915_gem_object *obj = NULL; struct drm_i915_gem_object *tmp, *next; + struct list_head *list; + int n; WARN_ON(!mutex_is_locked(&pool->dev->struct_mutex)); - list_for_each_entry_safe(tmp, next, - &pool->cache_list, batch_pool_list) { + /* Compute a power-of-two bucket, but throw everything greater than + * 16KiB into the same bucket: i.e. the the buckets hold objects of + * (1 page, 2 pages, 4 pages, 8+ pages). + */ + n = fls(size >> PAGE_SHIFT) - 1; + if (n >= ARRAY_SIZE(pool->cache_list)) + n = ARRAY_SIZE(pool->cache_list) - 1; + list = &pool->cache_list[n]; + + list_for_each_entry_safe(tmp, next, list, batch_pool_link) { /* The batches are strictly LRU ordered */ if (tmp->active) break; /* While we're looping, do some clean up */ if (tmp->madv == __I915_MADV_PURGED) { - list_del(&tmp->batch_pool_list); + list_del(&tmp->batch_pool_link); drm_gem_object_unreference(&tmp->base); continue; } - /* - * Select a buffer that is at least as big as needed - * but not 'too much' bigger. A better way to do this - * might be to bucket the pool objects based on size. - */ - if (tmp->base.size >= size && tmp->base.size <= 2 * size) { + if (tmp->base.size >= size) { obj = tmp; break; } @@ -132,7 +145,7 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, obj->madv = I915_MADV_DONTNEED; } - list_move_tail(&obj->batch_pool_list, &pool->cache_list); + list_move_tail(&obj->batch_pool_link, list); i915_gem_object_pin_pages(obj); return obj; } diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.h b/drivers/gpu/drm/i915/i915_gem_batch_pool.h index 5ed70ef6a88752..848e90703eed68 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.h +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.h @@ -29,7 +29,7 @@ struct i915_gem_batch_pool { struct drm_device *dev; - struct list_head cache_list; + struct list_head cache_list[4]; }; /* i915_gem_batch_pool.c */ From 481a3d43b94f30c36746dd7861e8de052cf4c6c9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:39 +0100 Subject: [PATCH 0083/3798] drm/i915: Include active flag when describing objects in debugfs Since we use obj->active as a hint in many places throughout the code, knowing its state in debugfs is extremely useful. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 11eebc28775ae6..e87f031abc995a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -123,8 +123,9 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) struct i915_vma *vma; int pin_count = 0; - seq_printf(m, "%pK: %s%s%s %8zdKiB %02x %02x %x %x %x%s%s%s", + seq_printf(m, "%pK: %s%s%s%s %8zdKiB %02x %02x %x %x %x%s%s%s", &obj->base, + obj->active ? "*" : " ", get_pin_flag(obj), get_tiling_flag(obj), get_global_flag(obj), From b0da1b79aa4136c955710e755857a196a8226a1b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:40 +0100 Subject: [PATCH 0084/3798] drm/i915: Suppress empty lines from debugfs/i915_gem_objects This is just so that I don't have to read about the batch pool on systems that are not using it! Rather than using a newline between the kernel clients and userspace clients, just distinguish the internal allocations with a '[k]' Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e87f031abc995a..fbba5c267f5da9 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -362,16 +362,18 @@ static int per_file_stats(int id, void *ptr, void *data) return 0; } -#define print_file_stats(m, name, stats) \ - seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu global, %zu shared, %zu unbound)\n", \ - name, \ - stats.count, \ - stats.total, \ - stats.active, \ - stats.inactive, \ - stats.global, \ - stats.shared, \ - stats.unbound) +#define print_file_stats(m, name, stats) do { \ + if (stats.count) \ + seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu global, %zu shared, %zu unbound)\n", \ + name, \ + stats.count, \ + stats.total, \ + stats.active, \ + stats.inactive, \ + stats.global, \ + stats.shared, \ + stats.unbound); \ +} while (0) static void print_batch_pool_stats(struct seq_file *m, struct drm_i915_private *dev_priv) @@ -392,7 +394,7 @@ static void print_batch_pool_stats(struct seq_file *m, } } - print_file_stats(m, "batch pool", stats); + print_file_stats(m, "[k]batch pool", stats); } #define count_vmas(list, member) do { \ @@ -478,8 +480,6 @@ static int i915_gem_object_info(struct seq_file *m, void* data) seq_putc(m, '\n'); print_batch_pool_stats(m, dev_priv); - - seq_putc(m, '\n'); list_for_each_entry_reverse(file, &dev->filelist, lhead) { struct file_stats stats; struct task_struct *task; From 94f8cf109e313e7758dff6cbc0357f6b07f83375 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:47 +0100 Subject: [PATCH 0085/3798] drm/i915: Record ring->start address in error state This is mostly useful for execlists where the rings switch between contexts (and so checking that the ring's start register matches the context is important). Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gpu_error.c | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6e0a0ae34a3fee..f4daa3d3c126b6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -455,6 +455,7 @@ struct drm_i915_error_state { u32 semaphore_seqno[I915_NUM_RINGS - 1]; /* Register state */ + u32 start; u32 tail; u32 head; u32 ctl; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 1d4e60df888367..ac22614dbb0ee6 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -251,10 +251,11 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m, return; err_printf(m, "%s command stream:\n", ring_str(ring_idx)); - err_printf(m, " HEAD: 0x%08x\n", ring->head); - err_printf(m, " TAIL: 0x%08x\n", ring->tail); - err_printf(m, " CTL: 0x%08x\n", ring->ctl); - err_printf(m, " HWS: 0x%08x\n", ring->hws); + err_printf(m, " START: 0x%08x\n", ring->start); + err_printf(m, " HEAD: 0x%08x\n", ring->head); + err_printf(m, " TAIL: 0x%08x\n", ring->tail); + err_printf(m, " CTL: 0x%08x\n", ring->ctl); + err_printf(m, " HWS: 0x%08x\n", ring->hws); err_printf(m, " ACTHD: 0x%08x %08x\n", (u32)(ring->acthd>>32), (u32)ring->acthd); err_printf(m, " IPEIR: 0x%08x\n", ring->ipeir); err_printf(m, " IPEHR: 0x%08x\n", ring->ipehr); @@ -883,6 +884,7 @@ static void i915_record_ring_state(struct drm_device *dev, ering->instpm = I915_READ(RING_INSTPM(ring->mmio_base)); ering->seqno = ring->get_seqno(ring, false); ering->acthd = intel_ring_get_active_head(ring); + ering->start = I915_READ_START(ring); ering->head = I915_READ_HEAD(ring); ering->tail = I915_READ_TAIL(ring); ering->ctl = I915_READ_CTL(ring); From ec565b3c1589566a15d20e76def021bf4c17ee6b Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 8 Apr 2015 12:13:23 +0100 Subject: [PATCH 0086/3798] drm/i915: Remove _entry from PPGTT page structures Lets try to keep this consistent: Page Directory Pointer (PDP). Page Directory (PD), also known as page directory pointer entries. Page Table (PT), also known as page directory entries. s/struct i915_page_table_entry/struct i915_page_table/ s/struct i915_page_directory_entry/struct i915_page_directory/ s/struct i915_page_directory_pointer_entry/struct i915_page_directory_pointer/ Suggested-by: Mika Kuoppala Signed-off-by: Michel Thierry Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 56 ++++++++++++++--------------- drivers/gpu/drm/i915/i915_gem_gtt.h | 16 ++++----- drivers/gpu/drm/i915/i915_trace.h | 4 +-- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 0239fbff7bf728..c1a2fab9c7904a 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -320,7 +320,7 @@ static inline int i915_dma_map_page_single(struct page *page, return 0; } -static void unmap_and_free_pt(struct i915_page_table_entry *pt, +static void unmap_and_free_pt(struct i915_page_table *pt, struct drm_device *dev) { if (WARN_ON(!pt->page)) @@ -332,9 +332,9 @@ static void unmap_and_free_pt(struct i915_page_table_entry *pt, kfree(pt); } -static struct i915_page_table_entry *alloc_pt_single(struct drm_device *dev) +static struct i915_page_table *alloc_pt_single(struct drm_device *dev) { - struct i915_page_table_entry *pt; + struct i915_page_table *pt; const size_t count = INTEL_INFO(dev)->gen >= 8 ? GEN8_PTES : GEN6_PTES; int ret = -ENOMEM; @@ -383,7 +383,7 @@ static struct i915_page_table_entry *alloc_pt_single(struct drm_device *dev) * * Return: 0 if allocation succeeded. */ -static int alloc_pt_range(struct i915_page_directory_entry *pd, uint16_t pde, size_t count, +static int alloc_pt_range(struct i915_page_directory *pd, uint16_t pde, size_t count, struct drm_device *dev) { int i, ret; @@ -393,7 +393,7 @@ static int alloc_pt_range(struct i915_page_directory_entry *pd, uint16_t pde, si return -EINVAL; for (i = pde; i < pde + count; i++) { - struct i915_page_table_entry *pt = alloc_pt_single(dev); + struct i915_page_table *pt = alloc_pt_single(dev); if (IS_ERR(pt)) { ret = PTR_ERR(pt); @@ -413,7 +413,7 @@ static int alloc_pt_range(struct i915_page_directory_entry *pd, uint16_t pde, si return ret; } -static void unmap_and_free_pd(struct i915_page_directory_entry *pd) +static void unmap_and_free_pd(struct i915_page_directory *pd) { if (pd->page) { __free_page(pd->page); @@ -421,9 +421,9 @@ static void unmap_and_free_pd(struct i915_page_directory_entry *pd) } } -static struct i915_page_directory_entry *alloc_pd_single(void) +static struct i915_page_directory *alloc_pd_single(void) { - struct i915_page_directory_entry *pd; + struct i915_page_directory *pd; pd = kzalloc(sizeof(*pd), GFP_KERNEL); if (!pd) @@ -497,8 +497,8 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm, I915_CACHE_LLC, use_scratch); while (num_entries) { - struct i915_page_directory_entry *pd; - struct i915_page_table_entry *pt; + struct i915_page_directory *pd; + struct i915_page_table *pt; struct page *page_table; if (WARN_ON(!ppgtt->pdp.page_directory[pdpe])) @@ -559,8 +559,8 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, break; if (pt_vaddr == NULL) { - struct i915_page_directory_entry *pd = ppgtt->pdp.page_directory[pdpe]; - struct i915_page_table_entry *pt = pd->page_table[pde]; + struct i915_page_directory *pd = ppgtt->pdp.page_directory[pdpe]; + struct i915_page_table *pt = pd->page_table[pde]; struct page *page_table = pt->page; pt_vaddr = kmap_atomic(page_table); @@ -588,7 +588,7 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, } } -static void gen8_free_page_tables(struct i915_page_directory_entry *pd, struct drm_device *dev) +static void gen8_free_page_tables(struct i915_page_directory *pd, struct drm_device *dev) { int i; @@ -632,8 +632,8 @@ static void gen8_ppgtt_unmap_pages(struct i915_hw_ppgtt *ppgtt) PCI_DMA_BIDIRECTIONAL); for (j = 0; j < I915_PDES; j++) { - struct i915_page_directory_entry *pd = ppgtt->pdp.page_directory[i]; - struct i915_page_table_entry *pt; + struct i915_page_directory *pd = ppgtt->pdp.page_directory[i]; + struct i915_page_table *pt; dma_addr_t addr; if (WARN_ON(!pd->page_table[j])) @@ -747,8 +747,8 @@ static int gen8_ppgtt_setup_page_tables(struct i915_hw_ppgtt *ppgtt, const int pt) { dma_addr_t pt_addr; - struct i915_page_directory_entry *pdir = ppgtt->pdp.page_directory[pd]; - struct i915_page_table_entry *ptab = pdir->page_table[pt]; + struct i915_page_directory *pdir = ppgtt->pdp.page_directory[pd]; + struct i915_page_table *ptab = pdir->page_table[pt]; struct page *p = ptab->page; int ret; @@ -815,11 +815,11 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) * will never need to touch the PDEs again. */ for (i = 0; i < GEN8_LEGACY_PDPES; i++) { - struct i915_page_directory_entry *pd = ppgtt->pdp.page_directory[i]; + struct i915_page_directory *pd = ppgtt->pdp.page_directory[i]; gen8_pde_t *pd_vaddr; pd_vaddr = kmap_atomic(ppgtt->pdp.page_directory[i]->page); for (j = 0; j < I915_PDES; j++) { - struct i915_page_table_entry *pt = pd->page_table[j]; + struct i915_page_table *pt = pd->page_table[j]; dma_addr_t addr = pt->daddr; pd_vaddr[j] = gen8_pde_encode(ppgtt->base.dev, addr, I915_CACHE_LLC); @@ -914,8 +914,8 @@ static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) } /* Write pde (index) from the page directory @pd to the page table @pt */ -static void gen6_write_pde(struct i915_page_directory_entry *pd, - const int pde, struct i915_page_table_entry *pt) +static void gen6_write_pde(struct i915_page_directory *pd, + const int pde, struct i915_page_table *pt) { /* Caller needs to make sure the write completes if necessary */ struct i915_hw_ppgtt *ppgtt = @@ -931,10 +931,10 @@ static void gen6_write_pde(struct i915_page_directory_entry *pd, /* Write all the page tables found in the ppgtt structure to incrementing page * directories. */ static void gen6_write_page_range(struct drm_i915_private *dev_priv, - struct i915_page_directory_entry *pd, + struct i915_page_directory *pd, uint32_t start, uint32_t length) { - struct i915_page_table_entry *pt; + struct i915_page_table *pt; uint32_t pde, temp; gen6_for_each_pde(pt, pd, start, length, temp, pde) @@ -1169,7 +1169,7 @@ static inline void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt) } static void gen6_initialize_pt(struct i915_address_space *vm, - struct i915_page_table_entry *pt) + struct i915_page_table *pt) { gen6_pte_t *pt_vaddr, scratch_pte; int i; @@ -1195,7 +1195,7 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, struct drm_i915_private *dev_priv = dev->dev_private; struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); - struct i915_page_table_entry *pt; + struct i915_page_table *pt; const uint32_t start_save = start, length_save = length; uint32_t pde, temp; int ret; @@ -1263,7 +1263,7 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, unwind_out: for_each_set_bit(pde, new_page_tables, I915_PDES) { - struct i915_page_table_entry *pt = ppgtt->pd.page_table[pde]; + struct i915_page_table *pt = ppgtt->pd.page_table[pde]; ppgtt->pd.page_table[pde] = ppgtt->scratch_pt; unmap_and_free_pt(pt, vm->dev); @@ -1278,7 +1278,7 @@ static void gen6_ppgtt_free(struct i915_hw_ppgtt *ppgtt) int i; for (i = 0; i < ppgtt->num_pd_entries; i++) { - struct i915_page_table_entry *pt = ppgtt->pd.page_table[i]; + struct i915_page_table *pt = ppgtt->pd.page_table[i]; if (pt != ppgtt->scratch_pt) unmap_and_free_pt(ppgtt->pd.page_table[i], ppgtt->base.dev); @@ -1358,7 +1358,7 @@ static int gen6_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt) static void gen6_scratch_va_range(struct i915_hw_ppgtt *ppgtt, uint64_t start, uint64_t length) { - struct i915_page_table_entry *unused; + struct i915_page_table *unused; uint32_t pde, temp; gen6_for_each_pde(unused, &ppgtt->pd, start, length, temp, pde) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index fc03c99317c94a..1384789673e302 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -206,26 +206,26 @@ struct i915_vma { u32 flags); }; -struct i915_page_table_entry { +struct i915_page_table { struct page *page; dma_addr_t daddr; unsigned long *used_ptes; }; -struct i915_page_directory_entry { +struct i915_page_directory { struct page *page; /* NULL for GEN6-GEN7 */ union { uint32_t pd_offset; dma_addr_t daddr; }; - struct i915_page_table_entry *page_table[I915_PDES]; /* PDEs */ + struct i915_page_table *page_table[I915_PDES]; /* PDEs */ }; -struct i915_page_directory_pointer_entry { +struct i915_page_directory_pointer { /* struct page *page; */ - struct i915_page_directory_entry *page_directory[GEN8_LEGACY_PDPES]; + struct i915_page_directory *page_directory[GEN8_LEGACY_PDPES]; }; struct i915_address_space { @@ -317,11 +317,11 @@ struct i915_hw_ppgtt { unsigned num_pd_entries; unsigned num_pd_pages; /* gen8+ */ union { - struct i915_page_directory_pointer_entry pdp; - struct i915_page_directory_entry pd; + struct i915_page_directory_pointer pdp; + struct i915_page_directory pd; }; - struct i915_page_table_entry *scratch_pt; + struct i915_page_table *scratch_pt; struct drm_i915_file_private *file_priv; diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index b3070a4501ab59..4574f0cc9b1cf1 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -221,7 +221,7 @@ DEFINE_EVENT(i915_page_table_entry, i915_page_table_entry_alloc, DECLARE_EVENT_CLASS(i915_page_table_entry_update, TP_PROTO(struct i915_address_space *vm, u32 pde, - struct i915_page_table_entry *pt, u32 first, u32 count, u32 bits), + struct i915_page_table *pt, u32 first, u32 count, u32 bits), TP_ARGS(vm, pde, pt, first, count, bits), TP_STRUCT__entry( @@ -251,7 +251,7 @@ DECLARE_EVENT_CLASS(i915_page_table_entry_update, DEFINE_EVENT(i915_page_table_entry_update, i915_page_table_entry_map, TP_PROTO(struct i915_address_space *vm, u32 pde, - struct i915_page_table_entry *pt, u32 first, u32 count, u32 bits), + struct i915_page_table *pt, u32 first, u32 count, u32 bits), TP_ARGS(vm, pde, pt, first, count, bits) ); From 9c57f07001f2c093e0455137465242b0bbb6fb66 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 8 Apr 2015 12:13:24 +0100 Subject: [PATCH 0087/3798] drm/i915: Remove unnecessary gen8_ppgtt_unmap_pages We are already unmapping them in gen8_ppgtt_free. This function became redundant since commit 06fda602dbca9c59d87db7da71192e4b54c9f5ff ("drm/i915: Create page table allocators"). Cc: Mika Kuoppala Signed-off-by: Michel Thierry Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 34 ----------------------------- 1 file changed, 34 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index c1a2fab9c7904a..a7d364ae05181e 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -617,44 +617,11 @@ static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt) } } -static void gen8_ppgtt_unmap_pages(struct i915_hw_ppgtt *ppgtt) -{ - struct pci_dev *hwdev = ppgtt->base.dev->pdev; - int i, j; - - for (i = 0; i < ppgtt->num_pd_pages; i++) { - /* TODO: In the future we'll support sparse mappings, so this - * will have to change. */ - if (!ppgtt->pdp.page_directory[i]->daddr) - continue; - - pci_unmap_page(hwdev, ppgtt->pdp.page_directory[i]->daddr, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - - for (j = 0; j < I915_PDES; j++) { - struct i915_page_directory *pd = ppgtt->pdp.page_directory[i]; - struct i915_page_table *pt; - dma_addr_t addr; - - if (WARN_ON(!pd->page_table[j])) - continue; - - pt = pd->page_table[j]; - addr = pt->daddr; - - if (addr) - pci_unmap_page(hwdev, addr, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - } - } -} - static void gen8_ppgtt_cleanup(struct i915_address_space *vm) { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); - gen8_ppgtt_unmap_pages(ppgtt); gen8_ppgtt_free(ppgtt); } @@ -851,7 +818,6 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) return 0; bail: - gen8_ppgtt_unmap_pages(ppgtt); gen8_ppgtt_free(ppgtt); return ret; } From 5a8e9943528dd84315db2e9dfd7330bcbb872414 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 8 Apr 2015 12:13:25 +0100 Subject: [PATCH 0088/3798] drm/i915/gen8: Initialize page tables Similar to gen6, while setting up a page table, make all entries of the pt point to the scratch page before mapping; this is to be safe in case of out of bound access or proactive prefetch. Systems without LLC require an explicit flush. v2: Expanded commit text and fixed indentation (Mika) Signed-off-by: Michel Thierry Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index a7d364ae05181e..c2045bd45e5e62 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -332,6 +332,24 @@ static void unmap_and_free_pt(struct i915_page_table *pt, kfree(pt); } +static void gen8_initialize_pt(struct i915_address_space *vm, + struct i915_page_table *pt) +{ + gen8_pte_t *pt_vaddr, scratch_pte; + int i; + + pt_vaddr = kmap_atomic(pt->page); + scratch_pte = gen8_pte_encode(vm->scratch.addr, + I915_CACHE_LLC, true); + + for (i = 0; i < GEN8_PTES; i++) + pt_vaddr[i] = scratch_pte; + + if (!HAS_LLC(vm->dev)) + drm_clflush_virt_range(pt_vaddr, PAGE_SIZE); + kunmap_atomic(pt_vaddr); +} + static struct i915_page_table *alloc_pt_single(struct drm_device *dev) { struct i915_page_table *pt; @@ -429,7 +447,7 @@ static struct i915_page_directory *alloc_pd_single(void) if (!pd) return ERR_PTR(-ENOMEM); - pd->page = alloc_page(GFP_KERNEL | __GFP_ZERO); + pd->page = alloc_page(GFP_KERNEL); if (!pd->page) { kfree(pd); return ERR_PTR(-ENOMEM); @@ -719,6 +737,8 @@ static int gen8_ppgtt_setup_page_tables(struct i915_hw_ppgtt *ppgtt, struct page *p = ptab->page; int ret; + gen8_initialize_pt(&ppgtt->base, ptab); + pt_addr = pci_map_page(ppgtt->base.dev->pdev, p, 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); ret = pci_dma_mapping_error(ppgtt->base.dev->pdev, pt_addr); From 9271d959dc03fc7514030e22280cdbd6ca763ca5 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 8 Apr 2015 12:13:26 +0100 Subject: [PATCH 0089/3798] drm/i915/gen8: Add dynamic allocation macros and helper functions Similar to gen6, we will use for_each_pde/for_each_pdpe and pte/pde/pdpe_index to iterate over these new structures. v2: Match trace_i915_va_teardown params v3: Multiple rebases. v4: Updated to use unmap_and_free_pt. v5: teardown_va_range logic no longer needed. v6: Rebase after s/page_tables/page_table/. v7: Renamed commit to match what it does now (it was "Use dynamic allocation idioms on free"). v8: Prevent (harmless) out of range access in gen8_for_each_pde and gen8_for_each_pdpe_e. Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Reviewed-by: Mika Kuoppala [danvet: s/BUG/WARN/] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.h | 52 +++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 1384789673e302..63fda82452ec98 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -397,6 +397,58 @@ static inline uint32_t gen6_pde_index(uint32_t addr) return i915_pde_index(addr, GEN6_PDE_SHIFT); } +/* Equivalent to the gen6 version, For each pde iterates over every pde + * between from start until start + length. On gen8+ it simply iterates + * over every page directory entry in a page directory. + */ +#define gen8_for_each_pde(pt, pd, start, length, temp, iter) \ + for (iter = gen8_pde_index(start); \ + pt = (pd)->page_table[iter], length > 0 && iter < I915_PDES; \ + iter++, \ + temp = ALIGN(start+1, 1 << GEN8_PDE_SHIFT) - start, \ + temp = min(temp, length), \ + start += temp, length -= temp) + +#define gen8_for_each_pdpe(pd, pdp, start, length, temp, iter) \ + for (iter = gen8_pdpe_index(start); \ + pd = (pdp)->page_directory[iter], length > 0 && iter < GEN8_LEGACY_PDPES; \ + iter++, \ + temp = ALIGN(start+1, 1 << GEN8_PDPE_SHIFT) - start, \ + temp = min(temp, length), \ + start += temp, length -= temp) + +/* Clamp length to the next page_directory boundary */ +static inline uint64_t gen8_clamp_pd(uint64_t start, uint64_t length) +{ + uint64_t next_pd = ALIGN(start + 1, 1 << GEN8_PDPE_SHIFT); + + if (next_pd > (start + length)) + return length; + + return next_pd - start; +} + +static inline uint32_t gen8_pte_index(uint64_t address) +{ + return i915_pte_index(address, GEN8_PDE_SHIFT); +} + +static inline uint32_t gen8_pde_index(uint64_t address) +{ + return i915_pde_index(address, GEN8_PDE_SHIFT); +} + +static inline uint32_t gen8_pdpe_index(uint64_t address) +{ + return (address >> GEN8_PDPE_SHIFT) & GEN8_PDPE_MASK; +} + +static inline uint32_t gen8_pml4e_index(uint64_t address) +{ + WARN_ON(1); /* For 64B */ + return 0; +} + int i915_gem_gtt_init(struct drm_device *dev); void i915_gem_init_global_gtt(struct drm_device *dev); void i915_global_gtt_cleanup(struct drm_device *dev); From 69876bed7e008f5fe01538a2d47c09f2862129d0 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 8 Apr 2015 12:13:27 +0100 Subject: [PATCH 0090/3798] drm/i915/gen8: page directories rework allocation Start using gen8_for_each_pdpe macro to allocate the page directories. Similar to PTs, while setting up a page directory, make all entries of the pd point to the scratch pd before mapping (and make all its entries point to the scratch page); this is to be safe in case of out of bound access or proactive prefetch. Systems without LLC require an explicit flush. v2: Rebased after s/free_pt_*/unmap_and_free_pt/ change. v3: Rebased after teardown va range logic was removed. v4: Keep setting up all page directories for systems with less than 4GB of memory. v5: Initialize PDs. (Mika) v6: Initialize also the extra PDs from systems with less than 4GB of memory. (Mika) Cc: Mika Kuoppala Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 100 +++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index c2045bd45e5e62..e5770189ebff3b 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -606,6 +606,36 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, } } +static void __gen8_do_map_pt(gen8_pde_t * const pde, + struct i915_page_table *pt, + struct drm_device *dev) +{ + gen8_pde_t entry = + gen8_pde_encode(dev, pt->daddr, I915_CACHE_LLC); + *pde = entry; +} + +static void gen8_initialize_pd(struct i915_address_space *vm, + struct i915_page_directory *pd) +{ + struct i915_hw_ppgtt *ppgtt = + container_of(vm, struct i915_hw_ppgtt, base); + gen8_pde_t *page_directory; + struct i915_page_table *pt; + int i; + + page_directory = kmap_atomic(pd->page); + pt = ppgtt->scratch_pt; + for (i = 0; i < I915_PDES; i++) + /* Map the PDE to the page table */ + __gen8_do_map_pt(page_directory + i, pt, vm->dev); + + if (!HAS_LLC(vm->dev)) + drm_clflush_virt_range(page_directory, PAGE_SIZE); + + kunmap_atomic(page_directory); +} + static void gen8_free_page_tables(struct i915_page_directory *pd, struct drm_device *dev) { int i; @@ -633,6 +663,8 @@ static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt) gen8_free_page_tables(ppgtt->pdp.page_directory[i], ppgtt->base.dev); unmap_and_free_pd(ppgtt->pdp.page_directory[i]); } + + unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev); } static void gen8_ppgtt_cleanup(struct i915_address_space *vm) @@ -663,25 +695,55 @@ static int gen8_ppgtt_allocate_page_tables(struct i915_hw_ppgtt *ppgtt) return -ENOMEM; } -static int gen8_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt, - const int max_pdp) +static int gen8_ppgtt_alloc_page_directories(struct i915_page_directory_pointer *pdp, + uint64_t start, + uint64_t length) { - int i; + struct i915_hw_ppgtt *ppgtt = + container_of(pdp, struct i915_hw_ppgtt, pdp); + struct i915_page_directory *unused; + uint64_t temp; + uint32_t pdpe; + + /* FIXME: PPGTT container_of won't work for 64b */ + WARN_ON((start + length) > 0x800000000ULL); + + gen8_for_each_pdpe(unused, pdp, start, length, temp, pdpe) { + WARN_ON(unused); + pdp->page_directory[pdpe] = alloc_pd_single(); + if (IS_ERR(ppgtt->pdp.page_directory[pdpe])) + goto unwind_out; + + gen8_initialize_pd(&ppgtt->base, + ppgtt->pdp.page_directory[pdpe]); + ppgtt->num_pd_pages++; + } - for (i = 0; i < max_pdp; i++) { - ppgtt->pdp.page_directory[i] = alloc_pd_single(); - if (IS_ERR(ppgtt->pdp.page_directory[i])) + /* XXX: Still alloc all page directories in systems with less than + * 4GB of memory. This won't be needed after a subsequent patch. + */ + while (ppgtt->num_pd_pages < GEN8_LEGACY_PDPES) { + ppgtt->pdp.page_directory[ppgtt->num_pd_pages] = alloc_pd_single(); + if (IS_ERR(ppgtt->pdp.page_directory[ppgtt->num_pd_pages])) goto unwind_out; + + gen8_initialize_pd(&ppgtt->base, + ppgtt->pdp.page_directory[ppgtt->num_pd_pages]); + pdpe++; + ppgtt->num_pd_pages++; } - ppgtt->num_pd_pages = max_pdp; BUG_ON(ppgtt->num_pd_pages > GEN8_LEGACY_PDPES); return 0; unwind_out: - while (i--) - unmap_and_free_pd(ppgtt->pdp.page_directory[i]); + while (pdpe--) { + unmap_and_free_pd(ppgtt->pdp.page_directory[pdpe]); + ppgtt->num_pd_pages--; + } + + WARN_ON(ppgtt->num_pd_pages); return -ENOMEM; } @@ -691,7 +753,8 @@ static int gen8_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt, { int ret; - ret = gen8_ppgtt_allocate_page_directories(ppgtt, max_pdp); + ret = gen8_ppgtt_alloc_page_directories(&ppgtt->pdp, ppgtt->base.start, + ppgtt->base.total); if (ret) return ret; @@ -769,6 +832,17 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) if (size % (1<<30)) DRM_INFO("Pages will be wasted unless GTT size (%llu) is divisible by 1GB\n", size); + ppgtt->base.start = 0; + /* This is the area that we advertise as usable for the caller */ + ppgtt->base.total = max_pdp * I915_PDES * GEN8_PTES * PAGE_SIZE; + WARN_ON(ppgtt->base.total == 0); + + ppgtt->scratch_pt = alloc_pt_single(ppgtt->base.dev); + if (IS_ERR(ppgtt->scratch_pt)) + return PTR_ERR(ppgtt->scratch_pt); + + gen8_initialize_pt(&ppgtt->base, ppgtt->scratch_pt); + /* 1. Do all our allocations for page directories and page tables. * We allocate more than was asked so that we can point the unused parts * to valid entries that point to scratch page. Dynamic page tables @@ -794,7 +868,7 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) } /* - * 3. Map all the page directory entires to point to the page tables + * 3. Map all the page directory entries to point to the page tables * we've allocated. * * For now, the PPGTT helper functions all require that the PDEs are @@ -820,10 +894,6 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) ppgtt->base.clear_range = gen8_ppgtt_clear_range; ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; ppgtt->base.cleanup = gen8_ppgtt_cleanup; - ppgtt->base.start = 0; - - /* This is the area that we advertise as usable for the caller */ - ppgtt->base.total = max_pdp * I915_PDES * GEN8_PTES * PAGE_SIZE; /* Set all ptes to a valid scratch page. Also above requested space */ ppgtt->base.clear_range(&ppgtt->base, 0, From 5441f0cbe119496c36fd1c7a7971ecd0e0578ca6 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 8 Apr 2015 12:13:28 +0100 Subject: [PATCH 0091/3798] drm/i915/gen8: pagetable allocation rework Start using gen8_for_each_pde macro to allocate page tables. v2: teardown_va_range references removed. v3: Rebase after s/page_tables/page_table/. v4: Keep setting up page tables for all page directories in systems with less than 4GB of memory. v5: Also initialize the page tables. (Mika) v6: Initialize all page tables, including the extra ones from systems with less than 4GB of memory. (Mika) Cc: Mika Kuoppala Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 83 ++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index e5770189ebff3b..aad3d6ffbabc0c 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -675,22 +675,41 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) gen8_ppgtt_free(ppgtt); } -static int gen8_ppgtt_allocate_page_tables(struct i915_hw_ppgtt *ppgtt) +static int gen8_ppgtt_alloc_pagetabs(struct i915_page_directory *pd, + uint64_t start, + uint64_t length, + struct i915_address_space *vm) { - int i, ret; + struct i915_page_table *unused; + uint64_t temp; + uint32_t pde; - for (i = 0; i < ppgtt->num_pd_pages; i++) { - ret = alloc_pt_range(ppgtt->pdp.page_directory[i], - 0, I915_PDES, ppgtt->base.dev); - if (ret) + gen8_for_each_pde(unused, pd, start, length, temp, pde) { + WARN_ON(unused); + pd->page_table[pde] = alloc_pt_single(vm->dev); + if (IS_ERR(pd->page_table[pde])) + goto unwind_out; + + gen8_initialize_pt(vm, pd->page_table[pde]); + } + + /* XXX: Still alloc all page tables in systems with less than + * 4GB of memory. This won't be needed after a subsequent patch. + */ + while (pde < I915_PDES) { + pd->page_table[pde] = alloc_pt_single(vm->dev); + if (IS_ERR(pd->page_table[pde])) goto unwind_out; + + gen8_initialize_pt(vm, pd->page_table[pde]); + pde++; } return 0; unwind_out: - while (i--) - gen8_free_page_tables(ppgtt->pdp.page_directory[i], ppgtt->base.dev); + while (pde--) + unmap_and_free_pt(pd->page_table[pde], vm->dev); return -ENOMEM; } @@ -749,20 +768,42 @@ static int gen8_ppgtt_alloc_page_directories(struct i915_page_directory_pointer } static int gen8_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt, - const int max_pdp) + uint64_t start, + uint64_t length) { + struct i915_page_directory *pd; + uint64_t temp; + uint32_t pdpe; int ret; - ret = gen8_ppgtt_alloc_page_directories(&ppgtt->pdp, ppgtt->base.start, - ppgtt->base.total); + ret = gen8_ppgtt_alloc_page_directories(&ppgtt->pdp, start, length); if (ret) return ret; - ret = gen8_ppgtt_allocate_page_tables(ppgtt); - if (ret) - goto err_out; + gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) { + ret = gen8_ppgtt_alloc_pagetabs(pd, start, length, + &ppgtt->base); + if (ret) + goto err_out; + + ppgtt->num_pd_entries += I915_PDES; + } - ppgtt->num_pd_entries = max_pdp * I915_PDES; + /* XXX: We allocated all page directories in systems with less than + * 4GB of memory. So initalize page tables of all PDPs. + * This won't be needed after the next patch. + */ + while (pdpe < GEN8_LEGACY_PDPES) { + ret = gen8_ppgtt_alloc_pagetabs(ppgtt->pdp.page_directory[pdpe], start, length, + &ppgtt->base); + if (ret) + goto err_out; + + ppgtt->num_pd_entries += I915_PDES; + pdpe++; + } + + WARN_ON(pdpe > ppgtt->num_pd_pages); return 0; @@ -833,9 +874,7 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) DRM_INFO("Pages will be wasted unless GTT size (%llu) is divisible by 1GB\n", size); ppgtt->base.start = 0; - /* This is the area that we advertise as usable for the caller */ - ppgtt->base.total = max_pdp * I915_PDES * GEN8_PTES * PAGE_SIZE; - WARN_ON(ppgtt->base.total == 0); + ppgtt->base.total = size; ppgtt->scratch_pt = alloc_pt_single(ppgtt->base.dev); if (IS_ERR(ppgtt->scratch_pt)) @@ -843,12 +882,8 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) gen8_initialize_pt(&ppgtt->base, ppgtt->scratch_pt); - /* 1. Do all our allocations for page directories and page tables. - * We allocate more than was asked so that we can point the unused parts - * to valid entries that point to scratch page. Dynamic page tables - * will fix this eventually. - */ - ret = gen8_ppgtt_alloc(ppgtt, GEN8_LEGACY_PDPES); + /* 1. Do all our allocations for page directories and page tables. */ + ret = gen8_ppgtt_alloc(ppgtt, ppgtt->base.start, ppgtt->base.total); if (ret) return ret; From 7cb6d7ac635ab0c80607e6ffaf8682d48752523f Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 8 Apr 2015 12:13:29 +0100 Subject: [PATCH 0092/3798] drm/i915/gen8: Update pdp switch and point unused PDPs to scratch page One important part of this patch is we now write a scratch page directory into any unused PDP descriptors. This matters for 2 reasons, first, we're not allowed to just use 0, or an invalid pointer, and second, we must wipe out any previous contents from the last context. The latter point only matters with full PPGTT. The former point only effect platforms with less than 4GB memory. v2: Updated commit message to point that we must set unused PDPs to the scratch page. v3: Unmap scratch_pd in gen8_ppgtt_free. v4: Initialize scratch_pd. (Mika) Cc: Mika Kuoppala Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 32 +++++++++++++++++++---------- drivers/gpu/drm/i915/i915_gem_gtt.h | 1 + 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index aad3d6ffbabc0c..4b91cc18eef38f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -457,8 +457,9 @@ static struct i915_page_directory *alloc_pd_single(void) } /* Broadwell Page Directory Pointer Descriptors */ -static int gen8_write_pdp(struct intel_engine_cs *ring, unsigned entry, - uint64_t val) +static int gen8_write_pdp(struct intel_engine_cs *ring, + unsigned entry, + dma_addr_t addr) { int ret; @@ -470,10 +471,10 @@ static int gen8_write_pdp(struct intel_engine_cs *ring, unsigned entry, intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); intel_ring_emit(ring, GEN8_RING_PDP_UDW(ring, entry)); - intel_ring_emit(ring, (u32)(val >> 32)); + intel_ring_emit(ring, upper_32_bits(addr)); intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); intel_ring_emit(ring, GEN8_RING_PDP_LDW(ring, entry)); - intel_ring_emit(ring, (u32)(val)); + intel_ring_emit(ring, lower_32_bits(addr)); intel_ring_advance(ring); return 0; @@ -484,12 +485,12 @@ static int gen8_mm_switch(struct i915_hw_ppgtt *ppgtt, { int i, ret; - /* bit of a hack to find the actual last used pd */ - int used_pd = ppgtt->num_pd_entries / I915_PDES; - - for (i = used_pd - 1; i >= 0; i--) { - dma_addr_t addr = ppgtt->pdp.page_directory[i]->daddr; - ret = gen8_write_pdp(ring, i, addr); + for (i = GEN8_LEGACY_PDPES - 1; i >= 0; i--) { + struct i915_page_directory *pd = ppgtt->pdp.page_directory[i]; + dma_addr_t pd_daddr = pd ? pd->daddr : ppgtt->scratch_pd->daddr; + /* The page directory might be NULL, but we need to clear out + * whatever the previous context might have used. */ + ret = gen8_write_pdp(ring, i, pd_daddr); if (ret) return ret; } @@ -664,6 +665,7 @@ static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt) unmap_and_free_pd(ppgtt->pdp.page_directory[i]); } + unmap_and_free_pd(ppgtt->scratch_pd); unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev); } @@ -880,12 +882,20 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) if (IS_ERR(ppgtt->scratch_pt)) return PTR_ERR(ppgtt->scratch_pt); + ppgtt->scratch_pd = alloc_pd_single(); + if (IS_ERR(ppgtt->scratch_pd)) + return PTR_ERR(ppgtt->scratch_pd); + gen8_initialize_pt(&ppgtt->base, ppgtt->scratch_pt); + gen8_initialize_pd(&ppgtt->base, ppgtt->scratch_pd); /* 1. Do all our allocations for page directories and page tables. */ ret = gen8_ppgtt_alloc(ppgtt, ppgtt->base.start, ppgtt->base.total); - if (ret) + if (ret) { + unmap_and_free_pd(ppgtt->scratch_pd); + unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev); return ret; + } /* * 2. Create DMA mappings for the page directories and page tables. diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 63fda82452ec98..acf8ed7f86ef1d 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -322,6 +322,7 @@ struct i915_hw_ppgtt { }; struct i915_page_table *scratch_pt; + struct i915_page_directory *scratch_pd; struct drm_i915_file_private *file_priv; From 09942c656b7f857e3fd875a20f5967d316a20c73 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 8 Apr 2015 12:13:30 +0100 Subject: [PATCH 0093/3798] drm/i915: num_pd_pages/num_pd_entries isn't useful These values are never quite useful for dynamic allocations of the page tables. Getting rid of them will help prevent later confusion. v2: Updated to use unmap_and_free_pd functions. v3: Updated gen8_ppgtt_free after teardown logic was removed. v4: Rebase after s/page_tables/page_table/. v5: Keep allocating all page directories in GEN8+ systems with less than 4GB of memory. Updated gen6_for_all_pdes. v6: Prevent (harmless) out of range access in gen6_for_all_pdes. Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 2 - drivers/gpu/drm/i915/i915_gem_gtt.c | 68 ++++++++--------------------- drivers/gpu/drm/i915/i915_gem_gtt.h | 7 ++- 3 files changed, 23 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index fbba5c267f5da9..e890728144b4c0 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2188,8 +2188,6 @@ static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev) if (!ppgtt) return; - seq_printf(m, "Page directories: %d\n", ppgtt->num_pd_pages); - seq_printf(m, "Page tables: %d\n", ppgtt->num_pd_entries); for_each_ring(ring, dev_priv, unused) { seq_printf(m, "%s\n", ring->name); for (i = 0; i < 4; i++) { diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 4b91cc18eef38f..c5ec35ac07335a 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -657,7 +657,7 @@ static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt) { int i; - for (i = 0; i < ppgtt->num_pd_pages; i++) { + for (i = 0; i < GEN8_LEGACY_PDPES; i++) { if (WARN_ON(!ppgtt->pdp.page_directory[i])) continue; @@ -737,34 +737,26 @@ static int gen8_ppgtt_alloc_page_directories(struct i915_page_directory_pointer gen8_initialize_pd(&ppgtt->base, ppgtt->pdp.page_directory[pdpe]); - ppgtt->num_pd_pages++; } /* XXX: Still alloc all page directories in systems with less than * 4GB of memory. This won't be needed after a subsequent patch. */ - while (ppgtt->num_pd_pages < GEN8_LEGACY_PDPES) { - ppgtt->pdp.page_directory[ppgtt->num_pd_pages] = alloc_pd_single(); - if (IS_ERR(ppgtt->pdp.page_directory[ppgtt->num_pd_pages])) + while (pdpe < GEN8_LEGACY_PDPES) { + ppgtt->pdp.page_directory[pdpe] = alloc_pd_single(); + if (IS_ERR(ppgtt->pdp.page_directory[pdpe])) goto unwind_out; gen8_initialize_pd(&ppgtt->base, - ppgtt->pdp.page_directory[ppgtt->num_pd_pages]); + ppgtt->pdp.page_directory[pdpe]); pdpe++; - ppgtt->num_pd_pages++; } - BUG_ON(ppgtt->num_pd_pages > GEN8_LEGACY_PDPES); - return 0; unwind_out: - while (pdpe--) { + while (pdpe--) unmap_and_free_pd(ppgtt->pdp.page_directory[pdpe]); - ppgtt->num_pd_pages--; - } - - WARN_ON(ppgtt->num_pd_pages); return -ENOMEM; } @@ -787,8 +779,6 @@ static int gen8_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt, &ppgtt->base); if (ret) goto err_out; - - ppgtt->num_pd_entries += I915_PDES; } /* XXX: We allocated all page directories in systems with less than @@ -801,12 +791,9 @@ static int gen8_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt, if (ret) goto err_out; - ppgtt->num_pd_entries += I915_PDES; pdpe++; } - WARN_ON(pdpe > ppgtt->num_pd_pages); - return 0; err_out: @@ -868,8 +855,6 @@ static int gen8_ppgtt_setup_page_tables(struct i915_hw_ppgtt *ppgtt, */ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) { - const int max_pdp = DIV_ROUND_UP(size, 1 << 30); - const int min_pt_pages = I915_PDES * max_pdp; int i, j, ret; if (size % (1<<30)) @@ -940,16 +925,7 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; ppgtt->base.cleanup = gen8_ppgtt_cleanup; - /* Set all ptes to a valid scratch page. Also above requested space */ - ppgtt->base.clear_range(&ppgtt->base, 0, - ppgtt->num_pd_pages * GEN8_PTES * PAGE_SIZE, - true); - - DRM_DEBUG_DRIVER("Allocated %d pages for page directories (%d wasted)\n", - ppgtt->num_pd_pages, ppgtt->num_pd_pages - max_pdp); - DRM_DEBUG_DRIVER("Allocated %d pages for page tables (%lld wasted)\n", - ppgtt->num_pd_entries, - (ppgtt->num_pd_entries - min_pt_pages) + size % (1<<30)); + ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true); return 0; bail: @@ -959,26 +935,20 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) { - struct drm_i915_private *dev_priv = ppgtt->base.dev->dev_private; struct i915_address_space *vm = &ppgtt->base; - gen6_pte_t __iomem *pd_addr; + struct i915_page_table *unused; gen6_pte_t scratch_pte; uint32_t pd_entry; - int pte, pde; + uint32_t pte, pde, temp; + uint32_t start = ppgtt->base.start, length = ppgtt->base.total; scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true, 0); - pd_addr = (gen6_pte_t __iomem *)dev_priv->gtt.gsm + - ppgtt->pd.pd_offset / sizeof(gen6_pte_t); - - seq_printf(m, " VM %p (pd_offset %x-%x):\n", vm, - ppgtt->pd.pd_offset, - ppgtt->pd.pd_offset + ppgtt->num_pd_entries); - for (pde = 0; pde < ppgtt->num_pd_entries; pde++) { + gen6_for_each_pde(unused, &ppgtt->pd, start, length, temp, pde) { u32 expected; gen6_pte_t *pt_vaddr; dma_addr_t pt_addr = ppgtt->pd.page_table[pde]->daddr; - pd_entry = readl(pd_addr + pde); + pd_entry = readl(ppgtt->pd_addr + pde); expected = (GEN6_PDE_ADDR_ENCODE(pt_addr) | GEN6_PDE_VALID); if (pd_entry != expected) @@ -1376,13 +1346,12 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, static void gen6_ppgtt_free(struct i915_hw_ppgtt *ppgtt) { - int i; - - for (i = 0; i < ppgtt->num_pd_entries; i++) { - struct i915_page_table *pt = ppgtt->pd.page_table[i]; + struct i915_page_table *pt; + uint32_t pde; + gen6_for_all_pdes(pt, ppgtt, pde) { if (pt != ppgtt->scratch_pt) - unmap_and_free_pt(ppgtt->pd.page_table[i], ppgtt->base.dev); + unmap_and_free_pt(pt, ppgtt->base.dev); } unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev); @@ -1443,7 +1412,6 @@ static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt) if (ppgtt->node.start < dev_priv->gtt.mappable_end) DRM_DEBUG("Forced to use aperture for PDEs\n"); - ppgtt->num_pd_entries = I915_PDES; return 0; err_out: @@ -1491,7 +1459,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing) if (aliasing) { /* preallocate all pts */ - ret = alloc_pt_range(&ppgtt->pd, 0, ppgtt->num_pd_entries, + ret = alloc_pt_range(&ppgtt->pd, 0, I915_PDES, ppgtt->base.dev); if (ret) { @@ -1505,7 +1473,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing) ppgtt->base.insert_entries = gen6_ppgtt_insert_entries; ppgtt->base.cleanup = gen6_ppgtt_cleanup; ppgtt->base.start = 0; - ppgtt->base.total = ppgtt->num_pd_entries * GEN6_PTES * PAGE_SIZE; + ppgtt->base.total = I915_PDES * GEN6_PTES * PAGE_SIZE; ppgtt->debug_dump = gen6_dump_ppgtt; ppgtt->pd.pd_offset = diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index acf8ed7f86ef1d..c3d5d40b78b260 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -314,8 +314,6 @@ struct i915_hw_ppgtt { struct kref ref; struct drm_mm_node node; unsigned long pd_dirty_rings; - unsigned num_pd_entries; - unsigned num_pd_pages; /* gen8+ */ union { struct i915_page_directory_pointer pdp; struct i915_page_directory pd; @@ -350,6 +348,11 @@ struct i915_hw_ppgtt { temp = min_t(unsigned, temp, length), \ start += temp, length -= temp) +#define gen6_for_all_pdes(pt, ppgtt, iter) \ + for (iter = 0; \ + pt = ppgtt->pd.page_table[iter], iter < I915_PDES; \ + iter++) + static inline uint32_t i915_pte_index(uint64_t address, uint32_t pde_shift) { const uint32_t mask = NUM_PTE(pde_shift) - 1; From c488dbbaa7626e510c3d2560e9aa2ddc45fb1e99 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 8 Apr 2015 12:13:31 +0100 Subject: [PATCH 0094/3798] drm/i915: Extract PPGTT param from page_directory alloc This will be useful for when we move to 48b addressing, and the PDP isn't the root of the page table structure. v2: Rebase after changes for Gen8+ systems with less than 4GB of memory. v3: Rebase after Mika's code review. Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2) Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index c5ec35ac07335a..539060b8b66a19 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -716,12 +716,11 @@ static int gen8_ppgtt_alloc_pagetabs(struct i915_page_directory *pd, return -ENOMEM; } -static int gen8_ppgtt_alloc_page_directories(struct i915_page_directory_pointer *pdp, +static int gen8_ppgtt_alloc_page_directories(struct i915_hw_ppgtt *ppgtt, + struct i915_page_directory_pointer *pdp, uint64_t start, uint64_t length) { - struct i915_hw_ppgtt *ppgtt = - container_of(pdp, struct i915_hw_ppgtt, pdp); struct i915_page_directory *unused; uint64_t temp; uint32_t pdpe; @@ -732,7 +731,7 @@ static int gen8_ppgtt_alloc_page_directories(struct i915_page_directory_pointer gen8_for_each_pdpe(unused, pdp, start, length, temp, pdpe) { WARN_ON(unused); pdp->page_directory[pdpe] = alloc_pd_single(); - if (IS_ERR(ppgtt->pdp.page_directory[pdpe])) + if (IS_ERR(pdp->page_directory[pdpe])) goto unwind_out; gen8_initialize_pd(&ppgtt->base, @@ -743,8 +742,8 @@ static int gen8_ppgtt_alloc_page_directories(struct i915_page_directory_pointer * 4GB of memory. This won't be needed after a subsequent patch. */ while (pdpe < GEN8_LEGACY_PDPES) { - ppgtt->pdp.page_directory[pdpe] = alloc_pd_single(); - if (IS_ERR(ppgtt->pdp.page_directory[pdpe])) + pdp->page_directory[pdpe] = alloc_pd_single(); + if (IS_ERR(pdp->page_directory[pdpe])) goto unwind_out; gen8_initialize_pd(&ppgtt->base, @@ -756,7 +755,7 @@ static int gen8_ppgtt_alloc_page_directories(struct i915_page_directory_pointer unwind_out: while (pdpe--) - unmap_and_free_pd(ppgtt->pdp.page_directory[pdpe]); + unmap_and_free_pd(pdp->page_directory[pdpe]); return -ENOMEM; } @@ -770,7 +769,7 @@ static int gen8_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt, uint32_t pdpe; int ret; - ret = gen8_ppgtt_alloc_page_directories(&ppgtt->pdp, start, length); + ret = gen8_ppgtt_alloc_page_directories(ppgtt, &ppgtt->pdp, start, length); if (ret) return ret; From e5815a2e0543f4381d3e8fa90f86c56ce68eee75 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 8 Apr 2015 12:13:32 +0100 Subject: [PATCH 0095/3798] drm/i915/gen8: Split out mappings When we do dynamic page table allocations for gen8, we'll need to have more control over how and when we map page tables, similar to gen6. In particular, DMA mappings for page directories/tables occur at allocation time. This patch adds the functionality and calls it at init, which should have no functional change. The PDPEs are still a special case for now. We'll need a function for that in the future as well. v2: Handle renamed unmap_and_free_page functions. v3: Updated after teardown_va logic was removed. v4: Rebase after s/page_tables/page_table/. v5: No longer allocate all PDPs in GEN8+ systems with less than 4GB of memory, and update populate_lr_context to handle this new case (proper tracking will be added later in the patch series). v6: Assign lrc page directory pointer addresses using a macro. (Mika) Cc: Mika Kuoppala Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 224 +++++++++------------------- drivers/gpu/drm/i915/intel_lrc.c | 25 +++- 2 files changed, 86 insertions(+), 163 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 539060b8b66a19..1e1b42f8da42be 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -333,7 +333,7 @@ static void unmap_and_free_pt(struct i915_page_table *pt, } static void gen8_initialize_pt(struct i915_address_space *vm, - struct i915_page_table *pt) + struct i915_page_table *pt) { gen8_pte_t *pt_vaddr, scratch_pte; int i; @@ -431,17 +431,20 @@ static int alloc_pt_range(struct i915_page_directory *pd, uint16_t pde, size_t c return ret; } -static void unmap_and_free_pd(struct i915_page_directory *pd) +static void unmap_and_free_pd(struct i915_page_directory *pd, + struct drm_device *dev) { if (pd->page) { + i915_dma_unmap_single(pd, dev); __free_page(pd->page); kfree(pd); } } -static struct i915_page_directory *alloc_pd_single(void) +static struct i915_page_directory *alloc_pd_single(struct drm_device *dev) { struct i915_page_directory *pd; + int ret; pd = kzalloc(sizeof(*pd), GFP_KERNEL); if (!pd) @@ -453,6 +456,13 @@ static struct i915_page_directory *alloc_pd_single(void) return ERR_PTR(-ENOMEM); } + ret = i915_dma_map_single(pd, dev); + if (ret) { + __free_page(pd->page); + kfree(pd); + return ERR_PTR(ret); + } + return pd; } @@ -637,6 +647,27 @@ static void gen8_initialize_pd(struct i915_address_space *vm, kunmap_atomic(page_directory); } +/* It's likely we'll map more than one pagetable at a time. This function will + * save us unnecessary kmap calls, but do no more functionally than multiple + * calls to map_pt. */ +static void gen8_map_pagetable_range(struct i915_page_directory *pd, + uint64_t start, + uint64_t length, + struct drm_device *dev) +{ + gen8_pde_t *page_directory = kmap_atomic(pd->page); + struct i915_page_table *pt; + uint64_t temp, pde; + + gen8_for_each_pde(pt, pd, start, length, temp, pde) + __gen8_do_map_pt(page_directory + pde, pt, dev); + + if (!HAS_LLC(dev)) + drm_clflush_virt_range(page_directory, PAGE_SIZE); + + kunmap_atomic(page_directory); +} + static void gen8_free_page_tables(struct i915_page_directory *pd, struct drm_device *dev) { int i; @@ -662,10 +693,10 @@ static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt) continue; gen8_free_page_tables(ppgtt->pdp.page_directory[i], ppgtt->base.dev); - unmap_and_free_pd(ppgtt->pdp.page_directory[i]); + unmap_and_free_pd(ppgtt->pdp.page_directory[i], ppgtt->base.dev); } - unmap_and_free_pd(ppgtt->scratch_pd); + unmap_and_free_pd(ppgtt->scratch_pd, ppgtt->base.dev); unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev); } @@ -677,41 +708,30 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) gen8_ppgtt_free(ppgtt); } -static int gen8_ppgtt_alloc_pagetabs(struct i915_page_directory *pd, +static int gen8_ppgtt_alloc_pagetabs(struct i915_hw_ppgtt *ppgtt, + struct i915_page_directory *pd, uint64_t start, - uint64_t length, - struct i915_address_space *vm) + uint64_t length) { + struct drm_device *dev = ppgtt->base.dev; struct i915_page_table *unused; uint64_t temp; uint32_t pde; gen8_for_each_pde(unused, pd, start, length, temp, pde) { WARN_ON(unused); - pd->page_table[pde] = alloc_pt_single(vm->dev); + pd->page_table[pde] = alloc_pt_single(dev); if (IS_ERR(pd->page_table[pde])) goto unwind_out; - gen8_initialize_pt(vm, pd->page_table[pde]); - } - - /* XXX: Still alloc all page tables in systems with less than - * 4GB of memory. This won't be needed after a subsequent patch. - */ - while (pde < I915_PDES) { - pd->page_table[pde] = alloc_pt_single(vm->dev); - if (IS_ERR(pd->page_table[pde])) - goto unwind_out; - - gen8_initialize_pt(vm, pd->page_table[pde]); - pde++; + gen8_initialize_pt(&ppgtt->base, pd->page_table[pde]); } return 0; unwind_out: while (pde--) - unmap_and_free_pt(pd->page_table[pde], vm->dev); + unmap_and_free_pt(pd->page_table[pde], dev); return -ENOMEM; } @@ -721,6 +741,7 @@ static int gen8_ppgtt_alloc_page_directories(struct i915_hw_ppgtt *ppgtt, uint64_t start, uint64_t length) { + struct drm_device *dev = ppgtt->base.dev; struct i915_page_directory *unused; uint64_t temp; uint32_t pdpe; @@ -730,40 +751,29 @@ static int gen8_ppgtt_alloc_page_directories(struct i915_hw_ppgtt *ppgtt, gen8_for_each_pdpe(unused, pdp, start, length, temp, pdpe) { WARN_ON(unused); - pdp->page_directory[pdpe] = alloc_pd_single(); - if (IS_ERR(pdp->page_directory[pdpe])) - goto unwind_out; - - gen8_initialize_pd(&ppgtt->base, - ppgtt->pdp.page_directory[pdpe]); - } - - /* XXX: Still alloc all page directories in systems with less than - * 4GB of memory. This won't be needed after a subsequent patch. - */ - while (pdpe < GEN8_LEGACY_PDPES) { - pdp->page_directory[pdpe] = alloc_pd_single(); + pdp->page_directory[pdpe] = alloc_pd_single(dev); if (IS_ERR(pdp->page_directory[pdpe])) goto unwind_out; gen8_initialize_pd(&ppgtt->base, ppgtt->pdp.page_directory[pdpe]); - pdpe++; } return 0; unwind_out: while (pdpe--) - unmap_and_free_pd(pdp->page_directory[pdpe]); + unmap_and_free_pd(pdp->page_directory[pdpe], dev); return -ENOMEM; } -static int gen8_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt, - uint64_t start, - uint64_t length) +static int gen8_alloc_va_range(struct i915_address_space *vm, + uint64_t start, + uint64_t length) { + struct i915_hw_ppgtt *ppgtt = + container_of(vm, struct i915_hw_ppgtt, base); struct i915_page_directory *pd; uint64_t temp; uint32_t pdpe; @@ -774,23 +784,9 @@ static int gen8_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt, return ret; gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) { - ret = gen8_ppgtt_alloc_pagetabs(pd, start, length, - &ppgtt->base); - if (ret) - goto err_out; - } - - /* XXX: We allocated all page directories in systems with less than - * 4GB of memory. So initalize page tables of all PDPs. - * This won't be needed after the next patch. - */ - while (pdpe < GEN8_LEGACY_PDPES) { - ret = gen8_ppgtt_alloc_pagetabs(ppgtt->pdp.page_directory[pdpe], start, length, - &ppgtt->base); + ret = gen8_ppgtt_alloc_pagetabs(ppgtt, pd, start, length); if (ret) goto err_out; - - pdpe++; } return 0; @@ -800,136 +796,54 @@ static int gen8_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt, return ret; } -static int gen8_ppgtt_setup_page_directories(struct i915_hw_ppgtt *ppgtt, - const int pd) -{ - dma_addr_t pd_addr; - int ret; - - pd_addr = pci_map_page(ppgtt->base.dev->pdev, - ppgtt->pdp.page_directory[pd]->page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - - ret = pci_dma_mapping_error(ppgtt->base.dev->pdev, pd_addr); - if (ret) - return ret; - - ppgtt->pdp.page_directory[pd]->daddr = pd_addr; - - return 0; -} - -static int gen8_ppgtt_setup_page_tables(struct i915_hw_ppgtt *ppgtt, - const int pd, - const int pt) -{ - dma_addr_t pt_addr; - struct i915_page_directory *pdir = ppgtt->pdp.page_directory[pd]; - struct i915_page_table *ptab = pdir->page_table[pt]; - struct page *p = ptab->page; - int ret; - - gen8_initialize_pt(&ppgtt->base, ptab); - - pt_addr = pci_map_page(ppgtt->base.dev->pdev, - p, 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - ret = pci_dma_mapping_error(ppgtt->base.dev->pdev, pt_addr); - if (ret) - return ret; - - ptab->daddr = pt_addr; - - return 0; -} - /* * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers * with a net effect resembling a 2-level page table in normal x86 terms. Each * PDP represents 1GB of memory 4 * 512 * 512 * 4096 = 4GB legacy 32b address * space. * - * FIXME: split allocation into smaller pieces. For now we only ever do this - * once, but with full PPGTT, the multiple contiguous allocations will be bad. - * TODO: Do something with the size parameter */ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) { - int i, j, ret; - - if (size % (1<<30)) - DRM_INFO("Pages will be wasted unless GTT size (%llu) is divisible by 1GB\n", size); + struct i915_page_directory *pd; + uint64_t temp, start = 0; + const uint64_t orig_length = size; + uint32_t pdpe; + int ret; ppgtt->base.start = 0; ppgtt->base.total = size; + ppgtt->base.clear_range = gen8_ppgtt_clear_range; + ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; + ppgtt->base.cleanup = gen8_ppgtt_cleanup; + ppgtt->switch_mm = gen8_mm_switch; ppgtt->scratch_pt = alloc_pt_single(ppgtt->base.dev); if (IS_ERR(ppgtt->scratch_pt)) return PTR_ERR(ppgtt->scratch_pt); - ppgtt->scratch_pd = alloc_pd_single(); + ppgtt->scratch_pd = alloc_pd_single(ppgtt->base.dev); if (IS_ERR(ppgtt->scratch_pd)) return PTR_ERR(ppgtt->scratch_pd); gen8_initialize_pt(&ppgtt->base, ppgtt->scratch_pt); gen8_initialize_pd(&ppgtt->base, ppgtt->scratch_pd); - /* 1. Do all our allocations for page directories and page tables. */ - ret = gen8_ppgtt_alloc(ppgtt, ppgtt->base.start, ppgtt->base.total); + ret = gen8_alloc_va_range(&ppgtt->base, start, size); if (ret) { - unmap_and_free_pd(ppgtt->scratch_pd); + unmap_and_free_pd(ppgtt->scratch_pd, ppgtt->base.dev); unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev); return ret; } - /* - * 2. Create DMA mappings for the page directories and page tables. - */ - for (i = 0; i < GEN8_LEGACY_PDPES; i++) { - ret = gen8_ppgtt_setup_page_directories(ppgtt, i); - if (ret) - goto bail; - - for (j = 0; j < I915_PDES; j++) { - ret = gen8_ppgtt_setup_page_tables(ppgtt, i, j); - if (ret) - goto bail; - } - } - - /* - * 3. Map all the page directory entries to point to the page tables - * we've allocated. - * - * For now, the PPGTT helper functions all require that the PDEs are - * plugged in correctly. So we do that now/here. For aliasing PPGTT, we - * will never need to touch the PDEs again. - */ - for (i = 0; i < GEN8_LEGACY_PDPES; i++) { - struct i915_page_directory *pd = ppgtt->pdp.page_directory[i]; - gen8_pde_t *pd_vaddr; - pd_vaddr = kmap_atomic(ppgtt->pdp.page_directory[i]->page); - for (j = 0; j < I915_PDES; j++) { - struct i915_page_table *pt = pd->page_table[j]; - dma_addr_t addr = pt->daddr; - pd_vaddr[j] = gen8_pde_encode(ppgtt->base.dev, addr, - I915_CACHE_LLC); - } - if (!HAS_LLC(ppgtt->base.dev)) - drm_clflush_virt_range(pd_vaddr, PAGE_SIZE); - kunmap_atomic(pd_vaddr); - } + start = 0; + size = orig_length; - ppgtt->switch_mm = gen8_mm_switch; - ppgtt->base.clear_range = gen8_ppgtt_clear_range; - ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; - ppgtt->base.cleanup = gen8_ppgtt_cleanup; + gen8_for_each_pdpe(pd, &ppgtt->pdp, start, size, temp, pdpe) + gen8_map_pagetable_range(pd, start, size, ppgtt->base.dev); ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true); return 0; - -bail: - gen8_ppgtt_free(ppgtt); - return ret; } static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) @@ -1354,7 +1268,7 @@ static void gen6_ppgtt_free(struct i915_hw_ppgtt *ppgtt) } unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev); - unmap_and_free_pd(&ppgtt->pd); + unmap_and_free_pd(&ppgtt->pd, ppgtt->base.dev); } static void gen6_ppgtt_cleanup(struct i915_address_space *vm) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 580248d927105f..c8edccb0d7825f 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -188,6 +188,15 @@ #define GEN8_CTX_FORCE_RESTORE (1<<2) #define GEN8_CTX_L3LLC_COHERENT (1<<5) #define GEN8_CTX_PRIVILEGE (1<<8) + +#define ASSIGN_CTX_PDP(ppgtt, reg_state, n) { \ + const u64 _addr = ppgtt->pdp.page_directory[n] ? \ + ppgtt->pdp.page_directory[n]->daddr : \ + ppgtt->scratch_pd->daddr; \ + reg_state[CTX_PDP ## n ## _UDW+1] = upper_32_bits(_addr); \ + reg_state[CTX_PDP ## n ## _LDW+1] = lower_32_bits(_addr); \ +} + enum { ADVANCED_CONTEXT = 0, LEGACY_CONTEXT, @@ -1755,14 +1764,14 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o reg_state[CTX_PDP1_LDW] = GEN8_RING_PDP_LDW(ring, 1); reg_state[CTX_PDP0_UDW] = GEN8_RING_PDP_UDW(ring, 0); reg_state[CTX_PDP0_LDW] = GEN8_RING_PDP_LDW(ring, 0); - reg_state[CTX_PDP3_UDW+1] = upper_32_bits(ppgtt->pdp.page_directory[3]->daddr); - reg_state[CTX_PDP3_LDW+1] = lower_32_bits(ppgtt->pdp.page_directory[3]->daddr); - reg_state[CTX_PDP2_UDW+1] = upper_32_bits(ppgtt->pdp.page_directory[2]->daddr); - reg_state[CTX_PDP2_LDW+1] = lower_32_bits(ppgtt->pdp.page_directory[2]->daddr); - reg_state[CTX_PDP1_UDW+1] = upper_32_bits(ppgtt->pdp.page_directory[1]->daddr); - reg_state[CTX_PDP1_LDW+1] = lower_32_bits(ppgtt->pdp.page_directory[1]->daddr); - reg_state[CTX_PDP0_UDW+1] = upper_32_bits(ppgtt->pdp.page_directory[0]->daddr); - reg_state[CTX_PDP0_LDW+1] = lower_32_bits(ppgtt->pdp.page_directory[0]->daddr); + /* XXX: Systems with less than 4GB of memory do not have + * all PDPs. Proper PDP tracking will be added in a + * subsequent patch. + */ + ASSIGN_CTX_PDP(ppgtt, reg_state, 3); + ASSIGN_CTX_PDP(ppgtt, reg_state, 2); + ASSIGN_CTX_PDP(ppgtt, reg_state, 1); + ASSIGN_CTX_PDP(ppgtt, reg_state, 0); if (ring->id == RCS) { reg_state[CTX_LRI_HEADER_2] = MI_LOAD_REGISTER_IMM(1); reg_state[CTX_R_PWR_CLK_STATE] = GEN8_R_PWR_CLK_STATE; From 33c8819f1b057b555c73886f69f9baabe72527e0 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 8 Apr 2015 12:13:33 +0100 Subject: [PATCH 0096/3798] drm/i915/gen8: begin bitmap tracking Like with gen6/7, we can enable bitmap tracking with all the preallocations to make sure things actually don't blow up. v2: Rebased to match changes from previous patches. v3: Without teardown logic, rely on used_pdpes and used_pdes when freeing page tables. v4: Rebased after s/page_tables/page_table/. v5: Rebased after page table generalizations. Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 59 +++++++++++++++++++++++------ drivers/gpu/drm/i915/i915_gem_gtt.h | 7 ++++ 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 1e1b42f8da42be..1be0a8ee8dd7fa 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -437,6 +437,7 @@ static void unmap_and_free_pd(struct i915_page_directory *pd, if (pd->page) { i915_dma_unmap_single(pd, dev); __free_page(pd->page); + kfree(pd->used_pdes); kfree(pd); } } @@ -444,26 +445,35 @@ static void unmap_and_free_pd(struct i915_page_directory *pd, static struct i915_page_directory *alloc_pd_single(struct drm_device *dev) { struct i915_page_directory *pd; - int ret; + int ret = -ENOMEM; pd = kzalloc(sizeof(*pd), GFP_KERNEL); if (!pd) return ERR_PTR(-ENOMEM); + pd->used_pdes = kcalloc(BITS_TO_LONGS(I915_PDES), + sizeof(*pd->used_pdes), GFP_KERNEL); + if (!pd->used_pdes) + goto free_pd; + pd->page = alloc_page(GFP_KERNEL); - if (!pd->page) { - kfree(pd); - return ERR_PTR(-ENOMEM); - } + if (!pd->page) + goto free_bitmap; ret = i915_dma_map_single(pd, dev); - if (ret) { - __free_page(pd->page); - kfree(pd); - return ERR_PTR(ret); - } + if (ret) + goto free_page; return pd; + +free_page: + __free_page(pd->page); +free_bitmap: + kfree(pd->used_pdes); +free_pd: + kfree(pd); + + return ERR_PTR(ret); } /* Broadwell Page Directory Pointer Descriptors */ @@ -675,7 +685,7 @@ static void gen8_free_page_tables(struct i915_page_directory *pd, struct drm_dev if (!pd->page) return; - for (i = 0; i < I915_PDES; i++) { + for_each_set_bit(i, pd->used_pdes, I915_PDES) { if (WARN_ON(!pd->page_table[i])) continue; @@ -688,7 +698,7 @@ static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt) { int i; - for (i = 0; i < GEN8_LEGACY_PDPES; i++) { + for_each_set_bit(i, ppgtt->pdp.used_pdpes, GEN8_LEGACY_PDPES) { if (WARN_ON(!ppgtt->pdp.page_directory[i])) continue; @@ -752,6 +762,7 @@ static int gen8_ppgtt_alloc_page_directories(struct i915_hw_ppgtt *ppgtt, gen8_for_each_pdpe(unused, pdp, start, length, temp, pdpe) { WARN_ON(unused); pdp->page_directory[pdpe] = alloc_pd_single(dev); + if (IS_ERR(pdp->page_directory[pdpe])) goto unwind_out; @@ -775,10 +786,13 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); struct i915_page_directory *pd; + const uint64_t orig_start = start; + const uint64_t orig_length = length; uint64_t temp; uint32_t pdpe; int ret; + /* Do the allocations first so we can easily bail out */ ret = gen8_ppgtt_alloc_page_directories(ppgtt, &ppgtt->pdp, start, length); if (ret) return ret; @@ -789,6 +803,27 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, goto err_out; } + /* Now mark everything we've touched as used. This doesn't allow for + * robust error checking, but it makes the code a hell of a lot simpler. + */ + start = orig_start; + length = orig_length; + + gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) { + struct i915_page_table *pt; + uint64_t pd_len = gen8_clamp_pd(start, length); + uint64_t pd_start = start; + uint32_t pde; + + gen8_for_each_pde(pt, &ppgtt->pd, pd_start, pd_len, temp, pde) { + bitmap_set(pd->page_table[pde]->used_ptes, + gen8_pte_index(start), + gen8_pte_count(start, length)); + set_bit(pde, pd->used_pdes); + } + set_bit(pdpe, ppgtt->pdp.used_pdpes); + } + return 0; err_out: diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index c3d5d40b78b260..29de64d1164efb 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -220,11 +220,13 @@ struct i915_page_directory { dma_addr_t daddr; }; + unsigned long *used_pdes; struct i915_page_table *page_table[I915_PDES]; /* PDEs */ }; struct i915_page_directory_pointer { /* struct page *page; */ + DECLARE_BITMAP(used_pdpes, GEN8_LEGACY_PDPES); struct i915_page_directory *page_directory[GEN8_LEGACY_PDPES]; }; @@ -453,6 +455,11 @@ static inline uint32_t gen8_pml4e_index(uint64_t address) return 0; } +static inline size_t gen8_pte_count(uint64_t address, uint64_t length) +{ + return i915_pte_count(address, length, GEN8_PDE_SHIFT); +} + int i915_gem_gtt_init(struct drm_device *dev); void i915_gem_init_global_gtt(struct drm_device *dev); void i915_global_gtt_cleanup(struct drm_device *dev); From d7b2633dba04ef0fd7385f02a7b552abc5f1062f Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 8 Apr 2015 12:13:34 +0100 Subject: [PATCH 0097/3798] drm/i915/gen8: Dynamic page table allocations This finishes off the dynamic page tables allocations, in the legacy 3 level style that already exists. Most everything has already been setup to this point, the patch finishes off the enabling by setting the appropriate function pointers. In LRC mode, contexts need to know the PDPs when they are populated. With dynamic page table allocations, these PDPs may not exist yet. Check if PDPs have been allocated and use the scratch page if they do not exist yet. Before submission, update the PDPs in the logic ring context as PDPs have been allocated. v2: Update aliasing/true ppgtt allocate/teardown/clear functions for gen 6 & 7. v3: Rebase. v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either teardown_va_range or clear_range functions exist (Daniel). v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed for aliasing ppgtt. Zombie tracking was originally added for teardown function and is no longer required. v6: Update err_out case in gen8_alloc_va_range (missed from lastest rebase). v7: Rebase after s/page_tables/page_table/. v8: Updated scratch_pt check after scratch flag was removed in previous patch. v9: Note that lrc mode needs to be updated to support init state without any PDP. v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs during page table allocation. v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken until it was updated to handle the init case without any PDP. v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps static and don't abuse of inline functions. (Mika) Cc: Mika Kuoppala Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry (v2+) Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 307 +++++++++++++++++++++------- drivers/gpu/drm/i915/intel_lrc.c | 23 ++- 2 files changed, 253 insertions(+), 77 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 1be0a8ee8dd7fa..f6b0ddc7a5fa3d 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -653,28 +653,6 @@ static void gen8_initialize_pd(struct i915_address_space *vm, if (!HAS_LLC(vm->dev)) drm_clflush_virt_range(page_directory, PAGE_SIZE); - - kunmap_atomic(page_directory); -} - -/* It's likely we'll map more than one pagetable at a time. This function will - * save us unnecessary kmap calls, but do no more functionally than multiple - * calls to map_pt. */ -static void gen8_map_pagetable_range(struct i915_page_directory *pd, - uint64_t start, - uint64_t length, - struct drm_device *dev) -{ - gen8_pde_t *page_directory = kmap_atomic(pd->page); - struct i915_page_table *pt; - uint64_t temp, pde; - - gen8_for_each_pde(pt, pd, start, length, temp, pde) - __gen8_do_map_pt(page_directory + pde, pt, dev); - - if (!HAS_LLC(dev)) - drm_clflush_virt_range(page_directory, PAGE_SIZE); - kunmap_atomic(page_directory); } @@ -718,73 +696,178 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) gen8_ppgtt_free(ppgtt); } +/** + * gen8_ppgtt_alloc_pagetabs() - Allocate page tables for VA range. + * @ppgtt: Master ppgtt structure. + * @pd: Page directory for this address range. + * @start: Starting virtual address to begin allocations. + * @length Size of the allocations. + * @new_pts: Bitmap set by function with new allocations. Likely used by the + * caller to free on error. + * + * Allocate the required number of page tables. Extremely similar to + * gen8_ppgtt_alloc_page_directories(). The main difference is here we are limited by + * the page directory boundary (instead of the page directory pointer). That + * boundary is 1GB virtual. Therefore, unlike gen8_ppgtt_alloc_page_directories(), it is + * possible, and likely that the caller will need to use multiple calls of this + * function to achieve the appropriate allocation. + * + * Return: 0 if success; negative error code otherwise. + */ static int gen8_ppgtt_alloc_pagetabs(struct i915_hw_ppgtt *ppgtt, struct i915_page_directory *pd, uint64_t start, - uint64_t length) + uint64_t length, + unsigned long *new_pts) { struct drm_device *dev = ppgtt->base.dev; - struct i915_page_table *unused; + struct i915_page_table *pt; uint64_t temp; uint32_t pde; - gen8_for_each_pde(unused, pd, start, length, temp, pde) { - WARN_ON(unused); - pd->page_table[pde] = alloc_pt_single(dev); - if (IS_ERR(pd->page_table[pde])) + gen8_for_each_pde(pt, pd, start, length, temp, pde) { + /* Don't reallocate page tables */ + if (pt) { + /* Scratch is never allocated this way */ + WARN_ON(pt == ppgtt->scratch_pt); + continue; + } + + pt = alloc_pt_single(dev); + if (IS_ERR(pt)) goto unwind_out; - gen8_initialize_pt(&ppgtt->base, pd->page_table[pde]); + gen8_initialize_pt(&ppgtt->base, pt); + pd->page_table[pde] = pt; + set_bit(pde, new_pts); } return 0; unwind_out: - while (pde--) + for_each_set_bit(pde, new_pts, I915_PDES) unmap_and_free_pt(pd->page_table[pde], dev); return -ENOMEM; } +/** + * gen8_ppgtt_alloc_page_directories() - Allocate page directories for VA range. + * @ppgtt: Master ppgtt structure. + * @pdp: Page directory pointer for this address range. + * @start: Starting virtual address to begin allocations. + * @length Size of the allocations. + * @new_pds Bitmap set by function with new allocations. Likely used by the + * caller to free on error. + * + * Allocate the required number of page directories starting at the pde index of + * @start, and ending at the pde index @start + @length. This function will skip + * over already allocated page directories within the range, and only allocate + * new ones, setting the appropriate pointer within the pdp as well as the + * correct position in the bitmap @new_pds. + * + * The function will only allocate the pages within the range for a give page + * directory pointer. In other words, if @start + @length straddles a virtually + * addressed PDP boundary (512GB for 4k pages), there will be more allocations + * required by the caller, This is not currently possible, and the BUG in the + * code will prevent it. + * + * Return: 0 if success; negative error code otherwise. + */ static int gen8_ppgtt_alloc_page_directories(struct i915_hw_ppgtt *ppgtt, struct i915_page_directory_pointer *pdp, uint64_t start, - uint64_t length) + uint64_t length, + unsigned long *new_pds) { struct drm_device *dev = ppgtt->base.dev; - struct i915_page_directory *unused; + struct i915_page_directory *pd; uint64_t temp; uint32_t pdpe; + WARN_ON(!bitmap_empty(new_pds, GEN8_LEGACY_PDPES)); + /* FIXME: PPGTT container_of won't work for 64b */ WARN_ON((start + length) > 0x800000000ULL); - gen8_for_each_pdpe(unused, pdp, start, length, temp, pdpe) { - WARN_ON(unused); - pdp->page_directory[pdpe] = alloc_pd_single(dev); + gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) { + if (pd) + continue; - if (IS_ERR(pdp->page_directory[pdpe])) + pd = alloc_pd_single(dev); + if (IS_ERR(pd)) goto unwind_out; - gen8_initialize_pd(&ppgtt->base, - ppgtt->pdp.page_directory[pdpe]); + gen8_initialize_pd(&ppgtt->base, pd); + pdp->page_directory[pdpe] = pd; + set_bit(pdpe, new_pds); } return 0; unwind_out: - while (pdpe--) + for_each_set_bit(pdpe, new_pds, GEN8_LEGACY_PDPES) unmap_and_free_pd(pdp->page_directory[pdpe], dev); return -ENOMEM; } +static void +free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long **new_pts) +{ + int i; + + for (i = 0; i < GEN8_LEGACY_PDPES; i++) + kfree(new_pts[i]); + kfree(new_pts); + kfree(new_pds); +} + +/* Fills in the page directory bitmap, and the array of page tables bitmap. Both + * of these are based on the number of PDPEs in the system. + */ +static +int __must_check alloc_gen8_temp_bitmaps(unsigned long **new_pds, + unsigned long ***new_pts) +{ + int i; + unsigned long *pds; + unsigned long **pts; + + pds = kcalloc(BITS_TO_LONGS(GEN8_LEGACY_PDPES), sizeof(unsigned long), GFP_KERNEL); + if (!pds) + return -ENOMEM; + + pts = kcalloc(GEN8_LEGACY_PDPES, sizeof(unsigned long *), GFP_KERNEL); + if (!pts) { + kfree(pds); + return -ENOMEM; + } + + for (i = 0; i < GEN8_LEGACY_PDPES; i++) { + pts[i] = kcalloc(BITS_TO_LONGS(I915_PDES), + sizeof(unsigned long), GFP_KERNEL); + if (!pts[i]) + goto err_out; + } + + *new_pds = pds; + *new_pts = pts; + + return 0; + +err_out: + free_gen8_temp_bitmaps(pds, pts); + return -ENOMEM; +} + static int gen8_alloc_va_range(struct i915_address_space *vm, uint64_t start, uint64_t length) { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); + unsigned long *new_page_dirs, **new_page_tables; struct i915_page_directory *pd; const uint64_t orig_start = start; const uint64_t orig_length = length; @@ -792,42 +875,98 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, uint32_t pdpe; int ret; - /* Do the allocations first so we can easily bail out */ - ret = gen8_ppgtt_alloc_page_directories(ppgtt, &ppgtt->pdp, start, length); +#ifndef CONFIG_64BIT + /* Disallow 64b address on 32b platforms. Nothing is wrong with doing + * this in hardware, but a lot of the drm code is not prepared to handle + * 64b offset on 32b platforms. + * This will be addressed when 48b PPGTT is added */ + if (start + length > 0x100000000ULL) + return -E2BIG; +#endif + + /* Wrap is never okay since we can only represent 48b, and we don't + * actually use the other side of the canonical address space. + */ + if (WARN_ON(start + length < start)) + return -ERANGE; + + ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables); if (ret) return ret; + /* Do the allocations first so we can easily bail out */ + ret = gen8_ppgtt_alloc_page_directories(ppgtt, &ppgtt->pdp, start, length, + new_page_dirs); + if (ret) { + free_gen8_temp_bitmaps(new_page_dirs, new_page_tables); + return ret; + } + + /* For every page directory referenced, allocate page tables */ gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) { - ret = gen8_ppgtt_alloc_pagetabs(ppgtt, pd, start, length); + ret = gen8_ppgtt_alloc_pagetabs(ppgtt, pd, start, length, + new_page_tables[pdpe]); if (ret) goto err_out; } - /* Now mark everything we've touched as used. This doesn't allow for - * robust error checking, but it makes the code a hell of a lot simpler. - */ start = orig_start; length = orig_length; + /* Allocations have completed successfully, so set the bitmaps, and do + * the mappings. */ gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) { + gen8_pde_t *const page_directory = kmap_atomic(pd->page); struct i915_page_table *pt; uint64_t pd_len = gen8_clamp_pd(start, length); uint64_t pd_start = start; uint32_t pde; - gen8_for_each_pde(pt, &ppgtt->pd, pd_start, pd_len, temp, pde) { - bitmap_set(pd->page_table[pde]->used_ptes, - gen8_pte_index(start), - gen8_pte_count(start, length)); + /* Every pd should be allocated, we just did that above. */ + WARN_ON(!pd); + + gen8_for_each_pde(pt, pd, pd_start, pd_len, temp, pde) { + /* Same reasoning as pd */ + WARN_ON(!pt); + WARN_ON(!pd_len); + WARN_ON(!gen8_pte_count(pd_start, pd_len)); + + /* Set our used ptes within the page table */ + bitmap_set(pt->used_ptes, + gen8_pte_index(pd_start), + gen8_pte_count(pd_start, pd_len)); + + /* Our pde is now pointing to the pagetable, pt */ set_bit(pde, pd->used_pdes); + + /* Map the PDE to the page table */ + __gen8_do_map_pt(page_directory + pde, pt, vm->dev); + + /* NB: We haven't yet mapped ptes to pages. At this + * point we're still relying on insert_entries() */ } + + if (!HAS_LLC(vm->dev)) + drm_clflush_virt_range(page_directory, PAGE_SIZE); + + kunmap_atomic(page_directory); + set_bit(pdpe, ppgtt->pdp.used_pdpes); } + free_gen8_temp_bitmaps(new_page_dirs, new_page_tables); return 0; err_out: - gen8_ppgtt_free(ppgtt); + while (pdpe--) { + for_each_set_bit(temp, new_page_tables[pdpe], I915_PDES) + unmap_and_free_pt(ppgtt->pdp.page_directory[pdpe]->page_table[temp], vm->dev); + } + + for_each_set_bit(pdpe, new_page_dirs, GEN8_LEGACY_PDPES) + unmap_and_free_pd(ppgtt->pdp.page_directory[pdpe], vm->dev); + + free_gen8_temp_bitmaps(new_page_dirs, new_page_tables); return ret; } @@ -838,21 +977,8 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, * space. * */ -static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) +static int gen8_ppgtt_init_common(struct i915_hw_ppgtt *ppgtt, uint64_t size) { - struct i915_page_directory *pd; - uint64_t temp, start = 0; - const uint64_t orig_length = size; - uint32_t pdpe; - int ret; - - ppgtt->base.start = 0; - ppgtt->base.total = size; - ppgtt->base.clear_range = gen8_ppgtt_clear_range; - ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; - ppgtt->base.cleanup = gen8_ppgtt_cleanup; - ppgtt->switch_mm = gen8_mm_switch; - ppgtt->scratch_pt = alloc_pt_single(ppgtt->base.dev); if (IS_ERR(ppgtt->scratch_pt)) return PTR_ERR(ppgtt->scratch_pt); @@ -864,6 +990,30 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) gen8_initialize_pt(&ppgtt->base, ppgtt->scratch_pt); gen8_initialize_pd(&ppgtt->base, ppgtt->scratch_pd); + ppgtt->base.start = 0; + ppgtt->base.total = size; + ppgtt->base.cleanup = gen8_ppgtt_cleanup; + ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; + + ppgtt->switch_mm = gen8_mm_switch; + + return 0; +} + +static int gen8_aliasing_ppgtt_init(struct i915_hw_ppgtt *ppgtt) +{ + struct drm_device *dev = ppgtt->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + uint64_t start = 0, size = dev_priv->gtt.base.total; + int ret; + + ret = gen8_ppgtt_init_common(ppgtt, dev_priv->gtt.base.total); + if (ret) + return ret; + + /* Aliasing PPGTT has to always work and be mapped because of the way we + * use RESTORE_INHIBIT in the context switch. This will be fixed + * eventually. */ ret = gen8_alloc_va_range(&ppgtt->base, start, size); if (ret) { unmap_and_free_pd(ppgtt->scratch_pd, ppgtt->base.dev); @@ -871,13 +1021,26 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) return ret; } - start = 0; - size = orig_length; + ppgtt->base.allocate_va_range = NULL; + ppgtt->base.clear_range = gen8_ppgtt_clear_range; + ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true); - gen8_for_each_pdpe(pd, &ppgtt->pdp, start, size, temp, pdpe) - gen8_map_pagetable_range(pd, start, size, ppgtt->base.dev); + return 0; +} + +static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) +{ + struct drm_device *dev = ppgtt->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int ret; + + ret = gen8_ppgtt_init_common(ppgtt, dev_priv->gtt.base.total); + if (ret) + return ret; + + ppgtt->base.allocate_va_range = gen8_alloc_va_range; + ppgtt->base.clear_range = gen8_ppgtt_clear_range; - ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true); return 0; } @@ -1416,7 +1579,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing) } } - ppgtt->base.allocate_va_range = gen6_alloc_va_range; + ppgtt->base.allocate_va_range = aliasing ? NULL : gen6_alloc_va_range; ppgtt->base.clear_range = gen6_ppgtt_clear_range; ppgtt->base.insert_entries = gen6_ppgtt_insert_entries; ppgtt->base.cleanup = gen6_ppgtt_cleanup; @@ -1457,8 +1620,10 @@ static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt, if (INTEL_INFO(dev)->gen < 8) return gen6_ppgtt_init(ppgtt, aliasing); + else if (aliasing) + return gen8_aliasing_ppgtt_init(ppgtt); else - return gen8_ppgtt_init(ppgtt, dev_priv->gtt.base.total); + return gen8_ppgtt_init(ppgtt); } int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) { diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index c8edccb0d7825f..58ac414cf60307 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -190,7 +190,7 @@ #define GEN8_CTX_PRIVILEGE (1<<8) #define ASSIGN_CTX_PDP(ppgtt, reg_state, n) { \ - const u64 _addr = ppgtt->pdp.page_directory[n] ? \ + const u64 _addr = test_bit(n, ppgtt->pdp.used_pdpes) ? \ ppgtt->pdp.page_directory[n]->daddr : \ ppgtt->scratch_pd->daddr; \ reg_state[CTX_PDP ## n ## _UDW+1] = upper_32_bits(_addr); \ @@ -330,6 +330,7 @@ static void execlists_elsp_write(struct intel_engine_cs *ring, static int execlists_update_context(struct drm_i915_gem_object *ctx_obj, struct drm_i915_gem_object *ring_obj, + struct i915_hw_ppgtt *ppgtt, u32 tail) { struct page *page; @@ -341,6 +342,16 @@ static int execlists_update_context(struct drm_i915_gem_object *ctx_obj, reg_state[CTX_RING_TAIL+1] = tail; reg_state[CTX_RING_BUFFER_START+1] = i915_gem_obj_ggtt_offset(ring_obj); + /* True PPGTT with dynamic page allocation: update PDP registers and + * point the unallocated PDPs to the scratch page + */ + if (ppgtt) { + ASSIGN_CTX_PDP(ppgtt, reg_state, 3); + ASSIGN_CTX_PDP(ppgtt, reg_state, 2); + ASSIGN_CTX_PDP(ppgtt, reg_state, 1); + ASSIGN_CTX_PDP(ppgtt, reg_state, 0); + } + kunmap_atomic(reg_state); return 0; @@ -359,7 +370,7 @@ static void execlists_submit_contexts(struct intel_engine_cs *ring, WARN_ON(!i915_gem_obj_is_pinned(ctx_obj0)); WARN_ON(!i915_gem_obj_is_pinned(ringbuf0->obj)); - execlists_update_context(ctx_obj0, ringbuf0->obj, tail0); + execlists_update_context(ctx_obj0, ringbuf0->obj, to0->ppgtt, tail0); if (to1) { ringbuf1 = to1->engine[ring->id].ringbuf; @@ -368,7 +379,7 @@ static void execlists_submit_contexts(struct intel_engine_cs *ring, WARN_ON(!i915_gem_obj_is_pinned(ctx_obj1)); WARN_ON(!i915_gem_obj_is_pinned(ringbuf1->obj)); - execlists_update_context(ctx_obj1, ringbuf1->obj, tail1); + execlists_update_context(ctx_obj1, ringbuf1->obj, to1->ppgtt, tail1); } execlists_elsp_write(ring, ctx_obj0, ctx_obj1); @@ -1764,9 +1775,9 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o reg_state[CTX_PDP1_LDW] = GEN8_RING_PDP_LDW(ring, 1); reg_state[CTX_PDP0_UDW] = GEN8_RING_PDP_UDW(ring, 0); reg_state[CTX_PDP0_LDW] = GEN8_RING_PDP_LDW(ring, 0); - /* XXX: Systems with less than 4GB of memory do not have - * all PDPs. Proper PDP tracking will be added in a - * subsequent patch. + + /* With dynamic page allocation, PDPs may not be allocated at this point, + * Point the unallocated PDPs to the scratch page */ ASSIGN_CTX_PDP(ppgtt, reg_state, 3); ASSIGN_CTX_PDP(ppgtt, reg_state, 2); From a4e0bedca678c81eea4cd79a4bd502335639f73a Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 8 Apr 2015 12:13:35 +0100 Subject: [PATCH 0098/3798] drm/i915: Use complete address space in true PPGTT True PPGTT is capable of having a full address space, even if the system has less allocated memory. Note that aliasing PPGTT always aliases the GGTT and thus should remain of the same size. Signed-off-by: Michel Thierry Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index f6b0ddc7a5fa3d..2a01d5620a192e 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1030,11 +1030,9 @@ static int gen8_aliasing_ppgtt_init(struct i915_hw_ppgtt *ppgtt) static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) { - struct drm_device *dev = ppgtt->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; int ret; - ret = gen8_ppgtt_init_common(ppgtt, dev_priv->gtt.base.total); + ret = gen8_ppgtt_init_common(ppgtt, (1ULL << 32)); if (ret) return ret; From 90e4f1592bb6e82f6690f0e05a8aadcf04d7bce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 25 Mar 2015 18:45:58 +0200 Subject: [PATCH 0099/3798] drm/i915: Fix the VBT child device parsing for BSW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recent BSW VBT has a VBT child device size 37 bytes instead of the 33 bytes our code assumes. This means we fail to parse the VBT and thus fail to detect eDP ports properly and just register them as DP ports instead. Fix it up by using the reported child device size from the VBT instead of assuming it matches out struct defintions. The latest spec I have shows that the child device size should be 36 bytes for rev >= 195, however on my BSW the size is actually 37 bytes. And our current struct definition is 33 bytes. Feels like the entire VBT parses would need to be rewritten to handle changes in the layout better, but for now I've decided to do just the bare minimum to get my eDP port back. Cc: Vijay Purushothaman Signed-off-by: Ville Syrjälä Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_bios.c | 26 +++++++++++++------------- drivers/gpu/drm/i915/intel_bios.h | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index ad2f3b0d922f11..c08368c03dad22 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -447,6 +447,12 @@ parse_general_definitions(struct drm_i915_private *dev_priv, } } +static union child_device_config * +child_device_ptr(struct bdb_general_definitions *p_defs, int i) +{ + return (void *) &p_defs->devices[i * p_defs->child_dev_size]; +} + static void parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, struct bdb_header *bdb) @@ -476,10 +482,10 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, block_size = get_blocksize(p_defs); /* get the number of child device */ child_device_num = (block_size - sizeof(*p_defs)) / - sizeof(*p_child); + p_defs->child_dev_size; count = 0; for (i = 0; i < child_device_num; i++) { - p_child = &(p_defs->devices[i]); + p_child = child_device_ptr(p_defs, i); if (!p_child->old.device_type) { /* skip the device block if device type is invalid */ continue; @@ -1067,25 +1073,19 @@ parse_device_mapping(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n"); return; } - /* judge whether the size of child device meets the requirements. - * If the child device size obtained from general definition block - * is different with sizeof(struct child_device_config), skip the - * parsing of sdvo device info - */ - if (p_defs->child_dev_size != sizeof(*p_child)) { - /* different child dev size . Ignore it */ - DRM_DEBUG_KMS("different child size is found. Invalid.\n"); + if (p_defs->child_dev_size < sizeof(*p_child)) { + DRM_ERROR("General definiton block child device size is too small.\n"); return; } /* get the block size of general definitions */ block_size = get_blocksize(p_defs); /* get the number of child device */ child_device_num = (block_size - sizeof(*p_defs)) / - sizeof(*p_child); + p_defs->child_dev_size; count = 0; /* get the number of child device that is present */ for (i = 0; i < child_device_num; i++) { - p_child = &(p_defs->devices[i]); + p_child = child_device_ptr(p_defs, i); if (!p_child->common.device_type) { /* skip the device block if device type is invalid */ continue; @@ -1105,7 +1105,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, dev_priv->vbt.child_dev_num = count; count = 0; for (i = 0; i < child_device_num; i++) { - p_child = &(p_defs->devices[i]); + p_child = child_device_ptr(p_defs, i); if (!p_child->common.device_type) { /* skip the device block if device type is invalid */ continue; diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 6afd5be3336761..af0b476527526c 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -277,9 +277,9 @@ struct bdb_general_definitions { * And the device num is related with the size of general definition * block. It is obtained by using the following formula: * number = (block_size - sizeof(bdb_general_definitions))/ - * sizeof(child_device_config); + * defs->child_dev_size; */ - union child_device_config devices[0]; + uint8_t devices[0]; } __packed; /* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */ From b5eba37283181fefe2a4c3b81f1c8f29d9d96904 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:48 +0100 Subject: [PATCH 0100/3798] drm/i915: Use simpler form of spin_lock_irq(execlist_lock) We can use the simpler spinlock form to disable interrupts as we are always outside of an irq/softirq handler. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 58ac414cf60307..2779070f59d243 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -522,7 +522,6 @@ static int execlists_context_queue(struct intel_engine_cs *ring, { struct drm_i915_gem_request *cursor; struct drm_i915_private *dev_priv = ring->dev->dev_private; - unsigned long flags; int num_elements = 0; if (to != ring->default_context) @@ -549,7 +548,7 @@ static int execlists_context_queue(struct intel_engine_cs *ring, intel_runtime_pm_get(dev_priv); - spin_lock_irqsave(&ring->execlist_lock, flags); + spin_lock_irq(&ring->execlist_lock); list_for_each_entry(cursor, &ring->execlist_queue, execlist_link) if (++num_elements > 2) @@ -575,7 +574,7 @@ static int execlists_context_queue(struct intel_engine_cs *ring, if (num_elements == 0) execlists_context_unqueue(ring); - spin_unlock_irqrestore(&ring->execlist_lock, flags); + spin_unlock_irq(&ring->execlist_lock); return 0; } @@ -960,7 +959,6 @@ void intel_execlists_retire_requests(struct intel_engine_cs *ring) { struct drm_i915_gem_request *req, *tmp; struct drm_i915_private *dev_priv = ring->dev->dev_private; - unsigned long flags; struct list_head retired_list; WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); @@ -968,9 +966,9 @@ void intel_execlists_retire_requests(struct intel_engine_cs *ring) return; INIT_LIST_HEAD(&retired_list); - spin_lock_irqsave(&ring->execlist_lock, flags); + spin_lock_irq(&ring->execlist_lock); list_replace_init(&ring->execlist_retired_req_list, &retired_list); - spin_unlock_irqrestore(&ring->execlist_lock, flags); + spin_unlock_irq(&ring->execlist_lock); list_for_each_entry_safe(req, tmp, &retired_list, execlist_link) { struct intel_context *ctx = req->ctx; From 4bb1bedb28e0f1d04fa6bf5bdcdaecabd904b21c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:49 +0100 Subject: [PATCH 0101/3798] drm/i915: Use the global runtime-pm wakelock for a busy GPU for execlists When we submit a request to the GPU, we first take the rpm wakelock, and only release it once the GPU has been idle for a small period of time after all requests have been complete. This means that we are sure no new interrupt can arrive whilst we do not hold the rpm wakelock and so can drop the individual get/put around every single request inside execlists. Note: to close one potential issue we should mark the GPU as busy earlier in __i915_add_request. To elaborate: The issue is that we emit the irq signalling sequence before we grab the rpm reference, which means we could miss the resulting interrupt (since that's not set up when suspended). The only bad side effect is a missed interrupt, gt mmio writes automatically wake up the hw itself. But otoh we have an umbrella rpm reference for the entirety of execbuf, as long as that's there we're covered. Signed-off-by: Chris Wilson [danvet: Explain a bit more about the add_request issue, which after some irc chatting with Chris turns out to not be an issue really.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 1 - drivers/gpu/drm/i915/intel_lrc.c | 3 --- 2 files changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8feafe9be1f08c..9fbc3558de67f8 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2605,7 +2605,6 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, struct drm_i915_gem_request, execlist_link); list_del(&submit_req->execlist_link); - intel_runtime_pm_put(dev_priv); if (submit_req->ctx != ring->default_context) intel_lr_context_unpin(ring, submit_req->ctx); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 2779070f59d243..3758298a353171 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -546,8 +546,6 @@ static int execlists_context_queue(struct intel_engine_cs *ring, } request->tail = tail; - intel_runtime_pm_get(dev_priv); - spin_lock_irq(&ring->execlist_lock); list_for_each_entry(cursor, &ring->execlist_queue, execlist_link) @@ -977,7 +975,6 @@ void intel_execlists_retire_requests(struct intel_engine_cs *ring) if (ctx_obj && (ctx != ring->default_context)) intel_lr_context_unpin(ring, ctx); - intel_runtime_pm_put(dev_priv); list_del(&req->execlist_link); i915_gem_request_unreference(req); } From 595e1eeb26d3fcf2e39b494f067ebb5eb3c77e08 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:51 +0100 Subject: [PATCH 0102/3798] drm/i915: Remove vestigal DRI1 ring quiescing code After the removal of DRI1, all access to the rings are through requests and so we can always be sure that there is a request to wait upon to free up available space. The fallback code only existed so that we could quiesce the GPU following unmediated access by DRI1. v2: Rebase Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_trace.h | 27 ------------ drivers/gpu/drm/i915/intel_lrc.c | 57 ++----------------------- drivers/gpu/drm/i915/intel_ringbuffer.c | 56 +----------------------- 3 files changed, 6 insertions(+), 134 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 4574f0cc9b1cf1..7bd48cd2c210b0 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -597,33 +597,6 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end, TP_ARGS(req) ); -DECLARE_EVENT_CLASS(i915_ring, - TP_PROTO(struct intel_engine_cs *ring), - TP_ARGS(ring), - - TP_STRUCT__entry( - __field(u32, dev) - __field(u32, ring) - ), - - TP_fast_assign( - __entry->dev = ring->dev->primary->index; - __entry->ring = ring->id; - ), - - TP_printk("dev=%u, ring=%u", __entry->dev, __entry->ring) -); - -DEFINE_EVENT(i915_ring, i915_ring_wait_begin, - TP_PROTO(struct intel_engine_cs *ring), - TP_ARGS(ring) -); - -DEFINE_EVENT(i915_ring, i915_ring_wait_end, - TP_PROTO(struct intel_engine_cs *ring), - TP_ARGS(ring) -); - TRACE_EVENT(i915_flip_request, TP_PROTO(int plane, struct drm_i915_gem_object *obj), diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 3758298a353171..43737541556b48 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -647,8 +647,9 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request return 0; } -static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, - int bytes) +static int logical_ring_wait_for_space(struct intel_ringbuffer *ringbuf, + struct intel_context *ctx, + int bytes) { struct intel_engine_cs *ring = ringbuf->ring; struct drm_i915_gem_request *request; @@ -674,7 +675,7 @@ static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, break; } - if (&request->list == &ring->request_list) + if (WARN_ON(&request->list == &ring->request_list)) return -ENOSPC; ret = i915_wait_request(request); @@ -712,56 +713,6 @@ intel_logical_ring_advance_and_submit(struct intel_ringbuffer *ringbuf, execlists_context_queue(ring, ctx, ringbuf->tail, request); } -static int logical_ring_wait_for_space(struct intel_ringbuffer *ringbuf, - struct intel_context *ctx, - int bytes) -{ - struct intel_engine_cs *ring = ringbuf->ring; - struct drm_device *dev = ring->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long end; - int ret; - - ret = logical_ring_wait_request(ringbuf, bytes); - if (ret != -ENOSPC) - return ret; - - /* Force the context submission in case we have been skipping it */ - intel_logical_ring_advance_and_submit(ringbuf, ctx, NULL); - - /* With GEM the hangcheck timer should kick us out of the loop, - * leaving it early runs the risk of corrupting GEM state (due - * to running on almost untested codepaths). But on resume - * timers don't work yet, so prevent a complete hang in that - * case by choosing an insanely large timeout. */ - end = jiffies + 60 * HZ; - - ret = 0; - do { - if (intel_ring_space(ringbuf) >= bytes) - break; - - msleep(1); - - if (dev_priv->mm.interruptible && signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - ret = i915_gem_check_wedge(&dev_priv->gpu_error, - dev_priv->mm.interruptible); - if (ret) - break; - - if (time_after(jiffies, end)) { - ret = -EBUSY; - break; - } - } while (1); - - return ret; -} - static int logical_ring_wrap_buffer(struct intel_ringbuffer *ringbuf, struct intel_context *ctx) { diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 1f9463a295a561..720d29a602a76c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2060,7 +2060,7 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) ring->buffer = NULL; } -static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) +static int ring_wait_for_space(struct intel_engine_cs *ring, int n) { struct intel_ringbuffer *ringbuf = ring->buffer; struct drm_i915_gem_request *request; @@ -2076,7 +2076,7 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) break; } - if (&request->list == &ring->request_list) + if (WARN_ON(&request->list == &ring->request_list)) return -ENOSPC; ret = i915_wait_request(request); @@ -2090,58 +2090,6 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) return 0; } -static int ring_wait_for_space(struct intel_engine_cs *ring, int n) -{ - struct drm_device *dev = ring->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_ringbuffer *ringbuf = ring->buffer; - unsigned long end; - int ret; - - ret = intel_ring_wait_request(ring, n); - if (ret != -ENOSPC) - return ret; - - /* force the tail write in case we have been skipping them */ - __intel_ring_advance(ring); - - /* With GEM the hangcheck timer should kick us out of the loop, - * leaving it early runs the risk of corrupting GEM state (due - * to running on almost untested codepaths). But on resume - * timers don't work yet, so prevent a complete hang in that - * case by choosing an insanely large timeout. */ - end = jiffies + 60 * HZ; - - ret = 0; - trace_i915_ring_wait_begin(ring); - do { - if (intel_ring_space(ringbuf) >= n) - break; - ringbuf->head = I915_READ_HEAD(ring); - if (intel_ring_space(ringbuf) >= n) - break; - - msleep(1); - - if (dev_priv->mm.interruptible && signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - ret = i915_gem_check_wedge(&dev_priv->gpu_error, - dev_priv->mm.interruptible); - if (ret) - break; - - if (time_after(jiffies, end)) { - ret = -EBUSY; - break; - } - } while (1); - trace_i915_ring_wait_end(ring); - return ret; -} - static int intel_wrap_ring_buffer(struct intel_engine_cs *ring) { uint32_t __iomem *virt; From f81338a52a82009863b0dc9d597fe1000d1caff6 Mon Sep 17 00:00:00 2001 From: Chandra Konduru Date: Thu, 9 Apr 2015 17:36:21 -0700 Subject: [PATCH 0103/3798] drm: Adding drm helper function drm_plane_from_index(). Adding drm helper function to return plane pointer from index where index is a returned by drm_plane_index. v2: -avoided nested loop by adding loop count (Daniel) v3: -updated patch header prefix to 'drm' (Matt) v4: -fixed a kerneldoc issue (kbuild-internal) Cc: dri-devel@lists.freedesktop.org Signed-off-by: Chandra Konduru Reviewed-by: Matt Roper Acked-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 23 +++++++++++++++++++++++ include/drm/drm_crtc.h | 1 + 2 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 9f970c2d481912..6254942141d35c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1285,6 +1285,29 @@ unsigned int drm_plane_index(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_index); +/** + * drm_plane_from_index - find the registered plane at an index + * @dev: DRM device + * @idx: index of registered plane to find for + * + * Given a plane index, return the registered plane from DRM device's + * list of planes with matching index. + */ +struct drm_plane * +drm_plane_from_index(struct drm_device *dev, int idx) +{ + struct drm_plane *plane; + unsigned int i = 0; + + list_for_each_entry(plane, &dev->mode_config.plane_list, head) { + if (i == idx) + return plane; + i++; + } + return NULL; +} +EXPORT_SYMBOL(drm_plane_from_index); + /** * drm_plane_force_disable - Forcibly disable a plane * @plane: plane to disable diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index adc9ea5acf02ea..ed769e79c675d9 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1264,6 +1264,7 @@ extern int drm_plane_init(struct drm_device *dev, bool is_primary); extern void drm_plane_cleanup(struct drm_plane *plane); extern unsigned int drm_plane_index(struct drm_plane *plane); +extern struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx); extern void drm_plane_force_disable(struct drm_plane *plane); extern int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format); From 3e1ab4b70571ea801de6f426f9973c80e1bddfb3 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 10 Apr 2015 09:31:40 +0200 Subject: [PATCH 0104/3798] drm/i915: Update DRIVER_DATE to 20150410 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f4daa3d3c126b6..ec6cf1bd7c2909 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -56,7 +56,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20150327" +#define DRIVER_DATE "20150410" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ From 70a101f8639a712576c3ca1d910564c7e2ec91d8 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Wed, 8 Apr 2015 18:56:53 -0700 Subject: [PATCH 0105/3798] drm/i915: Switch to full atomic helpers for plane updates/disable, take two Switch from our plane update/disable entrypoints to use the full atomic helpers (which generate a top-level atomic transaction) rather than the transitional helpers (which only create/manipulate orphaned plane states independent of a top-level transaction). Various upcoming work (SKL scalers, atomic watermarks, etc.) requires a full atomic transaction to behave properly/cleanly. Last time we tried this, we had to back out the change because we still call the drm_plane vfuncs directly from within our legacy modesetting code. This potentially results in nested atomic transactions, locking collisions, and other failures. To avoid that problem again, we sidestep the issue by calling the transitional helpers directly (rather than through a vfunc) when we're nested inside of other legacy modesetting code. However this does allow legacy SetPlane() ioctl's to process an entire drm_atomic_state transaction, which is important for upcoming patches. Cc: Chandra Konduru Signed-off-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 24 ++++++++++++------------ drivers/gpu/drm/i915/intel_sprite.c | 10 +++++----- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7bfe2af42030f9..11b958a56515ae 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5576,7 +5576,7 @@ static void intel_crtc_disable(struct drm_crtc *crtc) dev_priv->display.crtc_disable(crtc); dev_priv->display.off(crtc); - crtc->primary->funcs->disable_plane(crtc->primary); + drm_plane_helper_disable(crtc->primary); /* Update computed state. */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -11731,11 +11731,11 @@ static int __intel_set_mode(struct drm_crtc *crtc, int vdisplay, hdisplay; drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay); - ret = primary->funcs->update_plane(primary, &intel_crtc->base, - fb, 0, 0, - hdisplay, vdisplay, - x << 16, y << 16, - hdisplay << 16, vdisplay << 16); + ret = drm_plane_helper_update(primary, &intel_crtc->base, + fb, 0, 0, + hdisplay, vdisplay, + x << 16, y << 16, + hdisplay << 16, vdisplay << 16); } /* Now enable the clocks, plane, pipe, and connectors that we set up. */ @@ -12286,10 +12286,10 @@ static int intel_crtc_set_config(struct drm_mode_set *set) int vdisplay, hdisplay; drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay); - ret = primary->funcs->update_plane(primary, set->crtc, set->fb, - 0, 0, hdisplay, vdisplay, - set->x << 16, set->y << 16, - hdisplay << 16, vdisplay << 16); + ret = drm_plane_helper_update(primary, set->crtc, set->fb, + 0, 0, hdisplay, vdisplay, + set->x << 16, set->y << 16, + hdisplay << 16, vdisplay << 16); /* * We need to make sure the primary plane is re-enabled if it @@ -12773,8 +12773,8 @@ void intel_plane_destroy(struct drm_plane *plane) } const struct drm_plane_funcs intel_plane_funcs = { - .update_plane = drm_plane_helper_update, - .disable_plane = drm_plane_helper_disable, + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, .destroy = intel_plane_destroy, .set_property = drm_atomic_helper_plane_set_property, .atomic_get_property = intel_plane_atomic_get_property, diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index e9ff6fc6126726..f009c8f970eafb 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1139,11 +1139,11 @@ int intel_plane_restore(struct drm_plane *plane) if (!plane->crtc || !plane->state->fb) return 0; - return plane->funcs->update_plane(plane, plane->crtc, plane->state->fb, - plane->state->crtc_x, plane->state->crtc_y, - plane->state->crtc_w, plane->state->crtc_h, - plane->state->src_x, plane->state->src_y, - plane->state->src_w, plane->state->src_h); + return drm_plane_helper_update(plane, plane->crtc, plane->state->fb, + plane->state->crtc_x, plane->state->crtc_y, + plane->state->crtc_w, plane->state->crtc_h, + plane->state->src_x, plane->state->src_y, + plane->state->src_w, plane->state->src_h); } static uint32_t ilk_plane_formats[] = { From f1e2daea79e96a50cdbca1bdd1a70900e1af5da1 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 9 Apr 2015 10:48:38 -0700 Subject: [PATCH 0106/3798] drm/i915: Clear crtc atomic flags at beginning of transaction Once we have full atomic modeset, these kind of flags should be in a real intel_crtc_state that's tracked properly. In the meantime, make sure we clear out any old flags at the beginning of a transaction so that we don't wind up seeing leftover flags from old transactions that were checked, but never went to the commit step. At the moment, a failed check or prepare could leave stale flags behind that interfere with the next atomic transaction. v2: Just do a memset; the series this patch was originally part of placed additional fields into the structure that shouldn't be cleared, but that's no longer the case. Signed-off-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_atomic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 3903b90fb64efa..b4ea6762e4ef01 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -76,6 +76,8 @@ int intel_atomic_check(struct drm_device *dev, state->allow_modeset = false; for (i = 0; i < ncrtcs; i++) { struct intel_crtc *crtc = to_intel_crtc(state->crtcs[i]); + if (crtc) + memset(&crtc->atomic, 0, sizeof(crtc->atomic)); if (crtc && crtc->pipe != nuclear_pipe) not_nuclear = true; } From efab6d8dd158fdccbe6a030f89fbf9ca0a9564e4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:57 +0100 Subject: [PATCH 0107/3798] drm/i915: Use a separate slab for requests requests are even more frequently allocated than objects and equally benefit from having a dedicated slab. v2: Rebase Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 12 +++++--- drivers/gpu/drm/i915/i915_drv.h | 4 ++- drivers/gpu/drm/i915/i915_gem.c | 41 +++++++++++++++---------- drivers/gpu/drm/i915/intel_ringbuffer.c | 1 - 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 8f5428b46a2730..180b5d92b279c0 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1006,8 +1006,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) put_bridge: pci_dev_put(dev_priv->bridge_dev); free_priv: - if (dev_priv->slab) - kmem_cache_destroy(dev_priv->slab); + if (dev_priv->requests) + kmem_cache_destroy(dev_priv->requests); + if (dev_priv->objects) + kmem_cache_destroy(dev_priv->objects); kfree(dev_priv); return ret; } @@ -1090,8 +1092,10 @@ int i915_driver_unload(struct drm_device *dev) if (dev_priv->regs != NULL) pci_iounmap(dev->pdev, dev_priv->regs); - if (dev_priv->slab) - kmem_cache_destroy(dev_priv->slab); + if (dev_priv->requests) + kmem_cache_destroy(dev_priv->requests); + if (dev_priv->objects) + kmem_cache_destroy(dev_priv->objects); pci_dev_put(dev_priv->bridge_dev); kfree(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ec6cf1bd7c2909..855eaac9ddd1aa 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1558,7 +1558,8 @@ struct i915_virtual_gpu { struct drm_i915_private { struct drm_device *dev; - struct kmem_cache *slab; + struct kmem_cache *objects; + struct kmem_cache *requests; const struct intel_device_info info; @@ -2044,6 +2045,7 @@ struct drm_i915_gem_request { struct kref ref; /** On Which ring this request was generated */ + struct drm_i915_private *i915; struct intel_engine_cs *ring; /** GEM sequence number associated with this request. */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9fbc3558de67f8..20a61764a4a3c6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -378,13 +378,13 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj, void *i915_gem_object_alloc(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - return kmem_cache_zalloc(dev_priv->slab, GFP_KERNEL); + return kmem_cache_zalloc(dev_priv->objects, GFP_KERNEL); } void i915_gem_object_free(struct drm_i915_gem_object *obj) { struct drm_i915_private *dev_priv = obj->base.dev->dev_private; - kmem_cache_free(dev_priv->slab, obj); + kmem_cache_free(dev_priv->objects, obj); } static int @@ -2506,43 +2506,45 @@ void i915_gem_request_free(struct kref *req_ref) i915_gem_context_unreference(ctx); } - kfree(req); + kmem_cache_free(req->i915->requests, req); } int i915_gem_request_alloc(struct intel_engine_cs *ring, struct intel_context *ctx) { + struct drm_i915_private *dev_priv = to_i915(ring->dev); + struct drm_i915_gem_request *rq; int ret; - struct drm_i915_gem_request *request; - struct drm_i915_private *dev_private = ring->dev->dev_private; if (ring->outstanding_lazy_request) return 0; - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) + rq = kmem_cache_zalloc(dev_priv->requests, GFP_KERNEL); + if (rq == NULL) return -ENOMEM; - ret = i915_gem_get_seqno(ring->dev, &request->seqno); + kref_init(&rq->ref); + rq->i915 = dev_priv; + + ret = i915_gem_get_seqno(ring->dev, &rq->seqno); if (ret) { - kfree(request); + kfree(rq); return ret; } - kref_init(&request->ref); - request->ring = ring; - request->uniq = dev_private->request_uniq++; + rq->ring = ring; + rq->uniq = dev_priv->request_uniq++; if (i915.enable_execlists) - ret = intel_logical_ring_alloc_request_extras(request, ctx); + ret = intel_logical_ring_alloc_request_extras(rq, ctx); else - ret = intel_ring_alloc_request_extras(request); + ret = intel_ring_alloc_request_extras(rq); if (ret) { - kfree(request); + kfree(rq); return ret; } - ring->outstanding_lazy_request = request; + ring->outstanding_lazy_request = rq; return 0; } @@ -4984,11 +4986,16 @@ i915_gem_load(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int i; - dev_priv->slab = + dev_priv->objects = kmem_cache_create("i915_gem_object", sizeof(struct drm_i915_gem_object), 0, SLAB_HWCACHE_ALIGN, NULL); + dev_priv->requests = + kmem_cache_create("i915_gem_request", + sizeof(struct drm_i915_gem_request), 0, + SLAB_HWCACHE_ALIGN, + NULL); INIT_LIST_HEAD(&dev_priv->vm_list); i915_init_vm(dev_priv, &dev_priv->gtt.base); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 720d29a602a76c..9f3fc81149a429 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2139,7 +2139,6 @@ int intel_ring_idle(struct intel_engine_cs *ring) int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) { request->ringbuf = request->ring->buffer; - return 0; } From e20d2ab741b58ad1ac0209f7a4ee930ebb7a43f3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:58 +0100 Subject: [PATCH 0108/3798] drm/i915: Use a separate slab for vmas vma are more frequently allocated than objects and so should equally benefit from having a dedicated slab. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 4 ++++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 7 ++++++- drivers/gpu/drm/i915/i915_gem_gtt.c | 3 ++- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 180b5d92b279c0..d67cd9e0ef145c 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1008,6 +1008,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) free_priv: if (dev_priv->requests) kmem_cache_destroy(dev_priv->requests); + if (dev_priv->vmas) + kmem_cache_destroy(dev_priv->vmas); if (dev_priv->objects) kmem_cache_destroy(dev_priv->objects); kfree(dev_priv); @@ -1094,6 +1096,8 @@ int i915_driver_unload(struct drm_device *dev) if (dev_priv->requests) kmem_cache_destroy(dev_priv->requests); + if (dev_priv->vmas) + kmem_cache_destroy(dev_priv->vmas); if (dev_priv->objects) kmem_cache_destroy(dev_priv->objects); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 855eaac9ddd1aa..b6750751bb933a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1559,6 +1559,7 @@ struct i915_virtual_gpu { struct drm_i915_private { struct drm_device *dev; struct kmem_cache *objects; + struct kmem_cache *vmas; struct kmem_cache *requests; const struct intel_device_info info; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 20a61764a4a3c6..a57fdd98b4fec0 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4612,7 +4612,7 @@ void i915_gem_vma_destroy(struct i915_vma *vma) list_del(&vma->vma_link); - kfree(vma); + kmem_cache_free(to_i915(vma->obj->base.dev)->vmas, vma); } static void @@ -4991,6 +4991,11 @@ i915_gem_load(struct drm_device *dev) sizeof(struct drm_i915_gem_object), 0, SLAB_HWCACHE_ALIGN, NULL); + dev_priv->vmas = + kmem_cache_create("i915_gem_vma", + sizeof(struct i915_vma), 0, + SLAB_HWCACHE_ALIGN, + NULL); dev_priv->requests = kmem_cache_create("i915_gem_request", sizeof(struct drm_i915_gem_request), 0, diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2a01d5620a192e..559cecaccf7ff2 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2712,7 +2712,8 @@ __i915_gem_vma_create(struct drm_i915_gem_object *obj, if (WARN_ON(i915_is_ggtt(vm) != !!ggtt_view)) return ERR_PTR(-EINVAL); - vma = kzalloc(sizeof(*vma), GFP_KERNEL); + + vma = kmem_cache_zalloc(to_i915(obj->base.dev)->vmas, GFP_KERNEL); if (vma == NULL) return ERR_PTR(-ENOMEM); From 19ee66af15a59f405bfca9949af552d9ec0b03f4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 10 Apr 2015 10:18:47 +0200 Subject: [PATCH 0109/3798] drm/i915: Remove unused variable in intel_lrc.c Already tagged this one and 0-day builder is failing me. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 43737541556b48..037e94c5ab427c 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -907,7 +907,6 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file, void intel_execlists_retire_requests(struct intel_engine_cs *ring) { struct drm_i915_gem_request *req, *tmp; - struct drm_i915_private *dev_priv = ring->dev->dev_private; struct list_head retired_list; WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); From a6111f7b6604e6cf98856839b56a2ae436fc0bab Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:21:02 +0100 Subject: [PATCH 0110/3798] drm/i915: Reduce locking in execlist command submission This eliminates six needless spin lock/unlock pairs when writing out ELSP. v2: Respin with my preferred colour. v3: Mostly back to the original colour Signed-off-by: Tvrtko Ursulin [v1] Signed-off-by: Chris Wilson Cc: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 18 ++++++ drivers/gpu/drm/i915/intel_lrc.c | 16 ++--- drivers/gpu/drm/i915/intel_uncore.c | 98 ++++++++++++++++++++++------- 3 files changed, 103 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b6750751bb933a..0ddf6831a321b1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2537,6 +2537,13 @@ void intel_uncore_forcewake_get(struct drm_i915_private *dev_priv, enum forcewake_domains domains); void intel_uncore_forcewake_put(struct drm_i915_private *dev_priv, enum forcewake_domains domains); +/* Like above but the caller must manage the uncore.lock itself. + * Must be used with I915_READ_FW and friends. + */ +void intel_uncore_forcewake_get__locked(struct drm_i915_private *dev_priv, + enum forcewake_domains domains); +void intel_uncore_forcewake_put__locked(struct drm_i915_private *dev_priv, + enum forcewake_domains domains); void assert_forcewakes_inactive(struct drm_i915_private *dev_priv); static inline bool intel_vgpu_active(struct drm_device *dev) { @@ -3229,6 +3236,17 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val); #define POSTING_READ(reg) (void)I915_READ_NOTRACE(reg) #define POSTING_READ16(reg) (void)I915_READ16_NOTRACE(reg) +/* These are untraced mmio-accessors that are only valid to be used inside + * criticial sections inside IRQ handlers where forcewake is explicitly + * controlled. + * Think twice, and think again, before using these. + * Note: Should only be used between intel_uncore_forcewake_irqlock() and + * intel_uncore_forcewake_irqunlock(). + */ +#define I915_READ_FW(reg__) readl(dev_priv->regs + (reg__)) +#define I915_WRITE_FW(reg__, val__) writel(val__, dev_priv->regs + (reg__)) +#define POSTING_READ_FW(reg__) (void)I915_READ_FW(reg__) + /* "Broadcast RGB" property */ #define INTEL_BROADCAST_RGB_AUTO 0 #define INTEL_BROADCAST_RGB_FULL 1 diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 037e94c5ab427c..ed28e7d8adeaaa 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -315,17 +315,19 @@ static void execlists_elsp_write(struct intel_engine_cs *ring, desc[3] = (u32)(temp >> 32); desc[2] = (u32)temp; - intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); - I915_WRITE(RING_ELSP(ring), desc[1]); - I915_WRITE(RING_ELSP(ring), desc[0]); - I915_WRITE(RING_ELSP(ring), desc[3]); + spin_lock(&dev_priv->uncore.lock); + intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); + I915_WRITE_FW(RING_ELSP(ring), desc[1]); + I915_WRITE_FW(RING_ELSP(ring), desc[0]); + I915_WRITE_FW(RING_ELSP(ring), desc[3]); /* The context is automatically loaded after the following */ - I915_WRITE(RING_ELSP(ring), desc[2]); + I915_WRITE_FW(RING_ELSP(ring), desc[2]); /* ELSP is a wo register, so use another nearby reg for posting instead */ - POSTING_READ(RING_EXECLIST_STATUS(ring)); - intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); + POSTING_READ_FW(RING_EXECLIST_STATUS(ring)); + intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); + spin_unlock(&dev_priv->uncore.lock); } static int execlists_update_context(struct drm_i915_gem_object *ctx_obj, diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index ab5cc94588e10d..d96d15faf2687e 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -375,6 +375,26 @@ void intel_uncore_sanitize(struct drm_device *dev) intel_disable_gt_powersave(dev); } +static void __intel_uncore_forcewake_get(struct drm_i915_private *dev_priv, + enum forcewake_domains fw_domains) +{ + struct intel_uncore_forcewake_domain *domain; + enum forcewake_domain_id id; + + if (!dev_priv->uncore.funcs.force_wake_get) + return; + + fw_domains &= dev_priv->uncore.fw_domains; + + for_each_fw_domain_mask(domain, fw_domains, dev_priv, id) { + if (domain->wake_count++) + fw_domains &= ~(1 << id); + } + + if (fw_domains) + dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); +} + /** * intel_uncore_forcewake_get - grab forcewake domain references * @dev_priv: i915 device instance @@ -392,41 +412,39 @@ void intel_uncore_forcewake_get(struct drm_i915_private *dev_priv, enum forcewake_domains fw_domains) { unsigned long irqflags; - struct intel_uncore_forcewake_domain *domain; - enum forcewake_domain_id id; if (!dev_priv->uncore.funcs.force_wake_get) return; WARN_ON(dev_priv->pm.suspended); - fw_domains &= dev_priv->uncore.fw_domains; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - for_each_fw_domain_mask(domain, fw_domains, dev_priv, id) { - if (domain->wake_count++) - fw_domains &= ~(1 << id); - } - - if (fw_domains) - dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); - + __intel_uncore_forcewake_get(dev_priv, fw_domains); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } /** - * intel_uncore_forcewake_put - release a forcewake domain reference + * intel_uncore_forcewake_get__locked - grab forcewake domain references * @dev_priv: i915 device instance - * @fw_domains: forcewake domains to put references + * @fw_domains: forcewake domains to get reference on * - * This function drops the device-level forcewakes for specified - * domains obtained by intel_uncore_forcewake_get(). + * See intel_uncore_forcewake_get(). This variant places the onus + * on the caller to explicitly handle the dev_priv->uncore.lock spinlock. */ -void intel_uncore_forcewake_put(struct drm_i915_private *dev_priv, - enum forcewake_domains fw_domains) +void intel_uncore_forcewake_get__locked(struct drm_i915_private *dev_priv, + enum forcewake_domains fw_domains) +{ + assert_spin_locked(&dev_priv->uncore.lock); + + if (!dev_priv->uncore.funcs.force_wake_get) + return; + + __intel_uncore_forcewake_get(dev_priv, fw_domains); +} + +static void __intel_uncore_forcewake_put(struct drm_i915_private *dev_priv, + enum forcewake_domains fw_domains) { - unsigned long irqflags; struct intel_uncore_forcewake_domain *domain; enum forcewake_domain_id id; @@ -435,8 +453,6 @@ void intel_uncore_forcewake_put(struct drm_i915_private *dev_priv, fw_domains &= dev_priv->uncore.fw_domains; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - for_each_fw_domain_mask(domain, fw_domains, dev_priv, id) { if (WARN_ON(domain->wake_count == 0)) continue; @@ -447,10 +463,48 @@ void intel_uncore_forcewake_put(struct drm_i915_private *dev_priv, domain->wake_count++; fw_domain_arm_timer(domain); } +} +/** + * intel_uncore_forcewake_put - release a forcewake domain reference + * @dev_priv: i915 device instance + * @fw_domains: forcewake domains to put references + * + * This function drops the device-level forcewakes for specified + * domains obtained by intel_uncore_forcewake_get(). + */ +void intel_uncore_forcewake_put(struct drm_i915_private *dev_priv, + enum forcewake_domains fw_domains) +{ + unsigned long irqflags; + + if (!dev_priv->uncore.funcs.force_wake_put) + return; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + __intel_uncore_forcewake_put(dev_priv, fw_domains); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } +/** + * intel_uncore_forcewake_put__locked - grab forcewake domain references + * @dev_priv: i915 device instance + * @fw_domains: forcewake domains to get reference on + * + * See intel_uncore_forcewake_put(). This variant places the onus + * on the caller to explicitly handle the dev_priv->uncore.lock spinlock. + */ +void intel_uncore_forcewake_put__locked(struct drm_i915_private *dev_priv, + enum forcewake_domains fw_domains) +{ + assert_spin_locked(&dev_priv->uncore.lock); + + if (!dev_priv->uncore.funcs.force_wake_put) + return; + + __intel_uncore_forcewake_put(dev_priv, fw_domains); +} + void assert_forcewakes_inactive(struct drm_i915_private *dev_priv) { struct intel_uncore_forcewake_domain *domain; From cb0d205e0ffc78eb51d5e62c8ee841f286f10303 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:21:04 +0100 Subject: [PATCH 0111/3798] drm/i915: Reduce locking in gen8 IRQ handler Similar in vain in reducing the number of unrequired spinlocks used for execlist command submission (where the forcewake is required but manually controlled), we know that the IRQ registers are outside of the powerwell and so we can access them directly. Since we now have direct access exported via I915_READ_FW/I915_WRITE_FW, lets put those to use in the irq handlers as well. In the process, reorder the execlist submission to happen as early as possible. v2: Restrict the untraced register mmio to just the GT path (i.e. the hotpath for execlists) Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 47 ++++++++++++++++----------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8b5e0358c59287..c2c80bf490c694 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1285,56 +1285,56 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, irqreturn_t ret = IRQ_NONE; if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { - tmp = I915_READ(GEN8_GT_IIR(0)); + tmp = I915_READ_FW(GEN8_GT_IIR(0)); if (tmp) { - I915_WRITE(GEN8_GT_IIR(0), tmp); + I915_WRITE_FW(GEN8_GT_IIR(0), tmp); ret = IRQ_HANDLED; rcs = tmp >> GEN8_RCS_IRQ_SHIFT; ring = &dev_priv->ring[RCS]; - if (rcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, ring); if (rcs & GT_CONTEXT_SWITCH_INTERRUPT) intel_lrc_irq_handler(ring); + if (rcs & GT_RENDER_USER_INTERRUPT) + notify_ring(dev, ring); bcs = tmp >> GEN8_BCS_IRQ_SHIFT; ring = &dev_priv->ring[BCS]; - if (bcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, ring); if (bcs & GT_CONTEXT_SWITCH_INTERRUPT) intel_lrc_irq_handler(ring); + if (bcs & GT_RENDER_USER_INTERRUPT) + notify_ring(dev, ring); } else DRM_ERROR("The master control interrupt lied (GT0)!\n"); } if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) { - tmp = I915_READ(GEN8_GT_IIR(1)); + tmp = I915_READ_FW(GEN8_GT_IIR(1)); if (tmp) { - I915_WRITE(GEN8_GT_IIR(1), tmp); + I915_WRITE_FW(GEN8_GT_IIR(1), tmp); ret = IRQ_HANDLED; vcs = tmp >> GEN8_VCS1_IRQ_SHIFT; ring = &dev_priv->ring[VCS]; - if (vcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, ring); if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) intel_lrc_irq_handler(ring); + if (vcs & GT_RENDER_USER_INTERRUPT) + notify_ring(dev, ring); vcs = tmp >> GEN8_VCS2_IRQ_SHIFT; ring = &dev_priv->ring[VCS2]; - if (vcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, ring); if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) intel_lrc_irq_handler(ring); + if (vcs & GT_RENDER_USER_INTERRUPT) + notify_ring(dev, ring); } else DRM_ERROR("The master control interrupt lied (GT1)!\n"); } if (master_ctl & GEN8_GT_PM_IRQ) { - tmp = I915_READ(GEN8_GT_IIR(2)); + tmp = I915_READ_FW(GEN8_GT_IIR(2)); if (tmp & dev_priv->pm_rps_events) { - I915_WRITE(GEN8_GT_IIR(2), - tmp & dev_priv->pm_rps_events); + I915_WRITE_FW(GEN8_GT_IIR(2), + tmp & dev_priv->pm_rps_events); ret = IRQ_HANDLED; gen6_rps_irq_handler(dev_priv, tmp); } else @@ -1342,17 +1342,17 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, } if (master_ctl & GEN8_GT_VECS_IRQ) { - tmp = I915_READ(GEN8_GT_IIR(3)); + tmp = I915_READ_FW(GEN8_GT_IIR(3)); if (tmp) { - I915_WRITE(GEN8_GT_IIR(3), tmp); + I915_WRITE_FW(GEN8_GT_IIR(3), tmp); ret = IRQ_HANDLED; vcs = tmp >> GEN8_VECS_IRQ_SHIFT; ring = &dev_priv->ring[VECS]; - if (vcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, ring); if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) intel_lrc_irq_handler(ring); + if (vcs & GT_RENDER_USER_INTERRUPT) + notify_ring(dev, ring); } else DRM_ERROR("The master control interrupt lied (GT3)!\n"); } @@ -2178,13 +2178,12 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) aux_mask |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | GEN9_AUX_CHANNEL_D; - master_ctl = I915_READ(GEN8_MASTER_IRQ); + master_ctl = I915_READ_FW(GEN8_MASTER_IRQ); master_ctl &= ~GEN8_MASTER_IRQ_CONTROL; if (!master_ctl) return IRQ_NONE; - I915_WRITE(GEN8_MASTER_IRQ, 0); - POSTING_READ(GEN8_MASTER_IRQ); + I915_WRITE_FW(GEN8_MASTER_IRQ, 0); /* Find, clear, then process each source of interrupt */ @@ -2281,8 +2280,8 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) } - I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); - POSTING_READ(GEN8_MASTER_IRQ); + I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); + POSTING_READ_FW(GEN8_MASTER_IRQ); return ret; } From 74cdb337c0fc7d97e7db719051e51abcc7bd9579 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:21:05 +0100 Subject: [PATCH 0112/3798] drm/i915: Tidy gen8 IRQ handler Remove some needless variables and parameter passing. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 113 ++++++++++++++------------------ 1 file changed, 49 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c2c80bf490c694..46bcbff8976004 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -985,8 +985,7 @@ static void ironlake_rps_change_irq_handler(struct drm_device *dev) return; } -static void notify_ring(struct drm_device *dev, - struct intel_engine_cs *ring) +static void notify_ring(struct intel_engine_cs *ring) { if (!intel_ring_initialized(ring)) return; @@ -1248,9 +1247,9 @@ static void ilk_gt_irq_handler(struct drm_device *dev, { if (gt_iir & (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT)) - notify_ring(dev, &dev_priv->ring[RCS]); + notify_ring(&dev_priv->ring[RCS]); if (gt_iir & ILK_BSD_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[VCS]); + notify_ring(&dev_priv->ring[VCS]); } static void snb_gt_irq_handler(struct drm_device *dev, @@ -1260,11 +1259,11 @@ static void snb_gt_irq_handler(struct drm_device *dev, if (gt_iir & (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT)) - notify_ring(dev, &dev_priv->ring[RCS]); + notify_ring(&dev_priv->ring[RCS]); if (gt_iir & GT_BSD_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[VCS]); + notify_ring(&dev_priv->ring[VCS]); if (gt_iir & GT_BLT_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[BCS]); + notify_ring(&dev_priv->ring[BCS]); if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT | GT_BSD_CS_ERROR_INTERRUPT | @@ -1275,63 +1274,65 @@ static void snb_gt_irq_handler(struct drm_device *dev, ivybridge_parity_error_irq_handler(dev, gt_iir); } -static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, - struct drm_i915_private *dev_priv, +static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) { - struct intel_engine_cs *ring; - u32 rcs, bcs, vcs; - uint32_t tmp = 0; irqreturn_t ret = IRQ_NONE; if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { - tmp = I915_READ_FW(GEN8_GT_IIR(0)); + u32 tmp = I915_READ_FW(GEN8_GT_IIR(0)); if (tmp) { I915_WRITE_FW(GEN8_GT_IIR(0), tmp); ret = IRQ_HANDLED; - rcs = tmp >> GEN8_RCS_IRQ_SHIFT; - ring = &dev_priv->ring[RCS]; - if (rcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_lrc_irq_handler(ring); - if (rcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, ring); - - bcs = tmp >> GEN8_BCS_IRQ_SHIFT; - ring = &dev_priv->ring[BCS]; - if (bcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_lrc_irq_handler(ring); - if (bcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, ring); + if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT)) + intel_lrc_irq_handler(&dev_priv->ring[RCS]); + if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT)) + notify_ring(&dev_priv->ring[RCS]); + + if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT)) + intel_lrc_irq_handler(&dev_priv->ring[BCS]); + if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT)) + notify_ring(&dev_priv->ring[BCS]); } else DRM_ERROR("The master control interrupt lied (GT0)!\n"); } if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) { - tmp = I915_READ_FW(GEN8_GT_IIR(1)); + u32 tmp = I915_READ_FW(GEN8_GT_IIR(1)); if (tmp) { I915_WRITE_FW(GEN8_GT_IIR(1), tmp); ret = IRQ_HANDLED; - vcs = tmp >> GEN8_VCS1_IRQ_SHIFT; - ring = &dev_priv->ring[VCS]; - if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_lrc_irq_handler(ring); - if (vcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, ring); - - vcs = tmp >> GEN8_VCS2_IRQ_SHIFT; - ring = &dev_priv->ring[VCS2]; - if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_lrc_irq_handler(ring); - if (vcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, ring); + if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT)) + intel_lrc_irq_handler(&dev_priv->ring[VCS]); + if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT)) + notify_ring(&dev_priv->ring[VCS]); + + if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT)) + intel_lrc_irq_handler(&dev_priv->ring[VCS2]); + if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT)) + notify_ring(&dev_priv->ring[VCS2]); } else DRM_ERROR("The master control interrupt lied (GT1)!\n"); } + if (master_ctl & GEN8_GT_VECS_IRQ) { + u32 tmp = I915_READ_FW(GEN8_GT_IIR(3)); + if (tmp) { + I915_WRITE_FW(GEN8_GT_IIR(3), tmp); + ret = IRQ_HANDLED; + + if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT)) + intel_lrc_irq_handler(&dev_priv->ring[VECS]); + if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT)) + notify_ring(&dev_priv->ring[VECS]); + } else + DRM_ERROR("The master control interrupt lied (GT3)!\n"); + } + if (master_ctl & GEN8_GT_PM_IRQ) { - tmp = I915_READ_FW(GEN8_GT_IIR(2)); + u32 tmp = I915_READ_FW(GEN8_GT_IIR(2)); if (tmp & dev_priv->pm_rps_events) { I915_WRITE_FW(GEN8_GT_IIR(2), tmp & dev_priv->pm_rps_events); @@ -1341,22 +1342,6 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, DRM_ERROR("The master control interrupt lied (PM)!\n"); } - if (master_ctl & GEN8_GT_VECS_IRQ) { - tmp = I915_READ_FW(GEN8_GT_IIR(3)); - if (tmp) { - I915_WRITE_FW(GEN8_GT_IIR(3), tmp); - ret = IRQ_HANDLED; - - vcs = tmp >> GEN8_VECS_IRQ_SHIFT; - ring = &dev_priv->ring[VECS]; - if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_lrc_irq_handler(ring); - if (vcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, ring); - } else - DRM_ERROR("The master control interrupt lied (GT3)!\n"); - } - return ret; } @@ -1651,7 +1636,7 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) if (HAS_VEBOX(dev_priv->dev)) { if (pm_iir & PM_VEBOX_USER_INTERRUPT) - notify_ring(dev_priv->dev, &dev_priv->ring[VECS]); + notify_ring(&dev_priv->ring[VECS]); if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir); @@ -1845,7 +1830,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) I915_WRITE(VLV_IIR, iir); } - gen8_gt_irq_handler(dev, dev_priv, master_ctl); + gen8_gt_irq_handler(dev_priv, master_ctl); /* Call regardless, as some status bits might not be * signalled in iir */ @@ -2187,7 +2172,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) /* Find, clear, then process each source of interrupt */ - ret = gen8_gt_irq_handler(dev, dev_priv, master_ctl); + ret = gen8_gt_irq_handler(dev_priv, master_ctl); if (master_ctl & GEN8_DE_MISC_IRQ) { tmp = I915_READ(GEN8_DE_MISC_IIR); @@ -3692,7 +3677,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) new_iir = I915_READ16(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[RCS]); + notify_ring(&dev_priv->ring[RCS]); for_each_pipe(dev_priv, pipe) { int plane = pipe; @@ -3883,7 +3868,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) new_iir = I915_READ(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[RCS]); + notify_ring(&dev_priv->ring[RCS]); for_each_pipe(dev_priv, pipe) { int plane = pipe; @@ -4110,9 +4095,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) new_iir = I915_READ(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[RCS]); + notify_ring(&dev_priv->ring[RCS]); if (iir & I915_BSD_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[VCS]); + notify_ring(&dev_priv->ring[VCS]); for_each_pipe(dev_priv, pipe) { if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS && From 423795cbac3b6b1b9fea6845a9233ba2dcc61142 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:21:08 +0100 Subject: [PATCH 0113/3798] drm/i915: Prefer to check for idleness in worker rather than sync-flush Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a57fdd98b4fec0..95e46c7490ab73 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2411,7 +2411,6 @@ int __i915_add_request(struct intel_engine_cs *ring, i915_queue_hangcheck(ring->dev); - cancel_delayed_work_sync(&dev_priv->mm.idle_work); queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, round_jiffies_up_relative(HZ)); @@ -2797,6 +2796,12 @@ i915_gem_idle_work_handler(struct work_struct *work) struct drm_i915_private *dev_priv = container_of(work, typeof(*dev_priv), mm.idle_work.work); struct drm_device *dev = dev_priv->dev; + struct intel_engine_cs *ring; + int i; + + for_each_ring(ring, dev_priv, i) + if (!list_empty(&ring->request_list)) + return; intel_mark_idle(dev); From d7b9ca2f7a41cd36f5ca6c220df48ca9294ed37a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:21:09 +0100 Subject: [PATCH 0114/3798] drm/i915: Remove request->uniq We already assign a unique identifier to every request: seqno. That someone felt like adding a second one without even mentioning why and tweaking ABI smells very fishy. Fixes regression from commit b3a38998f042b862f5ba4d7f2268f3a8dfb4883a Author: Nick Hoath Date: Thu Feb 19 16:30:47 2015 +0000 drm/i915: Fix a use after free, and unbalanced refcounting v2: Rebase Signed-off-by: Chris Wilson Cc: Nick Hoath Cc: Thomas Daniel Cc: Daniel Vetter Cc: Jani Nikula [danvet: Fixup because different merge order.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 4 ---- drivers/gpu/drm/i915/i915_gem.c | 1 - drivers/gpu/drm/i915/i915_trace.h | 13 ++++--------- drivers/gpu/drm/i915/intel_lrc.c | 1 - 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0ddf6831a321b1..3668d613aeb816 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1823,8 +1823,6 @@ struct drm_i915_private { void (*stop_ring)(struct intel_engine_cs *ring); } gt; - uint32_t request_uniq; - /* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. @@ -2094,8 +2092,6 @@ struct drm_i915_gem_request { /** process identifier submitting this request */ struct pid *pid; - uint32_t uniq; - /** * The ELSP only accepts two elements at a time, so we queue * context/tail pairs on a given queue (ring->execlist_queue) until the diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 95e46c7490ab73..8d28a5d2437fbc 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2532,7 +2532,6 @@ int i915_gem_request_alloc(struct intel_engine_cs *ring, } rq->ring = ring; - rq->uniq = dev_priv->request_uniq++; if (i915.enable_execlists) ret = intel_logical_ring_alloc_request_extras(rq, ctx); diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 7bd48cd2c210b0..2aa140edbbd32d 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -505,7 +505,6 @@ DECLARE_EVENT_CLASS(i915_gem_request, TP_STRUCT__entry( __field(u32, dev) __field(u32, ring) - __field(u32, uniq) __field(u32, seqno) ), @@ -514,13 +513,11 @@ DECLARE_EVENT_CLASS(i915_gem_request, i915_gem_request_get_ring(req); __entry->dev = ring->dev->primary->index; __entry->ring = ring->id; - __entry->uniq = req ? req->uniq : 0; __entry->seqno = i915_gem_request_get_seqno(req); ), - TP_printk("dev=%u, ring=%u, uniq=%u, seqno=%u", - __entry->dev, __entry->ring, __entry->uniq, - __entry->seqno) + TP_printk("dev=%u, ring=%u, seqno=%u", + __entry->dev, __entry->ring, __entry->seqno) ); DEFINE_EVENT(i915_gem_request, i915_gem_request_add, @@ -565,7 +562,6 @@ TRACE_EVENT(i915_gem_request_wait_begin, TP_STRUCT__entry( __field(u32, dev) __field(u32, ring) - __field(u32, uniq) __field(u32, seqno) __field(bool, blocking) ), @@ -581,14 +577,13 @@ TRACE_EVENT(i915_gem_request_wait_begin, i915_gem_request_get_ring(req); __entry->dev = ring->dev->primary->index; __entry->ring = ring->id; - __entry->uniq = req ? req->uniq : 0; __entry->seqno = i915_gem_request_get_seqno(req); __entry->blocking = mutex_is_locked(&ring->dev->struct_mutex); ), - TP_printk("dev=%u, ring=%u, uniq=%u, seqno=%u, blocking=%s", - __entry->dev, __entry->ring, __entry->uniq, + TP_printk("dev=%u, ring=%u, seqno=%u, blocking=%s", + __entry->dev, __entry->ring, __entry->seqno, __entry->blocking ? "yes (NB)" : "no") ); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index ed28e7d8adeaaa..88c577cdd0386b 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -540,7 +540,6 @@ static int execlists_context_queue(struct intel_engine_cs *ring, request->ring = ring; request->ctx = to; kref_init(&request->ref); - request->uniq = dev_priv->request_uniq++; i915_gem_context_reference(request->ctx); } else { i915_gem_request_reference(request); From 149c86e74fe44dcbac5e9f8d145c5fbc5dc21261 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:21:11 +0100 Subject: [PATCH 0115/3798] drm/i915: Allocate context objects from stolen As we never expose context objects directly to userspace, we can forgo allocating a first-class GEM object for them and prefer to use the limited resource of reserved/stolen memory for them. Note this means that their initial contents are undefined. However, a downside of using stolen objects for execlists is that we cannot access the physical address directly (thanks MCH!) which prevents their use. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 4 +++- drivers/gpu/drm/i915/intel_lrc.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index f3e84c44d0091a..e4c57a3981b35e 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -157,7 +157,9 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size) struct drm_i915_gem_object *obj; int ret; - obj = i915_gem_alloc_object(dev, size); + obj = i915_gem_object_create_stolen(dev, size); + if (obj == NULL) + obj = i915_gem_alloc_object(dev, size); if (obj == NULL) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 88c577cdd0386b..aa3ea64e481562 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1845,7 +1845,7 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, context_size = round_up(get_lr_context_size(ring), 4096); - ctx_obj = i915_gem_alloc_context_obj(dev, context_size); + ctx_obj = i915_gem_alloc_object(dev, context_size); if (IS_ERR(ctx_obj)) { ret = PTR_ERR(ctx_obj); DRM_DEBUG_DRIVER("Alloc LRC backing obj failed: %d\n", ret); From f6234c1deedd7d35a09366dba8d92c523ff9cf09 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 17:28:17 +0100 Subject: [PATCH 0116/3798] drm/i915: Simplify object is-pinned checking for shrinker When looking for viable candidates to shrink, we only want objects that are not pinned. However to do so we performed a double iteration over the vma in the objects, first looking for the pin-count, then looking for allocations. We can do both at once and be slightly more explicit in our validity test. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_shrinker.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index f7929e76925070..f6ecbda2c60475 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -184,9 +184,12 @@ static int num_vma_bound(struct drm_i915_gem_object *obj) struct i915_vma *vma; int count = 0; - list_for_each_entry(vma, &obj->vma_list, vma_link) + list_for_each_entry(vma, &obj->vma_list, vma_link) { if (drm_mm_node_allocated(&vma->node)) count++; + if (vma->pin_count) + count++; + } return count; } @@ -210,8 +213,7 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) count += obj->base.size >> PAGE_SHIFT; list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { - if (!i915_gem_obj_is_pinned(obj) && - obj->pages_pin_count == num_vma_bound(obj)) + if (obj->pages_pin_count == num_vma_bound(obj)) count += obj->base.size >> PAGE_SHIFT; } From 8d90926139fa69100134917e200aec73607c543f Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Fri, 10 Apr 2015 11:38:31 +0300 Subject: [PATCH 0117/3798] drm/i915: Remove stale comment from __intel_set_mode() Since the following commit, the PLL calculations are done earlier, so the code following the comment doesn't do anything PLL or encoder related. It only updates the primary plane now. commit f3019a4d92f08b2dd92443a4b567a066a51c6ec0 Author: Ander Conselvan de Oliveira Date: Wed Oct 29 11:32:37 2014 +0200 drm/i915: Remove crtc_mode_set() hook Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 11b958a56515ae..d6698e58a27807 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11723,9 +11723,6 @@ static int __intel_set_mode(struct drm_crtc *crtc, modeset_update_crtc_power_domains(state); - /* Set up the DPLL and any encoders state that needs to adjust or depend - * on the DPLL. - */ for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) { struct drm_plane *primary = intel_crtc->base.primary; int vdisplay, hdisplay; From a4104c556ae3b6279a42b5d27901d255c452cab0 Mon Sep 17 00:00:00 2001 From: Sagar Kamble Date: Fri, 10 Apr 2015 14:11:29 +0530 Subject: [PATCH 0118/3798] drm/i915: Naming constants to be written to GEN9_PG_ENABLE Change-Id: I4253459c075c50d9b6f034b4ed4ad2f54cd7d1d7 Signed-off-by: Sagar Kamble Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 77d8874c2fc37c..4b48b3f92507a5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6198,6 +6198,8 @@ enum skl_disp_power_wells { #define GEN9_MEDIA_PG_IDLE_HYSTERESIS 0xA0C4 #define GEN9_RENDER_PG_IDLE_HYSTERESIS 0xA0C8 #define GEN9_PG_ENABLE 0xA210 +#define GEN9_RENDER_PG_ENABLE (1<<0) +#define GEN9_MEDIA_PG_ENABLE (1<<1) #define VLV_CHICKEN_3 (VLV_DISPLAY_BASE + 0x7040C) #define PIXEL_OVERLAP_CNT_MASK (3 << 30) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1ab9e897994aa5..e04ef19673a90a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4347,7 +4347,9 @@ static void gen9_enable_rc6(struct drm_device *dev) rc6_mask); /* 3b: Enable Coarse Power Gating only when RC6 is enabled */ - I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? 3 : 0); + I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? + (GEN9_RENDER_PG_ENABLE | GEN9_MEDIA_PG_ENABLE) : 0); + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); From d81063669a99b216eb6b9dfb17add4f38a839674 Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Fri, 10 Apr 2015 14:37:28 +0530 Subject: [PATCH 0119/3798] drm/i915/skl: Allow universal planes to position Signed-off-by: Sonika Jindal Reviewed-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d6698e58a27807..81110137206986 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12571,16 +12571,21 @@ intel_check_primary_plane(struct drm_plane *plane, struct drm_rect *dest = &state->dst; struct drm_rect *src = &state->src; const struct drm_rect *clip = &state->clip; + bool can_position = false; int ret; crtc = crtc ? crtc : plane->crtc; intel_crtc = to_intel_crtc(crtc); + if (INTEL_INFO(dev)->gen >= 9) + can_position = true; + ret = drm_plane_helper_check_update(plane, crtc, fb, src, dest, clip, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, - false, true, &state->visible); + can_position, true, + &state->visible); if (ret) return ret; From 3b7a5119b5d2def1161226a4c6a643db537dff7e Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Fri, 10 Apr 2015 14:37:29 +0530 Subject: [PATCH 0120/3798] drm/i915/skl: Support for 90/270 rotation v2: Moving creation of property in a function, checking for 90/270 rotation simultaneously (Chris) Letting primary plane to be positioned v3: Adding if/else for 90/270 and rest params programming, adding check for pixel_format, some cleanup (review comments) v4: Adding right pixel_formats, using src_* params instead of crtc_* for offset and size programming (Ville) v5: Rebased on -nightly and Tvrtko's series for gtt remapping. v6: Rebased on -nightly (Tvrtko's series merged) v7: Moving pixel_format check to intel_atomic_plane_check (Matt) Signed-off-by: Sonika Jindal Reviewed-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 2 + drivers/gpu/drm/i915/intel_atomic_plane.c | 24 +++++++ drivers/gpu/drm/i915/intel_display.c | 88 ++++++++++++++++------- drivers/gpu/drm/i915/intel_drv.h | 6 ++ drivers/gpu/drm/i915/intel_sprite.c | 52 ++++++++++---- 5 files changed, 131 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 4b48b3f92507a5..1d58d9c587c09e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4866,7 +4866,9 @@ enum skl_disp_power_wells { #define PLANE_CTL_ALPHA_HW_PREMULTIPLY ( 3 << 4) #define PLANE_CTL_ROTATE_MASK 0x3 #define PLANE_CTL_ROTATE_0 0x0 +#define PLANE_CTL_ROTATE_90 0x1 #define PLANE_CTL_ROTATE_180 0x2 +#define PLANE_CTL_ROTATE_270 0x3 #define _PLANE_STRIDE_1_A 0x70188 #define _PLANE_STRIDE_2_A 0x70288 #define _PLANE_STRIDE_3_A 0x70388 diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index 976b8915657077..a27ee8cbb62751 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -162,6 +162,30 @@ static int intel_plane_atomic_check(struct drm_plane *plane, (1 << drm_plane_index(plane)); } + if (state->fb && intel_rotation_90_or_270(state->rotation)) { + if (!(state->fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || + state->fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) { + DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n"); + return -EINVAL; + } + + /* + * 90/270 is not allowed with RGB64 16:16:16:16, + * RGB 16-bit 5:6:5, and Indexed 8-bit. + * TBD: Add RGB64 case once its added in supported format list. + */ + switch (state->fb->pixel_format) { + case DRM_FORMAT_C8: + case DRM_FORMAT_RGB565: + DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", + drm_get_format_name(state->fb->pixel_format)); + return -EINVAL; + + default: + break; + } + } + return intel_plane->check_plane(plane, intel_state); } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 81110137206986..a0be6ab7ba7b99 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2338,13 +2338,6 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, info->pitch = fb->pitches[0]; info->fb_modifier = fb->modifier[0]; - if (!(info->fb_modifier == I915_FORMAT_MOD_Y_TILED || - info->fb_modifier == I915_FORMAT_MOD_Yf_TILED)) { - DRM_DEBUG_KMS( - "Y or Yf tiling is needed for 90/270 rotation!\n"); - return -EINVAL; - } - return 0; } @@ -2945,8 +2938,12 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_i915_gem_object *obj; int pipe = intel_crtc->pipe; - u32 plane_ctl, stride_div; + u32 plane_ctl, stride_div, stride; + u32 tile_height, plane_offset, plane_size; + unsigned int rotation; + int x_offset, y_offset; unsigned long surf_addr; + struct drm_plane *plane; if (!intel_crtc->primary_enabled) { I915_WRITE(PLANE_CTL(pipe, 0), 0); @@ -3007,21 +3004,51 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, } plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE; - if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) + + plane = crtc->primary; + rotation = plane->state->rotation; + switch (rotation) { + case BIT(DRM_ROTATE_90): + plane_ctl |= PLANE_CTL_ROTATE_90; + break; + + case BIT(DRM_ROTATE_180): plane_ctl |= PLANE_CTL_ROTATE_180; + break; + + case BIT(DRM_ROTATE_270): + plane_ctl |= PLANE_CTL_ROTATE_270; + break; + } obj = intel_fb_obj(fb); stride_div = intel_fb_stride_alignment(dev, fb->modifier[0], fb->pixel_format); - surf_addr = intel_plane_obj_offset(to_intel_plane(crtc->primary), obj); + surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj); + + if (intel_rotation_90_or_270(rotation)) { + /* stride = Surface height in tiles */ + tile_height = intel_tile_height(dev, fb->bits_per_pixel, + fb->modifier[0]); + stride = DIV_ROUND_UP(fb->height, tile_height); + x_offset = stride * tile_height - y - (plane->state->src_h >> 16); + y_offset = x; + plane_size = ((plane->state->src_w >> 16) - 1) << 16 | + ((plane->state->src_h >> 16) - 1); + } else { + stride = fb->pitches[0] / stride_div; + x_offset = x; + y_offset = y; + plane_size = ((plane->state->src_h >> 16) - 1) << 16 | + ((plane->state->src_w >> 16) - 1); + } + plane_offset = y_offset << 16 | x_offset; I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl); I915_WRITE(PLANE_POS(pipe, 0), 0); - I915_WRITE(PLANE_OFFSET(pipe, 0), (y << 16) | x); - I915_WRITE(PLANE_SIZE(pipe, 0), - (intel_crtc->config->pipe_src_h - 1) << 16 | - (intel_crtc->config->pipe_src_w - 1)); - I915_WRITE(PLANE_STRIDE(pipe, 0), fb->pitches[0] / stride_div); + I915_WRITE(PLANE_OFFSET(pipe, 0), plane_offset); + I915_WRITE(PLANE_SIZE(pipe, 0), plane_size); + I915_WRITE(PLANE_STRIDE(pipe, 0), stride); I915_WRITE(PLANE_SURF(pipe, 0), surf_addr); POSTING_READ(PLANE_SURF(pipe, 0)); @@ -12827,23 +12854,32 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, intel_primary_formats, num_formats, DRM_PLANE_TYPE_PRIMARY); - if (INTEL_INFO(dev)->gen >= 4) { - if (!dev->mode_config.rotation_property) - dev->mode_config.rotation_property = - drm_mode_create_rotation_property(dev, - BIT(DRM_ROTATE_0) | - BIT(DRM_ROTATE_180)); - if (dev->mode_config.rotation_property) - drm_object_attach_property(&primary->base.base, - dev->mode_config.rotation_property, - state->base.rotation); - } + if (INTEL_INFO(dev)->gen >= 4) + intel_create_rotation_property(dev, primary); drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs); return &primary->base; } +void intel_create_rotation_property(struct drm_device *dev, struct intel_plane *plane) +{ + if (!dev->mode_config.rotation_property) { + unsigned long flags = BIT(DRM_ROTATE_0) | + BIT(DRM_ROTATE_180); + + if (INTEL_INFO(dev)->gen >= 9) + flags |= BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270); + + dev->mode_config.rotation_property = + drm_mode_create_rotation_property(dev, flags); + } + if (dev->mode_config.rotation_property) + drm_object_attach_property(&plane->base.base, + dev->mode_config.rotation_property, + plane->base.state->rotation); +} + static int intel_check_cursor_plane(struct drm_plane *plane, struct intel_plane_state *state) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index efa53d57dd37a9..7a0aa2431bc0e9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -996,6 +996,12 @@ intel_rotation_90_or_270(unsigned int rotation) return rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270)); } +unsigned int +intel_tile_height(struct drm_device *dev, uint32_t bits_per_pixel, + uint64_t fb_modifier); +void intel_create_rotation_property(struct drm_device *dev, + struct intel_plane *plane); + bool intel_wm_need_update(struct drm_plane *plane, struct drm_plane_state *state); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index f009c8f970eafb..21682a8b60a377 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -190,10 +190,13 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, struct drm_i915_gem_object *obj = intel_fb_obj(fb); const int pipe = intel_plane->pipe; const int plane = intel_plane->plane + 1; - u32 plane_ctl, stride_div; + u32 plane_ctl, stride_div, stride; int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); const struct drm_intel_sprite_colorkey *key = &intel_plane->ckey; unsigned long surf_addr; + u32 tile_height, plane_offset, plane_size; + unsigned int rotation; + int x_offset, y_offset; plane_ctl = PLANE_CTL_ENABLE | PLANE_CTL_PIPE_CSC_ENABLE; @@ -254,8 +257,20 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, MISSING_CASE(fb->modifier[0]); } - if (drm_plane->state->rotation == BIT(DRM_ROTATE_180)) + rotation = drm_plane->state->rotation; + switch (rotation) { + case BIT(DRM_ROTATE_90): + plane_ctl |= PLANE_CTL_ROTATE_90; + break; + + case BIT(DRM_ROTATE_180): plane_ctl |= PLANE_CTL_ROTATE_180; + break; + + case BIT(DRM_ROTATE_270): + plane_ctl |= PLANE_CTL_ROTATE_270; + break; + } intel_update_sprite_watermarks(drm_plane, crtc, src_w, src_h, pixel_size, true, @@ -283,10 +298,26 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, surf_addr = intel_plane_obj_offset(intel_plane, obj); - I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x); - I915_WRITE(PLANE_STRIDE(pipe, plane), fb->pitches[0] / stride_div); + if (intel_rotation_90_or_270(rotation)) { + /* stride: Surface height in tiles */ + tile_height = intel_tile_height(dev, fb->bits_per_pixel, + fb->modifier[0]); + stride = DIV_ROUND_UP(fb->height, tile_height); + plane_size = (src_w << 16) | src_h; + x_offset = stride * tile_height - y - (src_h + 1); + y_offset = x; + } else { + stride = fb->pitches[0] / stride_div; + plane_size = (src_h << 16) | src_w; + x_offset = x; + y_offset = y; + } + plane_offset = y_offset << 16 | x_offset; + + I915_WRITE(PLANE_OFFSET(pipe, plane), plane_offset); + I915_WRITE(PLANE_STRIDE(pipe, plane), stride); I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x); - I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w); + I915_WRITE(PLANE_SIZE(pipe, plane), plane_size); I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl); I915_WRITE(PLANE_SURF(pipe, plane), surf_addr); POSTING_READ(PLANE_SURF(pipe, plane)); @@ -1286,16 +1317,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) goto out; } - if (!dev->mode_config.rotation_property) - dev->mode_config.rotation_property = - drm_mode_create_rotation_property(dev, - BIT(DRM_ROTATE_0) | - BIT(DRM_ROTATE_180)); - - if (dev->mode_config.rotation_property) - drm_object_attach_property(&intel_plane->base.base, - dev->mode_config.rotation_property, - state->base.rotation); + intel_create_rotation_property(dev, intel_plane); drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); From 1d335d1b62dd8475317d20e3f95072515243a810 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Fri, 10 Apr 2015 15:54:58 +0300 Subject: [PATCH 0121/3798] drm/i915: Move vm page allocation in proper place Move to i915_vma_bind as it is part of the binding. Suggested-by: Chris Wilson Cc: Michel Thierry Signed-off-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 11 ----------- drivers/gpu/drm/i915/i915_gem_gtt.c | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8d28a5d2437fbc..8ce363aa492c99 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3556,17 +3556,6 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, if (ret) goto err_remove_node; - /* allocate before insert / bind */ - if (vma->vm->allocate_va_range) { - trace_i915_va_alloc(vma->vm, vma->node.start, vma->node.size, - VM_TO_TRACE_NAME(vma->vm)); - ret = vma->vm->allocate_va_range(vma->vm, - vma->node.start, - vma->node.size); - if (ret) - goto err_remove_node; - } - trace_i915_vma_bind(vma, flags); ret = i915_vma_bind(vma, obj->cache_level, flags & PIN_GLOBAL ? GLOBAL_BIND : 0); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 559cecaccf7ff2..0b679143772aec 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2927,8 +2927,22 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma) int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags) { + int ret; + + if (vma->vm->allocate_va_range) { + trace_i915_va_alloc(vma->vm, vma->node.start, + vma->node.size, + VM_TO_TRACE_NAME(vma->vm)); + + ret = vma->vm->allocate_va_range(vma->vm, + vma->node.start, + vma->node.size); + if (ret) + return ret; + } + if (i915_is_ggtt(vma->vm)) { - int ret = i915_get_ggtt_vma_pages(vma); + ret = i915_get_ggtt_vma_pages(vma); if (ret) return ret; From 249e87de5f2a5dd9176d4c316b35462f22c9d6dc Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 10 Apr 2015 16:59:32 +0300 Subject: [PATCH 0122/3798] drm/i915: fix build for DEBUG_FS=n Fix DEBUG_FS=n build broken by commit aa7471d228eb6dfddd0d201ea9746d6a2020972a Author: Jani Nikula Date: Wed Apr 1 11:15:21 2015 +0300 drm/i915: add i915 specific connector debugfs file for DPCD Reported-by: kbuild test robot Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3668d613aeb816..6bdd1a6b395d22 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3029,10 +3029,11 @@ int i915_verify_lists(struct drm_device *dev); /* i915_debugfs.c */ int i915_debugfs_init(struct drm_minor *minor); void i915_debugfs_cleanup(struct drm_minor *minor); -int i915_debugfs_connector_add(struct drm_connector *connector); #ifdef CONFIG_DEBUG_FS +int i915_debugfs_connector_add(struct drm_connector *connector); void intel_display_crc_init(struct drm_device *dev); #else +static inline int i915_debugfs_connector_add(struct drm_connector *connector) {} static inline void intel_display_crc_init(struct drm_device *dev) {} #endif From a6631bc8d60d4c3159bc3dd0897664096f9e9ccd Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Fri, 10 Apr 2015 11:24:27 +0100 Subject: [PATCH 0123/3798] drm/i915: Remove unused variable from execlists_context_queue After commit d7b9ca2f7a41cd36f5ca6c220df48ca9294ed37a ("drm/i915: Remove request->uniq") dev_priv is no longer needed. Cc: Chris Wilson Signed-off-by: Michel Thierry Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index aa3ea64e481562..0fc35dd8a15cb4 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -523,7 +523,6 @@ static int execlists_context_queue(struct intel_engine_cs *ring, struct drm_i915_gem_request *request) { struct drm_i915_gem_request *cursor; - struct drm_i915_private *dev_priv = ring->dev->dev_private; int num_elements = 0; if (to != ring->default_context) From 9bdbd0b911086d03a27e1fe9531b41f5411ccfac Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Fri, 10 Apr 2015 10:59:10 +0300 Subject: [PATCH 0124/3798] drm/i915: Allocate connector state together with the connectors Connector states were being allocated in intel_setup_outputs() in loop over all connectors. That meant hot-added connectors would have a NULL state. Since the change to use a struct drm_atomic_state for the legacy modeset, connector states are necessary for the i915 driver to function properly, so that would lead to oopses. v2: Fix test for intel_connector_init() success in lvds and sdvo (PRTS) Signed-off-by: Ander Conselvan de Oliveira Reported-and-tested-by: Nicolas Kalkhof Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 2 +- drivers/gpu/drm/i915/intel_ddi.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 62 +++++++++++++--------------- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_dp_mst.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_dsi.c | 2 +- drivers/gpu/drm/i915/intel_dvo.c | 2 +- drivers/gpu/drm/i915/intel_hdmi.c | 2 +- drivers/gpu/drm/i915/intel_lvds.c | 6 +++ drivers/gpu/drm/i915/intel_sdvo.c | 22 ++++++++-- drivers/gpu/drm/i915/intel_tv.c | 2 +- 12 files changed, 64 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index fa5699c8452b0a..93bb5159d09350 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -851,7 +851,7 @@ void intel_crt_init(struct drm_device *dev) if (!crt) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) { kfree(crt); return; diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 8c692d8a3ef60b..486f6fa68db1d8 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2101,7 +2101,7 @@ intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port) struct intel_connector *connector; enum port port = intel_dig_port->port; - connector = kzalloc(sizeof(*connector), GFP_KERNEL); + connector = intel_connector_alloc(); if (!connector) return NULL; @@ -2120,7 +2120,7 @@ intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port) struct intel_connector *connector; enum port port = intel_dig_port->port; - connector = kzalloc(sizeof(*connector), GFP_KERNEL); + connector = intel_connector_alloc(); if (!connector) return NULL; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a0be6ab7ba7b99..4a074aa685e6a0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5685,6 +5685,34 @@ static void intel_connector_check_state(struct intel_connector *connector) } } +int intel_connector_init(struct intel_connector *connector) +{ + struct drm_connector_state *connector_state; + + connector_state = kzalloc(sizeof *connector_state, GFP_KERNEL); + if (!connector_state) + return -ENOMEM; + + connector->base.state = connector_state; + return 0; +} + +struct intel_connector *intel_connector_alloc(void) +{ + struct intel_connector *connector; + + connector = kzalloc(sizeof *connector, GFP_KERNEL); + if (!connector) + return NULL; + + if (intel_connector_init(connector) < 0) { + kfree(connector); + return NULL; + } + + return connector; +} + /* Even simpler default implementation, if there's really no special case to * consider. */ void intel_connector_dpms(struct drm_connector *connector, int mode) @@ -13187,7 +13215,6 @@ static void intel_setup_outputs(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *encoder; - struct drm_connector *connector; bool dpd_is_edp = false; intel_lvds_init(dev); @@ -13323,39 +13350,6 @@ static void intel_setup_outputs(struct drm_device *dev) if (SUPPORTS_TV(dev)) intel_tv_init(dev); - /* - * FIXME: We don't have full atomic support yet, but we want to be - * able to enable/test plane updates via the atomic interface in the - * meantime. However as soon as we flip DRIVER_ATOMIC on, the DRM core - * will take some atomic codepaths to lookup properties during - * drmModeGetConnector() that unconditionally dereference - * connector->state. - * - * We create a dummy connector state here for each connector to ensure - * the DRM core doesn't try to dereference a NULL connector->state. - * The actual connector properties will never be updated or contain - * useful information, but since we're doing this specifically for - * testing/debug of the plane operations (and only when a specific - * kernel module option is given), that shouldn't really matter. - * - * We are also relying on these states to convert the legacy mode set - * to use a drm_atomic_state struct. The states are kept consistent - * with actual state, so that it is safe to rely on that instead of - * the staged config. - * - * Once atomic support for crtc's + connectors lands, this loop should - * be removed since we'll be setting up real connector state, which - * will contain Intel-specific properties. - */ - list_for_each_entry(connector, - &dev->mode_config.connector_list, - head) { - if (!WARN_ON(connector->state)) { - connector->state = kzalloc(sizeof(*connector->state), - GFP_KERNEL); - } - } - intel_psr_init(dev); for_each_intel_encoder(dev, encoder) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1b87969536ffc8..589cd92d5c303f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5602,7 +5602,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) if (!intel_dig_port) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) { kfree(intel_dig_port); return; diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index adcc5e641347db..73350894e2c960 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -415,7 +415,7 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo struct drm_connector *connector; int i; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) return NULL; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7a0aa2431bc0e9..638024fcc8ffdf 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -928,6 +928,8 @@ void intel_crtc_restore_mode(struct drm_crtc *crtc); void intel_crtc_control(struct drm_crtc *crtc, bool enable); void intel_crtc_update_dpms(struct drm_crtc *crtc); void intel_encoder_destroy(struct drm_encoder *encoder); +int intel_connector_init(struct intel_connector *); +struct intel_connector *intel_connector_alloc(void); void intel_connector_dpms(struct drm_connector *, int mode); bool intel_connector_get_hw_state(struct intel_connector *connector); void intel_modeset_check_state(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 572251e9810bc4..51966426addfbd 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -1007,7 +1007,7 @@ void intel_dsi_init(struct drm_device *dev) if (!intel_dsi) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) { kfree(intel_dsi); return; diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 9a27ec7100efa0..7c9f85285aeaa2 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -469,7 +469,7 @@ void intel_dvo_init(struct drm_device *dev) if (!intel_dvo) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) { kfree(intel_dvo); return; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 26222e6c1ff343..02252d9a0cc3b0 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1755,7 +1755,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) if (!intel_dig_port) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) { kfree(intel_dig_port); return; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 314a5d56ace25c..9a9df0fa67f99d 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -946,6 +946,12 @@ void intel_lvds_init(struct drm_device *dev) return; } + if (intel_connector_init(&lvds_connector->base) < 0) { + kfree(lvds_connector); + kfree(lvds_encoder); + return; + } + lvds_encoder->attached_connector = lvds_connector; intel_encoder = &lvds_encoder->base; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index b121796c86aa91..10cd3325283870 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2427,6 +2427,22 @@ intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo, } } +static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void) +{ + struct intel_sdvo_connector *sdvo_connector; + + sdvo_connector = kzalloc(sizeof(*sdvo_connector), GFP_KERNEL); + if (!sdvo_connector) + return NULL; + + if (intel_connector_init(&sdvo_connector->base) < 0) { + kfree(sdvo_connector); + return NULL; + } + + return sdvo_connector; +} + static bool intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) { @@ -2438,7 +2454,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) DRM_DEBUG_KMS("initialising DVI device %d\n", device); - intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = intel_sdvo_connector_alloc(); if (!intel_sdvo_connector) return false; @@ -2492,7 +2508,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) DRM_DEBUG_KMS("initialising TV type %d\n", type); - intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = intel_sdvo_connector_alloc(); if (!intel_sdvo_connector) return false; @@ -2571,7 +2587,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) DRM_DEBUG_KMS("initialising LVDS device %d\n", device); - intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = intel_sdvo_connector_alloc(); if (!intel_sdvo_connector) return false; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index bc1d9d74090411..8b9d325bda3c7e 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1621,7 +1621,7 @@ intel_tv_init(struct drm_device *dev) return; } - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = intel_connector_alloc(); if (!intel_connector) { kfree(intel_tv); return; From cb07bae0c47c5b66e8e1cc94988d8b48a415ec7d Mon Sep 17 00:00:00 2001 From: Sagar Kamble Date: Sun, 12 Apr 2015 11:28:14 +0530 Subject: [PATCH 0125/3798] drm/i915: Disable Render power gating When RC6 along with Render power gating is enabled, GPU hang happens due to lack of synchronization between GTI and Render power gating. v2: Updated commit message and WA name (Damien) Change-Id: If1614206341eb52a21eadae8c5ebb2655029b50c Reviewed-by: Damien Lespiau Signed-off-by: Sagar Kamble Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e04ef19673a90a..fc7e0c7545fdad 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4346,9 +4346,12 @@ static void gen9_enable_rc6(struct drm_device *dev) GEN6_RC_CTL_EI_MODE(1) | rc6_mask); - /* 3b: Enable Coarse Power Gating only when RC6 is enabled */ + /* + * 3b: Enable Coarse Power Gating only when RC6 is enabled. + * WaDisableRenderPowerGating:skl,bxt - Render PG need to be disabled with RC6. + */ I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? - (GEN9_RENDER_PG_ENABLE | GEN9_MEDIA_PG_ENABLE) : 0); + GEN9_MEDIA_PG_ENABLE : 0); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); From 1c9a2d4ace0d93ac4e0ef3b7cf6b7fd51d6af189 Mon Sep 17 00:00:00 2001 From: Chandra Konduru Date: Tue, 7 Apr 2015 15:28:35 -0700 Subject: [PATCH 0126/3798] drm/i915: Register definitions for skylake scalers Adding register definitions for skylake scalers. v2: -add #define for plane selection mask (me) Signed-off-by: Chandra Konduru Reviewed-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 115 ++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1d58d9c587c09e..da5c86acace5bc 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5110,6 +5110,121 @@ enum skl_disp_power_wells { #define PS_WIN_SZ(pipe) _PIPE(pipe, _PSA_WIN_SZ, _PSB_WIN_SZ) #define PS_WIN_POS(pipe) _PIPE(pipe, _PSA_WIN_POS, _PSB_WIN_POS) +/* + * Skylake scalers + */ +#define _PS_1A_CTRL 0x68180 +#define _PS_2A_CTRL 0x68280 +#define _PS_1B_CTRL 0x68980 +#define _PS_2B_CTRL 0x68A80 +#define _PS_1C_CTRL 0x69180 +#define PS_SCALER_EN (1 << 31) +#define PS_SCALER_MODE_MASK (3 << 28) +#define PS_SCALER_MODE_DYN (0 << 28) +#define PS_SCALER_MODE_HQ (1 << 28) +#define PS_PLANE_SEL_MASK (7 << 25) +#define PS_PLANE_SEL(plane) ((plane + 1) << 25) +#define PS_FILTER_MASK (3 << 23) +#define PS_FILTER_MEDIUM (0 << 23) +#define PS_FILTER_EDGE_ENHANCE (2 << 23) +#define PS_FILTER_BILINEAR (3 << 23) +#define PS_VERT3TAP (1 << 21) +#define PS_VERT_INT_INVERT_FIELD1 (0 << 20) +#define PS_VERT_INT_INVERT_FIELD0 (1 << 20) +#define PS_PWRUP_PROGRESS (1 << 17) +#define PS_V_FILTER_BYPASS (1 << 8) +#define PS_VADAPT_EN (1 << 7) +#define PS_VADAPT_MODE_MASK (3 << 5) +#define PS_VADAPT_MODE_LEAST_ADAPT (0 << 5) +#define PS_VADAPT_MODE_MOD_ADAPT (1 << 5) +#define PS_VADAPT_MODE_MOST_ADAPT (3 << 5) + +#define _PS_PWR_GATE_1A 0x68160 +#define _PS_PWR_GATE_2A 0x68260 +#define _PS_PWR_GATE_1B 0x68960 +#define _PS_PWR_GATE_2B 0x68A60 +#define _PS_PWR_GATE_1C 0x69160 +#define PS_PWR_GATE_DIS_OVERRIDE (1 << 31) +#define PS_PWR_GATE_SETTLING_TIME_32 (0 << 3) +#define PS_PWR_GATE_SETTLING_TIME_64 (1 << 3) +#define PS_PWR_GATE_SETTLING_TIME_96 (2 << 3) +#define PS_PWR_GATE_SETTLING_TIME_128 (3 << 3) +#define PS_PWR_GATE_SLPEN_8 0 +#define PS_PWR_GATE_SLPEN_16 1 +#define PS_PWR_GATE_SLPEN_24 2 +#define PS_PWR_GATE_SLPEN_32 3 + +#define _PS_WIN_POS_1A 0x68170 +#define _PS_WIN_POS_2A 0x68270 +#define _PS_WIN_POS_1B 0x68970 +#define _PS_WIN_POS_2B 0x68A70 +#define _PS_WIN_POS_1C 0x69170 + +#define _PS_WIN_SZ_1A 0x68174 +#define _PS_WIN_SZ_2A 0x68274 +#define _PS_WIN_SZ_1B 0x68974 +#define _PS_WIN_SZ_2B 0x68A74 +#define _PS_WIN_SZ_1C 0x69174 + +#define _PS_VSCALE_1A 0x68184 +#define _PS_VSCALE_2A 0x68284 +#define _PS_VSCALE_1B 0x68984 +#define _PS_VSCALE_2B 0x68A84 +#define _PS_VSCALE_1C 0x69184 + +#define _PS_HSCALE_1A 0x68190 +#define _PS_HSCALE_2A 0x68290 +#define _PS_HSCALE_1B 0x68990 +#define _PS_HSCALE_2B 0x68A90 +#define _PS_HSCALE_1C 0x69190 + +#define _PS_VPHASE_1A 0x68188 +#define _PS_VPHASE_2A 0x68288 +#define _PS_VPHASE_1B 0x68988 +#define _PS_VPHASE_2B 0x68A88 +#define _PS_VPHASE_1C 0x69188 + +#define _PS_HPHASE_1A 0x68194 +#define _PS_HPHASE_2A 0x68294 +#define _PS_HPHASE_1B 0x68994 +#define _PS_HPHASE_2B 0x68A94 +#define _PS_HPHASE_1C 0x69194 + +#define _PS_ECC_STAT_1A 0x681D0 +#define _PS_ECC_STAT_2A 0x682D0 +#define _PS_ECC_STAT_1B 0x689D0 +#define _PS_ECC_STAT_2B 0x68AD0 +#define _PS_ECC_STAT_1C 0x691D0 + +#define _ID(id, a, b) ((a) + (id)*((b)-(a))) +#define SKL_PS_CTRL(pipe, id) _PIPE(pipe, \ + _ID(id, _PS_1A_CTRL, _PS_2A_CTRL), \ + _ID(id, _PS_1B_CTRL, _PS_2B_CTRL)) +#define SKL_PS_PWR_GATE(pipe, id) _PIPE(pipe, \ + _ID(id, _PS_PWR_GATE_1A, _PS_PWR_GATE_2A), \ + _ID(id, _PS_PWR_GATE_1B, _PS_PWR_GATE_2B)) +#define SKL_PS_WIN_POS(pipe, id) _PIPE(pipe, \ + _ID(id, _PS_WIN_POS_1A, _PS_WIN_POS_2A), \ + _ID(id, _PS_WIN_POS_1B, _PS_WIN_POS_2B)) +#define SKL_PS_WIN_SZ(pipe, id) _PIPE(pipe, \ + _ID(id, _PS_WIN_SZ_1A, _PS_WIN_SZ_2A), \ + _ID(id, _PS_WIN_SZ_1B, _PS_WIN_SZ_2B)) +#define SKL_PS_VSCALE(pipe, id) _PIPE(pipe, \ + _ID(id, _PS_VSCALE_1A, _PS_VSCALE_2A), \ + _ID(id, _PS_VSCALE_1B, _PS_VSCALE_2B)) +#define SKL_PS_HSCALE(pipe, id) _PIPE(pipe, \ + _ID(id, _PS_HSCALE_1A, _PS_HSCALE_2A), \ + _ID(id, _PS_HSCALE_1B, _PS_HSCALE_2B)) +#define SKL_PS_VPHASE(pipe, id) _PIPE(pipe, \ + _ID(id, _PS_VPHASE_1A, _PS_VPHASE_2A), \ + _ID(id, _PS_VPHASE_1B, _PS_VPHASE_2B)) +#define SKL_PS_HPHASE(pipe, id) _PIPE(pipe, \ + _ID(id, _PS_HPHASE_1A, _PS_HPHASE_2A), \ + _ID(id, _PS_HPHASE_1B, _PS_HPHASE_2B)) +#define SKL_PS_ECC_STAT(pipe, id) _PIPE(pipe, \ + _ID(id, _PS_ECC_STAT_1A, _PS_ECC_STAT_2A), \ + _ID(id, _PS_ECC_STAT_1B, _PS_ECC_STAT_2B) + /* legacy palette */ #define _LGC_PALETTE_A 0x4a000 #define _LGC_PALETTE_B 0x4a800 From be41e336c72c74f439d2f8bf996f5daa6a8b5e3c Mon Sep 17 00:00:00 2001 From: Chandra Konduru Date: Tue, 7 Apr 2015 15:28:36 -0700 Subject: [PATCH 0127/3798] drm/i915: skylake scaler structure definitions skylake scaler structure definitions. scalers live in crtc_state as they are pipe resources. They can be used either as plane scaler or panel fitter. scaler assigned to either plane (for plane scaling) or crtc (for panel fitting) is saved in scaler_id in plane_state or crtc_state respectively. scaler_id is used instead of scaler pointer in plane or crtc state to avoid updating scaler pointer everytime a new crtc_state is created. v2: -made single copy of min/max values for scalers (Matt) v3: -updated commentary for scaler_id (me) v4: -converted src/dst ranges to #defines, dropped ratios (Matt) Signed-off-by: Chandra Konduru Reviewed-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 68 ++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 638024fcc8ffdf..40112751ca6eb8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -256,6 +256,26 @@ struct intel_plane_state { * enable/disable the primary plane */ bool hides_primary; + + /* + * scaler_id + * = -1 : not using a scaler + * >= 0 : using a scalers + * + * plane requiring a scaler: + * - During check_plane, its bit is set in + * crtc_state->scaler_state.scaler_users by calling helper function + * update_scaler_users. + * - scaler_id indicates the scaler it got assigned. + * + * plane doesn't require a scaler: + * - this can happen when scaling is no more required or plane simply + * got disabled. + * - During check_plane, corresponding bit is reset in + * crtc_state->scaler_state.scaler_users by calling helper function + * update_scaler_users. + */ + int scaler_id; }; struct intel_initial_plane_config { @@ -265,6 +285,49 @@ struct intel_initial_plane_config { u32 base; }; +#define SKL_MIN_SRC_W 8 +#define SKL_MAX_SRC_W 4096 +#define SKL_MIN_SRC_H 8 +#define SKL_MAX_SRC_H 2304 +#define SKL_MIN_DST_W 8 +#define SKL_MAX_DST_W 4096 +#define SKL_MIN_DST_H 8 +#define SKL_MAX_DST_H 2304 + +struct intel_scaler { + int id; + int in_use; + uint32_t mode; +}; + +struct intel_crtc_scaler_state { +#define SKL_NUM_SCALERS 2 + struct intel_scaler scalers[SKL_NUM_SCALERS]; + + /* + * scaler_users: keeps track of users requesting scalers on this crtc. + * + * If a bit is set, a user is using a scaler. + * Here user can be a plane or crtc as defined below: + * bits 0-30 - plane (bit position is index from drm_plane_index) + * bit 31 - crtc + * + * Instead of creating a new index to cover planes and crtc, using + * existing drm_plane_index for planes which is well less than 31 + * planes and bit 31 for crtc. This should be fine to cover all + * our platforms. + * + * intel_atomic_setup_scalers will setup available scalers to users + * requesting scalers. It will gracefully fail if request exceeds + * avilability. + */ +#define SKL_CRTC_INDEX 31 + unsigned scaler_users; + + /* scaler used by crtc for panel fitting purpose */ + int scaler_id; +}; + struct intel_crtc_state { struct drm_crtc_state base; @@ -391,6 +454,8 @@ struct intel_crtc_state { bool dp_encoder_is_mst; int pbn; + + struct intel_crtc_scaler_state scaler_state; }; struct intel_pipe_wm { @@ -492,6 +557,9 @@ struct intel_crtc { struct intel_mmio_flip mmio_flip; struct intel_crtc_atomic_commit atomic; + + /* scalers available on this crtc */ + int num_scalers; }; struct intel_plane_wm_parameters { From 08e221fbf69a1e8da66526b340560e99e3e4eed9 Mon Sep 17 00:00:00 2001 From: Chandra Konduru Date: Tue, 7 Apr 2015 15:28:37 -0700 Subject: [PATCH 0128/3798] drm/i915: Initialize plane colorkey to NONE This patch initializes plane colorkey to NONE. Signed-off-by: Chandra Konduru Reviewed-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 1 + drivers/gpu/drm/i915/intel_sprite.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4a074aa685e6a0..d98d5f239dd70e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12866,6 +12866,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, primary->plane = pipe; primary->check_plane = intel_check_primary_plane; primary->commit_plane = intel_commit_primary_plane; + primary->ckey.flags = I915_SET_COLORKEY_NONE; if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) primary->plane = !pipe; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 21682a8b60a377..7d1a5b86d06c26 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1307,6 +1307,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) intel_plane->plane = plane; intel_plane->check_plane = intel_check_sprite_plane; intel_plane->commit_plane = intel_commit_sprite_plane; + intel_plane->ckey.flags = I915_SET_COLORKEY_NONE; possible_crtcs = (1 << pipe); ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs, &intel_plane_funcs, From 549e2bfb54905c734aae77d2cdb809a7acaefeeb Mon Sep 17 00:00:00 2001 From: Chandra Konduru Date: Tue, 7 Apr 2015 15:28:38 -0700 Subject: [PATCH 0129/3798] drm/i915: Initialize skylake scalers Initializing scalers with supported values during crtc init. v2: -initialize single copy of min/max values (Matt) v3: -moved gen check to callsite (Matt) v4: -squashed planes begin with no scaler to here (me) v5: -updated init function with updated scaler state structure (Matt) Signed-off-by: Chandra Konduru Reviewed-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 32 ++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_sprite.c | 1 + 2 files changed, 33 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d98d5f239dd70e..402fad0870ba25 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -103,6 +103,8 @@ static void chv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); static void intel_begin_crtc_commit(struct drm_crtc *crtc); static void intel_finish_crtc_commit(struct drm_crtc *crtc); +static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc, + struct intel_crtc_state *crtc_state); static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe) { @@ -12862,6 +12864,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, primary->can_scale = false; primary->max_downscale = 1; + state->scaler_id = -1; primary->pipe = pipe; primary->plane = pipe; primary->check_plane = intel_check_primary_plane; @@ -13026,6 +13029,7 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, cursor->max_downscale = 1; cursor->pipe = pipe; cursor->plane = pipe; + state->scaler_id = -1; cursor->check_plane = intel_check_cursor_plane; cursor->commit_plane = intel_commit_cursor_plane; @@ -13052,6 +13056,24 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, return &cursor->base; } +static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc, + struct intel_crtc_state *crtc_state) +{ + int i; + struct intel_scaler *intel_scaler; + struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; + + for (i = 0; i < intel_crtc->num_scalers; i++) { + intel_scaler = &scaler_state->scalers[i]; + intel_scaler->in_use = 0; + intel_scaler->id = i; + + intel_scaler->mode = PS_SCALER_MODE_DYN; + } + + scaler_state->scaler_id = -1; +} + static void intel_crtc_init(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -13071,6 +13093,16 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc_set_state(intel_crtc, crtc_state); crtc_state->base.crtc = &intel_crtc->base; + /* initialize shared scalers */ + if (INTEL_INFO(dev)->gen >= 9) { + if (pipe == PIPE_C) + intel_crtc->num_scalers = 1; + else + intel_crtc->num_scalers = SKL_NUM_SCALERS; + + skl_init_scalers(dev, intel_crtc, crtc_state); + } + primary = intel_primary_plane_create(dev, pipe); if (!primary) goto fail; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 7d1a5b86d06c26..6d4e1ea4219f6d 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1294,6 +1294,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) intel_plane->max_downscale = 1; intel_plane->update_plane = skl_update_plane; intel_plane->disable_plane = skl_disable_plane; + state->scaler_id = -1; plane_formats = skl_plane_formats; num_plane_formats = ARRAY_SIZE(skl_plane_formats); From 0a5ae1b074899f420ea93c019619342b32fe1ad2 Mon Sep 17 00:00:00 2001 From: Chandra Konduru Date: Thu, 9 Apr 2015 16:41:54 -0700 Subject: [PATCH 0130/3798] drm/i915: Keep sprite plane src rect in 16.16 format This patch keeps intel_plane_state->src rect back into 16.16 format. v2: -sprite src rect to match primary format (Matt, Daniel) v3: -moved a hunk from #14 to keep src rect in check & commit in tandom (Matt) Signed-off-by: Chandra Konduru Reviewed-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sprite.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 6d4e1ea4219f6d..0cb37674b43a60 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1037,10 +1037,10 @@ intel_check_sprite_plane(struct drm_plane *plane, } if (state->visible) { - src->x1 = src_x; - src->x2 = src_x + src_w; - src->y1 = src_y; - src->y2 = src_y + src_h; + src->x1 = src_x << 16; + src->x2 = (src_x + src_w) << 16; + src->y1 = src_y << 16; + src->y2 = (src_y + src_h) << 16; } dst->x1 = crtc_x; @@ -1112,10 +1112,10 @@ intel_commit_sprite_plane(struct drm_plane *plane, crtc_y = state->dst.y1; crtc_w = drm_rect_width(&state->dst); crtc_h = drm_rect_height(&state->dst); - src_x = state->src.x1; - src_y = state->src.y1; - src_w = drm_rect_width(&state->src); - src_h = drm_rect_height(&state->src); + src_x = state->src.x1 >> 16; + src_y = state->src.y1 >> 16; + src_w = drm_rect_width(&state->src) >> 16; + src_h = drm_rect_height(&state->src) >> 16; intel_plane->update_plane(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h); From 6a60cd87cdc6fab14c33b2ddf338e5de6bf21e87 Mon Sep 17 00:00:00 2001 From: Chandra Konduru Date: Tue, 7 Apr 2015 15:28:40 -0700 Subject: [PATCH 0131/3798] drm/i915: Dump scaler_state too as part of dumping crtc_state Dumps scaler state as part of dumping crtc_state. v2: -use regular ints from plane_state->src (me) v3: -changes to align with updated scaler structures (Matt) -interpret plane_state->src as 16.16 format (Matt, Daniel) Signed-off-by: Chandra Konduru Reviewed-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 47 ++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 402fad0870ba25..26f1602bec68b0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10638,8 +10638,14 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config, const char *context) { - DRM_DEBUG_KMS("[CRTC:%d]%s config for pipe %c\n", crtc->base.base.id, - context, pipe_name(crtc->pipe)); + struct drm_device *dev = crtc->base.dev; + struct drm_plane *plane; + struct intel_plane *intel_plane; + struct intel_plane_state *state; + struct drm_framebuffer *fb; + + DRM_DEBUG_KMS("[CRTC:%d]%s config %p for pipe %c\n", crtc->base.base.id, + context, pipe_config, pipe_name(crtc->pipe)); DRM_DEBUG_KMS("cpu_transcoder: %c\n", transcoder_name(pipe_config->cpu_transcoder)); DRM_DEBUG_KMS("pipe bpp: %i, dithering: %i\n", @@ -10676,6 +10682,9 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, DRM_DEBUG_KMS("port clock: %d\n", pipe_config->port_clock); DRM_DEBUG_KMS("pipe src size: %dx%d\n", pipe_config->pipe_src_w, pipe_config->pipe_src_h); + DRM_DEBUG_KMS("num_scalers: %d\n", crtc->num_scalers); + DRM_DEBUG_KMS("scaler_users: 0x%x\n", pipe_config->scaler_state.scaler_users); + DRM_DEBUG_KMS("scaler id: %d\n", pipe_config->scaler_state.scaler_id); DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n", pipe_config->gmch_pfit.control, pipe_config->gmch_pfit.pgm_ratios, @@ -10686,6 +10695,40 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, pipe_config->pch_pfit.enabled ? "enabled" : "disabled"); DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled); DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide); + + DRM_DEBUG_KMS("planes on this crtc\n"); + list_for_each_entry(plane, &dev->mode_config.plane_list, head) { + intel_plane = to_intel_plane(plane); + if (intel_plane->pipe != crtc->pipe) + continue; + + state = to_intel_plane_state(plane->state); + fb = state->base.fb; + if (!fb) { + DRM_DEBUG_KMS("%s PLANE:%d plane: %u.%u idx: %d " + "disabled, scaler_id = %d\n", + plane->type == DRM_PLANE_TYPE_CURSOR ? "CURSOR" : "STANDARD", + plane->base.id, intel_plane->pipe, + (crtc->base.primary == plane) ? 0 : intel_plane->plane + 1, + drm_plane_index(plane), state->scaler_id); + continue; + } + + DRM_DEBUG_KMS("%s PLANE:%d plane: %u.%u idx: %d enabled", + plane->type == DRM_PLANE_TYPE_CURSOR ? "CURSOR" : "STANDARD", + plane->base.id, intel_plane->pipe, + crtc->base.primary == plane ? 0 : intel_plane->plane + 1, + drm_plane_index(plane)); + DRM_DEBUG_KMS("\tFB:%d, fb = %ux%u format = 0x%x", + fb->base.id, fb->width, fb->height, fb->pixel_format); + DRM_DEBUG_KMS("\tscaler:%d src (%u, %u) %ux%u dst (%u, %u) %ux%u\n", + state->scaler_id, + state->src.x1 >> 16, state->src.y1 >> 16, + drm_rect_width(&state->src) >> 16, + drm_rect_height(&state->src) >> 16, + state->dst.x1, state->dst.y1, + drm_rect_width(&state->dst), drm_rect_height(&state->dst)); + } } static bool encoders_cloneable(const struct intel_encoder *a, From 663a36407a71b3a98cea087f9a215660a6d6e387 Mon Sep 17 00:00:00 2001 From: Chandra Konduru Date: Tue, 7 Apr 2015 15:28:41 -0700 Subject: [PATCH 0132/3798] drm/i915: Preserve scaler state when clearing crtc_state crtc_state is cleared during mode set which wipes out complete scaler state too. This is causing issues. To fix, ensure scaler state is preserved because it contains not only crtc scaler usage, but also planes using scalers on this crtc. Signed-off-by: Chandra Konduru Reviewed-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 26f1602bec68b0..c14ab7b2f831bf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10839,11 +10839,14 @@ static void clear_intel_crtc_state(struct intel_crtc_state *crtc_state) { struct drm_crtc_state tmp_state; + struct intel_crtc_scaler_state scaler_state; - /* Clear only the intel specific part of the crtc state */ + /* Clear only the intel specific part of the crtc state excluding scalers */ tmp_state = crtc_state->base; + scaler_state = crtc_state->scaler_state; memset(crtc_state, 0, sizeof *crtc_state); crtc_state->base = tmp_state; + crtc_state->scaler_state = scaler_state; } static struct intel_crtc_state * From d03c93d4801563de43abf91e56ff4b3fbc8cc7e4 Mon Sep 17 00:00:00 2001 From: Chandra Konduru Date: Thu, 9 Apr 2015 16:42:46 -0700 Subject: [PATCH 0133/3798] drm/i915: setup scalers for crtc_compute_config Added intel_atomic_setup_scalers to setup scalers based on staged scaling requests from a crtc and its planes. If staged requests are supportable, this function assigns scalers to requested planes and crtc. Note that the scaler assignement itself is staged into crtc_state and respective plane_states for later commit after all checks have been done. overall high level flow: - scaler requests are staged into crtc_state by planes/crtc - check whether staged scaling requests can be supported - add planes using scalers that aren't in current transaction - assign scalers to requested users - as part of plane commit, scalers will be committed (i.e., either attached or detached) to respective planes in hw - as part of crtc_commit, scaler will be either attached or detached to crtc in hw crtc_compute_config calls intel_atomic_setup_scalers() to start scaler assignments as per scaler state in crtc config. This call should be moved to atomic crtc once it is available. v2: -removed a log message (me) -changed input parameter to crtc_state (me) v3: -remove assigning plane_state returned by drm_atomic_get_plane_state (Matt) -fail if there is an error from drm_atomic_get_plane_state (Matt) v4: -changes to align with updated scaler structure (Matt, me) v5: -added addtional checks before enabling HQ mode (me) -added comments to enable HQ mode (Matt) Signed-off-by: Chandra Konduru Reviewed-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_atomic.c | 148 +++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_display.c | 10 +- drivers/gpu/drm/i915/intel_drv.h | 3 + 3 files changed, 160 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index b4ea6762e4ef01..c5e4b6c3064313 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -243,3 +243,151 @@ intel_crtc_destroy_state(struct drm_crtc *crtc, { drm_atomic_helper_crtc_destroy_state(crtc, state); } + +/** + * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests + * @dev: DRM device + * @crtc: intel crtc + * @crtc_state: incoming crtc_state to validate and setup scalers + * + * This function sets up scalers based on staged scaling requests for + * a @crtc and its planes. It is called from crtc level check path. If request + * is a supportable request, it attaches scalers to requested planes and crtc. + * + * This function takes into account the current scaler(s) in use by any planes + * not being part of this atomic state + * + * Returns: + * 0 - scalers were setup succesfully + * error code - otherwise + */ +int intel_atomic_setup_scalers(struct drm_device *dev, + struct intel_crtc *intel_crtc, + struct intel_crtc_state *crtc_state) +{ + struct drm_plane *plane = NULL; + struct intel_plane *intel_plane; + struct intel_plane_state *plane_state = NULL; + struct intel_crtc_scaler_state *scaler_state; + struct drm_atomic_state *drm_state; + int num_scalers_need; + int i, j; + + if (INTEL_INFO(dev)->gen < 9 || !intel_crtc || !crtc_state) + return 0; + + scaler_state = &crtc_state->scaler_state; + drm_state = crtc_state->base.state; + + num_scalers_need = hweight32(scaler_state->scaler_users); + DRM_DEBUG_KMS("crtc_state = %p need = %d avail = %d scaler_users = 0x%x\n", + crtc_state, num_scalers_need, intel_crtc->num_scalers, + scaler_state->scaler_users); + + /* + * High level flow: + * - staged scaler requests are already in scaler_state->scaler_users + * - check whether staged scaling requests can be supported + * - add planes using scalers that aren't in current transaction + * - assign scalers to requested users + * - as part of plane commit, scalers will be committed + * (i.e., either attached or detached) to respective planes in hw + * - as part of crtc_commit, scaler will be either attached or detached + * to crtc in hw + */ + + /* fail if required scalers > available scalers */ + if (num_scalers_need > intel_crtc->num_scalers){ + DRM_DEBUG_KMS("Too many scaling requests %d > %d\n", + num_scalers_need, intel_crtc->num_scalers); + return -EINVAL; + } + + /* walkthrough scaler_users bits and start assigning scalers */ + for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) { + int *scaler_id; + + /* skip if scaler not required */ + if (!(scaler_state->scaler_users & (1 << i))) + continue; + + if (i == SKL_CRTC_INDEX) { + /* panel fitter case: assign as a crtc scaler */ + scaler_id = &scaler_state->scaler_id; + } else { + if (!drm_state) + continue; + + /* plane scaler case: assign as a plane scaler */ + /* find the plane that set the bit as scaler_user */ + plane = drm_state->planes[i]; + + /* + * to enable/disable hq mode, add planes that are using scaler + * into this transaction + */ + if (!plane) { + struct drm_plane_state *state; + plane = drm_plane_from_index(dev, i); + state = drm_atomic_get_plane_state(drm_state, plane); + if (IS_ERR(state)) { + DRM_DEBUG_KMS("Failed to add [PLANE:%d] to drm_state\n", + plane->base.id); + return PTR_ERR(state); + } + } + + intel_plane = to_intel_plane(plane); + + /* plane on different crtc cannot be a scaler user of this crtc */ + if (WARN_ON(intel_plane->pipe != intel_crtc->pipe)) { + continue; + } + + plane_state = to_intel_plane_state(drm_state->plane_states[i]); + scaler_id = &plane_state->scaler_id; + } + + if (*scaler_id < 0) { + /* find a free scaler */ + for (j = 0; j < intel_crtc->num_scalers; j++) { + if (!scaler_state->scalers[j].in_use) { + scaler_state->scalers[j].in_use = 1; + *scaler_id = scaler_state->scalers[j].id; + DRM_DEBUG_KMS("Attached scaler id %u.%u to %s:%d\n", + intel_crtc->pipe, + i == SKL_CRTC_INDEX ? scaler_state->scaler_id : + plane_state->scaler_id, + i == SKL_CRTC_INDEX ? "CRTC" : "PLANE", + i == SKL_CRTC_INDEX ? intel_crtc->base.base.id : + plane->base.id); + break; + } + } + } + + if (WARN_ON(*scaler_id < 0)) { + DRM_DEBUG_KMS("Cannot find scaler for %s:%d\n", + i == SKL_CRTC_INDEX ? "CRTC" : "PLANE", + i == SKL_CRTC_INDEX ? intel_crtc->base.base.id:plane->base.id); + continue; + } + + /* set scaler mode */ + if (num_scalers_need == 1 && intel_crtc->pipe != PIPE_C) { + /* + * when only 1 scaler is in use on either pipe A or B, + * scaler 0 operates in high quality (HQ) mode. + * In this case use scaler 0 to take advantage of HQ mode + */ + *scaler_id = 0; + scaler_state->scalers[0].in_use = 1; + scaler_state->scalers[0].mode = PS_SCALER_MODE_HQ; + scaler_state->scalers[1].in_use = 0; + } else { + scaler_state->scalers[*scaler_id].mode = PS_SCALER_MODE_DYN; + } + } + + return 0; +} diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c14ab7b2f831bf..48129fa9360d19 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5886,6 +5886,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + int ret; /* FIXME should check pixel clock limits on all platforms */ if (INTEL_INFO(dev)->gen < 4) { @@ -5940,7 +5941,14 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, if (pipe_config->has_pch_encoder) return ironlake_fdi_compute_config(crtc, pipe_config); - return 0; + /* FIXME: remove below call once atomic mode set is place and all crtc + * related checks called from atomic_crtc_check function */ + ret = 0; + DRM_DEBUG_KMS("intel_crtc = %p drm_state (pipe_config->base.state) = %p\n", + crtc, pipe_config->base.state); + ret = intel_atomic_setup_scalers(dev, crtc, pipe_config); + + return ret; } static int skylake_get_display_clock_speed(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 40112751ca6eb8..885e48295778c6 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1392,6 +1392,9 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state, return to_intel_crtc_state(crtc_state); } +int intel_atomic_setup_scalers(struct drm_device *dev, + struct intel_crtc *intel_crtc, + struct intel_crtc_state *crtc_state); /* intel_atomic_plane.c */ struct intel_plane_state *intel_create_plane_state(struct drm_plane *plane); From e04fa8036203e6f4f82b5a66e6e78e4118d9cfec Mon Sep 17 00:00:00 2001 From: Chandra Konduru Date: Tue, 7 Apr 2015 15:28:43 -0700 Subject: [PATCH 0134/3798] drm/i915: Ensure setting up scalers into staged crtc_state From intel_atomic_check, call intel_atomic_setup_scalers() to assign scalers based on staged scaling requests. Fail the transaction if setup returns error. Setting up of scalers should be moved to atomic crtc check once atomic crtc is ready. v2: -updated parameter passing to setup_scalers (me) Signed-off-by: Chandra Konduru Reviewed-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_atomic.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index c5e4b6c3064313..42045ce2989829 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -48,6 +48,8 @@ int intel_atomic_check(struct drm_device *dev, int ncrtcs = dev->mode_config.num_crtc; int nconnectors = dev->mode_config.num_connector; enum pipe nuclear_pipe = INVALID_PIPE; + struct intel_crtc *nuclear_crtc = NULL; + struct intel_crtc_state *crtc_state = NULL; int ret; int i; bool not_nuclear = false; @@ -80,6 +82,10 @@ int intel_atomic_check(struct drm_device *dev, memset(&crtc->atomic, 0, sizeof(crtc->atomic)); if (crtc && crtc->pipe != nuclear_pipe) not_nuclear = true; + if (crtc && crtc->pipe == nuclear_pipe) { + nuclear_crtc = crtc; + crtc_state = to_intel_crtc_state(state->crtc_states[i]); + } } for (i = 0; i < nconnectors; i++) if (state->connectors[i] != NULL) @@ -94,6 +100,11 @@ int intel_atomic_check(struct drm_device *dev, if (ret) return ret; + /* FIXME: move to crtc atomic check function once it is ready */ + ret = intel_atomic_setup_scalers(dev, nuclear_crtc, crtc_state); + if (ret) + return ret; + return ret; } From f76f35dc040e44d63369fdba3124701feec714f0 Mon Sep 17 00:00:00 2001 From: Chandra Konduru Date: Tue, 7 Apr 2015 15:28:44 -0700 Subject: [PATCH 0135/3798] drm/i915: copy staged scaler state from drm state to crtc->config. This is required for commit to perform as per staged assignment of scalers until atomic crtc commit function is available. As a place holder doing this copy from intel_atomic_commit for scaling to operate correctly. Signed-off-by: Chandra Konduru Reviewed-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_atomic.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 42045ce2989829..3c4b7cdeab7760 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -168,6 +168,18 @@ int intel_atomic_commit(struct drm_device *dev, swap(state->plane_states[i], plane->state); plane->state->state = NULL; } + + /* swap crtc_state */ + for (i = 0; i < dev->mode_config.num_crtc; i++) { + struct drm_crtc *crtc = state->crtcs[i]; + if (!crtc) { + continue; + } + + to_intel_crtc(crtc)->config->scaler_state = + to_intel_crtc_state(state->crtc_states[i])->scaler_state; + } + drm_atomic_helper_commit_planes(dev, state); drm_atomic_helper_wait_for_vblanks(dev, state); drm_atomic_helper_cleanup_planes(dev, state); From a1b2278e4dfcd2dbea85e319ebf73a6b7b2f180b Mon Sep 17 00:00:00 2001 From: Chandra Konduru Date: Tue, 7 Apr 2015 15:28:45 -0700 Subject: [PATCH 0136/3798] drm/i915: skylake panel fitting using shared scalers Enabling skylake panel fitting feature using shared scalers v2: -added force detach parameter for pfit disable purpose (me) -read crtc scaler state from hw state (Daniel) -replaced both skylake_pfit_enable and disable with skylake_pfit_update (me) -added scaler id check to intel_pipe_config_compare (Daniel) v3: -updated function header to kerneldoc format (Matt) -dropped need_scaling checks (Matt) v4: -move clearing of scaler id from commit path to check path (Matt) -updated colorkey checks based on recent updates (me) -squashed scaler check while enabling colorkey to here (me) -use values in plane_state->src as regular integers (me) -changes made not to modify state in commit path (Matt) v5: -squashed helper function to update scaler users to here (Matt) -squashed helper function to detach scaler to here (Matt, me) -changes to align with updated scaler structures (Matt, me) Signed-off-by: Chandra Konduru Reviewed-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 250 ++++++++++++++++++++++++--- drivers/gpu/drm/i915/intel_dp.c | 8 + drivers/gpu/drm/i915/intel_drv.h | 4 + 3 files changed, 235 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 48129fa9360d19..97922fb90824c7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2931,6 +2931,35 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane, return i915_gem_obj_ggtt_offset_view(obj, view); } +/* + * This function detaches (aka. unbinds) unused scalers in hardware + */ +void skl_detach_scalers(struct intel_crtc *intel_crtc) +{ + struct drm_device *dev; + struct drm_i915_private *dev_priv; + struct intel_crtc_scaler_state *scaler_state; + int i; + + if (!intel_crtc || !intel_crtc->config) + return; + + dev = intel_crtc->base.dev; + dev_priv = dev->dev_private; + scaler_state = &intel_crtc->config->scaler_state; + + /* loop through and disable scalers that aren't in use */ + for (i = 0; i < intel_crtc->num_scalers; i++) { + if (!scaler_state->scalers[i].in_use) { + I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, i), 0); + I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, i), 0); + I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, i), 0); + DRM_DEBUG_KMS("CRTC:%d Disabled scaler id %u.%u\n", + intel_crtc->base.base.id, intel_crtc->pipe, i); + } + } +} + static void skylake_update_primary_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y) @@ -4280,16 +4309,175 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe) } } -static void skylake_pfit_enable(struct intel_crtc *crtc) +/** + * skl_update_scaler_users - Stages update to crtc's scaler state + * @intel_crtc: crtc + * @crtc_state: crtc_state + * @plane: plane (NULL indicates crtc is requesting update) + * @plane_state: plane's state + * @force_detach: request unconditional detachment of scaler + * + * This function updates scaler state for requested plane or crtc. + * To request scaler usage update for a plane, caller shall pass plane pointer. + * To request scaler usage update for crtc, caller shall pass plane pointer + * as NULL. + * + * Return + * 0 - scaler_usage updated successfully + * error - requested scaling cannot be supported or other error condition + */ +int +skl_update_scaler_users( + struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state, + struct intel_plane *intel_plane, struct intel_plane_state *plane_state, + int force_detach) +{ + int need_scaling; + int idx; + int src_w, src_h, dst_w, dst_h; + int *scaler_id; + struct drm_framebuffer *fb; + struct intel_crtc_scaler_state *scaler_state; + + if (!intel_crtc || !crtc_state) + return 0; + + scaler_state = &crtc_state->scaler_state; + + idx = intel_plane ? drm_plane_index(&intel_plane->base) : SKL_CRTC_INDEX; + fb = intel_plane ? plane_state->base.fb : NULL; + + if (intel_plane) { + src_w = drm_rect_width(&plane_state->src) >> 16; + src_h = drm_rect_height(&plane_state->src) >> 16; + dst_w = drm_rect_width(&plane_state->dst); + dst_h = drm_rect_height(&plane_state->dst); + scaler_id = &plane_state->scaler_id; + } else { + struct drm_display_mode *adjusted_mode = + &crtc_state->base.adjusted_mode; + src_w = crtc_state->pipe_src_w; + src_h = crtc_state->pipe_src_h; + dst_w = adjusted_mode->hdisplay; + dst_h = adjusted_mode->vdisplay; + scaler_id = &scaler_state->scaler_id; + } + need_scaling = (src_w != dst_w || src_h != dst_h); + + /* + * if plane is being disabled or scaler is no more required or force detach + * - free scaler binded to this plane/crtc + * - in order to do this, update crtc->scaler_usage + * + * Here scaler state in crtc_state is set free so that + * scaler can be assigned to other user. Actual register + * update to free the scaler is done in plane/panel-fit programming. + * For this purpose crtc/plane_state->scaler_id isn't reset here. + */ + if (force_detach || !need_scaling || (intel_plane && + (!fb || !plane_state->visible))) { + if (*scaler_id >= 0) { + scaler_state->scaler_users &= ~(1 << idx); + scaler_state->scalers[*scaler_id].in_use = 0; + + DRM_DEBUG_KMS("Staged freeing scaler id %d.%d from %s:%d " + "crtc_state = %p scaler_users = 0x%x\n", + intel_crtc->pipe, *scaler_id, intel_plane ? "PLANE" : "CRTC", + intel_plane ? intel_plane->base.base.id : + intel_crtc->base.base.id, crtc_state, + scaler_state->scaler_users); + *scaler_id = -1; + } + return 0; + } + + /* range checks */ + if (src_w < SKL_MIN_SRC_W || src_h < SKL_MIN_SRC_H || + dst_w < SKL_MIN_DST_W || dst_h < SKL_MIN_DST_H || + + src_w > SKL_MAX_SRC_W || src_h > SKL_MAX_SRC_H || + dst_w > SKL_MAX_DST_W || dst_h > SKL_MAX_DST_H) { + DRM_DEBUG_KMS("%s:%d scaler_user index %u.%u: src %ux%u dst %ux%u " + "size is out of scaler range\n", + intel_plane ? "PLANE" : "CRTC", + intel_plane ? intel_plane->base.base.id : intel_crtc->base.base.id, + intel_crtc->pipe, idx, src_w, src_h, dst_w, dst_h); + return -EINVAL; + } + + /* check colorkey */ + if (intel_plane && intel_plane->ckey.flags != I915_SET_COLORKEY_NONE) { + DRM_DEBUG_KMS("PLANE:%d scaling with color key not allowed", + intel_plane->base.base.id); + return -EINVAL; + } + + /* Check src format */ + if (intel_plane) { + switch (fb->pixel_format) { + case DRM_FORMAT_RGB565: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_YUYV: + case DRM_FORMAT_YVYU: + case DRM_FORMAT_UYVY: + case DRM_FORMAT_VYUY: + break; + default: + DRM_DEBUG_KMS("PLANE:%d FB:%d unsupported scaling format 0x%x\n", + intel_plane->base.base.id, fb->base.id, fb->pixel_format); + return -EINVAL; + } + } + + /* mark this plane as a scaler user in crtc_state */ + scaler_state->scaler_users |= (1 << idx); + DRM_DEBUG_KMS("%s:%d staged scaling request for %ux%u->%ux%u " + "crtc_state = %p scaler_users = 0x%x\n", + intel_plane ? "PLANE" : "CRTC", + intel_plane ? intel_plane->base.base.id : intel_crtc->base.base.id, + src_w, src_h, dst_w, dst_h, crtc_state, scaler_state->scaler_users); + return 0; +} + +static void skylake_pfit_update(struct intel_crtc *crtc, int enable) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = crtc->pipe; + struct intel_crtc_scaler_state *scaler_state = + &crtc->config->scaler_state; + + DRM_DEBUG_KMS("for crtc_state = %p\n", crtc->config); + + /* To update pfit, first update scaler state */ + skl_update_scaler_users(crtc, crtc->config, NULL, NULL, !enable); + intel_atomic_setup_scalers(crtc->base.dev, crtc, crtc->config); + skl_detach_scalers(crtc); + if (!enable) + return; if (crtc->config->pch_pfit.enabled) { - I915_WRITE(PS_CTL(pipe), PS_ENABLE); - I915_WRITE(PS_WIN_POS(pipe), crtc->config->pch_pfit.pos); - I915_WRITE(PS_WIN_SZ(pipe), crtc->config->pch_pfit.size); + int id; + + if (WARN_ON(crtc->config->scaler_state.scaler_id < 0)) { + DRM_ERROR("Requesting pfit without getting a scaler first\n"); + return; + } + + id = scaler_state->scaler_id; + I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN | + PS_FILTER_MEDIUM | scaler_state->scalers[id].mode); + I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos); + I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size); + + DRM_DEBUG_KMS("for crtc_state = %p scaler_id = %d\n", crtc->config, id); } } @@ -4694,7 +4882,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_ddi_enable_pipe_clock(intel_crtc); if (IS_SKYLAKE(dev)) - skylake_pfit_enable(intel_crtc); + skylake_pfit_update(intel_crtc, 1); else ironlake_pfit_enable(intel_crtc); @@ -4730,21 +4918,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_crtc_enable_planes(crtc); } -static void skylake_pfit_disable(struct intel_crtc *crtc) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int pipe = crtc->pipe; - - /* To avoid upsetting the power well on haswell only disable the pfit if - * it's in use. The hw state code will make sure we get this right. */ - if (crtc->config->pch_pfit.enabled) { - I915_WRITE(PS_CTL(pipe), 0); - I915_WRITE(PS_WIN_POS(pipe), 0); - I915_WRITE(PS_WIN_SZ(pipe), 0); - } -} - static void ironlake_pfit_disable(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; @@ -4857,7 +5030,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder); if (IS_SKYLAKE(dev)) - skylake_pfit_disable(intel_crtc); + skylake_pfit_update(intel_crtc, 0); else ironlake_pfit_disable(intel_crtc); @@ -8146,14 +8319,28 @@ static void skylake_get_pfit_config(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t tmp; + struct intel_crtc_scaler_state *scaler_state = &pipe_config->scaler_state; + uint32_t ps_ctrl = 0; + int id = -1; + int i; - tmp = I915_READ(PS_CTL(crtc->pipe)); + /* find scaler attached to this pipe */ + for (i = 0; i < crtc->num_scalers; i++) { + ps_ctrl = I915_READ(SKL_PS_CTRL(crtc->pipe, i)); + if (ps_ctrl & PS_SCALER_EN && !(ps_ctrl & PS_PLANE_SEL_MASK)) { + id = i; + pipe_config->pch_pfit.enabled = true; + pipe_config->pch_pfit.pos = I915_READ(SKL_PS_WIN_POS(crtc->pipe, i)); + pipe_config->pch_pfit.size = I915_READ(SKL_PS_WIN_SZ(crtc->pipe, i)); + break; + } + } - if (tmp & PS_ENABLE) { - pipe_config->pch_pfit.enabled = true; - pipe_config->pch_pfit.pos = I915_READ(PS_WIN_POS(crtc->pipe)); - pipe_config->pch_pfit.size = I915_READ(PS_WIN_SZ(crtc->pipe)); + scaler_state->scaler_id = id; + if (id >= 0) { + scaler_state->scaler_users |= (1 << SKL_CRTC_INDEX); + } else { + scaler_state->scaler_users &= ~(1 << SKL_CRTC_INDEX); } } @@ -8787,12 +8974,19 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, intel_get_pipe_timings(crtc, pipe_config); + if (INTEL_INFO(dev)->gen >= 9) { + skl_init_scalers(dev, crtc, pipe_config); + } + pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe); if (intel_display_power_is_enabled(dev_priv, pfit_domain)) { if (IS_SKYLAKE(dev)) skylake_get_pfit_config(crtc, pipe_config); else ironlake_get_pfit_config(crtc, pipe_config); + } else { + pipe_config->scaler_state.scaler_id = -1; + pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX); } if (IS_HASWELL(dev)) @@ -11320,6 +11514,8 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I(pch_pfit.size); } + PIPE_CONF_CHECK_I(scaler_state.scaler_id); + /* BDW+ don't expose a synchronous way to read the state */ if (IS_HASWELL(dev)) PIPE_CONF_CHECK_I(ips_enabled); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 589cd92d5c303f..3ea68e164873a5 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1351,6 +1351,14 @@ intel_dp_compute_config(struct intel_encoder *encoder, if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) { intel_fixed_panel_mode(intel_connector->panel.fixed_mode, adjusted_mode); + + if (INTEL_INFO(dev)->gen >= 9) { + int ret; + ret = skl_update_scaler_users(intel_crtc, pipe_config, NULL, NULL, 0); + if (ret) + return ret; + } + if (!HAS_PCH_SPLIT(dev)) intel_gmch_panel_fitting(intel_crtc, pipe_config, intel_connector->panel.fitting_mode); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 885e48295778c6..6a2ee0c3816118 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1128,6 +1128,10 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode, struct intel_crtc_state *pipe_config); void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc); void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file); +void skl_detach_scalers(struct intel_crtc *intel_crtc); +int skl_update_scaler_users(struct intel_crtc *intel_crtc, + struct intel_crtc_state *crtc_state, struct intel_plane *intel_plane, + struct intel_plane_state *plane_state, int force_detach); unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane, struct drm_i915_gem_object *obj); From 2def4ad99befa25775dd2f714fdd4d92faec6e34 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 16:20:41 +0100 Subject: [PATCH 0137/3798] drm/i915: Optimistically spin for the request completion This provides a nice boost to mesa in swap bound scenarios (as mesa throttles itself to the previous frame and given the scenario that will complete shortly). It will also provide a good boost to systems running with semaphores disabled and so frequently waiting on the GPU as it switches rings. In the most favourable of microbenchmarks, this can increase performance by around 15% - though in practice improvements will be marginal and rarely noticeable. v2: Account for user timeouts v3: Limit the spinning to a single jiffie (~1us) at most. On an otherwise idle system, there is no scheduler contention and so without a limit we would spin until the GPU is ready. v4: Drop forcewake - the lazy coherent access doesn't require it, and we have no reason to believe that the forcewake itself improves seqno coherency - it only adds delay. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Tvrtko Ursulin Cc: Eero Tamminen Cc: "Rantala, Valtteri" Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 44 ++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8ce363aa492c99..b1c27da559e35e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1181,6 +1181,29 @@ static bool missed_irq(struct drm_i915_private *dev_priv, return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings); } +static int __i915_spin_request(struct drm_i915_gem_request *rq) +{ + unsigned long timeout; + + if (i915_gem_request_get_ring(rq)->irq_refcount) + return -EBUSY; + + timeout = jiffies + 1; + while (!need_resched()) { + if (i915_gem_request_completed(rq, true)) + return 0; + + if (time_after_eq(jiffies, timeout)) + break; + + cpu_relax_lowlatency(); + } + if (i915_gem_request_completed(rq, false)) + return 0; + + return -EAGAIN; +} + /** * __i915_wait_request - wait until execution of request has finished * @req: duh! @@ -1225,12 +1248,20 @@ int __i915_wait_request(struct drm_i915_gem_request *req, if (INTEL_INFO(dev)->gen >= 6) gen6_rps_boost(dev_priv, file_priv); - if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring))) - return -ENODEV; - /* Record current time in case interrupted by signal, or wedged */ trace_i915_gem_request_wait_begin(req); before = ktime_get_raw_ns(); + + /* Optimistic spin for the next jiffie before touching IRQs */ + ret = __i915_spin_request(req); + if (ret == 0) + goto out; + + if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring))) { + ret = -ENODEV; + goto out; + } + for (;;) { struct timer_list timer; @@ -1279,14 +1310,15 @@ int __i915_wait_request(struct drm_i915_gem_request *req, destroy_timer_on_stack(&timer); } } - now = ktime_get_raw_ns(); - trace_i915_gem_request_wait_end(req); - if (!irq_test_in_progress) ring->irq_put(ring); finish_wait(&ring->irq_queue, &wait); +out: + now = ktime_get_raw_ns(); + trace_i915_gem_request_wait_end(req); + if (timeout) { s64 tres = *timeout - (now - before); From 30154650b8b58cd2633475d5a730b44baa140d98 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Apr 2015 17:28:24 +0100 Subject: [PATCH 0138/3798] drm/i915: Remove obj->pin_mappable The obj->pin_mappable flag only exists for debug purposes and is a hindrance that is mistreated with rotated GGTT views. For debug purposes, it suffices to mark objects with pin_display as being of note. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 6 +++--- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_gem.c | 6 +----- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e890728144b4c0..5081e6f8a38512 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -160,9 +160,9 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) } if (obj->stolen) seq_printf(m, " (stolen: %08llx)", obj->stolen->start); - if (obj->pin_mappable || obj->fault_mappable) { + if (obj->pin_display || obj->fault_mappable) { char s[3], *t = s; - if (obj->pin_mappable) + if (obj->pin_display) *t++ = 'p'; if (obj->fault_mappable) *t++ = 'f'; @@ -458,7 +458,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data) size += i915_gem_obj_ggtt_size(obj); ++count; } - if (obj->pin_mappable) { + if (obj->pin_display) { mappable_size += i915_gem_obj_ggtt_size(obj); ++mappable_count; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6bdd1a6b395d22..745dcd84849db6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1963,7 +1963,6 @@ struct drm_i915_gem_object { * accurate mappable working set. */ unsigned int fault_mappable:1; - unsigned int pin_mappable:1; unsigned int pin_display:1; /* diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b1c27da559e35e..89d9ebe675209b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4255,9 +4255,6 @@ i915_gem_object_do_pin(struct drm_i915_gem_object *obj, WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable); vma->pin_count++; - if (flags & PIN_MAPPABLE) - obj->pin_mappable |= true; - return 0; } @@ -4295,8 +4292,7 @@ i915_gem_object_ggtt_unpin_view(struct drm_i915_gem_object *obj, WARN_ON(vma->pin_count == 0); WARN_ON(!i915_gem_obj_ggtt_bound_view(obj, view)); - if (--vma->pin_count == 0 && view->type == I915_GGTT_VIEW_NORMAL) - obj->pin_mappable = false; + --vma->pin_count; } bool From 9647ff36ae266b74c82780f7f4e3bb4a39506107 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Sun, 25 Jan 2015 13:27:11 -0800 Subject: [PATCH 0139/3798] drm/i915/gen9: fix PIPE_CONTROL flush for VS_INVALIDATE On GEN9+ per specification a NULL PIPE_CONTROL needs to be emitted before any PIPE_CONTROL command with the VS_INVALIDATE flag set. Signed-off-by: Imre Deak Reviewed-by: Nick Hoath Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index fcb074bd55dcb0..71aeeb35d0910a 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1262,6 +1262,7 @@ static int gen8_emit_flush_render(struct intel_ringbuffer *ringbuf, { struct intel_engine_cs *ring = ringbuf->ring; u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; + bool vf_flush_wa; u32 flags = 0; int ret; @@ -1283,10 +1284,26 @@ static int gen8_emit_flush_render(struct intel_ringbuffer *ringbuf, flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; } - ret = intel_logical_ring_begin(ringbuf, ctx, 6); + /* + * On GEN9+ Before VF_CACHE_INVALIDATE we need to emit a NULL pipe + * control. + */ + vf_flush_wa = INTEL_INFO(ring->dev)->gen >= 9 && + flags & PIPE_CONTROL_VF_CACHE_INVALIDATE; + + ret = intel_logical_ring_begin(ringbuf, ctx, vf_flush_wa ? 12 : 6); if (ret) return ret; + if (vf_flush_wa) { + intel_logical_ring_emit(ringbuf, GFX_OP_PIPE_CONTROL(6)); + intel_logical_ring_emit(ringbuf, 0); + intel_logical_ring_emit(ringbuf, 0); + intel_logical_ring_emit(ringbuf, 0); + intel_logical_ring_emit(ringbuf, 0); + intel_logical_ring_emit(ringbuf, 0); + } + intel_logical_ring_emit(ringbuf, GFX_OP_PIPE_CONTROL(6)); intel_logical_ring_emit(ringbuf, flags); intel_logical_ring_emit(ringbuf, scratch_addr); From a82abe43cecb26619a7ce7e2052c3e89ed0b9436 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 27 Mar 2015 14:00:04 +0200 Subject: [PATCH 0140/3798] drm/i915/bxt: add bxt_init_clock_gating v2: - Make the condition to select between SKL and BXT consistent with the corresponding condition in init_workarounds_ring (Nick) Signed-off-by: Imre Deak Reviewed-by: Nick Hoath Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1e25e3e26a6787..767a3e2ffdd13d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -94,6 +94,11 @@ static void skl_init_clock_gating(struct drm_device *dev) GEN8_LQSC_RO_PERF_DIS); } +static void bxt_init_clock_gating(struct drm_device *dev) +{ + gen9_init_clock_gating(dev); +} + static void i915_pineview_get_mem_freq(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -6548,7 +6553,12 @@ void intel_init_pm(struct drm_device *dev) if (INTEL_INFO(dev)->gen >= 9) { skl_setup_wm_latency(dev); - dev_priv->display.init_clock_gating = skl_init_clock_gating; + if (IS_BROXTON(dev)) + dev_priv->display.init_clock_gating = + bxt_init_clock_gating; + else if (IS_SKYLAKE(dev)) + dev_priv->display.init_clock_gating = + skl_init_clock_gating; dev_priv->display.update_wm = skl_update_wm; dev_priv->display.update_sprite_wm = skl_update_sprite_wm; } else if (HAS_PCH_SPLIT(dev)) { From 32608ca255ef0da1a70239a731a1fcdbb212d3f2 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 11 Mar 2015 11:10:27 +0200 Subject: [PATCH 0141/3798] drm/i915/bxt: add GEN8_SDEUNIT_CLOCK_GATE_DISABLE workaround Signed-off-by: Imre Deak Reviewed-by: Nick Hoath Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 767a3e2ffdd13d..a3247e83b07204 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -96,7 +96,18 @@ static void skl_init_clock_gating(struct drm_device *dev) static void bxt_init_clock_gating(struct drm_device *dev) { + struct drm_i915_private *dev_priv = dev->dev_private; + gen9_init_clock_gating(dev); + + /* + * FIXME: + * GEN8_SDEUNIT_CLOCK_GATE_DISABLE applies on A0 only. + */ + /* WaDisableSDEUnitClockGating:bxt */ + I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) | + GEN8_SDEUNIT_CLOCK_GATE_DISABLE); + } static void i915_pineview_get_mem_freq(struct drm_device *dev) From 868434c51ec13c773e46c2398da18d53f6c78422 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 11 Mar 2015 10:49:32 +0200 Subject: [PATCH 0142/3798] drm/i915/bxt: add GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ workaround Signed-off-by: Ben Widawsky Signed-off-by: Imre Deak Reviewed-by: Nick Hoath Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6c1ec72e94c464..fc3157999a0848 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6104,6 +6104,7 @@ enum skl_disp_power_wells { #define GEN8_UCGCTL6 0x9430 #define GEN8_GAPSUNIT_CLOCK_GATE_DISABLE (1<<24) #define GEN8_SDEUNIT_CLOCK_GATE_DISABLE (1<<14) +#define GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ (1<<28) #define GEN6_GFXPAUSE 0xA000 #define GEN6_RPNSWREQ 0xA008 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a3247e83b07204..07b3780677c92f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -103,10 +103,12 @@ static void bxt_init_clock_gating(struct drm_device *dev) /* * FIXME: * GEN8_SDEUNIT_CLOCK_GATE_DISABLE applies on A0 only. + * GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ applies on 3x6 GT SKUs only. */ /* WaDisableSDEUnitClockGating:bxt */ I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) | - GEN8_SDEUNIT_CLOCK_GATE_DISABLE); + GEN8_SDEUNIT_CLOCK_GATE_DISABLE | + GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ); } From 38a39a7be77a097f7474986fe382cb1b56bf484e Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 11 Mar 2015 10:54:53 +0200 Subject: [PATCH 0143/3798] drm/i915/bxt: add WaDisableMaskBasedCammingInRCC workaround Signed-off-by: Ben Widawsky Signed-off-by: Imre Deak Reviewed-by: Nick Hoath Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index fc3157999a0848..a2274585574079 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5346,6 +5346,10 @@ enum skl_disp_power_wells { #define HDC_FORCE_NON_COHERENT (1<<4) #define HDC_BARRIER_PERFORMANCE_DISABLE (1<<10) +/* GEN9 chicken */ +#define SLICE_ECO_CHICKEN0 0x7308 +#define PIXEL_MASK_CAMMING_DISABLE (1 << 14) + /* WaCatErrorRejectionIssue */ #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG 0x9030 #define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index abe062a95be8b5..e23cbdc029b829 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -966,6 +966,15 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, GEN9_CCS_TLB_PREFETCH_ENABLE); + /* + * FIXME: don't apply the following on BXT for stepping C. On BXT A0 + * the flag reads back as 0. + */ + /* WaDisableMaskBasedCammingInRCC:bxtA */ + if (IS_BROXTON(dev)) + WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, + PIXEL_MASK_CAMMING_DISABLE); + return 0; } From 8d09c8123db62859886bbbc504a56ff5d9d9e8cd Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 11 Mar 2015 11:23:12 +0200 Subject: [PATCH 0144/3798] drm/i915/skl: add WaDisableMaskBasedCammingInRCC workaround Signed-off-by: Ben Widawsky Signed-off-by: Imre Deak Reviewed-by: Nick Hoath Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index e23cbdc029b829..000f608d8ea643 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -970,8 +970,8 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) * FIXME: don't apply the following on BXT for stepping C. On BXT A0 * the flag reads back as 0. */ - /* WaDisableMaskBasedCammingInRCC:bxtA */ - if (IS_BROXTON(dev)) + /* WaDisableMaskBasedCammingInRCC:sklC,bxtA */ + if (INTEL_REVID(dev) == SKL_REVID_C0 || IS_BROXTON(dev)) WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, PIXEL_MASK_CAMMING_DISABLE); From e3a290553f3b09b657962e0a952fcf9b117bc08b Mon Sep 17 00:00:00 2001 From: Robert Beckett Date: Wed, 11 Mar 2015 10:28:25 +0200 Subject: [PATCH 0145/3798] drm/i915/bxt: add workaround to avoid PTE corruption Set TLBPF in TILECTL. This fixes an issue with BXT HW seeing corrupted pte entries. v2: - move the workaround to bxt_init_clock_gating (imre) Signed-off-by: Robert Beckett (v1) Signed-off-by: Imre Deak Reviewed-by: Nick Hoath Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a2274585574079..21e69cab6efe0c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1150,6 +1150,7 @@ enum skl_disp_power_wells { /* control register for cpu gtt access */ #define TILECTL 0x101000 #define TILECTL_SWZCTL (1 << 0) +#define TILECTL_TLBPF (1 << 1) #define TILECTL_TLB_PREFETCH_DIS (1 << 2) #define TILECTL_BACKSNOOP_DIS (1 << 3) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 07b3780677c92f..47246380675959 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -110,6 +110,8 @@ static void bxt_init_clock_gating(struct drm_device *dev) GEN8_SDEUNIT_CLOCK_GATE_DISABLE | GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ); + /* FIXME: apply on A0 only */ + I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); } static void i915_pineview_get_mem_freq(struct drm_device *dev) From c776eb2edfce88f0a44156b417cac3da11d1f944 Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Tue, 19 Aug 2014 12:05:01 +0530 Subject: [PATCH 0146/3798] drm/i915/bxt: don't use unsupported port detection The port detection register flags in SFUSE_STRAP and DDI_BUF_CTL_A are not defined for BXT, so don't use them. Suggested by Satheesh. v2: - DDI_BUF_CTL_A bit 0 is not useful on BXT. Making changes to use this bit when simulator or BXT is not applicable. Code re-arranged as per Damien's suggestion. v3: - clarify commit message, add code comment (imre) Signed-off-by: Vandana Kannan (v2) Cc: M, Satheeshakrishna Cc: Lespiau, Damien Cc: Shankar, Uma Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 75955fee6d24b1..d35f4064924705 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13011,7 +13011,16 @@ static void intel_setup_outputs(struct drm_device *dev) if (intel_crt_present(dev)) intel_crt_init(dev); - if (HAS_DDI(dev)) { + if (IS_BROXTON(dev)) { + /* + * FIXME: Broxton doesn't support port detection via the + * DDI_BUF_CTL_A or SFUSE_STRAP registers, find another way to + * detect the ports. + */ + intel_ddi_init(dev, PORT_A); + intel_ddi_init(dev, PORT_B); + intel_ddi_init(dev, PORT_C); + } else if (HAS_DDI(dev)) { int found; /* From 4c27283415ec9e352d0d336ac45717d5e408ce3c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 1 Apr 2015 10:58:05 +0300 Subject: [PATCH 0147/3798] drm/i915: add bxt gmbus support For BXT gmbus is pulled from PCH to CPU. From implementation point of view only pin pair configuration will change. The existing implementation supports all platforms previous to GEN8 and also SKL. But for BXT pin pair configuration is completely different than SKL or other previous GEN's. This patch introduces the new pin pair configuration structure specific to BXT and also ensures every real gmbus port has a gpio pin. v3 by Jani: with the platform independent prep work in place, the bxt enabling reduces to a fairly trivial patch. Credits are due Sunil for giving me the ideas (with his patches) what the platform independent parts should look like. v4: Fix intel_hdmi_init_connector() for bxt. Abstract gmbus_pin access more. s/GPU/PCH/ in commit message. v5: Rebase. Issue: VIZ-3574 Signed-off-by: A.Sunil Kamath Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_hdmi.c | 14 +++++++++++--- drivers/gpu/drm/i915/intel_i2c.c | 30 +++++++++++++++++++++++++++--- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 87d9c0fbc7d94b..9ef716a5093cce 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1794,6 +1794,9 @@ enum skl_disp_power_wells { #define GMBUS_PIN_DPB 5 /* SDVO, HDMIB */ #define GMBUS_PIN_DPD 6 /* HDMID */ #define GMBUS_PIN_RESERVED 7 /* 7 reserved */ +#define GMBUS_PIN_1_BXT 1 +#define GMBUS_PIN_2_BXT 2 +#define GMBUS_PIN_3_BXT 3 #define GMBUS_NUM_PINS 7 /* including 0 */ #define GMBUS1 0x5104 /* command/status */ #define GMBUS_SW_CLR_INT (1<<31) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 02252d9a0cc3b0..7dfc3584b6b437 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1681,15 +1681,23 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, switch (port) { case PORT_B: - intel_hdmi->ddc_bus = GMBUS_PIN_DPB; + if (IS_BROXTON(dev_priv)) + intel_hdmi->ddc_bus = GMBUS_PIN_1_BXT; + else + intel_hdmi->ddc_bus = GMBUS_PIN_DPB; intel_encoder->hpd_pin = HPD_PORT_B; break; case PORT_C: - intel_hdmi->ddc_bus = GMBUS_PIN_DPC; + if (IS_BROXTON(dev_priv)) + intel_hdmi->ddc_bus = GMBUS_PIN_2_BXT; + else + intel_hdmi->ddc_bus = GMBUS_PIN_DPC; intel_encoder->hpd_pin = HPD_PORT_C; break; case PORT_D: - if (IS_CHERRYVIEW(dev)) + if (WARN_ON(IS_BROXTON(dev_priv))) + intel_hdmi->ddc_bus = GMBUS_PIN_DISABLED; + else if (IS_CHERRYVIEW(dev_priv)) intel_hdmi->ddc_bus = GMBUS_PIN_DPD_CHV; else intel_hdmi->ddc_bus = GMBUS_PIN_DPD; diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index ec9cc8cf642e62..cadbc17d27751d 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -49,10 +49,33 @@ static const struct gmbus_pin gmbus_pins[] = { [GMBUS_PIN_DPD] = { "dpd", GPIOF }, }; +static const struct gmbus_pin gmbus_pins_bxt[] = { + [GMBUS_PIN_1_BXT] = { "dpb", PCH_GPIOB }, + [GMBUS_PIN_2_BXT] = { "dpc", PCH_GPIOC }, + [GMBUS_PIN_3_BXT] = { "misc", PCH_GPIOD }, +}; + +/* pin is expected to be valid */ +static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *dev_priv, + unsigned int pin) +{ + if (IS_BROXTON(dev_priv)) + return &gmbus_pins_bxt[pin]; + else + return &gmbus_pins[pin]; +} + bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv, unsigned int pin) { - return pin < ARRAY_SIZE(gmbus_pins) && gmbus_pins[pin].reg; + unsigned int size; + + if (IS_BROXTON(dev_priv)) + size = ARRAY_SIZE(gmbus_pins_bxt); + else + size = ARRAY_SIZE(gmbus_pins); + + return pin < size && get_gmbus_pin(dev_priv, pin)->reg; } /* Intel GPIO access functions */ @@ -196,7 +219,8 @@ intel_gpio_setup(struct intel_gmbus *bus, unsigned int pin) algo = &bus->bit_algo; - bus->gpio_reg = dev_priv->gpio_mmio_base + gmbus_pins[pin].reg; + bus->gpio_reg = dev_priv->gpio_mmio_base + + get_gmbus_pin(dev_priv, pin)->reg; bus->adapter.algo_data = algo; algo->setsda = set_data; @@ -550,7 +574,7 @@ int intel_setup_gmbus(struct drm_device *dev) snprintf(bus->adapter.name, sizeof(bus->adapter.name), "i915 gmbus %s", - gmbus_pins[pin].name); + get_gmbus_pin(dev_priv, pin)->name); bus->adapter.dev.parent = &dev->pdev->dev; bus->dev_priv = dev_priv; From e0a20ad78c06be27fe8afe53750b6eaf25da4ea6 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Fri, 27 Mar 2015 14:54:14 +0200 Subject: [PATCH 0148/3798] drm/i915/bxt: DDI Hotplug interrupt setup In BXT, DDI hotplug control has been moved to CPU from PCH. This patch adds a new IRQ setup function for BXT which: 1. Checks which HPD ports are requested to be enabled by encoders. 2. Enables those ports in the hot plug control register. 3. Un-masks these port interrupts in the IMR register. 4. Enables these port interrupts in the IER register. V3: Kept the default HPD filter count to default (500 us) as per satheesh's comment v4: Remove unused HPD filter defines (Damien) v5: warn if trying to setup HPD on port A (imre) v6: fix order of definitions for register bitfields (Daniel) v7: (jani) - define the size of the hpd_bxt array explicitly for bound checking - use for_each_intel_encoder instead of open coding it - fix format/order of definitions for BXT_HOTPLUG_CTL reg bitfields Reviewed-by: Satheeshakrishna M Signed-off-by: Damien Lespiau Signed-off-by: Shashank Sharma (v4) Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 47 ++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/i915_reg.h | 23 +++++++++++++++- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 46bcbff8976004..631484dd0b60f6 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -88,6 +88,12 @@ static const u32 hpd_status_i915[HPD_NUM_PINS] = { /* i915 and valleyview are th [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS }; +/* BXT hpd list */ +static const u32 hpd_bxt[HPD_NUM_PINS] = { + [HPD_PORT_B] = BXT_DE_PORT_HP_DDIB, + [HPD_PORT_C] = BXT_DE_PORT_HP_DDIC +}; + /* IIR can theoretically queue up two events. Be paranoid. */ #define GEN8_IRQ_RESET_NDX(type, which) do { \ I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \ @@ -3159,6 +3165,42 @@ static void ibx_hpd_irq_setup(struct drm_device *dev) I915_WRITE(PCH_PORT_HOTPLUG, hotplug); } +static void bxt_hpd_irq_setup(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_encoder *intel_encoder; + u32 hotplug_port = 0; + u32 hotplug_ctrl; + + /* Now, enable HPD */ + for_each_intel_encoder(dev, intel_encoder) { + if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark + == HPD_ENABLED) + hotplug_port |= hpd_bxt[intel_encoder->hpd_pin]; + } + + /* Mask all HPD control bits */ + hotplug_ctrl = I915_READ(BXT_HOTPLUG_CTL) & ~BXT_HOTPLUG_CTL_MASK; + + /* Enable requested port in hotplug control */ + /* TODO: implement (short) HPD support on port A */ + WARN_ON_ONCE(hotplug_port & BXT_DE_PORT_HP_DDIA); + if (hotplug_port & BXT_DE_PORT_HP_DDIB) + hotplug_ctrl |= BXT_DDIB_HPD_ENABLE; + if (hotplug_port & BXT_DE_PORT_HP_DDIC) + hotplug_ctrl |= BXT_DDIC_HPD_ENABLE; + I915_WRITE(BXT_HOTPLUG_CTL, hotplug_ctrl); + + /* Unmask DDI hotplug in IMR */ + hotplug_ctrl = I915_READ(GEN8_DE_PORT_IMR) & ~hotplug_port; + I915_WRITE(GEN8_DE_PORT_IMR, hotplug_ctrl); + + /* Enable DDI hotplug in IER */ + hotplug_ctrl = I915_READ(GEN8_DE_PORT_IER) | hotplug_port; + I915_WRITE(GEN8_DE_PORT_IER, hotplug_ctrl); + POSTING_READ(GEN8_DE_PORT_IER); +} + static void ibx_irq_postinstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -4279,7 +4321,10 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->driver->irq_uninstall = gen8_irq_uninstall; dev->driver->enable_vblank = gen8_enable_vblank; dev->driver->disable_vblank = gen8_disable_vblank; - dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup; + if (HAS_PCH_SPLIT(dev)) + dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup; + else + dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; } else if (HAS_PCH_SPLIT(dev)) { dev->driver->irq_handler = ironlake_irq_handler; dev->driver->irq_preinstall = ironlake_irq_reset; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9ef716a5093cce..ccdbd25b78a681 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5373,10 +5373,16 @@ enum skl_disp_power_wells { #define GEN8_DE_PORT_IMR 0x44444 #define GEN8_DE_PORT_IIR 0x44448 #define GEN8_DE_PORT_IER 0x4444c -#define GEN8_PORT_DP_A_HOTPLUG (1 << 3) #define GEN9_AUX_CHANNEL_D (1 << 27) #define GEN9_AUX_CHANNEL_C (1 << 26) #define GEN9_AUX_CHANNEL_B (1 << 25) +#define BXT_DE_PORT_HP_DDIC (1 << 5) +#define BXT_DE_PORT_HP_DDIB (1 << 4) +#define BXT_DE_PORT_HP_DDIA (1 << 3) +#define BXT_DE_PORT_HOTPLUG_MASK (BXT_DE_PORT_HP_DDIA | \ + BXT_DE_PORT_HP_DDIB | \ + BXT_DE_PORT_HP_DDIC) +#define GEN8_PORT_DP_A_HOTPLUG (1 << 3) #define GEN8_AUX_CHANNEL_A (1 << 0) #define GEN8_DE_MISC_ISR 0x44460 @@ -5390,6 +5396,21 @@ enum skl_disp_power_wells { #define GEN8_PCU_IIR 0x444e8 #define GEN8_PCU_IER 0x444ec +/* BXT hotplug control */ +#define BXT_HOTPLUG_CTL 0xC4030 +#define BXT_DDIA_HPD_ENABLE (1 << 28) +#define BXT_DDIA_HPD_STATUS (3 << 24) +#define BXT_DDIC_HPD_ENABLE (1 << 12) +#define BXT_DDIC_HPD_STATUS (3 << 8) +#define BXT_DDIB_HPD_ENABLE (1 << 4) +#define BXT_DDIB_HPD_STATUS (3 << 0) +#define BXT_HOTPLUG_CTL_MASK (BXT_DDIA_HPD_ENABLE | \ + BXT_DDIB_HPD_ENABLE | \ + BXT_DDIC_HPD_ENABLE) +#define BXT_HPD_STATUS_MASK (BXT_DDIA_HPD_STATUS | \ + BXT_DDIB_HPD_STATUS | \ + BXT_DDIC_HPD_STATUS) + #define ILK_DISPLAY_CHICKEN2 0x42004 /* Required on all Ironlake and Sandybridge according to the B-Spec. */ #define ILK_ELPIN_409_SELECT (1 << 25) From 6b5ad42f0a54e522e99734ad5fdbb7fe983277d2 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 27 Mar 2015 17:22:34 +0200 Subject: [PATCH 0149/3798] drm/i915/bxt: support for HPD long/short status decoding All non-GMCH platforms have the same register layout for HPD long/short status, so let's use this condition instead of HAS_PCH_SPLIT, as the latter doesn't apply for BXT. Noticed by Daniel. Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 631484dd0b60f6..7f73f71741ae12 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1428,7 +1428,7 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev, if (port && dev_priv->hpd_irq_port[port]) { bool long_hpd; - if (HAS_PCH_SPLIT(dev)) { + if (!HAS_GMCH_DISPLAY(dev_priv)) { dig_shift = pch_port_to_hotplug_shift(port); long_hpd = (dig_hotplug_reg >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT; } else { From d04a492dd574bba43a558612ddd49fa593a387fe Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Fri, 22 Aug 2014 17:40:41 +0530 Subject: [PATCH 0150/3798] drm/i915/bxt: Add DDI hpd handler This patch adds a hot plug interrupt handler function for BXT. What this function typically does is: 1. Check if hot plug is enabled from hot plug control register. 2. Call hpd_irq_handler with appropriate trigger to detect a plug storm and schedule a bottom half. 3. Clear sticky status bits in hot plug control register.. v2: (jani) - drop redundant unlikely() - s/Todo/FIXME:/ in code comment - declare 'found' var in the scope where it's used - check for IS_BROXTON before handling BXT_DE_PORT_HOTPLUG_MASK Reviewed-by: Satheeshakrishna M Signed-off-by: Damien Lespiau Signed-off-by: Shashank Sharma (v1) Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 46 +++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7f73f71741ae12..ac68b5bd8f1503 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2152,6 +2152,38 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) return ret; } +static void bxt_hpd_handler(struct drm_device *dev, uint32_t iir_status) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t hp_control; + uint32_t hp_trigger; + + /* Get the status */ + hp_trigger = iir_status & BXT_DE_PORT_HOTPLUG_MASK; + hp_control = I915_READ(BXT_HOTPLUG_CTL); + + /* Hotplug not enabled ? */ + if (!(hp_control & BXT_HOTPLUG_CTL_MASK)) { + DRM_ERROR("Interrupt when HPD disabled\n"); + return; + } + + DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", + hp_control & BXT_HOTPLUG_CTL_MASK); + + /* Check for HPD storm and schedule bottom half */ + intel_hpd_irq_handler(dev, hp_trigger, hp_control, hpd_bxt); + + /* + * FIXME: Save the hot plug status for bottom half before + * clearing the sticky status bits, else the status will be + * lost. + */ + + /* Clear sticky bits in hpd status */ + I915_WRITE(BXT_HOTPLUG_CTL, hp_control); +} + static irqreturn_t gen8_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; @@ -2197,12 +2229,22 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) if (master_ctl & GEN8_DE_PORT_IRQ) { tmp = I915_READ(GEN8_DE_PORT_IIR); if (tmp) { + bool found = false; + I915_WRITE(GEN8_DE_PORT_IIR, tmp); ret = IRQ_HANDLED; - if (tmp & aux_mask) + if (tmp & aux_mask) { dp_aux_irq_handler(dev); - else + found = true; + } + + if (IS_BROXTON(dev) && tmp & BXT_DE_PORT_HOTPLUG_MASK) { + bxt_hpd_handler(dev, tmp); + found = true; + } + + if (!found) DRM_ERROR("Unexpected DE Port interrupt\n"); } else From 266ea3d9c4f69a4d97533128aba494f7d8b52459 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Fri, 22 Aug 2014 17:40:42 +0530 Subject: [PATCH 0151/3798] drm/i915/bxt: Add BXT support in gen8_irq functions This patch adds conditional checks in gen8_irq functions to support BXT. Most of the checks just look for PCH split availability, and block the call to PCH interrupt functions if not available. v2: (jani) - drop redundant TODO comment about PCH IRQ flags on BXT - check HAS_PCH_SPLIT instead of IS_BROXTON when handling PCH specific IRQ events in gen8_irq_handler() - check HAS_PCH_SPLIT before calling the function instead of a corresponding early return within the called function for ibx_irq_reset(), ibx_irq_pre_postinstall(), ibx_irq_postinstall() v3: (jani) - in ironlake_irq_postinstall() and ironlake_irq_reset() HAS_PCH_SPLIT is always true, so drop the check for it Reviewed-by: Satheeshakrishna M Signed-off-by: Damien Lespiau Signed-off-by: Shashank Sharma (v1) Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ac68b5bd8f1503..17a8f8c61753e8 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2297,7 +2297,8 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) DRM_ERROR("The master control interrupt lied (DE PIPE)!\n"); } - if (!HAS_PCH_NOP(dev) && master_ctl & GEN8_DE_PCH_IRQ) { + if (HAS_PCH_SPLIT(dev) && !HAS_PCH_NOP(dev) && + master_ctl & GEN8_DE_PCH_IRQ) { /* * FIXME(BDW): Assume for now that the new interrupt handling * scheme also closed the SDE interrupt handling race we've seen @@ -3133,7 +3134,8 @@ static void gen8_irq_reset(struct drm_device *dev) GEN5_IRQ_RESET(GEN8_DE_MISC_); GEN5_IRQ_RESET(GEN8_PCU_); - ibx_irq_reset(dev); + if (HAS_PCH_SPLIT(dev)) + ibx_irq_reset(dev); } void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, @@ -3545,12 +3547,14 @@ static int gen8_irq_postinstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - ibx_irq_pre_postinstall(dev); + if (HAS_PCH_SPLIT(dev)) + ibx_irq_pre_postinstall(dev); gen8_gt_irq_postinstall(dev_priv); gen8_de_irq_postinstall(dev_priv); - ibx_irq_postinstall(dev); + if (HAS_PCH_SPLIT(dev)) + ibx_irq_postinstall(dev); I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL); POSTING_READ(GEN8_MASTER_IRQ); From 9e63743ebbcb138be83453f7dcf65f817893f851 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Fri, 22 Aug 2014 17:40:43 +0530 Subject: [PATCH 0152/3798] drm/i915/bxt: Enable GMBUS IRQ GMBUS interrupt has been moved to CPU side in BXT. What this patch does is: 1. Enable GMBUS IRQ in de_post_install function 2. Handle this interrupt as a port interrupt in display irq handler v2: Rebase on top of the for_each_pipe() change adding dev_priv as first argument (Damien). v3: read BXT_DE_PORT_GMBUS IIR flag only on BXT on other platforms it's reserved (imre) v4: (jani) - remove redundant 'BXT GMBUS' comment - fix formatting of BXT_DE_PORT_GMBUS definition Reviewed-by: Satheeshakrishna M Signed-off-by: Damien Lespiau Signed-off-by: Shashank Sharma (v1) Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 14 +++++++++++--- drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 17a8f8c61753e8..f776584ce36350 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2244,6 +2244,11 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) found = true; } + if (IS_BROXTON(dev) && (tmp & BXT_DE_PORT_GMBUS)) { + gmbus_irq_handler(dev); + found = true; + } + if (!found) DRM_ERROR("Unexpected DE Port interrupt\n"); } @@ -3515,13 +3520,16 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) uint32_t de_pipe_masked = GEN8_PIPE_CDCLK_CRC_DONE; uint32_t de_pipe_enables; int pipe; - u32 aux_en = GEN8_AUX_CHANNEL_A; + u32 de_port_en = GEN8_AUX_CHANNEL_A; if (IS_GEN9(dev_priv)) { de_pipe_masked |= GEN9_PIPE_PLANE1_FLIP_DONE | GEN9_DE_PIPE_IRQ_FAULT_ERRORS; - aux_en |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | + de_port_en |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | GEN9_AUX_CHANNEL_D; + + if (IS_BROXTON(dev_priv)) + de_port_en |= BXT_DE_PORT_GMBUS; } else de_pipe_masked |= GEN8_PIPE_PRIMARY_FLIP_DONE | GEN8_DE_PIPE_IRQ_FAULT_ERRORS; @@ -3540,7 +3548,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) dev_priv->de_irq_mask[pipe], de_pipe_enables); - GEN5_IRQ_INIT(GEN8_DE_PORT_, ~aux_en, aux_en); + GEN5_IRQ_INIT(GEN8_DE_PORT_, ~de_port_en, de_port_en); } static int gen8_irq_postinstall(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ccdbd25b78a681..4b53b2083c7867 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5383,6 +5383,7 @@ enum skl_disp_power_wells { BXT_DE_PORT_HP_DDIB | \ BXT_DE_PORT_HP_DDIC) #define GEN8_PORT_DP_A_HOTPLUG (1 << 3) +#define BXT_DE_PORT_GMBUS (1 << 1) #define GEN8_AUX_CHANNEL_A (1 << 0) #define GEN8_DE_MISC_ISR 0x44460 From 0b4a2a36d078b3a8de871025a958da547a6143f7 Mon Sep 17 00:00:00 2001 From: Satheeshakrishna M Date: Fri, 11 Jul 2014 14:51:13 +0530 Subject: [PATCH 0153/3798] drm/i915/bxt: Define BXT power domains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add BXT power domains v2: Use DOMAIN_PLLS instead of a new CDCLK one, whitespace fixes (Damien) v3: add VGA, TRANSCODER_A power domains (imre) Signed-off-by: Satheeshakrishna M (v1) Signed-off-by: Damien Lespiau Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_runtime_pm.c | 55 +++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index ce00e6994eeb95..ff5cce32c7d676 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -319,6 +319,38 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, SKL_DISPLAY_MISC_IO_POWER_DOMAINS)) | \ BIT(POWER_DOMAIN_INIT)) +#define BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \ + BIT(POWER_DOMAIN_TRANSCODER_A) | \ + BIT(POWER_DOMAIN_PIPE_B) | \ + BIT(POWER_DOMAIN_TRANSCODER_B) | \ + BIT(POWER_DOMAIN_PIPE_C) | \ + BIT(POWER_DOMAIN_TRANSCODER_C) | \ + BIT(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ + BIT(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ + BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ + BIT(POWER_DOMAIN_AUX_B) | \ + BIT(POWER_DOMAIN_AUX_C) | \ + BIT(POWER_DOMAIN_AUDIO) | \ + BIT(POWER_DOMAIN_VGA) | \ + BIT(POWER_DOMAIN_INIT)) +#define BXT_DISPLAY_POWERWELL_1_POWER_DOMAINS ( \ + BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ + BIT(POWER_DOMAIN_PIPE_A) | \ + BIT(POWER_DOMAIN_TRANSCODER_EDP) | \ + BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \ + BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) | \ + BIT(POWER_DOMAIN_AUX_A) | \ + BIT(POWER_DOMAIN_PLLS) | \ + BIT(POWER_DOMAIN_INIT)) +#define BXT_DISPLAY_ALWAYS_ON_POWER_DOMAINS ( \ + (POWER_DOMAIN_MASK & ~(BXT_DISPLAY_POWERWELL_1_POWER_DOMAINS | \ + BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS)) | \ + BIT(POWER_DOMAIN_INIT)) + static void skl_set_power_well(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool enable) { @@ -1313,6 +1345,27 @@ static struct i915_power_well skl_power_wells[] = { }, }; +static struct i915_power_well bxt_power_wells[] = { + { + .name = "always-on", + .always_on = 1, + .domains = BXT_DISPLAY_ALWAYS_ON_POWER_DOMAINS, + .ops = &i9xx_always_on_power_well_ops, + }, + { + .name = "power well 1", + .domains = BXT_DISPLAY_POWERWELL_1_POWER_DOMAINS, + .ops = &skl_power_well_ops, + .data = SKL_DISP_PW_1, + }, + { + .name = "power well 2", + .domains = BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS, + .ops = &skl_power_well_ops, + .data = SKL_DISP_PW_2, + } +}; + #define set_power_wells(power_domains, __power_wells) ({ \ (power_domains)->power_wells = (__power_wells); \ (power_domains)->power_well_count = ARRAY_SIZE(__power_wells); \ @@ -1341,6 +1394,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) set_power_wells(power_domains, bdw_power_wells); } else if (IS_SKYLAKE(dev_priv->dev)) { set_power_wells(power_domains, skl_power_wells); + } else if (IS_BROXTON(dev_priv->dev)) { + set_power_wells(power_domains, bxt_power_wells); } else if (IS_CHERRYVIEW(dev_priv->dev)) { set_power_wells(power_domains, chv_power_wells); } else if (IS_VALLEYVIEW(dev_priv->dev)) { From cff5190cb989f130afa18b96cd33745b733ffae9 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 10 Apr 2015 11:15:07 -0700 Subject: [PATCH 0154/3798] drm/i915: PSR: Remove wrong LINK_DISABLE. This wrong logic and useless define came from first versions and came along with all rework. Just now I notice how ugly, wrong and useless this is. val is already defined as 0 anyway and logic is completelly wrong and useless. So let's starting the link_standby fix with this cleaning. Signed-off-by: Rodrigo Vivi Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 - drivers/gpu/drm/i915/intel_psr.c | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 4b53b2083c7867..077cb90b0822a5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2688,7 +2688,6 @@ enum skl_disp_power_wells { #define EDP_PSR_CTL(dev) (EDP_PSR_BASE(dev) + 0) #define EDP_PSR_ENABLE (1<<31) #define BDW_PSR_SINGLE_FRAME (1<<30) -#define EDP_PSR_LINK_DISABLE (0<<27) #define EDP_PSR_LINK_STANDBY (1<<27) #define EDP_PSR_MIN_LINK_ENTRY_TIME_MASK (3<<25) #define EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES (0<<25) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 27608ce19b1cf6..db95b392bcd45b 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -269,8 +269,7 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) val |= EDP_PSR_TP2_TP3_TIME_0us; val |= EDP_PSR_TP1_TIME_0us; val |= EDP_PSR_SKIP_AUX_EXIT; - } else - val |= EDP_PSR_LINK_DISABLE; + } I915_WRITE(EDP_PSR_CTL(dev), val | (IS_BROADWELL(dev) ? 0 : link_entry_time) | From 3301d4092106ff07e14d7acbf12243d782600930 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 10 Apr 2015 11:15:08 -0700 Subject: [PATCH 0155/3798] drm/i915: PSR: Fix DP_PSR_NO_TRAIN_ON_EXIT logic Since the beginning there is a missunderstanding on the meaning of this dpcd bit. This bit shouldn't indicate whether to use link standby or not, but just be used to configure TP1, TP2 and TP3 times and tell hw aux should be skiped since HW is the responsible one. Even with help of frontbuffer tracking, HW is still fully responsible for PSR exit logic with/without DP training. DP_PSR_NO_TRAIN_ON_EXIT means the source doesn't need to do the training, but it doesn't tell to avoid TP patterns, so we will send minimal TP1 and avoid TP2. It also means that sink itself can take up to 5 idle frames for training. 6 in our case since we might be off by 1. So we also increment idle_frames by 4 here. v2: Fix and improve commit message (Durga). v3: Use minimal TP1 time avoiding TP2 and increase idle frame. Cc: Durgadoss R Cc: Arthur Runyan Signed-off-by: Rodrigo Vivi Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_psr.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index db95b392bcd45b..0e3b652b5946d7 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -264,11 +264,17 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) uint32_t val = 0x0; const uint32_t link_entry_time = EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES; - if (dev_priv->psr.link_standby) { + if (dev_priv->psr.link_standby) val |= EDP_PSR_LINK_STANDBY; + + if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT) { + /* It doesn't mean we shouldn't send TPS patters, so let's + send the minimal TP1 possible and skip TP2. */ + val |= EDP_PSR_TP1_TIME_100us; val |= EDP_PSR_TP2_TP3_TIME_0us; - val |= EDP_PSR_TP1_TIME_0us; val |= EDP_PSR_SKIP_AUX_EXIT; + /* Sink should be able to train with the 5 or 6 idle patterns */ + idle_frames += 4; } I915_WRITE(EDP_PSR_CTL(dev), val | @@ -381,8 +387,7 @@ void intel_psr_enable(struct intel_dp *intel_dp) /* First we check VBT, but we must respect sink and source * known restrictions */ dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link; - if ((intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT) || - (IS_BROADWELL(dev) && intel_dig_port->port != PORT_A)) + if (IS_BROADWELL(dev) && intel_dig_port->port != PORT_A) dev_priv->psr.link_standby = true; dev_priv->psr.busy_frontbuffer_bits = 0; From 89251b177b588adf5e62df42d51017d24047f44b Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 10 Apr 2015 11:15:09 -0700 Subject: [PATCH 0156/3798] drm/i915: PSR: deprecate link_standby support for core platforms. On Haswell and Broadwell with link in standby when exit event happens between vblank and VSC packet, PSR exit on panel but DPA transmitter still sends black pixel. When this condition hits, panel will intermittently display black frame. The known W/A for this case involve the of single_frame update that isn't supported on Haswell and to be supported on Broadwell 3 other workarounds would be required. So it is better and safe to just deprecate link_standby for now. Also, link fully off saves more power than link_standby and afwk no OEM is requesting link standby on VBT. There is no reason for that. For Skylake let's just consider it behaves like Broadwell until we prove otherwise. v2: Fix commit message (Durga). v3: Fix conflict with PSR2. Reference: HSD: bdwgfx/1912559 Signed-off-by: Rodrigo Vivi Reviewed-by: Durgadoss R Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 3 --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_psr.c | 26 ++++++++++---------------- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 23949247cf1031..07a71c0ff7756c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2358,9 +2358,6 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) } seq_puts(m, "\n"); - seq_printf(m, "Link standby: %s\n", - yesno((bool)dev_priv->psr.link_standby)); - /* CHV PSR has no kind of performance counter */ if (HAS_DDI(dev)) { psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) & diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3b21249300581c..37e74543ca1670 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -881,7 +881,6 @@ struct i915_psr { bool active; struct delayed_work work; unsigned busy_frontbuffer_bits; - bool link_standby; bool psr2_support; bool aux_frame_sync; }; diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 0e3b652b5946d7..5cd374b4a07ec7 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -170,13 +170,8 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0); - /* Enable PSR in sink */ - if (dev_priv->psr.link_standby) - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, - DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE); - else - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, - DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE); + drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, + DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE); /* Enable AUX frame sync at sink */ if (dev_priv->psr.aux_frame_sync) @@ -214,6 +209,8 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT)); } + + drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, DP_PSR_ENABLE); } static void vlv_psr_enable_source(struct intel_dp *intel_dp) @@ -264,9 +261,6 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) uint32_t val = 0x0; const uint32_t link_entry_time = EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES; - if (dev_priv->psr.link_standby) - val |= EDP_PSR_LINK_STANDBY; - if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT) { /* It doesn't mean we shouldn't send TPS patters, so let's send the minimal TP1 possible and skip TP2. */ @@ -325,6 +319,12 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) return false; } + if (!IS_VALLEYVIEW(dev) && ((dev_priv->vbt.psr.full_link) || + (dig_port->port != PORT_A))) { + DRM_DEBUG_KMS("PSR condition failed: Link Standby requested/needed but not supported on this platform\n"); + return false; + } + dev_priv->psr.source_ok = true; return true; } @@ -384,12 +384,6 @@ void intel_psr_enable(struct intel_dp *intel_dp) if (!intel_psr_match_conditions(intel_dp)) goto unlock; - /* First we check VBT, but we must respect sink and source - * known restrictions */ - dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link; - if (IS_BROADWELL(dev) && intel_dig_port->port != PORT_A) - dev_priv->psr.link_standby = true; - dev_priv->psr.busy_frontbuffer_bits = 0; if (HAS_DDI(dev)) { From c7240c3bc5d6610b42dbb10fda71bbbf1dad5515 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 10 Apr 2015 11:15:10 -0700 Subject: [PATCH 0157/3798] drm/i915: PSR VLV: Add single frame update. According to spec: "In PSR HW or SW mode, SW set this bit before writing registers for a flip. It will be self-clear when it gets to the PSR active state." Some versions of spec mention that this is needed when in "Persistent mode" but define it as same as "SW mode". Since this fix the page flip case let's assume this is exactly what we need. Cc: Dhinakaran Pandiyan Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_frontbuffer.c | 2 ++ drivers/gpu/drm/i915/intel_psr.c | 42 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6a2ee0c3816118..082be7161203d4 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1294,6 +1294,7 @@ void intel_psr_invalidate(struct drm_device *dev, void intel_psr_flush(struct drm_device *dev, unsigned frontbuffer_bits); void intel_psr_init(struct drm_device *dev); +void intel_psr_single_frame_update(struct drm_device *dev); /* intel_runtime_pm.c */ int intel_power_domains_init(struct drm_i915_private *); diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c b/drivers/gpu/drm/i915/intel_frontbuffer.c index a20cffb78c0f49..57095f54c1f2e2 100644 --- a/drivers/gpu/drm/i915/intel_frontbuffer.c +++ b/drivers/gpu/drm/i915/intel_frontbuffer.c @@ -243,6 +243,8 @@ void intel_frontbuffer_flip_prepare(struct drm_device *dev, /* Remove stale busy bits due to the old buffer. */ dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits; mutex_unlock(&dev_priv->fb_tracking.lock); + + intel_psr_single_frame_update(dev); } /** diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 5cd374b4a07ec7..5ee0fa57ed1999 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -593,6 +593,48 @@ static void intel_psr_exit(struct drm_device *dev) dev_priv->psr.active = false; } +/** + * intel_psr_single_frame_update - Single Frame Update + * @dev: DRM device + * + * Some platforms support a single frame update feature that is used to + * send and update only one frame on Remote Frame Buffer. + * So far it is only implemented for Valleyview and Cherryview because + * hardware requires this to be done before a page flip. + */ +void intel_psr_single_frame_update(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc; + enum pipe pipe; + u32 val; + + /* + * Single frame update is already supported on BDW+ but it requires + * many W/A and it isn't really needed. + */ + if (!IS_VALLEYVIEW(dev)) + return; + + mutex_lock(&dev_priv->psr.lock); + if (!dev_priv->psr.enabled) { + mutex_unlock(&dev_priv->psr.lock); + return; + } + + crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc; + pipe = to_intel_crtc(crtc)->pipe; + val = I915_READ(VLV_PSRCTL(pipe)); + + /* + * We need to set this bit before writing registers for a flip. + * This bit will be self-clear when it gets to the PSR active state. + */ + I915_WRITE(VLV_PSRCTL(pipe), val | VLV_EDP_PSR_SINGLE_FRAME_UPDATE); + + mutex_unlock(&dev_priv->psr.lock); +} + /** * intel_psr_invalidate - Invalidade PSR * @dev: DRM device From 164dfd2877249e7a768326256ffe0c78026a2863 Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Mon, 24 Nov 2014 13:37:41 +0530 Subject: [PATCH 0158/3798] drm/i915: Rename vlv_cdclk_freq to cdclk_freq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename vlv_cdclk_freq to cdclk_freq so that it can be used for all platforms as required. Needed by the next patch. Signed-off-by: Vandana Kannan Signed-off-by: A.Sunil Kamath Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_display.c | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 37e74543ca1670..2645ba35b13040 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1656,7 +1656,7 @@ struct drm_i915_private { int num_fence_regs; /* 8 on pre-965, 16 otherwise */ unsigned int fsb_freq, mem_freq, is_ddr3; - unsigned int vlv_cdclk_freq; + unsigned int cdclk_freq; unsigned int hpll_freq; /** diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9f72d9a76a387e..bb5f2a570a1d63 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5214,16 +5214,16 @@ static void vlv_update_cdclk(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - dev_priv->vlv_cdclk_freq = dev_priv->display.get_display_clock_speed(dev); + dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(dev); DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n", - dev_priv->vlv_cdclk_freq); + dev_priv->cdclk_freq); /* * Program the gmbus_freq based on the cdclk frequency. * BSpec erroneously claims we should aim for 4MHz, but * in fact 1MHz is the correct frequency. */ - I915_WRITE(GMBUSFREQ_VLV, DIV_ROUND_UP(dev_priv->vlv_cdclk_freq, 1000)); + I915_WRITE(GMBUSFREQ_VLV, DIV_ROUND_UP(dev_priv->cdclk_freq, 1000)); } /* Adjust CDclk dividers to allow high res or save power if possible */ @@ -5232,7 +5232,8 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) struct drm_i915_private *dev_priv = dev->dev_private; u32 val, cmd; - WARN_ON(dev_priv->display.get_display_clock_speed(dev) != dev_priv->vlv_cdclk_freq); + WARN_ON(dev_priv->display.get_display_clock_speed(dev) + != dev_priv->cdclk_freq); if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */ cmd = 2; @@ -5296,7 +5297,8 @@ static void cherryview_set_cdclk(struct drm_device *dev, int cdclk) struct drm_i915_private *dev_priv = dev->dev_private; u32 val, cmd; - WARN_ON(dev_priv->display.get_display_clock_speed(dev) != dev_priv->vlv_cdclk_freq); + WARN_ON(dev_priv->display.get_display_clock_speed(dev) + != dev_priv->cdclk_freq); switch (cdclk) { case 333333: @@ -5395,7 +5397,7 @@ static int valleyview_modeset_global_pipes(struct drm_atomic_state *state, return max_pixclk; if (valleyview_calc_cdclk(dev_priv, max_pixclk) == - dev_priv->vlv_cdclk_freq) + dev_priv->cdclk_freq) return 0; /* disable/enable all currently active pipes while we change cdclk */ @@ -5415,7 +5417,7 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv) else default_credits = PFI_CREDIT(8); - if (DIV_ROUND_CLOSEST(dev_priv->vlv_cdclk_freq, 1000) >= dev_priv->rps.cz_freq) { + if (DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 1000) >= dev_priv->rps.cz_freq) { /* CHV suggested value is 31 or 63 */ if (IS_CHERRYVIEW(dev_priv)) credits = PFI_CREDIT_31; @@ -5459,7 +5461,7 @@ static void valleyview_modeset_global_resources(struct drm_atomic_state *state) req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk); - if (req_cdclk != dev_priv->vlv_cdclk_freq) { + if (req_cdclk != dev_priv->cdclk_freq) { /* * FIXME: We can end up here with all power domains off, yet * with a CDCLK frequency other than the minimum. To account From f8437dd1b5a5a084302ba8e9fa29f76cdfc2f945 Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Mon, 24 Nov 2014 13:37:39 +0530 Subject: [PATCH 0159/3798] drm/i915/bxt: add display initialize/uninitialize sequence (CDCLK) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add CDCLK specific display clock initialization sequence as per BSpec. Note that the CDCLK initialization/uninitialization are done at their current place only for simplicity, in a future patch - when more of the runtime PM features will be enabled - these will be moved to power well#1 and modeset encoder enabling/disabling hooks respectively. This also means that atm dynamic power gating power well #1 is effectively disabled. The call to uninitialize CDCLK during system/runtime suspend will be added later in this patchset. v1: Added function definitions in header files v2: Imre's review comments addressed - Moved CDCLK related definitions to i915_reg.h - Removed defintions for CDCLK frequency - Split uninit_cdclk() by adding a phy_uninit function - Calculate freq and decimal based on input frequency - Program SSA precharge based on input frequency - Use wait_for 1ms instead 200us udelay for DE PLL locking - Removed initial value for divider, freq, decimal, ratio. - Replaced polling loops with wait_for - Parameterized latency optim setting - Fix the parts where DE PLL has to be disabled. - Call CDCLK selection from mode set v3: (imre) - add note about the plan to move the cdclk/phy init to a better place - take rps.hw_lock around pcode access - move DE PLL register macros here from another patch since they are used here first - add BXT_ prefix to CDCLK flags - add missing masking when programming CDCLK_FREQ_DECIMAL v4: (ville) - split the CDCLK/PHY parts into two patches, update commit message accordingly - s/DISPLAY_PCU_CONTROL/HSW_PCODE_DE_WRITE_FREQ_REQ/ - simplify BXT_DE_PLL_RATIO macros - fix BXT_DE_PLL_RATIO_MASK - s/bxt_select_cdclk_freq/broxton_set_cdclk_freq/ - move cdclk init/uninit/set code from intel_ddi.c to intel_display.c - remove redundant code comments for broxton_set_cdclk_freq() - sanitize fixed point<->integer frequency value conversion - use DRM_ERROR instead of WARN - do RMW when programming BXT_DE_PLL_CTL for safety - add note about PLL lock timeout being exactly 200us - make PCU error messages more descriptive - instead of using 0 freq to mean PLL off/bypass freq use 19200 for clarity, as the latter one is the actual rate - simplify pcode programming, removing duplicated sandybridge_pcode_write() call - sanitize code flow, remove unnecessary scratch vars in broxton_set_cdclk() (imre) - Remove bound check for maxmimum freq to match current code. This check will be added later at a more proper platform independent place once atomic support lands. - add note to remove freq guard band which isn't needed on BXT - add note to reduce freq to minimum if no pipe is enabled - combine broxton_modeset_global_pipes() with valleyview_modeset_global_pipes() Signed-off-by: Vandana Kannan (v2) Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 20 +++ drivers/gpu/drm/i915/intel_ddi.c | 2 + drivers/gpu/drm/i915/intel_display.c | 226 ++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_drv.h | 3 + 4 files changed, 248 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 077cb90b0822a5..164350cf760c4d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5451,6 +5451,9 @@ enum skl_disp_power_wells { #define DISP_FBC_WM_DIS (1<<15) #define DISP_ARB_CTL2 0x45004 #define DISP_DATA_PARTITION_5_6 (1<<6) +#define DBUF_CTL 0x45008 +#define DBUF_POWER_REQUEST (1<<31) +#define DBUF_POWER_STATE (1<<30) #define GEN7_MSG_CTL 0x45010 #define WAIT_FOR_PCH_RESET_ACK (1<<1) #define WAIT_FOR_PCH_FLR_ACK (1<<0) @@ -6402,6 +6405,7 @@ enum skl_disp_power_wells { #define GEN6_PCODE_WRITE_D_COMP 0x11 #define GEN6_ENCODE_RC6_VID(mv) (((mv) - 245) / 5) #define GEN6_DECODE_RC6_VID(vids) (((vids) * 5) + 245) +#define HSW_PCODE_DE_WRITE_FREQ_REQ 0x17 #define DISPLAY_IPS_CONTROL 0x19 #define HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL 0x1A #define GEN6_PCODE_DATA 0x138128 @@ -6873,6 +6877,13 @@ enum skl_disp_power_wells { #define CDCLK_FREQ_675_617 (3<<26) #define CDCLK_FREQ_DECIMAL_MASK (0x7ff) +#define BXT_CDCLK_CD2X_DIV_SEL_MASK (3<<22) +#define BXT_CDCLK_CD2X_DIV_SEL_1 (0<<22) +#define BXT_CDCLK_CD2X_DIV_SEL_1_5 (1<<22) +#define BXT_CDCLK_CD2X_DIV_SEL_2 (2<<22) +#define BXT_CDCLK_CD2X_DIV_SEL_4 (3<<22) +#define BXT_CDCLK_SSA_PRECHARGE_ENABLE (1<<16) + /* LCPLL_CTL */ #define LCPLL1_CTL 0x46010 #define LCPLL2_CTL 0x46014 @@ -6937,6 +6948,15 @@ enum skl_disp_power_wells { #define GET_CFG_CR1_REG(id) (DPLL1_CFGCR1 + (id - SKL_DPLL1) * 8) #define GET_CFG_CR2_REG(id) (DPLL1_CFGCR2 + (id - SKL_DPLL1) * 8) +/* BXT display engine PLL */ +#define BXT_DE_PLL_CTL 0x6d000 +#define BXT_DE_PLL_RATIO(x) (x) /* {60,65,100} * 19.2MHz */ +#define BXT_DE_PLL_RATIO_MASK 0xff + +#define BXT_DE_PLL_ENABLE 0x46070 +#define BXT_DE_PLL_PLL_ENABLE (1 << 31) +#define BXT_DE_PLL_LOCK (1 << 30) + /* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register, * since on HSW we can't write to it using I915_WRITE. */ #define D_COMP_HSW (MCHBAR_MIRROR_BASE_SNB + 0x5F0C) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 5b504843711575..25d697b9d3d9c8 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1880,6 +1880,8 @@ void intel_ddi_pll_init(struct drm_device *dev) if (IS_SKYLAKE(dev)) { if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) DRM_ERROR("LCPLL1 is disabled\n"); + } else if (IS_BROXTON(dev)) { + broxton_init_cdclk(dev); } else { /* * The LCPLL register should be turned on by the BIOS. For now diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bb5f2a570a1d63..5ee5d8cd9cd1a6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5196,6 +5196,181 @@ static void modeset_update_crtc_power_domains(struct drm_atomic_state *state) intel_display_set_init_power(dev_priv, false); } +void broxton_set_cdclk(struct drm_device *dev, int frequency) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t divider; + uint32_t ratio; + uint32_t current_freq; + int ret; + + /* frequency = 19.2MHz * ratio / 2 / div{1,1.5,2,4} */ + switch (frequency) { + case 144000: + divider = BXT_CDCLK_CD2X_DIV_SEL_4; + ratio = BXT_DE_PLL_RATIO(60); + break; + case 288000: + divider = BXT_CDCLK_CD2X_DIV_SEL_2; + ratio = BXT_DE_PLL_RATIO(60); + break; + case 384000: + divider = BXT_CDCLK_CD2X_DIV_SEL_1_5; + ratio = BXT_DE_PLL_RATIO(60); + break; + case 576000: + divider = BXT_CDCLK_CD2X_DIV_SEL_1; + ratio = BXT_DE_PLL_RATIO(60); + break; + case 624000: + divider = BXT_CDCLK_CD2X_DIV_SEL_1; + ratio = BXT_DE_PLL_RATIO(65); + break; + case 19200: + /* + * Bypass frequency with DE PLL disabled. Init ratio, divider + * to suppress GCC warning. + */ + ratio = 0; + divider = 0; + break; + default: + DRM_ERROR("unsupported CDCLK freq %d", frequency); + + return; + } + + mutex_lock(&dev_priv->rps.hw_lock); + /* Inform power controller of upcoming frequency change */ + ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, + 0x80000000); + mutex_unlock(&dev_priv->rps.hw_lock); + + if (ret) { + DRM_ERROR("PCode CDCLK freq change notify failed (err %d, freq %d)\n", + ret, frequency); + return; + } + + current_freq = I915_READ(CDCLK_CTL) & CDCLK_FREQ_DECIMAL_MASK; + /* convert from .1 fixpoint MHz with -1MHz offset to kHz */ + current_freq = current_freq * 500 + 1000; + + /* + * DE PLL has to be disabled when + * - setting to 19.2MHz (bypass, PLL isn't used) + * - before setting to 624MHz (PLL needs toggling) + * - before setting to any frequency from 624MHz (PLL needs toggling) + */ + if (frequency == 19200 || frequency == 624000 || + current_freq == 624000) { + I915_WRITE(BXT_DE_PLL_ENABLE, ~BXT_DE_PLL_PLL_ENABLE); + /* Timeout 200us */ + if (wait_for(!(I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_LOCK), + 1)) + DRM_ERROR("timout waiting for DE PLL unlock\n"); + } + + if (frequency != 19200) { + uint32_t val; + + val = I915_READ(BXT_DE_PLL_CTL); + val &= ~BXT_DE_PLL_RATIO_MASK; + val |= ratio; + I915_WRITE(BXT_DE_PLL_CTL, val); + + I915_WRITE(BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE); + /* Timeout 200us */ + if (wait_for(I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_LOCK, 1)) + DRM_ERROR("timeout waiting for DE PLL lock\n"); + + val = I915_READ(CDCLK_CTL); + val &= ~BXT_CDCLK_CD2X_DIV_SEL_MASK; + val |= divider; + /* + * Disable SSA Precharge when CD clock frequency < 500 MHz, + * enable otherwise. + */ + val &= ~BXT_CDCLK_SSA_PRECHARGE_ENABLE; + if (frequency >= 500000) + val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE; + + val &= ~CDCLK_FREQ_DECIMAL_MASK; + /* convert from kHz to .1 fixpoint MHz with -1MHz offset */ + val |= (frequency - 1000) / 500; + I915_WRITE(CDCLK_CTL, val); + } + + mutex_lock(&dev_priv->rps.hw_lock); + ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, + DIV_ROUND_UP(frequency, 25000)); + mutex_unlock(&dev_priv->rps.hw_lock); + + if (ret) { + DRM_ERROR("PCode CDCLK freq set failed, (err %d, freq %d)\n", + ret, frequency); + return; + } + + dev_priv->cdclk_freq = frequency; +} + +void broxton_init_cdclk(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t val; + + /* + * NDE_RSTWRN_OPT RST PCH Handshake En must always be 0b on BXT + * or else the reset will hang because there is no PCH to respond. + * Move the handshake programming to initialization sequence. + * Previously was left up to BIOS. + */ + val = I915_READ(HSW_NDE_RSTWRN_OPT); + val &= ~RESET_PCH_HANDSHAKE_ENABLE; + I915_WRITE(HSW_NDE_RSTWRN_OPT, val); + + /* Enable PG1 for cdclk */ + intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); + + /* check if cd clock is enabled */ + if (I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_PLL_ENABLE) { + DRM_DEBUG_KMS("Display already initialized\n"); + return; + } + + /* + * FIXME: + * - The initial CDCLK needs to be read from VBT. + * Need to make this change after VBT has changes for BXT. + * - check if setting the max (or any) cdclk freq is really necessary + * here, it belongs to modeset time + */ + broxton_set_cdclk(dev, 624000); + + I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) | DBUF_POWER_REQUEST); + udelay(10); + + if (!(I915_READ(DBUF_CTL) & DBUF_POWER_STATE)) + DRM_ERROR("DBuf power enable timeout!\n"); +} + +void broxton_uninit_cdclk(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) & ~DBUF_POWER_REQUEST); + udelay(10); + + if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE) + DRM_ERROR("DBuf power disable timeout!\n"); + + /* Set minimum (bypass) frequency, in effect turning off the DE PLL */ + broxton_set_cdclk(dev, 19200); + + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); +} + /* returns HPLL frequency in kHz */ static int valleyview_get_vco(struct drm_i915_private *dev_priv) { @@ -5363,6 +5538,26 @@ static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv, return 200000; } +static int broxton_calc_cdclk(struct drm_i915_private *dev_priv, + int max_pixclk) +{ + /* + * FIXME: + * - remove the guardband, it's not needed on BXT + * - set 19.2MHz bypass frequency if there are no active pipes + */ + if (max_pixclk > 576000*9/10) + return 624000; + else if (max_pixclk > 384000*9/10) + return 576000; + else if (max_pixclk > 288000*9/10) + return 384000; + else if (max_pixclk > 144000*9/10) + return 288000; + else + return 144000; +} + /* compute the max pixel clock for new configuration */ static int intel_mode_max_pixclk(struct drm_atomic_state *state) { @@ -5392,12 +5587,17 @@ static int valleyview_modeset_global_pipes(struct drm_atomic_state *state, struct drm_i915_private *dev_priv = to_i915(state->dev); struct intel_crtc *intel_crtc; int max_pixclk = intel_mode_max_pixclk(state); + int cdclk; if (max_pixclk < 0) return max_pixclk; - if (valleyview_calc_cdclk(dev_priv, max_pixclk) == - dev_priv->cdclk_freq) + if (IS_VALLEYVIEW(dev_priv)) + cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk); + else + cdclk = broxton_calc_cdclk(dev_priv, max_pixclk); + + if (cdclk == dev_priv->cdclk_freq) return 0; /* disable/enable all currently active pipes while we change cdclk */ @@ -8827,6 +9027,23 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv) intel_prepare_ddi(dev); } +static void broxton_modeset_global_resources(struct drm_atomic_state *state) +{ + struct drm_device *dev = state->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int max_pixclk = intel_mode_max_pixclk(state); + int req_cdclk; + + /* see the comment in valleyview_modeset_global_resources */ + if (WARN_ON(max_pixclk < 0)) + return; + + req_cdclk = broxton_calc_cdclk(dev_priv, max_pixclk); + + if (req_cdclk != dev_priv->cdclk_freq) + broxton_set_cdclk(dev, req_cdclk); +} + static int haswell_crtc_compute_clock(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) { @@ -11983,7 +12200,7 @@ static int __intel_set_mode(struct drm_crtc *crtc, * mode set on this crtc. For other crtcs we need to use the * adjusted_mode bits in the crtc directly. */ - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_BROXTON(dev)) { ret = valleyview_modeset_global_pipes(state, &prepare_pipes); if (ret) goto done; @@ -14005,6 +14222,9 @@ static void intel_init_display(struct drm_device *dev) } else if (IS_VALLEYVIEW(dev)) { dev_priv->display.modeset_global_resources = valleyview_modeset_global_resources; + } else if (IS_BROXTON(dev)) { + dev_priv->display.modeset_global_resources = + broxton_modeset_global_resources; } switch (INTEL_INFO(dev)->gen) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 082be7161203d4..164f932f9f89af 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1112,6 +1112,9 @@ void intel_prepare_reset(struct drm_device *dev); void intel_finish_reset(struct drm_device *dev); void hsw_enable_pc8(struct drm_i915_private *dev_priv); void hsw_disable_pc8(struct drm_i915_private *dev_priv); +void broxton_init_cdclk(struct drm_device *dev); +void broxton_uninit_cdclk(struct drm_device *dev); +void broxton_set_cdclk(struct drm_device *dev, int frequency); void intel_dp_get_m_n(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n); From 5c6706e5644b608c2270f1d17c1b277901b3a121 Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Mon, 24 Nov 2014 13:37:39 +0530 Subject: [PATCH 0160/3798] drm/i915/bxt: add display initialize/uninitialize sequence (PHY) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add PHY specific display initialization sequence as per BSpec. Note that the PHY initialization/uninitialization are done at their current place only for simplicity, in a future patch - when more of the runtime PM features will be enabled - these will be moved to power well#1 and modeset encoder enabling/disabling hooks respectively. The call to uninitialize the PHY during system/runtime suspend will be added later in this patchset. v1: Added function definitions in header files v2: Imre's review comments addressed - Moved CDCLK related definitions to i915_reg.h - Removed defintions for CDCLK frequency - Split uninit_cdclk() by adding a phy_uninit function - Calculate freq and decimal based on input frequency - Program SSA precharge based on input frequency - Use wait_for 1ms instead 200us udelay for DE PLL locking - Removed initial value for divider, freq, decimal, ratio. - Replaced polling loops with wait_for - Parameterized latency optim setting - Fix the parts where DE PLL has to be disabled. - Call CDCLK selection from mode set v3: (imre) - add note about the plan to move the cdclk/phy init to a better place - take rps.hw_lock around pcode access - fix DDI PHY timeout value - squash in Vandana's "PORT_CL2CM_DW6_A BUN fix", "DDI PHY programming register defn", "Do ddi_phy_init always", - move PHY register macros next to the corresponding CHV/VLV macros - move DE PLL register macros here from another patch since they are used here first - add BXT_ prefix to CDCLK flags - s/COMMON_RESET/COMMON_RESET_DIS/ and clarify related code comments - fix incorrect read value for the RMW of BXT_PHY_CTL_FAMILY_DDI - fix using GT_DISPLAY_EDP_POWER_ON vs. GT_DISPLAY_DDI_POWER_ON when powering on DDI ports - fix incorrect port when setting BXT_PORT_TX_DW14_LN for DDI ports - add missing masking when programming CDCLK_FREQ_DECIMAL - add missing powering on for DDI-C port, rename OCL2_LDOFUSE_PWR_EN to OCL2_LDOFUSE_PWR_DIS to reduce confusion - add note about mismatch with bspec in the PORT_REF_DW6 fields - factor out PHY init code to a new function, so we can call it for PHY1 and PHY0, instead of open-coding the same v4: (ville) - split the CDCLK/PHY parts into two patches, update commit message accordingly - use the existing dpio_phy enum instead of adding a new one for the same purpose - flip the meaning of PHYs so that PHY_A is PHY1 and PHY_BC is PHY0 to better match CHV - s/BXT_PHY/_BXT_PHY/ - use _PIPE for _BXT_PHY instead of open-coding it - drop _0_2_0_GTTMMADR suffix from BXT_P_CR_GT_DISP_PWRON - define GT_DISPLAY_POWER_ON in a more standard way - make a note that the CHV ConfigDB also disagrees about GRC_CODE field definitions - fix lane optimization refactoring fumble from v3 - add per PHY uninit functions to match the init counterparts Signed-off-by: Vandana Kannan (v2) Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 96 ++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ddi.c | 125 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 2 + 3 files changed, 223 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 164350cf760c4d..6e0913db6e24a6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1117,6 +1117,102 @@ enum skl_disp_power_wells { #define DPIO_FRC_LATENCY_SHFIT 8 #define CHV_TX_DW14(ch, lane) _TXLANE(ch, lane, 0xb8) #define DPIO_UPAR_SHIFT 30 + +/* BXT PHY registers */ +#define _BXT_PHY(phy, a, b) _PIPE((phy), (a), (b)) + +#define BXT_P_CR_GT_DISP_PWRON 0x138090 +#define GT_DISPLAY_POWER_ON(phy) (1 << (phy)) + +#define _PHY_CTL_FAMILY_EDP 0x64C80 +#define _PHY_CTL_FAMILY_DDI 0x64C90 +#define COMMON_RESET_DIS (1 << 31) +#define BXT_PHY_CTL_FAMILY(phy) _BXT_PHY((phy), _PHY_CTL_FAMILY_DDI, \ + _PHY_CTL_FAMILY_EDP) + +/* BXT PHY common lane registers */ +#define _PORT_CL1CM_DW0_A 0x162000 +#define _PORT_CL1CM_DW0_BC 0x6C000 +#define PHY_POWER_GOOD (1 << 16) +#define BXT_PORT_CL1CM_DW0(phy) _BXT_PHY((phy), _PORT_CL1CM_DW0_BC, \ + _PORT_CL1CM_DW0_A) + +#define _PORT_CL1CM_DW9_A 0x162024 +#define _PORT_CL1CM_DW9_BC 0x6C024 +#define IREF0RC_OFFSET_SHIFT 8 +#define IREF0RC_OFFSET_MASK (0xFF << IREF0RC_OFFSET_SHIFT) +#define BXT_PORT_CL1CM_DW9(phy) _BXT_PHY((phy), _PORT_CL1CM_DW9_BC, \ + _PORT_CL1CM_DW9_A) + +#define _PORT_CL1CM_DW10_A 0x162028 +#define _PORT_CL1CM_DW10_BC 0x6C028 +#define IREF1RC_OFFSET_SHIFT 8 +#define IREF1RC_OFFSET_MASK (0xFF << IREF1RC_OFFSET_SHIFT) +#define BXT_PORT_CL1CM_DW10(phy) _BXT_PHY((phy), _PORT_CL1CM_DW10_BC, \ + _PORT_CL1CM_DW10_A) + +#define _PORT_CL1CM_DW28_A 0x162070 +#define _PORT_CL1CM_DW28_BC 0x6C070 +#define OCL1_POWER_DOWN_EN (1 << 23) +#define DW28_OLDO_DYN_PWR_DOWN_EN (1 << 22) +#define SUS_CLK_CONFIG 0x3 +#define BXT_PORT_CL1CM_DW28(phy) _BXT_PHY((phy), _PORT_CL1CM_DW28_BC, \ + _PORT_CL1CM_DW28_A) + +#define _PORT_CL1CM_DW30_A 0x162078 +#define _PORT_CL1CM_DW30_BC 0x6C078 +#define OCL2_LDOFUSE_PWR_DIS (1 << 6) +#define BXT_PORT_CL1CM_DW30(phy) _BXT_PHY((phy), _PORT_CL1CM_DW30_BC, \ + _PORT_CL1CM_DW30_A) + +/* Defined for PHY0 only */ +#define BXT_PORT_CL2CM_DW6_BC 0x6C358 +#define DW6_OLDO_DYN_PWR_DOWN_EN (1 << 28) + +/* BXT PHY Ref registers */ +#define _PORT_REF_DW3_A 0x16218C +#define _PORT_REF_DW3_BC 0x6C18C +#define GRC_DONE (1 << 22) +#define BXT_PORT_REF_DW3(phy) _BXT_PHY((phy), _PORT_REF_DW3_BC, \ + _PORT_REF_DW3_A) + +#define _PORT_REF_DW6_A 0x162198 +#define _PORT_REF_DW6_BC 0x6C198 +/* + * FIXME: BSpec/CHV ConfigDB disagrees on the following two fields, fix them + * after testing. + */ +#define GRC_CODE_SHIFT 23 +#define GRC_CODE_MASK (0x1FF << GRC_CODE_SHIFT) +#define GRC_CODE_FAST_SHIFT 16 +#define GRC_CODE_FAST_MASK (0x7F << GRC_CODE_FAST_SHIFT) +#define GRC_CODE_SLOW_SHIFT 8 +#define GRC_CODE_SLOW_MASK (0xFF << GRC_CODE_SLOW_SHIFT) +#define GRC_CODE_NOM_MASK 0xFF +#define BXT_PORT_REF_DW6(phy) _BXT_PHY((phy), _PORT_REF_DW6_BC, \ + _PORT_REF_DW6_A) + +#define _PORT_REF_DW8_A 0x1621A0 +#define _PORT_REF_DW8_BC 0x6C1A0 +#define GRC_DIS (1 << 15) +#define GRC_RDY_OVRD (1 << 1) +#define BXT_PORT_REF_DW8(phy) _BXT_PHY((phy), _PORT_REF_DW8_BC, \ + _PORT_REF_DW8_A) + +/* BXT PHY TX registers */ +#define _BXT_LANE_OFFSET(lane) (((lane) >> 1) * 0x200 + \ + ((lane) & 1) * 0x80) + +#define _PORT_TX_DW14_LN0_A 0x162538 +#define _PORT_TX_DW14_LN0_B 0x6C538 +#define _PORT_TX_DW14_LN0_C 0x6C938 +#define LATENCY_OPTIM_SHIFT 30 +#define LATENCY_OPTIM (1 << LATENCY_OPTIM_SHIFT) +#define BXT_PORT_TX_DW14_LN(port, lane) (_PORT3((port), _PORT_TX_DW14_LN0_A, \ + _PORT_TX_DW14_LN0_B, \ + _PORT_TX_DW14_LN0_C) + \ + _BXT_LANE_OFFSET(lane)) + /* * Fence registers */ diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 25d697b9d3d9c8..31cadb83429d42 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1864,6 +1864,130 @@ static void skl_shared_dplls_init(struct drm_i915_private *dev_priv) } } +static void broxton_phy_init(struct drm_i915_private *dev_priv, + enum dpio_phy phy) +{ + enum port port; + uint32_t val; + + val = I915_READ(BXT_P_CR_GT_DISP_PWRON); + val |= GT_DISPLAY_POWER_ON(phy); + I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val); + + /* Considering 10ms timeout until BSpec is updated */ + if (wait_for(I915_READ(BXT_PORT_CL1CM_DW0(phy)) & PHY_POWER_GOOD, 10)) + DRM_ERROR("timeout during PHY%d power on\n", phy); + + for (port = (phy == DPIO_PHY0 ? PORT_B : PORT_A); + port <= (phy == DPIO_PHY0 ? PORT_C : PORT_A); port++) { + int lane; + + for (lane = 0; lane < 4; lane++) { + val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane)); + /* + * Note that on CHV this flag is called UPAR, but has + * the same function. + */ + val &= ~LATENCY_OPTIM; + if (lane != 1) + val |= LATENCY_OPTIM; + + I915_WRITE(BXT_PORT_TX_DW14_LN(port, lane), val); + } + } + + /* Program PLL Rcomp code offset */ + val = I915_READ(BXT_PORT_CL1CM_DW9(phy)); + val &= ~IREF0RC_OFFSET_MASK; + val |= 0xE4 << IREF0RC_OFFSET_SHIFT; + I915_WRITE(BXT_PORT_CL1CM_DW9(phy), val); + + val = I915_READ(BXT_PORT_CL1CM_DW10(phy)); + val &= ~IREF1RC_OFFSET_MASK; + val |= 0xE4 << IREF1RC_OFFSET_SHIFT; + I915_WRITE(BXT_PORT_CL1CM_DW10(phy), val); + + /* Program power gating */ + val = I915_READ(BXT_PORT_CL1CM_DW28(phy)); + val |= OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | + SUS_CLK_CONFIG; + I915_WRITE(BXT_PORT_CL1CM_DW28(phy), val); + + if (phy == DPIO_PHY0) { + val = I915_READ(BXT_PORT_CL2CM_DW6_BC); + val |= DW6_OLDO_DYN_PWR_DOWN_EN; + I915_WRITE(BXT_PORT_CL2CM_DW6_BC, val); + } + + val = I915_READ(BXT_PORT_CL1CM_DW30(phy)); + val &= ~OCL2_LDOFUSE_PWR_DIS; + /* + * On PHY1 disable power on the second channel, since no port is + * connected there. On PHY0 both channels have a port, so leave it + * enabled. + * TODO: port C is only connected on BXT-P, so on BXT0/1 we should + * power down the second channel on PHY0 as well. + */ + if (phy == DPIO_PHY1) + val |= OCL2_LDOFUSE_PWR_DIS; + I915_WRITE(BXT_PORT_CL1CM_DW30(phy), val); + + if (phy == DPIO_PHY0) { + uint32_t grc_code; + /* + * PHY0 isn't connected to an RCOMP resistor so copy over + * the corresponding calibrated value from PHY1, and disable + * the automatic calibration on PHY0. + */ + if (wait_for(I915_READ(BXT_PORT_REF_DW3(DPIO_PHY1)) & GRC_DONE, + 10)) + DRM_ERROR("timeout waiting for PHY1 GRC\n"); + + val = I915_READ(BXT_PORT_REF_DW6(DPIO_PHY1)); + val = (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT; + grc_code = val << GRC_CODE_FAST_SHIFT | + val << GRC_CODE_SLOW_SHIFT | + val; + I915_WRITE(BXT_PORT_REF_DW6(DPIO_PHY0), grc_code); + + val = I915_READ(BXT_PORT_REF_DW8(DPIO_PHY0)); + val |= GRC_DIS | GRC_RDY_OVRD; + I915_WRITE(BXT_PORT_REF_DW8(DPIO_PHY0), val); + } + + val = I915_READ(BXT_PHY_CTL_FAMILY(phy)); + val |= COMMON_RESET_DIS; + I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val); +} + +void broxton_ddi_phy_init(struct drm_device *dev) +{ + /* Enable PHY1 first since it provides Rcomp for PHY0 */ + broxton_phy_init(dev->dev_private, DPIO_PHY1); + broxton_phy_init(dev->dev_private, DPIO_PHY0); +} + +static void broxton_phy_uninit(struct drm_i915_private *dev_priv, + enum dpio_phy phy) +{ + uint32_t val; + + val = I915_READ(BXT_PHY_CTL_FAMILY(phy)); + val &= ~COMMON_RESET_DIS; + I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val); +} + +void broxton_ddi_phy_uninit(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + broxton_phy_uninit(dev_priv, DPIO_PHY1); + broxton_phy_uninit(dev_priv, DPIO_PHY0); + + /* FIXME: do this in broxton_phy_uninit per phy */ + I915_WRITE(BXT_P_CR_GT_DISP_PWRON, 0); +} + void intel_ddi_pll_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -1882,6 +2006,7 @@ void intel_ddi_pll_init(struct drm_device *dev) DRM_ERROR("LCPLL1 is disabled\n"); } else if (IS_BROXTON(dev)) { broxton_init_cdclk(dev); + broxton_ddi_phy_init(dev); } else { /* * The LCPLL register should be turned on by the BIOS. For now diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 164f932f9f89af..1ae0c3a1ad0b29 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1115,6 +1115,8 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv); void broxton_init_cdclk(struct drm_device *dev); void broxton_uninit_cdclk(struct drm_device *dev); void broxton_set_cdclk(struct drm_device *dev, int frequency); +void broxton_ddi_phy_init(struct drm_device *dev); +void broxton_ddi_phy_uninit(struct drm_device *dev); void intel_dp_get_m_n(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n); From eee215660cedb4ee3c93de52a9bbc742891bb290 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 10 Mar 2015 21:18:30 +0200 Subject: [PATCH 0161/3798] drm/i915/bxt: add description about the BXT PHYs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend the VLV/CHV DPIO (PHY) documentation with the BXT specifics. v2: - add more detail about the mapping between ports and transcoders (ville) Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 4 ++-- drivers/gpu/drm/i915/i915_reg.h | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index f4976cd7b32bac..a8509c2b9c170a 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -4067,7 +4067,7 @@ int num_ioctls; DPIO !Pdrivers/gpu/drm/i915/i915_reg.h DPIO - Dual channel PHY (VLV/CHV) + Dual channel PHY (VLV/CHV/BXT) @@ -4118,7 +4118,7 @@ int num_ioctls;
- Single channel PHY (CHV) + Single channel PHY (CHV/BXT) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6e0913db6e24a6..11b9a0898111a2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -715,7 +715,7 @@ enum skl_disp_power_wells { /** * DOC: DPIO * - * VLV and CHV have slightly peculiar display PHYs for driving DP/HDMI + * VLV, CHV and BXT have slightly peculiar display PHYs for driving DP/HDMI * ports. DPIO is the name given to such a display PHY. These PHYs * don't follow the standard programming model using direct MMIO * registers, and instead their registers must be accessed trough IOSF @@ -746,7 +746,7 @@ enum skl_disp_power_wells { * controlled from the display controller side. No DPIO registers * need to be accessed during AUX communication, * - * Generally the common lane corresponds to the pipe and + * Generally on VLV/CHV the common lane corresponds to the pipe and * the spline (PCS/TX) corresponds to the port. * * For dual channel PHY (VLV/CHV): @@ -768,11 +768,17 @@ enum skl_disp_power_wells { * * port D == PCS/TX CH0 * - * Note: digital port B is DDI0, digital port C is DDI1, - * digital port D is DDI2 + * On BXT the entire PHY channel corresponds to the port. That means + * the PLL is also now associated with the port rather than the pipe, + * and so the clock needs to be routed to the appropriate transcoder. + * Port A PLL is directly connected to transcoder EDP and port B/C + * PLLs can be routed to any transcoder A/B/C. + * + * Note: DDI0 is digital port B, DD1 is digital port C, and DDI2 is + * digital port D (CHV) or port A (BXT). */ /* - * Dual channel PHY (VLV/CHV) + * Dual channel PHY (VLV/CHV/BXT) * --------------------------------- * | CH0 | CH1 | * | CMN/PLL/REF | CMN/PLL/REF | @@ -784,7 +790,7 @@ enum skl_disp_power_wells { * | DDI0 | DDI1 | DP/HDMI ports * --------------------------------- * - * Single channel PHY (CHV) + * Single channel PHY (CHV/BXT) * ----------------- * | CH0 | * | CMN/PLL/REF | From 664326f8a5b7e4ab7ed469acaadc63d2a05d8720 Mon Sep 17 00:00:00 2001 From: "A.Sunil Kamath" Date: Mon, 24 Nov 2014 13:37:44 +0530 Subject: [PATCH 0162/3798] drm/i915/bxt: Implement enable/disable for Display C9 state v2: Modified as per review comments from Imre - Mention enabling instead of allowing in the debug trace and remove unnecessary comments. v3: - Rebase to latest. - Move DC9-related functions from intel_display.c to intel_runtime_pm.c. v4: (imre) - remove DC5 disabling, it's a nop at this point - squashed in Suketu's "Assert the requirements to enter or exit DC9" patch - remove check for RUNTIME_PM from assert_can_enable_dc9, it's not a dependency Signed-off-by: A.Sunil Kamath (v3) Signed-off-by: Imre Deak Reviewed-by: Sagar Kamble Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 5 ++ drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_runtime_pm.c | 66 +++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 11b9a0898111a2..29c41f1bba34ed 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7059,6 +7059,11 @@ enum skl_disp_power_wells { #define BXT_DE_PLL_PLL_ENABLE (1 << 31) #define BXT_DE_PLL_LOCK (1 << 30) +/* GEN9 DC */ +#define DC_STATE_EN 0x45504 +#define DC_STATE_EN_UPTO_DC5 (1<<0) +#define DC_STATE_EN_DC9 (1<<3) + /* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register, * since on HSW we can't write to it using I915_WRITE. */ #define D_COMP_HSW (MCHBAR_MIRROR_BASE_SNB + 0x5F0C) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1ae0c3a1ad0b29..1cad3ddaf3c723 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1117,6 +1117,8 @@ void broxton_uninit_cdclk(struct drm_device *dev); void broxton_set_cdclk(struct drm_device *dev, int frequency); void broxton_ddi_phy_init(struct drm_device *dev); void broxton_ddi_phy_uninit(struct drm_device *dev); +void bxt_enable_dc9(struct drm_i915_private *dev_priv); +void bxt_disable_dc9(struct drm_i915_private *dev_priv); void intel_dp_get_m_n(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n); diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index ff5cce32c7d676..8fe2fdeab652fc 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -351,6 +351,72 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS)) | \ BIT(POWER_DOMAIN_INIT)) +static void assert_can_enable_dc9(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + + WARN(!IS_BROXTON(dev), "Platform doesn't support DC9.\n"); + WARN((I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9), + "DC9 already programmed to be enabled.\n"); + WARN(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5, + "DC5 still not disabled to enable DC9.\n"); + WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on.\n"); + WARN(intel_irqs_enabled(dev_priv), "Interrupts not disabled yet.\n"); + + /* + * TODO: check for the following to verify the conditions to enter DC9 + * state are satisfied: + * 1] Check relevant display engine registers to verify if mode set + * disable sequence was followed. + * 2] Check if display uninitialize sequence is initialized. + */ +} + +static void assert_can_disable_dc9(struct drm_i915_private *dev_priv) +{ + WARN(intel_irqs_enabled(dev_priv), "Interrupts not disabled yet.\n"); + WARN(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9), + "DC9 already programmed to be disabled.\n"); + WARN(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5, + "DC5 still not disabled.\n"); + + /* + * TODO: check for the following to verify DC9 state was indeed + * entered before programming to disable it: + * 1] Check relevant display engine registers to verify if mode + * set disable sequence was followed. + * 2] Check if display uninitialize sequence is initialized. + */ +} + +void bxt_enable_dc9(struct drm_i915_private *dev_priv) +{ + uint32_t val; + + assert_can_enable_dc9(dev_priv); + + DRM_DEBUG_KMS("Enabling DC9\n"); + + val = I915_READ(DC_STATE_EN); + val |= DC_STATE_EN_DC9; + I915_WRITE(DC_STATE_EN, val); + POSTING_READ(DC_STATE_EN); +} + +void bxt_disable_dc9(struct drm_i915_private *dev_priv) +{ + uint32_t val; + + assert_can_disable_dc9(dev_priv); + + DRM_DEBUG_KMS("Disabling DC9\n"); + + val = I915_READ(DC_STATE_EN); + val &= ~DC_STATE_EN_DC9; + I915_WRITE(DC_STATE_EN, val); + POSTING_READ(DC_STATE_EN); +} + static void skl_set_power_well(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool enable) { From 31335cec02604cba72deee44bb18cb82790ef2aa Mon Sep 17 00:00:00 2001 From: Suketu Shah Date: Mon, 24 Nov 2014 13:37:45 +0530 Subject: [PATCH 0163/3798] drm/i915/bxt: Add DC9 Trigger sequence Add triggers for DC9 as per details provided in bxt_enable_dc9 and bxt_disable_dc9 implementations. v1: - Add SKL check in gen9_disable_dc5 as it is possible for DC5 to remain disabled only for SKL. - Add additional checks for whether DC5 is already disabled during DC5-disabling only for BXT. v2: - rebase to latest. - Load CSR during DC9 disabling in the beginning before DC9 is disabled. - Make gen9_disable_dc5 function non-static as it's being called by functions in i915_drv.c. - Enable DC9-related functionality using a macro. v3: (imre) - remove BXT_ENABLE_DC9, we want DC9 always, and it's only valid on BXT - remove DC5 disabling and CSR FW loaded check, these are nop atm - squash in Vandana's "Do ddi_phy_init always" patch v4: - add TODO to re-enable DC5 during resume if CSR FW is available (sagar) Signed-off-by: Suketu Shah Signed-off-by: A.Sunil Kamath (v2) Signed-off-by: Imre Deak Reviewed-by: Sagar Kamble Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 39 ++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c1a3cdb5189b31..ad77131cdcffad 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1009,6 +1009,38 @@ static int hsw_suspend_complete(struct drm_i915_private *dev_priv) return 0; } +static int bxt_suspend_complete(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + + /* TODO: when DC5 support is added disable DC5 here. */ + + broxton_ddi_phy_uninit(dev); + broxton_uninit_cdclk(dev); + bxt_enable_dc9(dev_priv); + + return 0; +} + +static int bxt_resume_prepare(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + + /* TODO: when CSR FW support is added make sure the FW is loaded */ + + bxt_disable_dc9(dev_priv); + + /* + * TODO: when DC5 support is added enable DC5 here if the CSR FW + * is available. + */ + broxton_init_cdclk(dev); + broxton_ddi_phy_init(dev); + intel_prepare_ddi(dev); + + return 0; +} + /* * Save all Gunit registers that may be lost after a D3 and a subsequent * S0i[R123] transition. The list of registers needing a save/restore is @@ -1479,6 +1511,9 @@ static int intel_runtime_resume(struct device *device) if (IS_GEN6(dev_priv)) intel_init_pch_refclk(dev); + + if (IS_BROXTON(dev)) + ret = bxt_resume_prepare(dev_priv); else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) hsw_disable_pc8(dev_priv); else if (IS_VALLEYVIEW(dev_priv)) @@ -1511,7 +1546,9 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv) struct drm_device *dev = dev_priv->dev; int ret; - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_BROXTON(dev)) + ret = bxt_suspend_complete(dev_priv); + else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) ret = hsw_suspend_complete(dev_priv); else if (IS_VALLEYVIEW(dev)) ret = vlv_suspend_complete(dev_priv); From 475d231be9bae4b997eb7e5a9a3cb214259cf90a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 10 Apr 2015 16:22:39 +0200 Subject: [PATCH 0164/3798] drm/atomic-helper: Don't call atomic_update_plane when it stays off It's a silly thing to do and surprises driver writers. Most likely this did already blow up for exynos. It's also a silly thing to change plane state when it's off, but fbdev is silly (it does an unconditional modeset over all planes). And userspace can be evil. So I think we need this. With this check in the helpers we can remove the one in i915 code for the same conditions (becuase ->crtc iff ->fb). Cc: Gustavo Padovan Cc: dri-devel@lists.freedesktop.org Cc: Inki Dae Cc: Matt Roper Acked-by: Laurent Pinchart Tested-by: Laurent Pinchart Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 3 ++- drivers/gpu/drm/i915/intel_atomic_plane.c | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index a2fb0d45217ad3..d536817699c194 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1138,7 +1138,8 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, if (drm_atomic_plane_disabling(plane, old_plane_state) && funcs->atomic_disable) funcs->atomic_disable(plane, old_plane_state); - else + else if (plane->state->crtc || + drm_atomic_plane_disabling(plane, old_plane_state)) funcs->atomic_update(plane, old_plane_state); } diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index 976b8915657077..cb383a0fc39251 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -172,10 +172,6 @@ static void intel_plane_atomic_update(struct drm_plane *plane, struct intel_plane_state *intel_state = to_intel_plane_state(plane->state); - /* Don't disable an already disabled plane */ - if (!plane->state->fb && !old_state->fb) - return; - intel_plane->commit_plane(plane, intel_state); } From 5678ad736758db6554c8466921dfc496f1fe58b4 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 17 Mar 2015 14:45:29 +0000 Subject: [PATCH 0165/3798] drm/i915: Fix view type in warning message One month passed between posting a patch and it getting merged, and unfortunately even though it still applies, it needs fixing to account for changes in function parameters since: commit d385612e15b8b6eb3db328d83f1872ef8a381788 Author: Tvrtko Ursulin Date: Tue Mar 17 14:45:29 2015 +0000 drm/i915: Log view type when printing warnings Signed-off-by: Tvrtko Ursulin Cc: Joonas Lahtinen [danvet: Squash in fixup from Tvrtko to fix the rebase conflict.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 89d9ebe675209b..f7b8766e09fc8f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5181,7 +5181,7 @@ i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o, i915_ggtt_view_equal(&vma->ggtt_view, view)) return vma->node.start; - WARN(1, "global vma for this object not found.\n"); + WARN(1, "global vma for this object not found. (view=%u)\n", view->type); return -1; } From d328c9d78d64ca11e744fe227096990430a88477 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 10 Apr 2015 16:22:37 +0200 Subject: [PATCH 0166/3798] drm/i915: Select starting pipe bpp irrespective or the primary plane Since universal planes the primary plane might not be around, and it's kinda silly to restrict the pipe bpp to the primary plane if we might end up displaying a 10bpc video overlay. And with atomic we might very well enable a pipe without a primary plane. So just use the platform max as a starting point and then restrict appropriately. Of course this is all still a bit moot as long as we artificially compress everything to max 8bpc because we don't use the hi-bpc gamma tables. Signed-off-by: Daniel Vetter Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 61 ++++++---------------------- 1 file changed, 12 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5ee5d8cd9cd1a6..0654fc549ba383 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6302,14 +6302,6 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, adjusted_mode->hsync_start == adjusted_mode->hdisplay) return -EINVAL; - if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) && pipe_config->pipe_bpp > 10*3) { - pipe_config->pipe_bpp = 10*3; /* 12bpc is gen5+ */ - } else if (INTEL_INFO(dev)->gen <= 4 && pipe_config->pipe_bpp > 8*3) { - /* only a 8bpc pipe, with 6bpc dither through the panel fitter - * for lvds. */ - pipe_config->pipe_bpp = 8*3; - } - if (HAS_IPS(dev)) hsw_compute_ips_config(crtc, pipe_config); @@ -10981,7 +10973,6 @@ connected_sink_compute_bpp(struct intel_connector *connector, static int compute_baseline_pipe_bpp(struct intel_crtc *crtc, - struct drm_framebuffer *fb, struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; @@ -10989,41 +10980,13 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc, struct intel_connector *connector; int bpp, i; - switch (fb->pixel_format) { - case DRM_FORMAT_C8: - bpp = 8*3; /* since we go through a colormap */ - break; - case DRM_FORMAT_XRGB1555: - case DRM_FORMAT_ARGB1555: - /* checked in intel_framebuffer_init already */ - if (WARN_ON(INTEL_INFO(dev)->gen > 3)) - return -EINVAL; - case DRM_FORMAT_RGB565: - bpp = 6*3; /* min is 18bpp */ - break; - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_ABGR8888: - /* checked in intel_framebuffer_init already */ - if (WARN_ON(INTEL_INFO(dev)->gen < 4)) - return -EINVAL; - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ARGB8888: - bpp = 8*3; - break; - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_ABGR2101010: - /* checked in intel_framebuffer_init already */ - if (WARN_ON(INTEL_INFO(dev)->gen < 4)) - return -EINVAL; + if ((IS_G4X(dev) || IS_VALLEYVIEW(dev))) bpp = 10*3; - break; - /* TODO: gen4+ supports 16 bpc floating point, too. */ - default: - DRM_DEBUG_KMS("unsupported depth\n"); - return -EINVAL; - } + else if (INTEL_INFO(dev)->gen >= 5) + bpp = 12*3; + else + bpp = 8*3; + pipe_config->pipe_bpp = bpp; @@ -11280,7 +11243,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, struct intel_connector *connector; struct drm_connector_state *connector_state; struct intel_crtc_state *pipe_config; - int plane_bpp, ret = -EINVAL; + int base_bpp, ret = -EINVAL; int i; bool retry = true; @@ -11325,9 +11288,9 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, * plane pixel format and any sink constraints into account. Returns the * source plane bpp so that dithering can be selected on mismatches * after encoders and crtc also have had their say. */ - plane_bpp = compute_baseline_pipe_bpp(to_intel_crtc(crtc), - fb, pipe_config); - if (plane_bpp < 0) + base_bpp = compute_baseline_pipe_bpp(to_intel_crtc(crtc), + pipe_config); + if (base_bpp < 0) goto fail; /* @@ -11395,9 +11358,9 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, goto encoder_retry; } - pipe_config->dither = pipe_config->pipe_bpp != plane_bpp; + pipe_config->dither = pipe_config->pipe_bpp != base_bpp; DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n", - plane_bpp, pipe_config->pipe_bpp, pipe_config->dither); + base_bpp, pipe_config->pipe_bpp, pipe_config->dither); return pipe_config; fail: From 8805aa713e3590b74500dc2283e2df02ba363a4a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 10 Apr 2015 16:22:38 +0200 Subject: [PATCH 0167/3798] drm/i915: Drop unecessary fb arguments from function signatures This is a separate patch to simplify conflict handling with other ongoing atomic work. Signed-off-by: Daniel Vetter Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0654fc549ba383..783d6008fdeda3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11235,7 +11235,6 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state) static struct intel_crtc_state * intel_modeset_pipe_config(struct drm_crtc *crtc, - struct drm_framebuffer *fb, struct drm_display_mode *mode, struct drm_atomic_state *state) { @@ -12040,7 +12039,6 @@ static void update_scanline_offset(struct intel_crtc *crtc) static struct intel_crtc_state * intel_modeset_compute_config(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_framebuffer *fb, struct drm_atomic_state *state, unsigned *modeset_pipes, unsigned *prepare_pipes, @@ -12078,7 +12076,7 @@ intel_modeset_compute_config(struct drm_crtc *crtc, if (WARN_ON(&intel_crtc->base != crtc)) continue; - pipe_config = intel_modeset_pipe_config(crtc, fb, mode, state); + pipe_config = intel_modeset_pipe_config(crtc, mode, state); if (IS_ERR(pipe_config)) return pipe_config; @@ -12281,7 +12279,7 @@ static int intel_set_mode(struct drm_crtc *crtc, unsigned modeset_pipes, prepare_pipes, disable_pipes; int ret = 0; - pipe_config = intel_modeset_compute_config(crtc, mode, fb, state, + pipe_config = intel_modeset_compute_config(crtc, mode, state, &modeset_pipes, &prepare_pipes, &disable_pipes); @@ -12739,7 +12737,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set) goto fail; pipe_config = intel_modeset_compute_config(set->crtc, set->mode, - set->fb, state, + state, &modeset_pipes, &prepare_pipes, &disable_pipes); From b7192a567ca472ac774b19a672dab77cb1e4b4db Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Wed, 15 Apr 2015 11:02:33 +0530 Subject: [PATCH 0168/3798] drm/i915/skl: Add back HDMI translation table The HDMI translation table is added back to bspec, so adding it, and defaulting the 800mV+0dB entry. The HDMI translation table was removed by following commit as per HW team's recommendation: commit 7ff446708bd1 ("drm/i915/skl: Only use the 800mV+2bB HDMI translation entry") v2: Adding reference to commit which removed this table (Jani) Cc: Damien Lespiau Signed-off-by: Sonika Jindal Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 31cadb83429d42..24ecb486465b0c 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -155,8 +155,17 @@ static const struct ddi_buf_trans skl_ddi_translations_edp[] = { static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { - /* Idx NT mV T mV db */ - { 0x00004014, 0x00000087 }, /* 0: 800 1000 2 */ + { 0x00000018, 0x000000ac }, + { 0x00005012, 0x0000009d }, + { 0x00007011, 0x00000088 }, + { 0x00000018, 0x000000a1 }, + { 0x00000018, 0x00000098 }, + { 0x00004013, 0x00000088 }, + { 0x00006012, 0x00000087 }, + { 0x00000018, 0x000000df }, + { 0x00003015, 0x00000087 }, + { 0x00003015, 0x000000c7 }, + { 0x00000018, 0x000000c7 }, }; enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) @@ -214,16 +223,9 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) n_edp_entries = ARRAY_SIZE(skl_ddi_translations_dp); } - /* - * On SKL, the recommendation from the hw team is to always use - * a certain type of level shifter (and thus the corresponding - * 800mV+2dB entry). Given that's the only validated entry, we - * override what is in the VBT, at least until further notice. - */ - hdmi_level = 0; ddi_translations_hdmi = skl_ddi_translations_hdmi; n_hdmi_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); - hdmi_default_entry = 0; + hdmi_default_entry = 7; } else if (IS_BROADWELL(dev)) { ddi_translations_fdi = bdw_ddi_translations_fdi; ddi_translations_dp = bdw_ddi_translations_dp; From 1f30a61482df44ee75c4db73f7f3d70052b93e83 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 15 Apr 2015 16:39:59 +0100 Subject: [PATCH 0169/3798] drm/i915: Simplify i915_gem_obj_is_pinned() test for set-tiling Since the removal of the user pin_ioctl, the only means for pinning an object is either through binding to the scanout or during execbuf reservation. As the later prevents a call to set-tiling, we need only check if the obj is pinned into the display plane to see if we need reject the set-tiling ioctl. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_tiling.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 6377b22269ad1e..633bd1fcab6925 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -336,7 +336,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, } mutex_lock(&dev->struct_mutex); - if (i915_gem_obj_is_pinned(obj) || obj->framebuffer_references) { + if (obj->pin_display || obj->framebuffer_references) { ret = -EBUSY; goto err; } From baaa5cfb42d94440385e1229c000da1ecc369d47 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 15 Apr 2015 16:42:46 +0100 Subject: [PATCH 0170/3798] drm/i915: Update meaning of debugfs object's pin_flag Since the pin_ioctl is defunct, we only care about whether an object is pinned into the display for debug purposes. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 07a71c0ff7756c..1bd2ec5a5a5708 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -96,7 +96,7 @@ static int i915_capabilities(struct seq_file *m, void *data) static const char *get_pin_flag(struct drm_i915_gem_object *obj) { - if (i915_gem_obj_is_pinned(obj)) + if (obj->pin_display) return "p"; else return " "; From 535afa2e9e3c1867460d6981d879b04d8b2b9ab3 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 15 Apr 2015 16:52:29 -0700 Subject: [PATCH 0171/3798] drm/i915/vlv: check port in infoframe_enabled v2 Same as IBX and G4x, they all share the same genetic material. v2: we all need a bit more port in our lives Signed-off-by: Jesse Barnes Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 7dfc3584b6b437..56d1d13c075a21 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -324,10 +324,15 @@ static bool vlv_infoframe_enabled(struct drm_encoder *encoder) struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); + struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); + u32 port = intel_dig_port->port; - return val & VIDEO_DIP_ENABLE; + if (port == (val & VIDEO_DIP_PORT_MASK)) + return val & VIDEO_DIP_ENABLE; + + return false; } static void hsw_write_infoframe(struct drm_encoder *encoder, From 1ab23380f8b990ad865349040ec14c3ebe3a09c5 Mon Sep 17 00:00:00 2001 From: Satheeshakrishna M Date: Fri, 22 Aug 2014 09:49:06 +0530 Subject: [PATCH 0172/3798] drm/i915/bxt: Restrict PORT_CLK_SEL programming below gen9 PORT_CLK_SEL programming is needed only on HSW/BDW. v2: - don't program PORT_CLK_SEL from mst encoders either (imre) v3: - fix the check for GEN9+ in intel_mst_pre_enable_dp() (damien) Signed-off-by: Satheeshakrishna M Signed-off-by: Imre Deak Reviewed-by: Sagar Kamble Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 4 ++-- drivers/gpu/drm/i915/intel_dp_mst.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 24ecb486465b0c..f98a403c662563 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1567,7 +1567,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) I915_WRITE(DPLL_CTRL2, val); - } else { + } else if (INTEL_INFO(dev)->gen < 9) { WARN_ON(crtc->config->ddi_pll_sel == PORT_CLK_SEL_NONE); I915_WRITE(PORT_CLK_SEL(port), crtc->config->ddi_pll_sel); } @@ -1626,7 +1626,7 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) if (IS_SKYLAKE(dev)) I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) | DPLL_CTRL2_DDI_CLK_OFF(port))); - else + else if (INTEL_INFO(dev)->gen < 9) I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); } diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 73350894e2c960..3945057c5bbeb9 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -173,8 +173,10 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder) if (intel_dp->active_mst_links == 0) { enum port port = intel_ddi_get_encoder_port(encoder); - I915_WRITE(PORT_CLK_SEL(port), - intel_crtc->config->ddi_pll_sel); + /* FIXME: add support for SKL */ + if (INTEL_INFO(dev)->gen < 9) + I915_WRITE(PORT_CLK_SEL(port), + intel_crtc->config->ddi_pll_sel); intel_ddi_init_dp_buf_reg(&intel_dig_port->base); From ff6d9f55fe3f217dabce6b5ee7dbd306be5f4391 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 21 Jan 2015 17:19:54 -0800 Subject: [PATCH 0173/3798] drm/i915/bxt: fix panel fitter setup in crtc disable/enable Broxton has the same panel fitter registers as Skylake. v2: - add MISSING_CASE for future platforms (daniel) Signed-off-by: Jesse Barnes Signed-off-by: Imre Deak Reviewed-by: Sagar Kamble Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 783d6008fdeda3..3322e5a12e8e6d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4881,10 +4881,12 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_ddi_enable_pipe_clock(intel_crtc); - if (IS_SKYLAKE(dev)) + if (INTEL_INFO(dev)->gen == 9) skylake_pfit_update(intel_crtc, 1); - else + else if (INTEL_INFO(dev)->gen < 9) ironlake_pfit_enable(intel_crtc); + else + MISSING_CASE(INTEL_INFO(dev)->gen); /* * On ILK+ LUT must be loaded before the pipe is running but with @@ -5029,10 +5031,12 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder); - if (IS_SKYLAKE(dev)) + if (INTEL_INFO(dev)->gen == 9) skylake_pfit_update(intel_crtc, 0); - else + else if (INTEL_INFO(dev)->gen < 9) ironlake_pfit_disable(intel_crtc); + else + MISSING_CASE(INTEL_INFO(dev)->gen); intel_ddi_disable_pipe_clock(intel_crtc); @@ -9191,10 +9195,13 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe); if (intel_display_power_is_enabled(dev_priv, pfit_domain)) { - if (IS_SKYLAKE(dev)) + if (INTEL_INFO(dev)->gen == 9) skylake_get_pfit_config(crtc, pipe_config); - else + else if (INTEL_INFO(dev)->gen < 9) ironlake_get_pfit_config(crtc, pipe_config); + else + MISSING_CASE(INTEL_INFO(dev)->gen); + } else { pipe_config->scaler_state.scaler_id = -1; pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX); From dfb82408471ee2e56b26c05dcd50317f873bee57 Mon Sep 17 00:00:00 2001 From: Satheeshakrishna M Date: Fri, 22 Aug 2014 09:49:09 +0530 Subject: [PATCH 0174/3798] drm/i915/bxt: Define bxt DDI PLLs and implement enable/disable sequence Plug bxt PLL code into existing shared DPLL framework. v2: (imre) - squash in Satheeshakrishna's "Define BXT clock registers" and "Add state variables for bxt clock registers" patches - squash in Vandanas's "Change grp access to lane access for PLL" - fix group vs. lane access in bxt_ddi_pll_get_hw_state - add code comment why we read from lane registers while writing to group registers - clean up register macros - use BXT_PORT_PLL_* macros instead of open-coding the same - check if BXT_PORT_PCS_DW12_LN01 matches BXT_PORT_PCS_DW12_LN23 during hardware state readout - add missing LANESTAGGER_STRAP_OVRD masking - add note about missing step according to the latest BUN for PORT_PLL_9/lockthresh Signed-off-by: Satheeshakrishna M (v1) Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 + drivers/gpu/drm/i915/i915_reg.h | 76 ++++++++++++++ drivers/gpu/drm/i915/intel_ddi.c | 165 +++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2645ba35b13040..a7049ea164e293 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -303,6 +303,9 @@ struct intel_dpll_hw_state { uint32_t ctrl1; /* HDMI only, 0 when used for DP */ uint32_t cfgcr1, cfgcr2; + + /* bxt */ + uint32_t ebb0, pll0, pll1, pll2, pll3, pll6, pll8, pcsdw12; }; struct intel_shared_dpll_config { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 29c41f1bba34ed..5c81728e4400e5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1136,6 +1136,60 @@ enum skl_disp_power_wells { #define BXT_PHY_CTL_FAMILY(phy) _BXT_PHY((phy), _PHY_CTL_FAMILY_DDI, \ _PHY_CTL_FAMILY_EDP) +/* BXT PHY PLL registers */ +#define _PORT_PLL_A 0x46074 +#define _PORT_PLL_B 0x46078 +#define _PORT_PLL_C 0x4607c +#define PORT_PLL_ENABLE (1 << 31) +#define PORT_PLL_LOCK (1 << 30) +#define PORT_PLL_REF_SEL (1 << 27) +#define BXT_PORT_PLL_ENABLE(port) _PORT(port, _PORT_PLL_A, _PORT_PLL_B) + +#define _PORT_PLL_EBB_0_A 0x162034 +#define _PORT_PLL_EBB_0_B 0x6C034 +#define _PORT_PLL_EBB_0_C 0x6C340 +#define PORT_PLL_P1_MASK (0x07 << 13) +#define PORT_PLL_P1(x) ((x) << 13) +#define PORT_PLL_P2_MASK (0x1f << 8) +#define PORT_PLL_P2(x) ((x) << 8) +#define BXT_PORT_PLL_EBB_0(port) _PORT3(port, _PORT_PLL_EBB_0_A, \ + _PORT_PLL_EBB_0_B, \ + _PORT_PLL_EBB_0_C) + +#define _PORT_PLL_EBB_4_A 0x162038 +#define _PORT_PLL_EBB_4_B 0x6C038 +#define _PORT_PLL_EBB_4_C 0x6C344 +#define PORT_PLL_10BIT_CLK_ENABLE (1 << 13) +#define PORT_PLL_RECALIBRATE (1 << 14) +#define BXT_PORT_PLL_EBB_4(port) _PORT3(port, _PORT_PLL_EBB_4_A, \ + _PORT_PLL_EBB_4_B, \ + _PORT_PLL_EBB_4_C) + +#define _PORT_PLL_0_A 0x162100 +#define _PORT_PLL_0_B 0x6C100 +#define _PORT_PLL_0_C 0x6C380 +/* PORT_PLL_0_A */ +#define PORT_PLL_M2_MASK 0xFF +/* PORT_PLL_1_A */ +#define PORT_PLL_N_MASK (0x0F << 8) +#define PORT_PLL_N(x) ((x) << 8) +/* PORT_PLL_2_A */ +#define PORT_PLL_M2_FRAC_MASK 0x3FFFFF +/* PORT_PLL_3_A */ +#define PORT_PLL_M2_FRAC_ENABLE (1 << 16) +/* PORT_PLL_6_A */ +#define PORT_PLL_PROP_COEFF_MASK 0xF +#define PORT_PLL_INT_COEFF_MASK (0x1F << 8) +#define PORT_PLL_INT_COEFF(x) ((x) << 8) +#define PORT_PLL_GAIN_CTL_MASK (0x07 << 16) +#define PORT_PLL_GAIN_CTL(x) ((x) << 16) +/* PORT_PLL_8_A */ +#define PORT_PLL_TARGET_CNT_MASK 0x3FF +#define _PORT_PLL_BASE(port) _PORT3(port, _PORT_PLL_0_A, \ + _PORT_PLL_0_B, \ + _PORT_PLL_0_C) +#define BXT_PORT_PLL(port, idx) (_PORT_PLL_BASE(port) + (idx) * 4) + /* BXT PHY common lane registers */ #define _PORT_CL1CM_DW0_A 0x162000 #define _PORT_CL1CM_DW0_BC 0x6C000 @@ -1205,6 +1259,28 @@ enum skl_disp_power_wells { #define BXT_PORT_REF_DW8(phy) _BXT_PHY((phy), _PORT_REF_DW8_BC, \ _PORT_REF_DW8_A) +/* BXT PHY PCS registers */ +#define _PORT_PCS_DW12_LN01_A 0x162430 +#define _PORT_PCS_DW12_LN01_B 0x6C430 +#define _PORT_PCS_DW12_LN01_C 0x6C830 +#define _PORT_PCS_DW12_LN23_A 0x162630 +#define _PORT_PCS_DW12_LN23_B 0x6C630 +#define _PORT_PCS_DW12_LN23_C 0x6CA30 +#define _PORT_PCS_DW12_GRP_A 0x162c30 +#define _PORT_PCS_DW12_GRP_B 0x6CC30 +#define _PORT_PCS_DW12_GRP_C 0x6CE30 +#define LANESTAGGER_STRAP_OVRD (1 << 6) +#define LANE_STAGGER_MASK 0x1F +#define BXT_PORT_PCS_DW12_LN01(port) _PORT3(port, _PORT_PCS_DW12_LN01_A, \ + _PORT_PCS_DW12_LN01_B, \ + _PORT_PCS_DW12_LN01_C) +#define BXT_PORT_PCS_DW12_LN23(port) _PORT3(port, _PORT_PCS_DW12_LN23_A, \ + _PORT_PCS_DW12_LN23_B, \ + _PORT_PCS_DW12_LN23_C) +#define BXT_PORT_PCS_DW12_GRP(port) _PORT3(port, _PORT_PCS_DW12_GRP_A, \ + _PORT_PCS_DW12_GRP_B, \ + _PORT_PCS_DW12_GRP_C) + /* BXT PHY TX registers */ #define _BXT_LANE_OFFSET(lane) (((lane) >> 1) * 0x200 + \ ((lane) & 1) * 0x80) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index f98a403c662563..a6d0cb0b10fc4c 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1990,6 +1990,169 @@ void broxton_ddi_phy_uninit(struct drm_device *dev) I915_WRITE(BXT_P_CR_GT_DISP_PWRON, 0); } +static const char * const bxt_ddi_pll_names[] = { + "PORT PLL A", + "PORT PLL B", + "PORT PLL C", +}; + +static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + uint32_t temp; + enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ + + temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); + temp &= ~PORT_PLL_REF_SEL; + /* Non-SSC reference */ + I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); + + /* Disable 10 bit clock */ + temp = I915_READ(BXT_PORT_PLL_EBB_4(port)); + temp &= ~PORT_PLL_10BIT_CLK_ENABLE; + I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); + + /* Write P1 & P2 */ + temp = I915_READ(BXT_PORT_PLL_EBB_0(port)); + temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK); + temp |= pll->config.hw_state.ebb0; + I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp); + + /* Write M2 integer */ + temp = I915_READ(BXT_PORT_PLL(port, 0)); + temp &= ~PORT_PLL_M2_MASK; + temp |= pll->config.hw_state.pll0; + I915_WRITE(BXT_PORT_PLL(port, 0), temp); + + /* Write N */ + temp = I915_READ(BXT_PORT_PLL(port, 1)); + temp &= ~PORT_PLL_N_MASK; + temp |= pll->config.hw_state.pll1; + I915_WRITE(BXT_PORT_PLL(port, 1), temp); + + /* Write M2 fraction */ + temp = I915_READ(BXT_PORT_PLL(port, 2)); + temp &= ~PORT_PLL_M2_FRAC_MASK; + temp |= pll->config.hw_state.pll2; + I915_WRITE(BXT_PORT_PLL(port, 2), temp); + + /* Write M2 fraction enable */ + temp = I915_READ(BXT_PORT_PLL(port, 3)); + temp &= ~PORT_PLL_M2_FRAC_ENABLE; + temp |= pll->config.hw_state.pll3; + I915_WRITE(BXT_PORT_PLL(port, 3), temp); + + /* Write coeff */ + temp = I915_READ(BXT_PORT_PLL(port, 6)); + temp &= ~PORT_PLL_PROP_COEFF_MASK; + temp &= ~PORT_PLL_INT_COEFF_MASK; + temp &= ~PORT_PLL_GAIN_CTL_MASK; + temp |= pll->config.hw_state.pll6; + I915_WRITE(BXT_PORT_PLL(port, 6), temp); + + /* Write calibration val */ + temp = I915_READ(BXT_PORT_PLL(port, 8)); + temp &= ~PORT_PLL_TARGET_CNT_MASK; + temp |= pll->config.hw_state.pll8; + I915_WRITE(BXT_PORT_PLL(port, 8), temp); + + /* + * FIXME: program PORT_PLL_9/i_lockthresh according to the latest + * specification update. + */ + + /* Recalibrate with new settings */ + temp = I915_READ(BXT_PORT_PLL_EBB_4(port)); + temp |= PORT_PLL_RECALIBRATE; + I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); + /* Enable 10 bit clock */ + temp |= PORT_PLL_10BIT_CLK_ENABLE; + I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); + + /* Enable PLL */ + temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); + temp |= PORT_PLL_ENABLE; + I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); + POSTING_READ(BXT_PORT_PLL_ENABLE(port)); + + if (wait_for_atomic_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & + PORT_PLL_LOCK), 200)) + DRM_ERROR("PLL %d not locked\n", port); + + /* + * While we write to the group register to program all lanes at once we + * can read only lane registers and we pick lanes 0/1 for that. + */ + temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port)); + temp &= ~LANE_STAGGER_MASK; + temp &= ~LANESTAGGER_STRAP_OVRD; + temp |= pll->config.hw_state.pcsdw12; + I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp); +} + +static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ + uint32_t temp; + + temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); + temp &= ~PORT_PLL_ENABLE; + I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); + POSTING_READ(BXT_PORT_PLL_ENABLE(port)); +} + +static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + struct intel_dpll_hw_state *hw_state) +{ + enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ + uint32_t val; + + if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) + return false; + + val = I915_READ(BXT_PORT_PLL_ENABLE(port)); + if (!(val & PORT_PLL_ENABLE)) + return false; + + hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port)); + hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0)); + hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1)); + hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2)); + hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3)); + hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6)); + hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8)); + /* + * While we write to the group register to program all lanes at once we + * can read only lane registers. We configure all lanes the same way, so + * here just read out lanes 0/1 and output a note if lanes 2/3 differ. + */ + hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port)); + if (I915_READ(BXT_PORT_PCS_DW12_LN23(port) != hw_state->pcsdw12)) + DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n", + hw_state->pcsdw12, + I915_READ(BXT_PORT_PCS_DW12_LN23(port))); + + return true; +} + +static void bxt_shared_dplls_init(struct drm_i915_private *dev_priv) +{ + int i; + + dev_priv->num_shared_dpll = 3; + + for (i = 0; i < dev_priv->num_shared_dpll; i++) { + dev_priv->shared_dplls[i].id = i; + dev_priv->shared_dplls[i].name = bxt_ddi_pll_names[i]; + dev_priv->shared_dplls[i].disable = bxt_ddi_pll_disable; + dev_priv->shared_dplls[i].enable = bxt_ddi_pll_enable; + dev_priv->shared_dplls[i].get_hw_state = + bxt_ddi_pll_get_hw_state; + } +} + void intel_ddi_pll_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -1997,6 +2160,8 @@ void intel_ddi_pll_init(struct drm_device *dev) if (IS_SKYLAKE(dev)) skl_shared_dplls_init(dev_priv); + else if (IS_BROXTON(dev)) + bxt_shared_dplls_init(dev_priv); else hsw_shared_dplls_init(dev_priv); From 5ab7b0b71e00d5ebfab35f4535e437eb88105d20 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 6 Mar 2015 03:29:25 +0200 Subject: [PATCH 0175/3798] drm/i915/bxt: add bxt_find_best_dpll Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 33 ++++++++++++++++++++++++---- drivers/gpu/drm/i915/intel_drv.h | 2 ++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3322e5a12e8e6d..ef58a775373e64 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -105,6 +105,8 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc); static void intel_finish_crtc_commit(struct drm_crtc *crtc); static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state); +static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state, + int num_connectors); static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe) { @@ -402,6 +404,18 @@ static const intel_limit_t intel_limits_chv = { .p2 = { .p2_slow = 1, .p2_fast = 14 }, }; +static const intel_limit_t intel_limits_bxt = { + /* FIXME: find real dot limits */ + .dot = { .min = 0, .max = INT_MAX }, + .vco = { .min = 4800000, .max = 6480000 }, + .n = { .min = 1, .max = 1 }, + .m1 = { .min = 2, .max = 2 }, + /* FIXME: find real m2 limits */ + .m2 = { .min = 2 << 22, .max = 255 << 22 }, + .p1 = { .min = 2, .max = 4 }, + .p2 = { .p2_slow = 1, .p2_fast = 20 }, +}; + static void vlv_clock(int refclk, intel_clock_t *clock) { clock->m = clock->m1 * clock->m2; @@ -513,7 +527,9 @@ intel_limit(struct intel_crtc_state *crtc_state, int refclk) struct drm_device *dev = crtc_state->base.crtc->dev; const intel_limit_t *limit; - if (HAS_PCH_SPLIT(dev)) + if (IS_BROXTON(dev)) + limit = &intel_limits_bxt; + else if (HAS_PCH_SPLIT(dev)) limit = intel_ironlake_limit(crtc_state, refclk); else if (IS_G4X(dev)) { limit = intel_g4x_limit(crtc_state); @@ -598,11 +614,11 @@ static bool intel_PLL_is_valid(struct drm_device *dev, if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) INTELPllInvalid("m1 out of range\n"); - if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev)) + if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) && !IS_BROXTON(dev)) if (clock->m1 <= clock->m2) INTELPllInvalid("m1 <= m2\n"); - if (!IS_VALLEYVIEW(dev)) { + if (!IS_VALLEYVIEW(dev) && !IS_BROXTON(dev)) { if (clock->p < limit->p.min || limit->p.max < clock->p) INTELPllInvalid("p out of range\n"); if (clock->m < limit->m.min || limit->m.max < clock->m) @@ -955,6 +971,15 @@ chv_find_best_dpll(const intel_limit_t *limit, return found; } +bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock, + intel_clock_t *best_clock) +{ + int refclk = i9xx_get_refclk(crtc_state, 0); + + return chv_find_best_dpll(intel_limit(crtc_state, refclk), crtc_state, + target_clock, refclk, NULL, best_clock); +} + bool intel_crtc_active(struct drm_crtc *crtc) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -6574,7 +6599,7 @@ static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state, WARN_ON(!crtc_state->base.state); - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_BROXTON(dev)) { refclk = 100000; } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1cad3ddaf3c723..d7436cbac87336 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1126,6 +1126,8 @@ int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n); void ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config, int dotclock); +bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock, + intel_clock_t *best_clock); bool intel_crtc_active(struct drm_crtc *crtc); void hsw_enable_ips(struct intel_crtc *crtc); void hsw_disable_ips(struct intel_crtc *crtc); From d683f3bc48655d71b36a8e18babae3036823c44e Mon Sep 17 00:00:00 2001 From: Satheeshakrishna M Date: Fri, 22 Aug 2014 09:49:08 +0530 Subject: [PATCH 0176/3798] drm/i915/bxt: BXT clock divider calculation Calculate and cache clock parameters. Follow bspec algorithm for HDMI. Use precalculated values for DisplayPort linkrates. v2: (imre) - rebase against upstream crtc_state change - use the existing CHV based helper instead of handrolling the same Signed-off-by: Satheeshakrishna M (v1) Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 129 +++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index a6d0cb0b10fc4c..471631e5ea0008 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1212,6 +1212,132 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc, return true; } +/* bxt clock parameters */ +struct bxt_clk_div { + uint32_t p1; + uint32_t p2; + uint32_t m2_int; + uint32_t m2_frac; + bool m2_frac_en; + uint32_t n; + uint32_t prop_coef; + uint32_t int_coef; + uint32_t gain_ctl; + uint32_t targ_cnt; + uint32_t lanestagger; +}; + +/* pre-calculated values for DP linkrates */ +static struct bxt_clk_div bxt_dp_clk_val[7] = { + /* 162 */ {4, 2, 32, 1677722, 1, 1, 5, 11, 2, 9, 0xd}, + /* 270 */ {4, 1, 27, 0, 0, 1, 3, 8, 1, 9, 0xd}, + /* 540 */ {2, 1, 27, 0, 0, 1, 3, 8, 1, 9, 0x18}, + /* 216 */ {3, 2, 32, 1677722, 1, 1, 5, 11, 2, 9, 0xd}, + /* 243 */ {4, 1, 24, 1258291, 1, 1, 5, 11, 2, 9, 0xd}, + /* 324 */ {4, 1, 32, 1677722, 1, 1, 5, 11, 2, 9, 0xd}, + /* 432 */ {3, 1, 32, 1677722, 1, 1, 5, 11, 2, 9, 0x18} +}; + +static bool +bxt_ddi_pll_select(struct intel_crtc *intel_crtc, + struct intel_crtc_state *crtc_state, + struct intel_encoder *intel_encoder, + int clock) +{ + struct intel_shared_dpll *pll; + struct bxt_clk_div clk_div = {0}; + + if (intel_encoder->type == INTEL_OUTPUT_HDMI) { + intel_clock_t best_clock; + + /* Calculate HDMI div */ + /* + * FIXME: tie the following calculation into + * i9xx_crtc_compute_clock + */ + if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) { + DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n", + clock, pipe_name(intel_crtc->pipe)); + return false; + } + + clk_div.p1 = best_clock.p1; + clk_div.p2 = best_clock.p2; + WARN_ON(best_clock.m1 != 2); + clk_div.n = best_clock.n; + clk_div.m2_int = best_clock.m2 >> 22; + clk_div.m2_frac = best_clock.m2 & ((1 << 22) - 1); + clk_div.m2_frac_en = clk_div.m2_frac != 0; + + /* FIXME: set coef, gain, targcnt based on freq band */ + clk_div.prop_coef = 5; + clk_div.int_coef = 11; + clk_div.gain_ctl = 2; + clk_div.targ_cnt = 9; + if (clock > 270000) + clk_div.lanestagger = 0x18; + else if (clock > 135000) + clk_div.lanestagger = 0x0d; + else if (clock > 67000) + clk_div.lanestagger = 0x07; + else if (clock > 33000) + clk_div.lanestagger = 0x04; + else + clk_div.lanestagger = 0x02; + } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT || + intel_encoder->type == INTEL_OUTPUT_EDP) { + struct drm_encoder *encoder = &intel_encoder->base; + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + switch (intel_dp->link_bw) { + case DP_LINK_BW_1_62: + clk_div = bxt_dp_clk_val[0]; + break; + case DP_LINK_BW_2_7: + clk_div = bxt_dp_clk_val[1]; + break; + case DP_LINK_BW_5_4: + clk_div = bxt_dp_clk_val[2]; + break; + default: + clk_div = bxt_dp_clk_val[0]; + DRM_ERROR("Unknown link rate\n"); + } + } + + crtc_state->dpll_hw_state.ebb0 = + PORT_PLL_P1(clk_div.p1) | PORT_PLL_P2(clk_div.p2); + crtc_state->dpll_hw_state.pll0 = clk_div.m2_int; + crtc_state->dpll_hw_state.pll1 = PORT_PLL_N(clk_div.n); + crtc_state->dpll_hw_state.pll2 = clk_div.m2_frac; + + if (clk_div.m2_frac_en) + crtc_state->dpll_hw_state.pll3 = + PORT_PLL_M2_FRAC_ENABLE; + + crtc_state->dpll_hw_state.pll6 = + clk_div.prop_coef | PORT_PLL_INT_COEFF(clk_div.int_coef); + crtc_state->dpll_hw_state.pll6 |= + PORT_PLL_GAIN_CTL(clk_div.gain_ctl); + + crtc_state->dpll_hw_state.pll8 = clk_div.targ_cnt; + + crtc_state->dpll_hw_state.pcsdw12 = + LANESTAGGER_STRAP_OVRD | clk_div.lanestagger; + + pll = intel_get_shared_dpll(intel_crtc, crtc_state); + if (pll == NULL) { + DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", + pipe_name(intel_crtc->pipe)); + return false; + } + + /* shared DPLL id 0 is DPLL A */ + crtc_state->ddi_pll_sel = pll->id; + + return true; +} + /* * Tries to find a *shared* PLL for the CRTC and store it in * intel_crtc->ddi_pll_sel. @@ -1230,6 +1356,9 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc, if (IS_SKYLAKE(dev)) return skl_ddi_pll_select(intel_crtc, crtc_state, intel_encoder, clock); + else if (IS_BROXTON(dev)) + return bxt_ddi_pll_select(intel_crtc, crtc_state, + intel_encoder, clock); else return hsw_ddi_pll_select(intel_crtc, crtc_state, intel_encoder, clock); From bcddf61077592ad9f670502858491ad2788856ef Mon Sep 17 00:00:00 2001 From: Satheeshakrishna M Date: Fri, 22 Aug 2014 09:49:10 +0530 Subject: [PATCH 0177/3798] drm/i915/bxt: Assign PLL for pipe Assign PLL for pipe (dependent on port attached to the pipe) v2: - fix incorrect encoder vs. new_encoder check for crtc (imre) v3: - warn and return error if no encoder is attached (imre) Signed-off-by: Satheeshakrishna M (v2) Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes [danvet: Don't move intel_ddi_get_crtc_new_encoder around.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 20 ++++++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 2 ++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 471631e5ea0008..404cef0536882e 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -493,7 +493,7 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc) return ret; } -static struct intel_encoder * +struct intel_encoder * intel_ddi_get_crtc_new_encoder(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ef58a775373e64..c51565a0f2aa86 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4209,6 +4209,26 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, goto found; } + if (IS_BROXTON(dev_priv->dev)) { + /* PLL is attached to port in bxt */ + struct intel_encoder *encoder; + struct intel_digital_port *intel_dig_port; + + encoder = intel_ddi_get_crtc_new_encoder(crtc_state); + if (WARN_ON(!encoder)) + return NULL; + + intel_dig_port = enc_to_dig_port(&encoder->base); + /* 1:1 mapping between ports and PLLs */ + i = (enum intel_dpll_id)intel_dig_port->port; + pll = &dev_priv->shared_dplls[i]; + DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", + crtc->base.base.id, pll->name); + WARN_ON(pll->new_config->crtc_mask); + + goto found; + } + for (i = 0; i < dev_priv->num_shared_dpll; i++) { pll = &dev_priv->shared_dplls[i]; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d7436cbac87336..7e11a54f0d4623 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -936,6 +936,8 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); void intel_ddi_fdi_disable(struct drm_crtc *crtc); void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); +struct intel_encoder * +intel_ddi_get_crtc_new_encoder(struct intel_crtc_state *crtc_state); void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder); void intel_ddi_clock_get(struct intel_encoder *encoder, From 3760b59cba7d592e0ed70cb64291f0403b12f805 Mon Sep 17 00:00:00 2001 From: Satheeshakrishna M Date: Fri, 22 Aug 2014 09:49:11 +0530 Subject: [PATCH 0178/3798] drm/i915/bxt: Determine PLL attached to pipe Determine PLL attached to pipe (which is same as DDI PLL) v2: - rebased on upstream s/crtc_config/crtc_state/ (imre) Signed-off-by: Satheeshakrishna M (v1) Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c51565a0f2aa86..278f80760d57fe 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9096,6 +9096,28 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc, return 0; } +static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv, + enum port port, + struct intel_crtc_state *pipe_config) +{ + switch (port) { + case PORT_A: + pipe_config->ddi_pll_sel = SKL_DPLL0; + pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1; + break; + case PORT_B: + pipe_config->ddi_pll_sel = SKL_DPLL1; + pipe_config->shared_dpll = DPLL_ID_SKL_DPLL2; + break; + case PORT_C: + pipe_config->ddi_pll_sel = SKL_DPLL2; + pipe_config->shared_dpll = DPLL_ID_SKL_DPLL3; + break; + default: + DRM_ERROR("Incorrect port type\n"); + } +} + static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, struct intel_crtc_state *pipe_config) @@ -9158,6 +9180,8 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, if (IS_SKYLAKE(dev)) skylake_get_ddi_pll(dev_priv, port, pipe_config); + else if (IS_BROXTON(dev)) + bxt_get_ddi_pll(dev_priv, port, pipe_config); else haswell_get_ddi_pll(dev_priv, port, pipe_config); From 977bb38d2dc5a4bcfb8841131e5e44d0463f3411 Mon Sep 17 00:00:00 2001 From: Satheeshakrishna M Date: Fri, 22 Aug 2014 09:49:12 +0530 Subject: [PATCH 0179/3798] drm/i915/bxt: Determine programmed frequency Add placeholder function for calculating programmed pixel clock. Note: Formula to back calculate link clock from dividers not available currently. v2: - rebased on upstream s/crtc_config/crtc_state/ change (imre) Signed-off-by: Satheeshakrishna M (v1) Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 30 +++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_dp.c | 2 ++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 404cef0536882e..f9f55bc05e7d82 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -880,6 +880,32 @@ static void hsw_ddi_clock_get(struct intel_encoder *encoder, pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock; } +static int bxt_calc_pll_link(struct drm_i915_private *dev_priv, + enum intel_dpll_id dpll) +{ + /* FIXME formula not available in bspec */ + return 0; +} + +static void bxt_ddi_clock_get(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config) +{ + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + enum port port = intel_ddi_get_encoder_port(encoder); + uint32_t dpll = port; + + pipe_config->port_clock = + bxt_calc_pll_link(dev_priv, dpll); + + if (pipe_config->has_dp_encoder) + pipe_config->base.adjusted_mode.crtc_clock = + intel_dotclock_calculate(pipe_config->port_clock, + &pipe_config->dp_m_n); + else + pipe_config->base.adjusted_mode.crtc_clock = + pipe_config->port_clock; +} + void intel_ddi_clock_get(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { @@ -887,8 +913,10 @@ void intel_ddi_clock_get(struct intel_encoder *encoder, if (INTEL_INFO(dev)->gen <= 8) hsw_ddi_clock_get(encoder, pipe_config); - else + else if (IS_SKYLAKE(dev)) skl_ddi_clock_get(encoder, pipe_config); + else if (IS_BROXTON(dev)) + bxt_ddi_clock_get(encoder, pipe_config); } static void diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3ea68e164873a5..550ac9be1f58ea 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1471,6 +1471,8 @@ intel_dp_compute_config(struct intel_encoder *encoder, if (IS_SKYLAKE(dev) && is_edp(intel_dp)) skl_edp_set_pll_config(pipe_config, common_rates[clock]); + else if (IS_BROXTON(dev)) + /* handled in ddi */; else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw); else From 503604038b739b244781904113a377385a341937 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 16 Jan 2015 00:55:16 -0800 Subject: [PATCH 0180/3798] drm/i915: suppress false PLL state warnings on non-GMCH platforms The checks for PLL enabled state on CPU ports are valid only on GMCH platforms but atm we'd also call them on non-PCH-split/non-GMCH platforms like BXT, triggering false warnings. Until the proper check is implented for these platforms simply disable the check. Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 278f80760d57fe..be69e84399a495 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2131,7 +2131,7 @@ static void intel_enable_pipe(struct intel_crtc *crtc) * a plane. On ILK+ the pipe PLLs are integrated, so we don't * need the check. */ - if (!HAS_PCH_SPLIT(dev_priv->dev)) + if (HAS_GMCH_DISPLAY(dev_priv->dev)) if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI)) assert_dsi_pll_enabled(dev_priv); else @@ -4666,7 +4666,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc) if (!crtc->state->enable || !intel_crtc->active) return; - if (!HAS_PCH_SPLIT(dev_priv->dev)) { + if (HAS_GMCH_DISPLAY(dev_priv->dev)) { if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI)) assert_dsi_pll_enabled(dev_priv); else From b403745c84592b26a0713e6944c2b109f6df5c82 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Mon, 4 Aug 2014 22:01:33 +0100 Subject: [PATCH 0181/3798] drm/i915: Iterate through the initialized DDIs to prepare their buffers Not every DDIs is necessarily connected can be strapped off and, in the future, we'll have platforms with a different number of default DDI ports. So, let's only call intel_prepare_ddi_buffers() on DDI ports that are actually detected. We also use the opportunity to give a struct intel_digital_port to intel_prepare_ddi_buffers() as we'll need it in a following patch to query if the port supports HMDI or not. On my HSW machine this removes the initialization of a couple of (unused) DDIs. Signed-off-by: Damien Lespiau Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 4 ++++ drivers/gpu/drm/i915/intel_ddi.c | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a7049ea164e293..fd72f3f0cf84dc 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -251,6 +251,10 @@ enum hpd_pin { &dev->mode_config.connector_list, \ base.head) +#define for_each_digital_port(dev, digital_port) \ + list_for_each_entry(digital_port, \ + &dev->mode_config.encoder_list, \ + base.base.head) #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \ list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \ diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index f9f55bc05e7d82..e0b618851a5353 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -198,10 +198,12 @@ enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) * in either FDI or DP modes only, as HDMI connections will work with both * of those */ -static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) +static void intel_prepare_ddi_buffers(struct drm_device *dev, + struct intel_digital_port *intel_dig_port) { struct drm_i915_private *dev_priv = dev->dev_private; u32 reg; + int port = intel_dig_port->port; int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_default_entry, size; int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; @@ -309,13 +311,19 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) */ void intel_prepare_ddi(struct drm_device *dev) { - int port; + struct intel_digital_port *intel_dig_port; + bool visited[I915_MAX_PORTS] = { 0, }; if (!HAS_DDI(dev)) return; - for (port = PORT_A; port <= PORT_E; port++) - intel_prepare_ddi_buffers(dev, port); + for_each_digital_port(dev, intel_dig_port) { + if (visited[intel_dig_port->port]) + continue; + + intel_prepare_ddi_buffers(dev, intel_dig_port); + visited[intel_dig_port->port] = true; + } } static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, From ce3b7e9bcfdc2d255d9ab1a0e1f76d8b0912b8a4 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Mon, 4 Aug 2014 15:04:43 +0100 Subject: [PATCH 0182/3798] drm/i915: Don't write the HDMI buffer translation entry when not needed We don't actually need to write the HDMI entry on DDIs that have no chance to be used as HDMI ports. While this patch shouldn't change the current behaviour, it makes further enabling work easier as we'll have an eDP table filling the full 10 entries. v2: Rely on the logic from intel_ddi_init() to figure out if the DDI port supports HDMI or not (Paulo). Suggested-by: Satheeshakrishna M Signed-off-by: Damien Lespiau Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index e0b618851a5353..43b38d76761cf8 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -191,6 +191,12 @@ enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) } } +static bool +intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) +{ + return intel_dig_port->hdmi.hdmi_reg; +} + /* * Starting with Haswell, DDI port buffers must be programmed with correct * values in advance. The buffer values are different for FDI and DP modes, @@ -294,6 +300,9 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, reg += 4; } + if (!intel_dig_port_supports_hdmi(intel_dig_port)) + return; + /* Choose a good default if VBT is badly populated */ if (hdmi_level == HDMI_LEVEL_SHIFT_UNKNOWN || hdmi_level >= n_hdmi_entries) From 96fb9f9b154a8dbfe1f74c384cd82f73539fda93 Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Tue, 18 Nov 2014 15:45:27 +0530 Subject: [PATCH 0183/3798] drm/i915/bxt: VSwing programming sequence VSwing programming sequence as specified in the updated BXT BSpec v2: Satheesh's review comments addressed. - clear value before setting into registers - move print statement to bxt function Other changes - since signal level will not be set into DDI_BUF_CTL, the value need not be returned to intel_dp_set_signal_levels(). Making the bxt specific function to return void and setting signal_levels = 0 for bxt inside intel_dp_set_signal_levels() - instead of signal levels, printing vswing level and pre-emphasis level - in case none of the pre-emphasis levels or vswing levels are set, setting default of 400mV + 0dB v3: Satheesh's review comments - Check for mask before printing signal_levels. - Removing redundant register writes - Call intel_prepare_ddi_buffers only for HAS_PCH_SPLIT - Making register write part generic as it will be required for HDMI as well. Re-structure the code to include an array for vswing related values, set signal levels v4: Satheesh's review comments - Rebase over latest renaming patches - use hsw_signal_levels for HAS_DDI Other changes - Modified vswing_sequence() func definition - Rebased on top of register macro definitions v5: Satheesh's review comments - Check ddi translation table size v6: Imre's review comments - removed comments in vswing sequence - added vswing, pre-emphasis prints in intel_dp_set_signal_levels - added comment explaining use of DP vswing values for eDP - initialize n_entries and ddi_transaltion table based on encoder type - create bxt_ddi_buf_trans structure and use decimal values - adding a flag in bxt buffer translation table to indicate def entry v7: (imre) - squash in Vandana's "VSwing register definition", "HDMI VSwing programming", "Re-enable vswing programming", "Fix vswing sequence" patches - use BXT_PORT_* regs directly instead of via a temp var - simplify BXT_PORT_* macro definitions - add code comment why we read lane while write group registers - fix readout of DP_TRAIN_PRE_EMPHASIS in debug message Signed-off-by: Vandana Kannan (v6) Signed-off-by: Imre Deak Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 61 ++++++++++++++++ drivers/gpu/drm/i915/intel_ddi.c | 120 ++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_dp.c | 64 ++++++++++++++++- drivers/gpu/drm/i915/intel_drv.h | 2 + 4 files changed, 244 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5c81728e4400e5..d47afbc97a21fc 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1260,6 +1260,21 @@ enum skl_disp_power_wells { _PORT_REF_DW8_A) /* BXT PHY PCS registers */ +#define _PORT_PCS_DW10_LN01_A 0x162428 +#define _PORT_PCS_DW10_LN01_B 0x6C428 +#define _PORT_PCS_DW10_LN01_C 0x6C828 +#define _PORT_PCS_DW10_GRP_A 0x162C28 +#define _PORT_PCS_DW10_GRP_B 0x6CC28 +#define _PORT_PCS_DW10_GRP_C 0x6CE28 +#define BXT_PORT_PCS_DW10_LN01(port) _PORT3(port, _PORT_PCS_DW10_LN01_A, \ + _PORT_PCS_DW10_LN01_B, \ + _PORT_PCS_DW10_LN01_C) +#define BXT_PORT_PCS_DW10_GRP(port) _PORT3(port, _PORT_PCS_DW10_GRP_A, \ + _PORT_PCS_DW10_GRP_B, \ + _PORT_PCS_DW10_GRP_C) +#define TX2_SWING_CALC_INIT (1 << 31) +#define TX1_SWING_CALC_INIT (1 << 30) + #define _PORT_PCS_DW12_LN01_A 0x162430 #define _PORT_PCS_DW12_LN01_B 0x6C430 #define _PORT_PCS_DW12_LN01_C 0x6C830 @@ -1285,6 +1300,52 @@ enum skl_disp_power_wells { #define _BXT_LANE_OFFSET(lane) (((lane) >> 1) * 0x200 + \ ((lane) & 1) * 0x80) +#define _PORT_TX_DW2_LN0_A 0x162508 +#define _PORT_TX_DW2_LN0_B 0x6C508 +#define _PORT_TX_DW2_LN0_C 0x6C908 +#define _PORT_TX_DW2_GRP_A 0x162D08 +#define _PORT_TX_DW2_GRP_B 0x6CD08 +#define _PORT_TX_DW2_GRP_C 0x6CF08 +#define BXT_PORT_TX_DW2_GRP(port) _PORT3(port, _PORT_TX_DW2_GRP_A, \ + _PORT_TX_DW2_GRP_B, \ + _PORT_TX_DW2_GRP_C) +#define BXT_PORT_TX_DW2_LN0(port) _PORT3(port, _PORT_TX_DW2_LN0_A, \ + _PORT_TX_DW2_LN0_B, \ + _PORT_TX_DW2_LN0_C) +#define MARGIN_000_SHIFT 16 +#define MARGIN_000 (0xFF << MARGIN_000_SHIFT) +#define UNIQ_TRANS_SCALE_SHIFT 8 +#define UNIQ_TRANS_SCALE (0xFF << UNIQ_TRANS_SCALE_SHIFT) + +#define _PORT_TX_DW3_LN0_A 0x16250C +#define _PORT_TX_DW3_LN0_B 0x6C50C +#define _PORT_TX_DW3_LN0_C 0x6C90C +#define _PORT_TX_DW3_GRP_A 0x162D0C +#define _PORT_TX_DW3_GRP_B 0x6CD0C +#define _PORT_TX_DW3_GRP_C 0x6CF0C +#define BXT_PORT_TX_DW3_GRP(port) _PORT3(port, _PORT_TX_DW3_GRP_A, \ + _PORT_TX_DW3_GRP_B, \ + _PORT_TX_DW3_GRP_C) +#define BXT_PORT_TX_DW3_LN0(port) _PORT3(port, _PORT_TX_DW3_LN0_A, \ + _PORT_TX_DW3_LN0_B, \ + _PORT_TX_DW3_LN0_C) +#define UNIQE_TRANGE_EN_METHOD (1 << 27) + +#define _PORT_TX_DW4_LN0_A 0x162510 +#define _PORT_TX_DW4_LN0_B 0x6C510 +#define _PORT_TX_DW4_LN0_C 0x6C910 +#define _PORT_TX_DW4_GRP_A 0x162D10 +#define _PORT_TX_DW4_GRP_B 0x6CD10 +#define _PORT_TX_DW4_GRP_C 0x6CF10 +#define BXT_PORT_TX_DW4_LN0(port) _PORT3(port, _PORT_TX_DW4_LN0_A, \ + _PORT_TX_DW4_LN0_B, \ + _PORT_TX_DW4_LN0_C) +#define BXT_PORT_TX_DW4_GRP(port) _PORT3(port, _PORT_TX_DW4_GRP_A, \ + _PORT_TX_DW4_GRP_B, \ + _PORT_TX_DW4_GRP_C) +#define DEEMPH_SHIFT 24 +#define DE_EMPHASIS (0xFF << DEEMPH_SHIFT) + #define _PORT_TX_DW14_LN0_A 0x162538 #define _PORT_TX_DW14_LN0_B 0x6C538 #define _PORT_TX_DW14_LN0_C 0x6C938 diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 43b38d76761cf8..455d44b49c66b6 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -168,6 +168,48 @@ static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { { 0x00000018, 0x000000c7 }, }; +struct bxt_ddi_buf_trans { + u32 margin; /* swing value */ + u32 scale; /* scale value */ + u32 enable; /* scale enable */ + u32 deemphasis; + bool default_index; /* true if the entry represents default value */ +}; + +/* BSpec does not define separate vswing/pre-emphasis values for eDP. + * Using DP values for eDP as well. + */ +static const struct bxt_ddi_buf_trans bxt_ddi_translations_dp[] = { + /* Idx NT mV diff db */ + { 52, 0, 0, 128, true }, /* 0: 400 0 */ + { 78, 0, 0, 85, false }, /* 1: 400 3.5 */ + { 104, 0, 0, 64, false }, /* 2: 400 6 */ + { 154, 0, 0, 43, false }, /* 3: 400 9.5 */ + { 77, 0, 0, 128, false }, /* 4: 600 0 */ + { 116, 0, 0, 85, false }, /* 5: 600 3.5 */ + { 154, 0, 0, 64, false }, /* 6: 600 6 */ + { 102, 0, 0, 128, false }, /* 7: 800 0 */ + { 154, 0, 0, 85, false }, /* 8: 800 3.5 */ + { 154, 0x9A, 1, 128, false }, /* 9: 1200 0 */ +}; + +/* BSpec has 2 recommended values - entries 0 and 8. + * Using the entry with higher vswing. + */ +static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = { + /* Idx NT mV diff db */ + { 52, 0, 0, 128, false }, /* 0: 400 0 */ + { 52, 0, 0, 85, false }, /* 1: 400 3.5 */ + { 52, 0, 0, 64, false }, /* 2: 400 6 */ + { 42, 0, 0, 43, false }, /* 3: 400 9.5 */ + { 77, 0, 0, 128, false }, /* 4: 600 0 */ + { 77, 0, 0, 85, false }, /* 5: 600 3.5 */ + { 77, 0, 0, 64, false }, /* 6: 600 6 */ + { 102, 0, 0, 128, false }, /* 7: 800 0 */ + { 102, 0, 0, 85, false }, /* 8: 800 3.5 */ + { 154, 0x9A, 1, 128, true }, /* 9: 1200 0 */ +}; + enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) { struct drm_encoder *encoder = &intel_encoder->base; @@ -219,7 +261,15 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, const struct ddi_buf_trans *ddi_translations_hdmi; const struct ddi_buf_trans *ddi_translations; - if (IS_SKYLAKE(dev)) { + if (IS_BROXTON(dev)) { + if (!intel_dig_port_supports_hdmi(intel_dig_port)) + return; + + /* Vswing programming for HDMI */ + bxt_ddi_vswing_sequence(dev, hdmi_level, port, + INTEL_OUTPUT_HDMI); + return; + } else if (IS_SKYLAKE(dev)) { ddi_translations_fdi = NULL; ddi_translations_dp = skl_ddi_translations_dp; n_dp_entries = ARRAY_SIZE(skl_ddi_translations_dp); @@ -1695,6 +1745,67 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc) TRANS_CLK_SEL_DISABLED); } +void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, + enum port port, int type) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + const struct bxt_ddi_buf_trans *ddi_translations; + u32 n_entries, i; + uint32_t val; + + if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { + n_entries = ARRAY_SIZE(bxt_ddi_translations_dp); + ddi_translations = bxt_ddi_translations_dp; + } else if (type == INTEL_OUTPUT_HDMI) { + n_entries = ARRAY_SIZE(bxt_ddi_translations_hdmi); + ddi_translations = bxt_ddi_translations_hdmi; + } else { + DRM_DEBUG_KMS("Vswing programming not done for encoder %d\n", + type); + return; + } + + /* Check if default value has to be used */ + if (level >= n_entries || + (type == INTEL_OUTPUT_HDMI && level == HDMI_LEVEL_SHIFT_UNKNOWN)) { + for (i = 0; i < n_entries; i++) { + if (ddi_translations[i].default_index) { + level = i; + break; + } + } + } + + /* + * While we write to the group register to program all lanes at once we + * can read only lane registers and we pick lanes 0/1 for that. + */ + val = I915_READ(BXT_PORT_PCS_DW10_LN01(port)); + val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT); + I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); + + val = I915_READ(BXT_PORT_TX_DW2_LN0(port)); + val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE); + val |= ddi_translations[level].margin << MARGIN_000_SHIFT | + ddi_translations[level].scale << UNIQ_TRANS_SCALE_SHIFT; + I915_WRITE(BXT_PORT_TX_DW2_GRP(port), val); + + val = I915_READ(BXT_PORT_TX_DW3_LN0(port)); + val &= ~UNIQE_TRANGE_EN_METHOD; + if (ddi_translations[level].enable) + val |= UNIQE_TRANGE_EN_METHOD; + I915_WRITE(BXT_PORT_TX_DW3_GRP(port), val); + + val = I915_READ(BXT_PORT_TX_DW4_LN0(port)); + val &= ~DE_EMPHASIS; + val |= ddi_translations[level].deemphasis << DEEMPH_SHIFT; + I915_WRITE(BXT_PORT_TX_DW4_GRP(port), val); + + val = I915_READ(BXT_PORT_PCS_DW10_LN01(port)); + val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT; + I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); +} + static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) { struct drm_encoder *encoder = &intel_encoder->base; @@ -1703,6 +1814,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); enum port port = intel_ddi_get_encoder_port(intel_encoder); int type = intel_encoder->type; + int hdmi_level; if (type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); @@ -1759,6 +1871,12 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) } else if (type == INTEL_OUTPUT_HDMI) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + if (IS_BROXTON(dev)) { + hdmi_level = dev_priv->vbt. + ddi_port_info[port].hdmi_level_shift; + bxt_ddi_vswing_sequence(dev, hdmi_level, port, + INTEL_OUTPUT_HDMI); + } intel_hdmi->set_infoframes(encoder, crtc->config->has_hdmi_sink, &crtc->config->base.adjusted_mode); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 550ac9be1f58ea..2e27b5215a368d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3409,6 +3409,55 @@ intel_hsw_signal_levels(uint8_t train_set) } } +static void intel_bxt_signal_levels(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dport = dp_to_dig_port(intel_dp); + enum port port = dport->port; + struct drm_device *dev = dport->base.base.dev; + struct intel_encoder *encoder = &dport->base; + uint8_t train_set = intel_dp->train_set[0]; + uint32_t level = 0; + + int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | + DP_TRAIN_PRE_EMPHASIS_MASK); + switch (signal_levels) { + default: + DRM_DEBUG_KMS("Unsupported voltage swing/pre-emph level\n"); + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: + level = 0; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: + level = 1; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: + level = 2; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: + level = 3; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: + level = 4; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: + level = 5; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: + level = 6; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: + level = 7; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: + level = 8; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: + level = 9; + break; + } + + bxt_ddi_vswing_sequence(dev, level, port, encoder->type); +} + /* Properly updates "DP" with the correct signal levels. */ static void intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) @@ -3419,7 +3468,11 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) uint32_t signal_levels, mask; uint8_t train_set = intel_dp->train_set[0]; - if (IS_HASWELL(dev) || IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) { + if (IS_BROXTON(dev)) { + signal_levels = 0; + intel_bxt_signal_levels(intel_dp); + mask = 0; + } else if (HAS_DDI(dev)) { signal_levels = intel_hsw_signal_levels(train_set); mask = DDI_BUF_EMP_MASK; } else if (IS_CHERRYVIEW(dev)) { @@ -3439,7 +3492,14 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) mask = DP_VOLTAGE_MASK | DP_PRE_EMPHASIS_MASK; } - DRM_DEBUG_KMS("Using signal levels %08x\n", signal_levels); + if (mask) + DRM_DEBUG_KMS("Using signal levels %08x\n", signal_levels); + + DRM_DEBUG_KMS("Using vswing level %d\n", + train_set & DP_TRAIN_VOLTAGE_SWING_MASK); + DRM_DEBUG_KMS("Using pre-emphasis level %d\n", + (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) >> + DP_TRAIN_PRE_EMPHASIS_SHIFT); *DP = (*DP & ~mask) | signal_levels; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7e11a54f0d4623..a7ec8726662620 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -943,6 +943,8 @@ void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder); void intel_ddi_clock_get(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state); +void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, + enum port port, int type); /* intel_frontbuffer.c */ void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, From 9314726b9f7329e223dd279819b42842ab7d413f Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Tue, 18 Nov 2014 15:45:29 +0530 Subject: [PATCH 0184/3798] drm/i915/bxt: Update max level of vswing Broxton supports 3 voltage swing levels on all DP ports. Max level of pre-emphasis will be taken care with the existing code. v2: Patch rebased v3: (imre) - keep existing behavior for other platforms - clarify commit message Signed-off-by: Vandana Kannan (v2) Signed-off-by: Imre Deak Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2e27b5215a368d..aa13608d27ffb8 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2887,7 +2887,9 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dev->dev_private; enum port port = dp_to_dig_port(intel_dp)->port; - if (INTEL_INFO(dev)->gen >= 9) { + if (IS_BROXTON(dev)) + return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; + else if (INTEL_INFO(dev)->gen >= 9) { if (dev_priv->vbt.edp_low_vswing && port == PORT_A) return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; From 5829975ce098171b7a4b86a5914929b16980d1bd Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 16 Apr 2015 11:36:52 +0200 Subject: [PATCH 0185/3798] drm/i915/dp: Remove intel_ prefix from hw signal_levels functions intel_ is for generic code bxt_ and friends for platform specific functions. Remove the intel_ prefix to be consistent with our naming. Random OCD bikeshed I've spotted while merging bxt patches. v2: Oops, git add fail. Cc: Imre Deak Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index aa13608d27ffb8..5a955e33ba133f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2971,7 +2971,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) } } -static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp) +static uint32_t vlv_signal_levels(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = dev->dev_private; @@ -3071,7 +3071,7 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp) return 0; } -static uint32_t intel_chv_signal_levels(struct intel_dp *intel_dp) +static uint32_t chv_signal_levels(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = dev->dev_private; @@ -3278,7 +3278,7 @@ intel_get_adjust_train(struct intel_dp *intel_dp, } static uint32_t -intel_gen4_signal_levels(uint8_t train_set) +gen4_signal_levels(uint8_t train_set) { uint32_t signal_levels = 0; @@ -3317,7 +3317,7 @@ intel_gen4_signal_levels(uint8_t train_set) /* Gen6's DP voltage swing and pre-emphasis control */ static uint32_t -intel_gen6_edp_signal_levels(uint8_t train_set) +gen6_edp_signal_levels(uint8_t train_set) { int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | DP_TRAIN_PRE_EMPHASIS_MASK); @@ -3345,7 +3345,7 @@ intel_gen6_edp_signal_levels(uint8_t train_set) /* Gen7's DP voltage swing and pre-emphasis control */ static uint32_t -intel_gen7_edp_signal_levels(uint8_t train_set) +gen7_edp_signal_levels(uint8_t train_set) { int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | DP_TRAIN_PRE_EMPHASIS_MASK); @@ -3376,7 +3376,7 @@ intel_gen7_edp_signal_levels(uint8_t train_set) /* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */ static uint32_t -intel_hsw_signal_levels(uint8_t train_set) +hsw_signal_levels(uint8_t train_set) { int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | DP_TRAIN_PRE_EMPHASIS_MASK); @@ -3411,7 +3411,7 @@ intel_hsw_signal_levels(uint8_t train_set) } } -static void intel_bxt_signal_levels(struct intel_dp *intel_dp) +static void bxt_signal_levels(struct intel_dp *intel_dp) { struct intel_digital_port *dport = dp_to_dig_port(intel_dp); enum port port = dport->port; @@ -3472,25 +3472,25 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) if (IS_BROXTON(dev)) { signal_levels = 0; - intel_bxt_signal_levels(intel_dp); + bxt_signal_levels(intel_dp); mask = 0; } else if (HAS_DDI(dev)) { - signal_levels = intel_hsw_signal_levels(train_set); + signal_levels = hsw_signal_levels(train_set); mask = DDI_BUF_EMP_MASK; } else if (IS_CHERRYVIEW(dev)) { - signal_levels = intel_chv_signal_levels(intel_dp); + signal_levels = chv_signal_levels(intel_dp); mask = 0; } else if (IS_VALLEYVIEW(dev)) { - signal_levels = intel_vlv_signal_levels(intel_dp); + signal_levels = vlv_signal_levels(intel_dp); mask = 0; } else if (IS_GEN7(dev) && port == PORT_A) { - signal_levels = intel_gen7_edp_signal_levels(train_set); + signal_levels = gen7_edp_signal_levels(train_set); mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; } else if (IS_GEN6(dev) && port == PORT_A) { - signal_levels = intel_gen6_edp_signal_levels(train_set); + signal_levels = gen6_edp_signal_levels(train_set); mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB; } else { - signal_levels = intel_gen4_signal_levels(train_set); + signal_levels = gen4_signal_levels(train_set); mask = DP_VOLTAGE_MASK | DP_PRE_EMPHASIS_MASK; } From b3f9d7d7bc5a35664e70fceed906eb35593dc644 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Thu, 16 Apr 2015 18:34:06 +0800 Subject: [PATCH 0186/3798] drm/i915: fix semicolon.cocci warnings drivers/gpu/drm/i915/i915_debugfs.c:4850:2-3: Unneeded semicolon Removes unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci CC: Jani Nikula Signed-off-by: Fengguang Wu Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1bd2ec5a5a5708..9c2b9e45079956 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4950,7 +4950,7 @@ static int i915_dpcd_show(struct seq_file *m, void *data) } seq_printf(m, "%04x: %*ph\n", b->offset, (int) size, buf); - }; + } return 0; } From c5d5ab7a05bc311dd0e57bdfd925ae4720f77a58 Mon Sep 17 00:00:00 2001 From: Todd Previte Date: Wed, 15 Apr 2015 08:38:38 -0700 Subject: [PATCH 0187/3798] drm/i915: Add automated testing support for Displayport compliance testing Add the skeleton framework for supporting automation for Displayport compliance testing. This patch adds the necessary framework for the source device to appropriately respond to test automation requests from a sink device. V2: - Addressed previous mailing list feedback - Fixed compilation issue (struct members declared in a later patch) - Updated debug messages to be more accurate - Added status checks for the DPCD read/write calls - Removed excess comments and debug messages - Fixed debug message compilation warnings - Fixed compilation issue with missing variables - Updated link training autotest to ACK V3: - Fixed the checks on the DPCD return code to be <= 0 rather than != 0 - Removed extraneous assignment of a NAK return code in the DPCD read failure case - Changed the return in the DPCD read failure case to a goto to the exit point where the status code is written to the sink - Removed FAUX test case since it's deprecated now - Removed the compliance flag assignment in handle_test_request V4: - Moved declaration of type_type here - Removed declaration of test_data (moved to a later patch) - Added reset to 0 for compliance test variables V5: - Moved test_active variable declaration and initialization out of this patch and into the patch where it's used - Changed variable name compliance_testing_active to compliance_test_active to unify the naming convention - Added initialization for compliance_test_type variable Signed-off-by: Todd Previte Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 75 ++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_drv.h | 3 ++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5a955e33ba133f..371d1e6129e597 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4039,11 +4039,78 @@ intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector) return true; } -static void -intel_dp_handle_test_request(struct intel_dp *intel_dp) +static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp) +{ + uint8_t test_result = DP_TEST_ACK; + return test_result; +} + +static uint8_t intel_dp_autotest_video_pattern(struct intel_dp *intel_dp) +{ + uint8_t test_result = DP_TEST_NAK; + return test_result; +} + +static uint8_t intel_dp_autotest_edid(struct intel_dp *intel_dp) +{ + uint8_t test_result = DP_TEST_NAK; + return test_result; +} + +static uint8_t intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp) +{ + uint8_t test_result = DP_TEST_NAK; + return test_result; +} + +static void intel_dp_handle_test_request(struct intel_dp *intel_dp) { - /* NAK by default */ - drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_RESPONSE, DP_TEST_NAK); + uint8_t response = DP_TEST_NAK; + uint8_t rxdata = 0; + int status = 0; + + intel_dp->compliance_test_type = 0; + intel_dp->aux.i2c_nack_count = 0; + intel_dp->aux.i2c_defer_count = 0; + + status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_REQUEST, &rxdata, 1); + if (status <= 0) { + DRM_DEBUG_KMS("Could not read test request from sink\n"); + goto update_status; + } + + switch (rxdata) { + case DP_TEST_LINK_TRAINING: + DRM_DEBUG_KMS("LINK_TRAINING test requested\n"); + intel_dp->compliance_test_type = DP_TEST_LINK_TRAINING; + response = intel_dp_autotest_link_training(intel_dp); + break; + case DP_TEST_LINK_VIDEO_PATTERN: + DRM_DEBUG_KMS("TEST_PATTERN test requested\n"); + intel_dp->compliance_test_type = DP_TEST_LINK_VIDEO_PATTERN; + response = intel_dp_autotest_video_pattern(intel_dp); + break; + case DP_TEST_LINK_EDID_READ: + DRM_DEBUG_KMS("EDID test requested\n"); + intel_dp->compliance_test_type = DP_TEST_LINK_EDID_READ; + response = intel_dp_autotest_edid(intel_dp); + break; + case DP_TEST_LINK_PHY_TEST_PATTERN: + DRM_DEBUG_KMS("PHY_PATTERN test requested\n"); + intel_dp->compliance_test_type = DP_TEST_LINK_PHY_TEST_PATTERN; + response = intel_dp_autotest_phy_pattern(intel_dp); + break; + default: + DRM_DEBUG_KMS("Invalid test request '%02x'\n", rxdata); + break; + } + +update_status: + status = drm_dp_dpcd_write(&intel_dp->aux, + DP_TEST_RESPONSE, + &response, 1); + if (status <= 0) + DRM_DEBUG_KMS("Could not write test response to sink\n"); } static int diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a7ec8726662620..23a42a40abaec9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -739,6 +739,9 @@ struct intel_dp { bool has_aux_irq, int send_bytes, uint32_t aux_clock_divider); + + /* Displayport compliance testing */ + unsigned long compliance_test_type; }; struct intel_digital_port { From 74ebf294a1dd816bdc248ac733009a8915d59eb5 Mon Sep 17 00:00:00 2001 From: Todd Previte Date: Wed, 15 Apr 2015 08:38:41 -0700 Subject: [PATCH 0188/3798] drm/i915: Add a delay in Displayport AUX transactions for compliance testing The Displayport Link Layer Compliance Testing Specification 1.2 rev 1.1 specifies that repeated AUX transactions after a failure (no response / invalid response) must have a minimum delay of 400us before the resend can occur. Tests 4.2.1.1 and 4.2.1.2 are two tests that require this specifically. Also, the check for DP_AUX_CH_CTL_TIME_OUT_ERROR has been moved out into a separate case. This case just continues with the next iteration of the loop as the HW has already waited the required amount of time. V2: - Changed udelay() to usleep_range() V3: - Removed extraneous check for timeout - Updated comment to reflect this change V4: - Reformatted a comment V5: - Added separate check for HW timeout on AUX transactions. A message is logged upon detection of this case. V6: - Add continue statement to HW timeout detect case - Remove the log message indicating a timeout has been detected (review feedback) V7: - Updated the commit message to remove verbage about the HW timeout case that is no longer valid. Signed-off-by: Todd Previte Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 371d1e6129e597..ae4baf96bb00f2 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -874,9 +874,18 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, DP_AUX_CH_CTL_TIME_OUT_ERROR | DP_AUX_CH_CTL_RECEIVE_ERROR); - if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR | - DP_AUX_CH_CTL_RECEIVE_ERROR)) + if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) continue; + + /* DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2 + * 400us delay required for errors and timeouts + * Timeout errors from the HW already meet this + * requirement so skip to next iteration + */ + if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { + usleep_range(400, 500); + continue; + } if (status & DP_AUX_CH_CTL_DONE) break; } From 747552b947e1013276851b6a19a9867a94ff1c4f Mon Sep 17 00:00:00 2001 From: Todd Previte Date: Wed, 15 Apr 2015 08:38:47 -0700 Subject: [PATCH 0189/3798] drm: Fix the 'native defer' message in drm_dp_i2c_do_msg() The debug message is missing a newline at the end and it makes the logs hard to read when a device defers a lot. Simple 2-character fix adds the newline at the end. Signed-off-by: Todd Previte Cc: dri-devel@lists.freedesktop.org Reviewed-by: Paulo Zanoni Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_dp_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 71dcbc64ae98b8..575172ed6c3282 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -466,7 +466,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) return -EREMOTEIO; case DP_AUX_NATIVE_REPLY_DEFER: - DRM_DEBUG_KMS("native defer"); + DRM_DEBUG_KMS("native defer\n"); /* * We could check for I2C bit rate capabilities and if * available adjust this interval. We could also be From f4f71c7dfc5c989f53a1861f3ac42e24018fad4c Mon Sep 17 00:00:00 2001 From: Deepak S Date: Sat, 28 Mar 2015 15:23:35 +0530 Subject: [PATCH 0190/3798] drm/i915: Re-adjusting rc6 promotional timer for chv After feedback from the hardware team we are changing the RC6 promotional timer to increase the power saving without changing performance. Signed-off-by: Deepak S Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a80bfd565ce4eb..a7516ed24eee5f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5046,8 +5046,8 @@ static void cherryview_enable_rps(struct drm_device *dev) I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); - /* TO threshold set to 1750 us ( 0x557 * 1.28 us) */ - I915_WRITE(GEN6_RC6_THRESHOLD, 0x557); + /* TO threshold set to 500 us ( 0x186 * 1.28 us) */ + I915_WRITE(GEN6_RC6_THRESHOLD, 0x186); /* allows RC6 residency counter to work */ I915_WRITE(VLV_COUNTER_CONTROL, From 097f8261ddda4b1896dd335dec95dedeecfeaa1b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 16 Apr 2015 21:11:08 +0800 Subject: [PATCH 0191/3798] drm/i915/audio: remove duplicated include from intel_audio.c Remove duplicated include. Signed-off-by: Wei Yongjun Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_audio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 0d5b1cea47156c..f72e93a45e11c5 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -28,7 +28,6 @@ #include #include -#include "intel_drv.h" #include "i915_drv.h" /** From 63de9f92cc35212c4fbf0caf6cb9d8cabe488214 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Fri, 3 Apr 2015 15:47:31 +0300 Subject: [PATCH 0192/3798] iio: sx9500: rename GPIO interrupt pin Signed-off-by: Vlad Dogaru Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9500.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index d2c52f9da937f2..c3d5316e696b6b 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -30,7 +30,8 @@ #define SX9500_DRIVER_NAME "sx9500" #define SX9500_IRQ_NAME "sx9500_event" -#define SX9500_GPIO_NAME "sx9500_gpio" + +#define SX9500_GPIO_NAME "interrupt" /* Register definitions. */ #define SX9500_REG_IRQ_SRC 0x00 From a40c0ac108f4802a47c27c734569c1c371bded5f Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Fri, 3 Apr 2015 15:47:34 +0300 Subject: [PATCH 0193/3798] iio: sx9500: fix formatting Signed-off-by: Vlad Dogaru Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index c3d5316e696b6b..c6cb7f9270183d 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -775,7 +775,7 @@ MODULE_DEVICE_TABLE(acpi, sx9500_acpi_match); static const struct i2c_device_id sx9500_id[] = { {"sx9500", 0}, - {} + { }, }; MODULE_DEVICE_TABLE(i2c, sx9500_id); From 2f2c96338afc9f90aa5a0fca04ece1a5c389ee31 Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Fri, 17 Apr 2015 22:15:10 -0700 Subject: [PATCH 0194/3798] iio: ltr501: Add regmap support. Added regmap support. It will be useful to handle bitwise updates to als & ps control registers. Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Jonathan Cameron --- drivers/iio/light/ltr501.c | 129 ++++++++++++++++++++++++------------- 1 file changed, 86 insertions(+), 43 deletions(-) diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index f208c9871107b1..e2f73547fdc52c 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,7 @@ #define LTR501_ALS_DATA0 0x8a /* 16-bit, little endian */ #define LTR501_ALS_PS_STATUS 0x8c #define LTR501_PS_DATA 0x8d /* 16-bit, little endian */ +#define LTR501_MAX_REG 0x9f #define LTR501_ALS_CONTR_SW_RESET BIT(2) #define LTR501_CONTR_PS_GAIN_MASK (BIT(3) | BIT(2)) @@ -45,23 +47,25 @@ #define LTR501_PS_DATA_MASK 0x7ff +#define LTR501_REGMAP_NAME "ltr501_regmap" + struct ltr501_data { struct i2c_client *client; struct mutex lock_als, lock_ps; u8 als_contr, ps_contr; + struct regmap *regmap; }; static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) { int tries = 100; - int ret; + int ret, status; while (tries--) { - ret = i2c_smbus_read_byte_data(data->client, - LTR501_ALS_PS_STATUS); + ret = regmap_read(data->regmap, LTR501_ALS_PS_STATUS, &status); if (ret < 0) return ret; - if ((ret & drdy_mask) == drdy_mask) + if ((status & drdy_mask) == drdy_mask) return 0; msleep(25); } @@ -72,21 +76,30 @@ static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2]) { - int ret = ltr501_drdy(data, LTR501_STATUS_ALS_RDY); + int ret; + + ret = ltr501_drdy(data, LTR501_STATUS_ALS_RDY); if (ret < 0) return ret; /* always read both ALS channels in given order */ - return i2c_smbus_read_i2c_block_data(data->client, - LTR501_ALS_DATA1, - 2 * sizeof(__le16), (u8 *)buf); + return regmap_bulk_read(data->regmap, LTR501_ALS_DATA1, + buf, 2 * sizeof(__le16)); } static int ltr501_read_ps(struct ltr501_data *data) { - int ret = ltr501_drdy(data, LTR501_STATUS_PS_RDY); + int ret, status; + + ret = ltr501_drdy(data, LTR501_STATUS_PS_RDY); + if (ret < 0) + return ret; + + ret = regmap_bulk_read(data->regmap, LTR501_PS_DATA, + &status, 2); if (ret < 0) return ret; - return i2c_smbus_read_word_data(data->client, LTR501_PS_DATA); + + return status; } #define LTR501_INTENSITY_CHANNEL(_idx, _addr, _mod, _shared) { \ @@ -170,11 +183,10 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, *val = 0; *val2 = 5000; return IIO_VAL_INT_PLUS_MICRO; - } else { - *val = 1; - *val2 = 0; - return IIO_VAL_INT; } + *val = 1; + *val2 = 0; + return IIO_VAL_INT; case IIO_PROXIMITY: i = (data->ps_contr & LTR501_CONTR_PS_GAIN_MASK) >> LTR501_CONTR_PS_GAIN_SHIFT; @@ -219,18 +231,18 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, data->als_contr &= ~LTR501_CONTR_ALS_GAIN_MASK; else return -EINVAL; - return i2c_smbus_write_byte_data(data->client, - LTR501_ALS_CONTR, - data->als_contr); + + return regmap_write(data->regmap, LTR501_ALS_CONTR, + data->als_contr); case IIO_PROXIMITY: i = ltr501_get_ps_gain_index(val, val2); if (i < 0) return -EINVAL; data->ps_contr &= ~LTR501_CONTR_PS_GAIN_MASK; data->ps_contr |= i << LTR501_CONTR_PS_GAIN_SHIFT; - return i2c_smbus_write_byte_data(data->client, - LTR501_PS_CONTR, - data->ps_contr); + + return regmap_write(data->regmap, LTR501_PS_CONTR, + data->ps_contr); default: return -EINVAL; } @@ -258,13 +270,15 @@ static const struct iio_info ltr501_info = { .driver_module = THIS_MODULE, }; -static int ltr501_write_contr(struct i2c_client *client, u8 als_val, u8 ps_val) +static int ltr501_write_contr(struct ltr501_data *data, u8 als_val, u8 ps_val) { - int ret = i2c_smbus_write_byte_data(client, LTR501_ALS_CONTR, als_val); + int ret; + + ret = regmap_write(data->regmap, LTR501_ALS_CONTR, als_val); if (ret < 0) return ret; - return i2c_smbus_write_byte_data(client, LTR501_PS_CONTR, ps_val); + return regmap_write(data->regmap, LTR501_PS_CONTR, ps_val); } static irqreturn_t ltr501_trigger_handler(int irq, void *p) @@ -276,7 +290,7 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) __le16 als_buf[2]; u8 mask = 0; int j = 0; - int ret; + int ret, psdata; memset(buf, 0, sizeof(buf)); @@ -292,10 +306,8 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) goto done; if (mask & LTR501_STATUS_ALS_RDY) { - ret = i2c_smbus_read_i2c_block_data(data->client, - LTR501_ALS_DATA1, - sizeof(als_buf), - (u8 *)als_buf); + ret = regmap_bulk_read(data->regmap, LTR501_ALS_DATA1, + (u8 *)als_buf, sizeof(als_buf)); if (ret < 0) return ret; if (test_bit(0, indio_dev->active_scan_mask)) @@ -305,10 +317,11 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) } if (mask & LTR501_STATUS_PS_RDY) { - ret = i2c_smbus_read_word_data(data->client, LTR501_PS_DATA); + ret = regmap_bulk_read(data->regmap, LTR501_PS_DATA, + &psdata, 2); if (ret < 0) goto done; - buf[j++] = ret & LTR501_PS_DATA_MASK; + buf[j++] = psdata & LTR501_PS_DATA_MASK; } iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); @@ -321,26 +334,48 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) static int ltr501_init(struct ltr501_data *data) { - int ret; + int ret, status; - ret = i2c_smbus_read_byte_data(data->client, LTR501_ALS_CONTR); + ret = regmap_read(data->regmap, LTR501_ALS_CONTR, &status); if (ret < 0) return ret; - data->als_contr = ret | LTR501_CONTR_ACTIVE; - ret = i2c_smbus_read_byte_data(data->client, LTR501_PS_CONTR); + data->als_contr = status | LTR501_CONTR_ACTIVE; + + ret = regmap_read(data->regmap, LTR501_PS_CONTR, &status); if (ret < 0) return ret; - data->ps_contr = ret | LTR501_CONTR_ACTIVE; - return ltr501_write_contr(data->client, data->als_contr, - data->ps_contr); + data->ps_contr = status | LTR501_CONTR_ACTIVE; + + return ltr501_write_contr(data, data->als_contr, data->ps_contr); } +static bool ltr501_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case LTR501_ALS_DATA1: + case LTR501_ALS_DATA0: + case LTR501_ALS_PS_STATUS: + case LTR501_PS_DATA: + return true; + default: + return false; + } +} + +static struct regmap_config ltr501_regmap_config = { + .name = LTR501_REGMAP_NAME, + .reg_bits = 8, + .val_bits = 8, + .max_register = LTR501_MAX_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = ltr501_is_volatile_reg, +}; + static int ltr501_powerdown(struct ltr501_data *data) { - return ltr501_write_contr(data->client, - data->als_contr & ~LTR501_CONTR_ACTIVE, + return ltr501_write_contr(data, data->als_contr & ~LTR501_CONTR_ACTIVE, data->ps_contr & ~LTR501_CONTR_ACTIVE); } @@ -349,22 +384,30 @@ static int ltr501_probe(struct i2c_client *client, { struct ltr501_data *data; struct iio_dev *indio_dev; - int ret; + struct regmap *regmap; + int ret, partid; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; + regmap = devm_regmap_init_i2c(client, <r501_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Regmap initialization failed.\n"); + return PTR_ERR(regmap); + } + data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; + data->regmap = regmap; mutex_init(&data->lock_als); mutex_init(&data->lock_ps); - ret = i2c_smbus_read_byte_data(data->client, LTR501_PART_ID); + ret = regmap_read(data->regmap, LTR501_PART_ID, &partid); if (ret < 0) return ret; - if ((ret >> 4) != 0x8) + if ((partid >> 4) != 0x8) return -ENODEV; indio_dev->dev.parent = &client->dev; @@ -420,7 +463,7 @@ static int ltr501_resume(struct device *dev) struct ltr501_data *data = iio_priv(i2c_get_clientdata( to_i2c_client(dev))); - return ltr501_write_contr(data->client, data->als_contr, + return ltr501_write_contr(data, data->als_contr, data->ps_contr); } #endif From 6069f47f08ea670e28ae709c645e308e98636d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vianney=20le=20Cl=C3=A9ment=20de=20Saint-Marcq?= Date: Fri, 17 Apr 2015 16:05:35 +0200 Subject: [PATCH 0195/3798] iio: mlx90614: Fix duplicate const warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a typo triggering a duplicate const warning on some compilers. Signed-off-by: Vianney le Clément de Saint-Marcq Cc: Arnout Vandecappelle (Essensium/Mind) Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/mlx90614.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c index 06b7b967798233..b2d3b56f1260ad 100644 --- a/drivers/iio/temperature/mlx90614.c +++ b/drivers/iio/temperature/mlx90614.c @@ -263,7 +263,7 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev, } static int mlx90614_write_raw_get_fmt(struct iio_dev *indio_dev, - const struct iio_chan_spec const *channel, + struct iio_chan_spec const *channel, long mask) { switch (mask) { From 59bd0427c01cf0172055a1b99457bee6fd75d865 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Sun, 12 Apr 2015 20:09:19 +0300 Subject: [PATCH 0196/3798] iio: sx9500: optimize power usage In the interest of lowering power usage, we only activate the proximity channels and interrupts that we are currently using. For raw reads, we activate the corresponding channel and the data ready interrupt and wait for the interrupt to trigger. If no interrupt is available, we wait for the documented scan period, as specified in the datasheet. The following types of usage patterns may overlap: * raw proximity reads (need a single data ready interrupt) * trigger usage (needs data ready interrupts as long as active) * proximity events (need near/far interrupts) * triggered buffer reads (don't need any interrupts, but are usually coupled with our own trigger. To mitigate all possible patterns, we implement usage counting for all the resources used: data ready interrupts, near/far interrupts and individual channels. The device enters sleep mode as documented in the data sheet when its buffer, trigger and events are disabled, and no raw reads are currently running. Because of this new usage pattern, it is important that we give the device a chance to perform an initial compensation for all its channels at probe time. Signed-off-by: Vlad Dogaru Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9500.c | 360 ++++++++++++++++++++++++++++----- 1 file changed, 306 insertions(+), 54 deletions(-) diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index c6cb7f9270183d..8db9d5bfecc3c6 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -75,6 +76,7 @@ #define SX9500_CONVDONE_IRQ BIT(3) #define SX9500_PROXSTAT_SHIFT 4 +#define SX9500_COMPSTAT_MASK GENMASK(3, 0) #define SX9500_NUM_CHANNELS 4 @@ -93,6 +95,9 @@ struct sx9500_data { u16 *buffer; /* Remember enabled channels and sample rate during suspend. */ unsigned int suspend_ctrl0; + struct completion completion; + int data_rdy_users, close_far_users; + int channel_users[SX9500_NUM_CHANNELS]; }; static const struct iio_event_spec sx9500_events[] = { @@ -143,6 +148,10 @@ static const struct { {2, 500000}, }; +static const unsigned int sx9500_scan_period_table[] = { + 30, 60, 90, 120, 150, 200, 300, 400, +}; + static const struct regmap_range sx9500_writable_reg_ranges[] = { regmap_reg_range(SX9500_REG_IRQ_MSK, SX9500_REG_IRQ_MSK), regmap_reg_range(SX9500_REG_PROX_CTRL0, SX9500_REG_PROX_CTRL8), @@ -195,7 +204,67 @@ static const struct regmap_config sx9500_regmap_config = { .volatile_table = &sx9500_volatile_regs, }; -static int sx9500_read_proximity(struct sx9500_data *data, +static int sx9500_inc_users(struct sx9500_data *data, int *counter, + unsigned int reg, unsigned int bitmask) +{ + (*counter)++; + if (*counter != 1) + /* Bit is already active, nothing to do. */ + return 0; + + return regmap_update_bits(data->regmap, reg, bitmask, bitmask); +} + +static int sx9500_dec_users(struct sx9500_data *data, int *counter, + unsigned int reg, unsigned int bitmask) +{ + (*counter)--; + if (*counter != 0) + /* There are more users, do not deactivate. */ + return 0; + + return regmap_update_bits(data->regmap, reg, bitmask, 0); +} + +static int sx9500_inc_chan_users(struct sx9500_data *data, int chan) +{ + return sx9500_inc_users(data, &data->channel_users[chan], + SX9500_REG_PROX_CTRL0, BIT(chan)); +} + +static int sx9500_dec_chan_users(struct sx9500_data *data, int chan) +{ + return sx9500_dec_users(data, &data->channel_users[chan], + SX9500_REG_PROX_CTRL0, BIT(chan)); +} + +static int sx9500_inc_data_rdy_users(struct sx9500_data *data) +{ + return sx9500_inc_users(data, &data->data_rdy_users, + SX9500_REG_IRQ_MSK, SX9500_CONVDONE_IRQ); +} + +static int sx9500_dec_data_rdy_users(struct sx9500_data *data) +{ + return sx9500_dec_users(data, &data->data_rdy_users, + SX9500_REG_IRQ_MSK, SX9500_CONVDONE_IRQ); +} + +static int sx9500_inc_close_far_users(struct sx9500_data *data) +{ + return sx9500_inc_users(data, &data->close_far_users, + SX9500_REG_IRQ_MSK, + SX9500_CLOSE_IRQ | SX9500_FAR_IRQ); +} + +static int sx9500_dec_close_far_users(struct sx9500_data *data) +{ + return sx9500_dec_users(data, &data->close_far_users, + SX9500_REG_IRQ_MSK, + SX9500_CLOSE_IRQ | SX9500_FAR_IRQ); +} + +static int sx9500_read_prox_data(struct sx9500_data *data, const struct iio_chan_spec *chan, int *val) { @@ -215,6 +284,79 @@ static int sx9500_read_proximity(struct sx9500_data *data, return IIO_VAL_INT; } +/* + * If we have no interrupt support, we have to wait for a scan period + * after enabling a channel to get a result. + */ +static int sx9500_wait_for_sample(struct sx9500_data *data) +{ + int ret; + unsigned int val; + + ret = regmap_read(data->regmap, SX9500_REG_PROX_CTRL0, &val); + if (ret < 0) + return ret; + + val = (val & SX9500_SCAN_PERIOD_MASK) >> SX9500_SCAN_PERIOD_SHIFT; + + msleep(sx9500_scan_period_table[val]); + + return 0; +} + +static int sx9500_read_proximity(struct sx9500_data *data, + const struct iio_chan_spec *chan, + int *val) +{ + int ret; + + mutex_lock(&data->mutex); + + ret = sx9500_inc_chan_users(data, chan->channel); + if (ret < 0) + goto out; + + ret = sx9500_inc_data_rdy_users(data); + if (ret < 0) + goto out_dec_chan; + + mutex_unlock(&data->mutex); + + if (data->client->irq > 0) + ret = wait_for_completion_interruptible(&data->completion); + else + ret = sx9500_wait_for_sample(data); + + if (ret < 0) + return ret; + + mutex_lock(&data->mutex); + + ret = sx9500_read_prox_data(data, chan, val); + if (ret < 0) + goto out; + + ret = sx9500_dec_chan_users(data, chan->channel); + if (ret < 0) + goto out; + + ret = sx9500_dec_data_rdy_users(data); + if (ret < 0) + goto out; + + ret = IIO_VAL_INT; + + goto out; + +out_dec_chan: + sx9500_dec_chan_users(data, chan->channel); +out: + mutex_unlock(&data->mutex); + reinit_completion(&data->completion); + + return ret; +} + static int sx9500_read_samp_freq(struct sx9500_data *data, int *val, int *val2) { @@ -240,7 +382,6 @@ static int sx9500_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct sx9500_data *data = iio_priv(indio_dev); - int ret; switch (chan->type) { case IIO_PROXIMITY: @@ -248,10 +389,7 @@ static int sx9500_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_RAW: if (iio_buffer_enabled(indio_dev)) return -EBUSY; - mutex_lock(&data->mutex); - ret = sx9500_read_proximity(data, chan, val); - mutex_unlock(&data->mutex); - return ret; + return sx9500_read_proximity(data, chan, val); case IIO_CHAN_INFO_SAMP_FREQ: return sx9500_read_samp_freq(data, val, val2); default: @@ -322,28 +460,16 @@ static irqreturn_t sx9500_irq_handler(int irq, void *private) return IRQ_WAKE_THREAD; } -static irqreturn_t sx9500_irq_thread_handler(int irq, void *private) +static void sx9500_push_events(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = private; - struct sx9500_data *data = iio_priv(indio_dev); int ret; unsigned int val, chan; - - mutex_lock(&data->mutex); - - ret = regmap_read(data->regmap, SX9500_REG_IRQ_SRC, &val); - if (ret < 0) { - dev_err(&data->client->dev, "i2c transfer error in irq\n"); - goto out; - } - - if (!(val & (SX9500_CLOSE_IRQ | SX9500_FAR_IRQ))) - goto out; + struct sx9500_data *data = iio_priv(indio_dev); ret = regmap_read(data->regmap, SX9500_REG_STAT, &val); if (ret < 0) { dev_err(&data->client->dev, "i2c transfer error in irq\n"); - goto out; + return; } val >>= SX9500_PROXSTAT_SHIFT; @@ -358,15 +484,34 @@ static irqreturn_t sx9500_irq_thread_handler(int irq, void *private) /* No change on this channel. */ continue; - dir = new_prox ? IIO_EV_DIR_FALLING : - IIO_EV_DIR_RISING; - ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, - chan, - IIO_EV_TYPE_THRESH, - dir); + dir = new_prox ? IIO_EV_DIR_FALLING : IIO_EV_DIR_RISING; + ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, chan, + IIO_EV_TYPE_THRESH, dir); iio_push_event(indio_dev, ev, iio_get_time_ns()); data->prox_stat[chan] = new_prox; } +} + +static irqreturn_t sx9500_irq_thread_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct sx9500_data *data = iio_priv(indio_dev); + int ret; + unsigned int val; + + mutex_lock(&data->mutex); + + ret = regmap_read(data->regmap, SX9500_REG_IRQ_SRC, &val); + if (ret < 0) { + dev_err(&data->client->dev, "i2c transfer error in irq\n"); + goto out; + } + + if (val & (SX9500_CLOSE_IRQ | SX9500_FAR_IRQ)) + sx9500_push_events(indio_dev); + + if (val & SX9500_CONVDONE_IRQ) + complete_all(&data->completion); out: mutex_unlock(&data->mutex); @@ -395,9 +540,7 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev, int state) { struct sx9500_data *data = iio_priv(indio_dev); - int ret, i; - bool any_active = false; - unsigned int irqmask; + int ret; if (chan->type != IIO_PROXIMITY || type != IIO_EV_TYPE_THRESH || dir != IIO_EV_DIR_EITHER) @@ -405,24 +548,32 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev, mutex_lock(&data->mutex); - data->event_enabled[chan->channel] = state; + if (state == 1) { + ret = sx9500_inc_chan_users(data, chan->channel); + if (ret < 0) + goto out_unlock; + ret = sx9500_inc_close_far_users(data); + if (ret < 0) + goto out_undo_chan; + } else { + ret = sx9500_dec_chan_users(data, chan->channel); + if (ret < 0) + goto out_unlock; + ret = sx9500_dec_close_far_users(data); + if (ret < 0) + goto out_undo_chan; + } - for (i = 0; i < SX9500_NUM_CHANNELS; i++) - if (data->event_enabled[i]) { - any_active = true; - break; - } + data->event_enabled[chan->channel] = state; + goto out_unlock; - irqmask = SX9500_CLOSE_IRQ | SX9500_FAR_IRQ; - if (any_active) - ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, - irqmask, irqmask); +out_undo_chan: + if (state == 1) + sx9500_dec_chan_users(data, chan->channel); else - ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, - irqmask, 0); - + sx9500_inc_chan_users(data, chan->channel); +out_unlock: mutex_unlock(&data->mutex); - return ret; } @@ -473,12 +624,16 @@ static int sx9500_set_trigger_state(struct iio_trigger *trig, mutex_lock(&data->mutex); - ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, - SX9500_CONVDONE_IRQ, - state ? SX9500_CONVDONE_IRQ : 0); - if (ret == 0) - data->trigger_enabled = state; + if (state) + ret = sx9500_inc_data_rdy_users(data); + else + ret = sx9500_dec_data_rdy_users(data); + if (ret < 0) + goto out; + + data->trigger_enabled = state; +out: mutex_unlock(&data->mutex); return ret; @@ -500,7 +655,7 @@ static irqreturn_t sx9500_trigger_handler(int irq, void *private) for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) { - ret = sx9500_read_proximity(data, &indio_dev->channels[bit], + ret = sx9500_read_prox_data(data, &indio_dev->channels[bit], &val); if (ret < 0) goto out; @@ -519,6 +674,62 @@ static irqreturn_t sx9500_trigger_handler(int irq, void *private) return IRQ_HANDLED; } +static int sx9500_buffer_preenable(struct iio_dev *indio_dev) +{ + struct sx9500_data *data = iio_priv(indio_dev); + int ret, i; + + mutex_lock(&data->mutex); + + for (i = 0; i < SX9500_NUM_CHANNELS; i++) + if (test_bit(i, indio_dev->active_scan_mask)) { + ret = sx9500_inc_chan_users(data, i); + if (ret) + break; + } + + if (ret) + for (i = i - 1; i >= 0; i--) + if (test_bit(i, indio_dev->active_scan_mask)) + sx9500_dec_chan_users(data, i); + + mutex_unlock(&data->mutex); + + return ret; +} + +static int sx9500_buffer_predisable(struct iio_dev *indio_dev) +{ + struct sx9500_data *data = iio_priv(indio_dev); + int ret, i; + + iio_triggered_buffer_predisable(indio_dev); + + mutex_lock(&data->mutex); + + for (i = 0; i < SX9500_NUM_CHANNELS; i++) + if (test_bit(i, indio_dev->active_scan_mask)) { + ret = sx9500_dec_chan_users(data, i); + if (ret) + break; + } + + if (ret) + for (i = i - 1; i >= 0; i--) + if (test_bit(i, indio_dev->active_scan_mask)) + sx9500_inc_chan_users(data, i); + + mutex_unlock(&data->mutex); + + return ret; +} + +static const struct iio_buffer_setup_ops sx9500_buffer_setup_ops = { + .preenable = sx9500_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = sx9500_buffer_predisable, +}; + struct sx9500_reg_default { u8 reg; u8 def; @@ -574,11 +785,44 @@ static const struct sx9500_reg_default sx9500_default_regs[] = { }, { .reg = SX9500_REG_PROX_CTRL0, - /* Scan period: 30ms, all sensors enabled. */ - .def = 0x0f, + /* Scan period: 30ms, all sensors disabled. */ + .def = 0x00, }, }; +/* Activate all channels and perform an initial compensation. */ +static int sx9500_init_compensation(struct iio_dev *indio_dev) +{ + struct sx9500_data *data = iio_priv(indio_dev); + int i, ret; + unsigned int val; + + ret = regmap_update_bits(data->regmap, SX9500_REG_PROX_CTRL0, + GENMASK(SX9500_NUM_CHANNELS, 0), + GENMASK(SX9500_NUM_CHANNELS, 0)); + if (ret < 0) + return ret; + + for (i = 10; i >= 0; i--) { + usleep_range(10000, 20000); + ret = regmap_read(data->regmap, SX9500_REG_STAT, &val); + if (ret < 0) + goto out; + if (!(val & SX9500_COMPSTAT_MASK)) + break; + } + + if (i < 0) { + dev_err(&data->client->dev, "initial compensation timed out"); + ret = -ETIMEDOUT; + } + +out: + regmap_update_bits(data->regmap, SX9500_REG_PROX_CTRL0, + GENMASK(SX9500_NUM_CHANNELS, 0), 0); + return ret; +} + static int sx9500_init_device(struct iio_dev *indio_dev) { struct sx9500_data *data = iio_priv(indio_dev); @@ -606,6 +850,10 @@ static int sx9500_init_device(struct iio_dev *indio_dev) return ret; } + ret = sx9500_init_compensation(indio_dev); + if (ret < 0) + return ret; + return 0; } @@ -649,6 +897,7 @@ static int sx9500_probe(struct i2c_client *client, data = iio_priv(indio_dev); data->client = client; mutex_init(&data->mutex); + init_completion(&data->completion); data->trigger_enabled = false; data->regmap = devm_regmap_init_i2c(client, &sx9500_regmap_config); @@ -668,7 +917,9 @@ static int sx9500_probe(struct i2c_client *client, if (client->irq <= 0) client->irq = sx9500_gpio_probe(client, data); - if (client->irq > 0) { + if (client->irq <= 0) + dev_warn(&client->dev, "no valid irq found\n"); + else { ret = devm_request_threaded_irq(&client->dev, client->irq, sx9500_irq_handler, sx9500_irq_thread_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, @@ -691,7 +942,8 @@ static int sx9500_probe(struct i2c_client *client, } ret = iio_triggered_buffer_setup(indio_dev, NULL, - sx9500_trigger_handler, NULL); + sx9500_trigger_handler, + &sx9500_buffer_setup_ops); if (ret < 0) goto out_trigger_unregister; From 821ace2929612aa1ecf49feba123e5c7130d1970 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Sun, 12 Apr 2015 20:09:20 +0300 Subject: [PATCH 0197/3798] iio: sx9500: refactor GPIO interrupt code Signed-off-by: Vlad Dogaru Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9500.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 8db9d5bfecc3c6..1b3d894e8c69a6 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -32,7 +32,7 @@ #define SX9500_DRIVER_NAME "sx9500" #define SX9500_IRQ_NAME "sx9500_event" -#define SX9500_GPIO_NAME "interrupt" +#define SX9500_GPIO_INT "interrupt" /* Register definitions. */ #define SX9500_REG_IRQ_SRC 0x00 @@ -857,30 +857,24 @@ static int sx9500_init_device(struct iio_dev *indio_dev) return 0; } -static int sx9500_gpio_probe(struct i2c_client *client, - struct sx9500_data *data) +static void sx9500_gpio_probe(struct i2c_client *client, + struct sx9500_data *data) { struct device *dev; struct gpio_desc *gpio; - int ret; if (!client) - return -EINVAL; + return; dev = &client->dev; - /* data ready gpio interrupt pin */ - gpio = devm_gpiod_get_index(dev, SX9500_GPIO_NAME, 0, GPIOD_IN); - if (IS_ERR(gpio)) { - dev_err(dev, "acpi gpio get index failed\n"); - return PTR_ERR(gpio); + if (client->irq <= 0) { + gpio = devm_gpiod_get_index(dev, SX9500_GPIO_INT, 0, GPIOD_IN); + if (IS_ERR(gpio)) + dev_err(dev, "gpio get irq failed\n"); + else + client->irq = gpiod_to_irq(gpio); } - - ret = gpiod_to_irq(gpio); - - dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); - - return ret; } static int sx9500_probe(struct i2c_client *client, @@ -914,8 +908,7 @@ static int sx9500_probe(struct i2c_client *client, indio_dev->modes = INDIO_DIRECT_MODE; i2c_set_clientdata(client, indio_dev); - if (client->irq <= 0) - client->irq = sx9500_gpio_probe(client, data); + sx9500_gpio_probe(client, data); if (client->irq <= 0) dev_warn(&client->dev, "no valid irq found\n"); From 45fd5f8e10d3b5bdff577b82db4b9dd78d4b60a3 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Sun, 12 Apr 2015 20:09:21 +0300 Subject: [PATCH 0198/3798] iio: sx9500: add GPIO reset pin If a GPIO reset pin is listed in ACPI or Device Tree, use it to reset the device on initialization. Signed-off-by: Vlad Dogaru Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9500.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 1b3d894e8c69a6..f1e9d734b6b6ba 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -33,6 +33,7 @@ #define SX9500_IRQ_NAME "sx9500_event" #define SX9500_GPIO_INT "interrupt" +#define SX9500_GPIO_RESET "reset" /* Register definitions. */ #define SX9500_REG_IRQ_SRC 0x00 @@ -85,6 +86,7 @@ struct sx9500_data { struct i2c_client *client; struct iio_trigger *trig; struct regmap *regmap; + struct gpio_desc *gpiod_rst; /* * Last reading of the proximity status for each channel. We * only send an event to user space when this changes. @@ -829,6 +831,13 @@ static int sx9500_init_device(struct iio_dev *indio_dev) int ret, i; unsigned int val; + if (data->gpiod_rst) { + gpiod_set_value_cansleep(data->gpiod_rst, 0); + usleep_range(1000, 2000); + gpiod_set_value_cansleep(data->gpiod_rst, 1); + usleep_range(1000, 2000); + } + ret = regmap_write(data->regmap, SX9500_REG_IRQ_MSK, 0); if (ret < 0) return ret; @@ -875,6 +884,13 @@ static void sx9500_gpio_probe(struct i2c_client *client, else client->irq = gpiod_to_irq(gpio); } + + data->gpiod_rst = devm_gpiod_get_index(dev, SX9500_GPIO_RESET, + 0, GPIOD_OUT_HIGH); + if (IS_ERR(data->gpiod_rst)) { + dev_warn(dev, "gpio get reset pin failed\n"); + data->gpiod_rst = NULL; + } } static int sx9500_probe(struct i2c_client *client, @@ -898,8 +914,6 @@ static int sx9500_probe(struct i2c_client *client, if (IS_ERR(data->regmap)) return PTR_ERR(data->regmap); - sx9500_init_device(indio_dev); - indio_dev->dev.parent = &client->dev; indio_dev->name = SX9500_DRIVER_NAME; indio_dev->channels = sx9500_channels; @@ -910,6 +924,10 @@ static int sx9500_probe(struct i2c_client *client, sx9500_gpio_probe(client, data); + ret = sx9500_init_device(indio_dev); + if (ret < 0) + return ret; + if (client->irq <= 0) dev_warn(&client->dev, "no valid irq found\n"); else { From 6b57573bd0cd92c54a44ade46c6362b732d55a6c Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Wed, 15 Apr 2015 22:39:36 +0200 Subject: [PATCH 0199/3798] iio:tsl4531: Fix leftover TCS3472_ prefix in tsl4531 driver just cleanup, no functional change Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/iio/light/tsl4531.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/iio/light/tsl4531.c b/drivers/iio/light/tsl4531.c index 0763b863257387..63c26e2d5d9722 100644 --- a/drivers/iio/light/tsl4531.c +++ b/drivers/iio/light/tsl4531.c @@ -24,12 +24,12 @@ #define TSL4531_DRV_NAME "tsl4531" -#define TCS3472_COMMAND BIT(7) +#define TSL4531_COMMAND BIT(7) -#define TSL4531_CONTROL (TCS3472_COMMAND | 0x00) -#define TSL4531_CONFIG (TCS3472_COMMAND | 0x01) -#define TSL4531_DATA (TCS3472_COMMAND | 0x04) -#define TSL4531_ID (TCS3472_COMMAND | 0x0a) +#define TSL4531_CONTROL (TSL4531_COMMAND | 0x00) +#define TSL4531_CONFIG (TSL4531_COMMAND | 0x01) +#define TSL4531_DATA (TSL4531_COMMAND | 0x04) +#define TSL4531_ID (TSL4531_COMMAND | 0x0a) /* operating modes in control register */ #define TSL4531_MODE_POWERDOWN 0x00 From 6fa273c1aaa0ab0c22ac4b52879e6bfeea516369 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Wed, 15 Apr 2015 22:39:37 +0200 Subject: [PATCH 0200/3798] iio:tsl2563: Use tsl2563_ prefix for driver's functions just cleanup, no functional change Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/iio/light/tsl2563.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c index 94daa9fc12478b..12731d6b89ecdf 100644 --- a/drivers/iio/light/tsl2563.c +++ b/drivers/iio/light/tsl2563.c @@ -240,7 +240,7 @@ static int tsl2563_read_id(struct tsl2563_chip *chip, u8 *id) * convert between normalized values and HW values obtained using given * timing and gain settings. */ -static int adc_shiftbits(u8 timing) +static int tsl2563_adc_shiftbits(u8 timing) { int shift = 0; @@ -263,9 +263,9 @@ static int adc_shiftbits(u8 timing) } /* Convert a HW ADC value to normalized scale. */ -static u32 normalize_adc(u16 adc, u8 timing) +static u32 tsl2563_normalize_adc(u16 adc, u8 timing) { - return adc << adc_shiftbits(timing); + return adc << tsl2563_adc_shiftbits(timing); } static void tsl2563_wait_adc(struct tsl2563_chip *chip) @@ -350,8 +350,8 @@ static int tsl2563_get_adc(struct tsl2563_chip *chip) retry = tsl2563_adjust_gainlevel(chip, adc0); } - chip->data0 = normalize_adc(adc0, chip->gainlevel->gaintime); - chip->data1 = normalize_adc(adc1, chip->gainlevel->gaintime); + chip->data0 = tsl2563_normalize_adc(adc0, chip->gainlevel->gaintime); + chip->data1 = tsl2563_normalize_adc(adc1, chip->gainlevel->gaintime); if (!chip->int_enabled) schedule_delayed_work(&chip->poweroff_work, 5 * HZ); @@ -361,13 +361,13 @@ static int tsl2563_get_adc(struct tsl2563_chip *chip) return ret; } -static inline int calib_to_sysfs(u32 calib) +static inline int tsl2563_calib_to_sysfs(u32 calib) { return (int) (((calib * CALIB_BASE_SYSFS) + CALIB_FRAC_HALF) >> CALIB_FRAC_BITS); } -static inline u32 calib_from_sysfs(int value) +static inline u32 tsl2563_calib_from_sysfs(int value) { return (((u32) value) << CALIB_FRAC_BITS) / CALIB_BASE_SYSFS; } @@ -426,7 +426,7 @@ static const struct tsl2563_lux_coeff lux_table[] = { }; /* Convert normalized, scaled ADC values to lux. */ -static unsigned int adc_to_lux(u32 adc0, u32 adc1) +static unsigned int tsl2563_adc_to_lux(u32 adc0, u32 adc1) { const struct tsl2563_lux_coeff *lp = lux_table; unsigned long ratio, lux, ch0 = adc0, ch1 = adc1; @@ -442,7 +442,7 @@ static unsigned int adc_to_lux(u32 adc0, u32 adc1) } /* Apply calibration coefficient to ADC count. */ -static u32 calib_adc(u32 adc, u32 calib) +static u32 tsl2563_calib_adc(u32 adc, u32 calib) { unsigned long scaled = adc; @@ -463,9 +463,9 @@ static int tsl2563_write_raw(struct iio_dev *indio_dev, if (mask != IIO_CHAN_INFO_CALIBSCALE) return -EINVAL; if (chan->channel2 == IIO_MOD_LIGHT_BOTH) - chip->calib0 = calib_from_sysfs(val); + chip->calib0 = tsl2563_calib_from_sysfs(val); else if (chan->channel2 == IIO_MOD_LIGHT_IR) - chip->calib1 = calib_from_sysfs(val); + chip->calib1 = tsl2563_calib_from_sysfs(val); else return -EINVAL; @@ -491,11 +491,11 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev, ret = tsl2563_get_adc(chip); if (ret) goto error_ret; - calib0 = calib_adc(chip->data0, chip->calib0) * + calib0 = tsl2563_calib_adc(chip->data0, chip->calib0) * chip->cover_comp_gain; - calib1 = calib_adc(chip->data1, chip->calib1) * + calib1 = tsl2563_calib_adc(chip->data1, chip->calib1) * chip->cover_comp_gain; - *val = adc_to_lux(calib0, calib1); + *val = tsl2563_adc_to_lux(calib0, calib1); ret = IIO_VAL_INT; break; case IIO_INTENSITY: @@ -515,9 +515,9 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_CALIBSCALE: if (chan->channel2 == IIO_MOD_LIGHT_BOTH) - *val = calib_to_sysfs(chip->calib0); + *val = tsl2563_calib_to_sysfs(chip->calib0); else - *val = calib_to_sysfs(chip->calib1); + *val = tsl2563_calib_to_sysfs(chip->calib1); ret = IIO_VAL_INT; break; default: @@ -750,8 +750,8 @@ static int tsl2563_probe(struct i2c_client *client, chip->high_thres = 0xffff; chip->gainlevel = tsl2563_gainlevel_table; chip->intr = TSL2563_INT_PERSIST(4); - chip->calib0 = calib_from_sysfs(CALIB_BASE_SYSFS); - chip->calib1 = calib_from_sysfs(CALIB_BASE_SYSFS); + chip->calib0 = tsl2563_calib_from_sysfs(CALIB_BASE_SYSFS); + chip->calib1 = tsl2563_calib_from_sysfs(CALIB_BASE_SYSFS); if (pdata) chip->cover_comp_gain = pdata->cover_comp_gain; From 49064b5a618df70dbe1ba58a122fd218c58d381d Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Wed, 15 Apr 2015 22:39:38 +0200 Subject: [PATCH 0201/3798] iio:tmp006: Prefix #defines with TMP006_ just cleanup, no functional change Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/tmp006.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c index 84a0789c3d9688..fcc49f89b9464c 100644 --- a/drivers/iio/temperature/tmp006.c +++ b/drivers/iio/temperature/tmp006.c @@ -41,8 +41,8 @@ #define TMP006_CONFIG_CR_MASK 0x0e00 #define TMP006_CONFIG_CR_SHIFT 9 -#define MANUFACTURER_MAGIC 0x5449 -#define DEVICE_MAGIC 0x0067 +#define TMP006_MANUFACTURER_MAGIC 0x5449 +#define TMP006_DEVICE_MAGIC 0x0067 struct tmp006_data { struct i2c_client *client; @@ -191,7 +191,7 @@ static bool tmp006_check_identification(struct i2c_client *client) if (did < 0) return false; - return mid == MANUFACTURER_MAGIC && did == DEVICE_MAGIC; + return mid == TMP006_MANUFACTURER_MAGIC && did == TMP006_DEVICE_MAGIC; } static int tmp006_probe(struct i2c_client *client, From 844b47027da0754e089c224c8c7d371f812320fd Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Sun, 19 Apr 2015 02:10:01 -0700 Subject: [PATCH 0202/3798] iio: ltr501: Add integration time support Added support to modify and read ALS integration time. Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Jonathan Cameron --- drivers/iio/light/ltr501.c | 90 +++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index e2f73547fdc52c..809260402a53c3 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -28,6 +28,7 @@ #define LTR501_ALS_CONTR 0x80 /* ALS operation mode, SW reset */ #define LTR501_PS_CONTR 0x81 /* PS operation mode */ +#define LTR501_ALS_MEAS_RATE 0x85 /* ALS integ time, measurement rate*/ #define LTR501_PART_ID 0x86 #define LTR501_MANUFAC_ID 0x87 #define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */ @@ -49,11 +50,17 @@ #define LTR501_REGMAP_NAME "ltr501_regmap" +static const int int_time_mapping[] = {100000, 50000, 200000, 400000}; + +static const struct reg_field reg_field_it = + REG_FIELD(LTR501_ALS_MEAS_RATE, 3, 4); + struct ltr501_data { struct i2c_client *client; struct mutex lock_als, lock_ps; u8 als_contr, ps_contr; struct regmap *regmap; + struct regmap_field *reg_it; }; static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) @@ -74,6 +81,58 @@ static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) return -EIO; } +static int ltr501_set_it_time(struct ltr501_data *data, int it) +{ + int ret, i, index = -1, status; + + for (i = 0; i < ARRAY_SIZE(int_time_mapping); i++) { + if (int_time_mapping[i] == it) { + index = i; + break; + } + } + /* Make sure integ time index is valid */ + if (index < 0) + return -EINVAL; + + ret = regmap_read(data->regmap, LTR501_ALS_CONTR, &status); + if (ret < 0) + return ret; + + if (status & LTR501_CONTR_ALS_GAIN_MASK) { + /* + * 200 ms and 400 ms integ time can only be + * used in dynamic range 1 + */ + if (index > 1) + return -EINVAL; + } else + /* 50 ms integ time can only be used in dynamic range 2 */ + if (index == 1) + return -EINVAL; + + return regmap_field_write(data->reg_it, index); +} + +/* read int time in micro seconds */ +static int ltr501_read_it_time(struct ltr501_data *data, int *val, int *val2) +{ + int ret, index; + + ret = regmap_field_read(data->reg_it, &index); + if (ret < 0) + return ret; + + /* Make sure integ time index is valid */ + if (index < 0 || index >= ARRAY_SIZE(int_time_mapping)) + return -EINVAL; + + *val2 = int_time_mapping[index]; + *val = 0; + + return IIO_VAL_INT_PLUS_MICRO; +} + static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2]) { int ret; @@ -121,7 +180,8 @@ static int ltr501_read_ps(struct ltr501_data *data) static const struct iio_chan_spec ltr501_channels[] = { LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0), LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR, - BIT(IIO_CHAN_INFO_SCALE)), + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_INT_TIME)), { .type = IIO_PROXIMITY, .address = LTR501_PS_DATA, @@ -196,6 +256,13 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_CHAN_INFO_INT_TIME: + switch (chan->type) { + case IIO_INTENSITY: + return ltr501_read_it_time(data, val, val2); + default: + return -EINVAL; + } } return -EINVAL; } @@ -246,16 +313,30 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_CHAN_INFO_INT_TIME: + switch (chan->type) { + case IIO_INTENSITY: + if (val != 0) + return -EINVAL; + mutex_lock(&data->lock_als); + i = ltr501_set_it_time(data, val2); + mutex_unlock(&data->lock_als); + return i; + default: + return -EINVAL; + } } return -EINVAL; } static IIO_CONST_ATTR(in_proximity_scale_available, "1 0.25 0.125 0.0625"); static IIO_CONST_ATTR(in_intensity_scale_available, "1 0.005"); +static IIO_CONST_ATTR_INT_TIME_AVAIL("0.05 0.1 0.2 0.4"); static struct attribute *ltr501_attributes[] = { &iio_const_attr_in_proximity_scale_available.dev_attr.attr, &iio_const_attr_in_intensity_scale_available.dev_attr.attr, + &iio_const_attr_integration_time_available.dev_attr.attr, NULL }; @@ -404,6 +485,13 @@ static int ltr501_probe(struct i2c_client *client, mutex_init(&data->lock_als); mutex_init(&data->lock_ps); + data->reg_it = devm_regmap_field_alloc(&client->dev, regmap, + reg_field_it); + if (IS_ERR(data->reg_it)) { + dev_err(&client->dev, "Integ time reg field init failed.\n"); + return PTR_ERR(data->reg_it); + } + ret = regmap_read(data->regmap, LTR501_PART_ID, &partid); if (ret < 0) return ret; From 7ac702b3144b635a8f7770e628d88ea1cbeda7ee Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Sun, 19 Apr 2015 02:10:02 -0700 Subject: [PATCH 0203/3798] iio: ltr501: Add interrupt support This patch adds interrupt support for Liteon 501 chip. Interrupt will be generated whenever ALS or proximity data exceeds values given in upper and lower threshold register settings. Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Jonathan Cameron --- drivers/iio/light/ltr501.c | 319 ++++++++++++++++++++++++++++++++++++- 1 file changed, 313 insertions(+), 6 deletions(-) diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index 809260402a53c3..593dbb11ec3805 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -9,7 +9,7 @@ * * 7-bit I2C slave address 0x23 * - * TODO: interrupt, threshold, measurement rate, IR LED characteristics + * TODO: measurement rate, IR LED characteristics */ #include @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -35,6 +36,11 @@ #define LTR501_ALS_DATA0 0x8a /* 16-bit, little endian */ #define LTR501_ALS_PS_STATUS 0x8c #define LTR501_PS_DATA 0x8d /* 16-bit, little endian */ +#define LTR501_INTR 0x8f /* output mode, polarity, mode */ +#define LTR501_PS_THRESH_UP 0x90 /* 11 bit, ps upper threshold */ +#define LTR501_PS_THRESH_LOW 0x92 /* 11 bit, ps lower threshold */ +#define LTR501_ALS_THRESH_UP 0x97 /* 16 bit, ALS upper threshold */ +#define LTR501_ALS_THRESH_LOW 0x99 /* 16 bit, ALS lower threshold */ #define LTR501_MAX_REG 0x9f #define LTR501_ALS_CONTR_SW_RESET BIT(2) @@ -43,10 +49,14 @@ #define LTR501_CONTR_ALS_GAIN_MASK BIT(3) #define LTR501_CONTR_ACTIVE BIT(1) +#define LTR501_STATUS_ALS_INTR BIT(3) #define LTR501_STATUS_ALS_RDY BIT(2) +#define LTR501_STATUS_PS_INTR BIT(1) #define LTR501_STATUS_PS_RDY BIT(0) #define LTR501_PS_DATA_MASK 0x7ff +#define LTR501_PS_THRESH_MASK 0x7ff +#define LTR501_ALS_THRESH_MASK 0xffff #define LTR501_REGMAP_NAME "ltr501_regmap" @@ -54,6 +64,10 @@ static const int int_time_mapping[] = {100000, 50000, 200000, 400000}; static const struct reg_field reg_field_it = REG_FIELD(LTR501_ALS_MEAS_RATE, 3, 4); +static const struct reg_field reg_field_als_intr = + REG_FIELD(LTR501_INTR, 0, 0); +static const struct reg_field reg_field_ps_intr = + REG_FIELD(LTR501_INTR, 1, 1); struct ltr501_data { struct i2c_client *client; @@ -61,6 +75,8 @@ struct ltr501_data { u8 als_contr, ps_contr; struct regmap *regmap; struct regmap_field *reg_it; + struct regmap_field *reg_als_intr; + struct regmap_field *reg_ps_intr; }; static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) @@ -161,7 +177,41 @@ static int ltr501_read_ps(struct ltr501_data *data) return status; } -#define LTR501_INTENSITY_CHANNEL(_idx, _addr, _mod, _shared) { \ +static const struct iio_event_spec ltr501_als_event_spec[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + }, + +}; + +static const struct iio_event_spec ltr501_pxs_event_spec[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + }, +}; + +#define LTR501_INTENSITY_CHANNEL(_idx, _addr, _mod, _shared, \ + _evspec, _evsize) { \ .type = IIO_INTENSITY, \ .modified = 1, \ .address = (_addr), \ @@ -174,14 +224,19 @@ static int ltr501_read_ps(struct ltr501_data *data) .realbits = 16, \ .storagebits = 16, \ .endianness = IIO_CPU, \ - } \ + }, \ + .event_spec = _evspec,\ + .num_event_specs = _evsize,\ } static const struct iio_chan_spec ltr501_channels[] = { - LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0), + LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0, + ltr501_als_event_spec, + ARRAY_SIZE(ltr501_als_event_spec)), LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR, BIT(IIO_CHAN_INFO_SCALE) | - BIT(IIO_CHAN_INFO_INT_TIME)), + BIT(IIO_CHAN_INFO_INT_TIME), + NULL, 0), { .type = IIO_PROXIMITY, .address = LTR501_PS_DATA, @@ -194,6 +249,8 @@ static const struct iio_chan_spec ltr501_channels[] = { .storagebits = 16, .endianness = IIO_CPU, }, + .event_spec = ltr501_pxs_event_spec, + .num_event_specs = ARRAY_SIZE(ltr501_pxs_event_spec), }, IIO_CHAN_SOFT_TIMESTAMP(3), }; @@ -329,6 +386,185 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, return -EINVAL; } +static int ltr501_read_thresh(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct ltr501_data *data = iio_priv(indio_dev); + int ret, thresh_data; + + switch (chan->type) { + case IIO_INTENSITY: + switch (dir) { + case IIO_EV_DIR_RISING: + ret = regmap_bulk_read(data->regmap, + LTR501_ALS_THRESH_UP, + &thresh_data, 2); + if (ret < 0) + return ret; + *val = thresh_data & LTR501_ALS_THRESH_MASK; + return IIO_VAL_INT; + case IIO_EV_DIR_FALLING: + ret = regmap_bulk_read(data->regmap, + LTR501_ALS_THRESH_LOW, + &thresh_data, 2); + if (ret < 0) + return ret; + *val = thresh_data & LTR501_ALS_THRESH_MASK; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_PROXIMITY: + switch (dir) { + case IIO_EV_DIR_RISING: + ret = regmap_bulk_read(data->regmap, + LTR501_PS_THRESH_UP, + &thresh_data, 2); + if (ret < 0) + return ret; + *val = thresh_data & LTR501_PS_THRESH_MASK; + return IIO_VAL_INT; + case IIO_EV_DIR_FALLING: + ret = regmap_bulk_read(data->regmap, + LTR501_PS_THRESH_LOW, + &thresh_data, 2); + if (ret < 0) + return ret; + *val = thresh_data & LTR501_PS_THRESH_MASK; + return IIO_VAL_INT; + default: + return -EINVAL; + } + default: + return -EINVAL; + } + + return -EINVAL; +} + +static int ltr501_write_thresh(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct ltr501_data *data = iio_priv(indio_dev); + int ret; + + if (val < 0) + return -EINVAL; + + switch (chan->type) { + case IIO_INTENSITY: + if (val > LTR501_ALS_THRESH_MASK) + return -EINVAL; + switch (dir) { + case IIO_EV_DIR_RISING: + mutex_lock(&data->lock_als); + ret = regmap_bulk_write(data->regmap, + LTR501_ALS_THRESH_UP, + &val, 2); + mutex_unlock(&data->lock_als); + return ret; + case IIO_EV_DIR_FALLING: + mutex_lock(&data->lock_als); + ret = regmap_bulk_write(data->regmap, + LTR501_ALS_THRESH_LOW, + &val, 2); + mutex_unlock(&data->lock_als); + return ret; + default: + return -EINVAL; + } + case IIO_PROXIMITY: + switch (dir) { + if (val > LTR501_PS_THRESH_MASK) + return -EINVAL; + case IIO_EV_DIR_RISING: + mutex_lock(&data->lock_ps); + ret = regmap_bulk_write(data->regmap, + LTR501_PS_THRESH_UP, + &val, 2); + mutex_unlock(&data->lock_ps); + return ret; + case IIO_EV_DIR_FALLING: + mutex_lock(&data->lock_ps); + ret = regmap_bulk_write(data->regmap, + LTR501_PS_THRESH_LOW, + &val, 2); + mutex_unlock(&data->lock_ps); + return ret; + default: + return -EINVAL; + } + default: + return -EINVAL; + } + + return -EINVAL; +} + +static int ltr501_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct ltr501_data *data = iio_priv(indio_dev); + int ret, status; + + switch (chan->type) { + case IIO_INTENSITY: + ret = regmap_field_read(data->reg_als_intr, &status); + if (ret < 0) + return ret; + return status; + case IIO_PROXIMITY: + ret = regmap_field_read(data->reg_ps_intr, &status); + if (ret < 0) + return ret; + return status; + default: + return -EINVAL; + } + + return -EINVAL; +} + +static int ltr501_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, int state) +{ + struct ltr501_data *data = iio_priv(indio_dev); + int ret; + + /* only 1 and 0 are valid inputs */ + if (state != 1 || state != 0) + return -EINVAL; + + switch (chan->type) { + case IIO_INTENSITY: + mutex_lock(&data->lock_als); + ret = regmap_field_write(data->reg_als_intr, state); + mutex_unlock(&data->lock_als); + return ret; + case IIO_PROXIMITY: + mutex_lock(&data->lock_ps); + ret = regmap_field_write(data->reg_ps_intr, state); + mutex_unlock(&data->lock_ps); + return ret; + default: + return -EINVAL; + } + + return -EINVAL; +} + static IIO_CONST_ATTR(in_proximity_scale_available, "1 0.25 0.125 0.0625"); static IIO_CONST_ATTR(in_intensity_scale_available, "1 0.005"); static IIO_CONST_ATTR_INT_TIME_AVAIL("0.05 0.1 0.2 0.4"); @@ -344,10 +580,21 @@ static const struct attribute_group ltr501_attribute_group = { .attrs = ltr501_attributes, }; +static const struct iio_info ltr501_info_no_irq = { + .read_raw = ltr501_read_raw, + .write_raw = ltr501_write_raw, + .attrs = <r501_attribute_group, + .driver_module = THIS_MODULE, +}; + static const struct iio_info ltr501_info = { .read_raw = ltr501_read_raw, .write_raw = ltr501_write_raw, .attrs = <r501_attribute_group, + .read_event_value = <r501_read_thresh, + .write_event_value = <r501_write_thresh, + .read_event_config = <r501_read_event_config, + .write_event_config = <r501_write_event_config, .driver_module = THIS_MODULE, }; @@ -413,6 +660,36 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) return IRQ_HANDLED; } +static irqreturn_t ltr501_interrupt_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct ltr501_data *data = iio_priv(indio_dev); + int ret, status; + + ret = regmap_read(data->regmap, LTR501_ALS_PS_STATUS, &status); + if (ret < 0) { + dev_err(&data->client->dev, + "irq read int reg failed\n"); + return IRQ_HANDLED; + } + + if (status & LTR501_STATUS_ALS_INTR) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_EITHER), + iio_get_time_ns()); + + if (status & LTR501_STATUS_PS_INTR) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_EITHER), + iio_get_time_ns()); + + return IRQ_HANDLED; +} + static int ltr501_init(struct ltr501_data *data) { int ret, status; @@ -492,6 +769,20 @@ static int ltr501_probe(struct i2c_client *client, return PTR_ERR(data->reg_it); } + data->reg_als_intr = devm_regmap_field_alloc(&client->dev, regmap, + reg_field_als_intr); + if (IS_ERR(data->reg_als_intr)) { + dev_err(&client->dev, "ALS intr mode reg field init failed\n"); + return PTR_ERR(data->reg_als_intr); + } + + data->reg_ps_intr = devm_regmap_field_alloc(&client->dev, regmap, + reg_field_ps_intr); + if (IS_ERR(data->reg_ps_intr)) { + dev_err(&client->dev, "PS intr mode reg field init failed.\n"); + return PTR_ERR(data->reg_ps_intr); + } + ret = regmap_read(data->regmap, LTR501_PART_ID, &partid); if (ret < 0) return ret; @@ -499,7 +790,6 @@ static int ltr501_probe(struct i2c_client *client, return -ENODEV; indio_dev->dev.parent = &client->dev; - indio_dev->info = <r501_info; indio_dev->channels = ltr501_channels; indio_dev->num_channels = ARRAY_SIZE(ltr501_channels); indio_dev->name = LTR501_DRV_NAME; @@ -509,6 +799,23 @@ static int ltr501_probe(struct i2c_client *client, if (ret < 0) return ret; + if (client->irq > 0) { + indio_dev->info = <r501_info; + ret = devm_request_threaded_irq(&client->dev, client->irq, + NULL, ltr501_interrupt_handler, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, + "ltr501_thresh_event", + indio_dev); + if (ret) { + dev_err(&client->dev, "request irq (%d) failed\n", + client->irq); + return ret; + } + } else { + indio_dev->info = <r501_info_no_irq; + } + ret = iio_triggered_buffer_setup(indio_dev, NULL, ltr501_trigger_handler, NULL); if (ret) From eea53b4a2562e439bfc1a6d13b231f902d9b9e5f Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Sun, 19 Apr 2015 02:10:03 -0700 Subject: [PATCH 0204/3798] iio: ltr501: Add interrupt rate control support Added rate control support for ALS and proximity threshold interrupts.Also, Added support to modify and read ALS & proximity sensor sampling frequency. LTR-501 supports interrupt rate control using persistence register settings. Writing to persistence register would generate interrupt only if there are consecutive data values outside the threshold range. Since we don't have any existing ABI's to directly control the persistence register count, we have implemented the rate control using IIO_EV_INFO_PERIOD. _period event attribute represents the amount of time in seconds an event should be true for the device to generate the interrupt. So using _period value and device frequency, persistence count is calculated in driver using following logic. count = period / measurement_rate If the given period is not a multiple of measurement rate then we round up the value to next multiple. This patch also handles change to persistence count whenever there is change in frequency. Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Jonathan Cameron --- drivers/iio/light/ltr501.c | 413 ++++++++++++++++++++++++++++++++++++- 1 file changed, 406 insertions(+), 7 deletions(-) diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index 593dbb11ec3805..d9b4536f006728 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -9,7 +9,7 @@ * * 7-bit I2C slave address 0x23 * - * TODO: measurement rate, IR LED characteristics + * TODO: IR LED characteristics */ #include @@ -29,6 +29,7 @@ #define LTR501_ALS_CONTR 0x80 /* ALS operation mode, SW reset */ #define LTR501_PS_CONTR 0x81 /* PS operation mode */ +#define LTR501_PS_MEAS_RATE 0x84 /* measurement rate*/ #define LTR501_ALS_MEAS_RATE 0x85 /* ALS integ time, measurement rate*/ #define LTR501_PART_ID 0x86 #define LTR501_MANUFAC_ID 0x87 @@ -41,6 +42,7 @@ #define LTR501_PS_THRESH_LOW 0x92 /* 11 bit, ps lower threshold */ #define LTR501_ALS_THRESH_UP 0x97 /* 16 bit, ALS upper threshold */ #define LTR501_ALS_THRESH_LOW 0x99 /* 16 bit, ALS lower threshold */ +#define LTR501_INTR_PRST 0x9e /* ps thresh, als thresh */ #define LTR501_MAX_REG 0x9f #define LTR501_ALS_CONTR_SW_RESET BIT(2) @@ -58,6 +60,9 @@ #define LTR501_PS_THRESH_MASK 0x7ff #define LTR501_ALS_THRESH_MASK 0xffff +#define LTR501_ALS_DEF_PERIOD 500000 +#define LTR501_PS_DEF_PERIOD 100000 + #define LTR501_REGMAP_NAME "ltr501_regmap" static const int int_time_mapping[] = {100000, 50000, 200000, 400000}; @@ -68,17 +73,171 @@ static const struct reg_field reg_field_als_intr = REG_FIELD(LTR501_INTR, 0, 0); static const struct reg_field reg_field_ps_intr = REG_FIELD(LTR501_INTR, 1, 1); +static const struct reg_field reg_field_als_rate = + REG_FIELD(LTR501_ALS_MEAS_RATE, 0, 2); +static const struct reg_field reg_field_ps_rate = + REG_FIELD(LTR501_PS_MEAS_RATE, 0, 3); +static const struct reg_field reg_field_als_prst = + REG_FIELD(LTR501_INTR_PRST, 0, 3); +static const struct reg_field reg_field_ps_prst = + REG_FIELD(LTR501_INTR_PRST, 4, 7); + +struct ltr501_samp_table { + int freq_val; /* repetition frequency in micro HZ*/ + int time_val; /* repetition rate in micro seconds */ +}; struct ltr501_data { struct i2c_client *client; struct mutex lock_als, lock_ps; u8 als_contr, ps_contr; + int als_period, ps_period; /* period in micro seconds */ struct regmap *regmap; struct regmap_field *reg_it; struct regmap_field *reg_als_intr; struct regmap_field *reg_ps_intr; + struct regmap_field *reg_als_rate; + struct regmap_field *reg_ps_rate; + struct regmap_field *reg_als_prst; + struct regmap_field *reg_ps_prst; +}; + +static const struct ltr501_samp_table ltr501_als_samp_table[] = { + {20000000, 50000}, {10000000, 100000}, + {5000000, 200000}, {2000000, 500000}, + {1000000, 1000000}, {500000, 2000000}, + {500000, 2000000}, {500000, 2000000} }; +static const struct ltr501_samp_table ltr501_ps_samp_table[] = { + {20000000, 50000}, {14285714, 70000}, + {10000000, 100000}, {5000000, 200000}, + {2000000, 500000}, {1000000, 1000000}, + {500000, 2000000}, {500000, 2000000}, + {500000, 2000000} +}; + +static unsigned int ltr501_match_samp_freq(const struct ltr501_samp_table *tab, + int len, int val, int val2) +{ + int i, freq; + + freq = val * 1000000 + val2; + + for (i = 0; i < len; i++) { + if (tab[i].freq_val == freq) + return i; + } + + return -EINVAL; +} + +static int ltr501_als_read_samp_freq(struct ltr501_data *data, + int *val, int *val2) +{ + int ret, i; + + ret = regmap_field_read(data->reg_als_rate, &i); + if (ret < 0) + return ret; + + if (i < 0 || i >= ARRAY_SIZE(ltr501_als_samp_table)) + return -EINVAL; + + *val = ltr501_als_samp_table[i].freq_val / 1000000; + *val2 = ltr501_als_samp_table[i].freq_val % 1000000; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int ltr501_ps_read_samp_freq(struct ltr501_data *data, + int *val, int *val2) +{ + int ret, i; + + ret = regmap_field_read(data->reg_ps_rate, &i); + if (ret < 0) + return ret; + + if (i < 0 || i >= ARRAY_SIZE(ltr501_ps_samp_table)) + return -EINVAL; + + *val = ltr501_ps_samp_table[i].freq_val / 1000000; + *val2 = ltr501_ps_samp_table[i].freq_val % 1000000; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int ltr501_als_write_samp_freq(struct ltr501_data *data, + int val, int val2) +{ + int i, ret; + + i = ltr501_match_samp_freq(ltr501_als_samp_table, + ARRAY_SIZE(ltr501_als_samp_table), + val, val2); + + if (i < 0) + return i; + + mutex_lock(&data->lock_als); + ret = regmap_field_write(data->reg_als_rate, i); + mutex_unlock(&data->lock_als); + + return ret; +} + +static int ltr501_ps_write_samp_freq(struct ltr501_data *data, + int val, int val2) +{ + int i, ret; + + i = ltr501_match_samp_freq(ltr501_ps_samp_table, + ARRAY_SIZE(ltr501_ps_samp_table), + val, val2); + + if (i < 0) + return i; + + mutex_lock(&data->lock_ps); + ret = regmap_field_write(data->reg_ps_rate, i); + mutex_unlock(&data->lock_ps); + + return ret; +} + +static int ltr501_als_read_samp_period(struct ltr501_data *data, int *val) +{ + int ret, i; + + ret = regmap_field_read(data->reg_als_rate, &i); + if (ret < 0) + return ret; + + if (i < 0 || i >= ARRAY_SIZE(ltr501_als_samp_table)) + return -EINVAL; + + *val = ltr501_als_samp_table[i].time_val; + + return IIO_VAL_INT; +} + +static int ltr501_ps_read_samp_period(struct ltr501_data *data, int *val) +{ + int ret, i; + + ret = regmap_field_read(data->reg_ps_rate, &i); + if (ret < 0) + return ret; + + if (i < 0 || i >= ARRAY_SIZE(ltr501_ps_samp_table)) + return -EINVAL; + + *val = ltr501_ps_samp_table[i].time_val; + + return IIO_VAL_INT; +} + static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) { int tries = 100; @@ -177,6 +336,104 @@ static int ltr501_read_ps(struct ltr501_data *data) return status; } +static int ltr501_read_intr_prst(struct ltr501_data *data, + enum iio_chan_type type, + int *val2) +{ + int ret, samp_period, prst; + + switch (type) { + case IIO_INTENSITY: + ret = regmap_field_read(data->reg_als_prst, &prst); + if (ret < 0) + return ret; + + ret = ltr501_als_read_samp_period(data, &samp_period); + + if (ret < 0) + return ret; + *val2 = samp_period * prst; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_PROXIMITY: + ret = regmap_field_read(data->reg_ps_prst, &prst); + if (ret < 0) + return ret; + + ret = ltr501_ps_read_samp_period(data, &samp_period); + + if (ret < 0) + return ret; + + *val2 = samp_period * prst; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + + return -EINVAL; +} + +static int ltr501_write_intr_prst(struct ltr501_data *data, + enum iio_chan_type type, + int val, int val2) +{ + int ret, samp_period, new_val; + unsigned long period; + + if (val < 0 || val2 < 0) + return -EINVAL; + + /* period in microseconds */ + period = ((val * 1000000) + val2); + + switch (type) { + case IIO_INTENSITY: + ret = ltr501_als_read_samp_period(data, &samp_period); + if (ret < 0) + return ret; + + /* period should be atleast equal to sampling period */ + if (period < samp_period) + return -EINVAL; + + new_val = DIV_ROUND_UP(period, samp_period); + if (new_val < 0 || new_val > 0x0f) + return -EINVAL; + + mutex_lock(&data->lock_als); + ret = regmap_field_write(data->reg_als_prst, new_val); + mutex_unlock(&data->lock_als); + if (ret >= 0) + data->als_period = period; + + return ret; + case IIO_PROXIMITY: + ret = ltr501_ps_read_samp_period(data, &samp_period); + if (ret < 0) + return ret; + + /* period should be atleast equal to rate */ + if (period < samp_period) + return -EINVAL; + + new_val = DIV_ROUND_UP(period, samp_period); + if (new_val < 0 || new_val > 0x0f) + return -EINVAL; + + mutex_lock(&data->lock_ps); + ret = regmap_field_write(data->reg_ps_prst, new_val); + mutex_unlock(&data->lock_ps); + if (ret >= 0) + data->ps_period = period; + + return ret; + default: + return -EINVAL; + } + + return -EINVAL; +} + static const struct iio_event_spec ltr501_als_event_spec[] = { { .type = IIO_EV_TYPE_THRESH, @@ -189,7 +446,8 @@ static const struct iio_event_spec ltr501_als_event_spec[] = { }, { .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_EITHER, - .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_PERIOD), }, }; @@ -206,7 +464,8 @@ static const struct iio_event_spec ltr501_pxs_event_spec[] = { }, { .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_EITHER, - .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_PERIOD), }, }; @@ -235,7 +494,8 @@ static const struct iio_chan_spec ltr501_channels[] = { ARRAY_SIZE(ltr501_als_event_spec)), LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR, BIT(IIO_CHAN_INFO_SCALE) | - BIT(IIO_CHAN_INFO_INT_TIME), + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_SAMP_FREQ), NULL, 0), { .type = IIO_PROXIMITY, @@ -320,6 +580,15 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_CHAN_INFO_SAMP_FREQ: + switch (chan->type) { + case IIO_INTENSITY: + return ltr501_als_read_samp_freq(data, val, val2); + case IIO_PROXIMITY: + return ltr501_ps_read_samp_freq(data, val, val2); + default: + return -EINVAL; + } } return -EINVAL; } @@ -340,7 +609,7 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct ltr501_data *data = iio_priv(indio_dev); - int i; + int i, ret, freq_val, freq_val2; if (iio_buffer_enabled(indio_dev)) return -EBUSY; @@ -382,6 +651,49 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_CHAN_INFO_SAMP_FREQ: + switch (chan->type) { + case IIO_INTENSITY: + ret = ltr501_als_read_samp_freq(data, &freq_val, + &freq_val2); + if (ret < 0) + return ret; + + ret = ltr501_als_write_samp_freq(data, val, val2); + if (ret < 0) + return ret; + + /* update persistence count when changing frequency */ + ret = ltr501_write_intr_prst(data, chan->type, + 0, data->als_period); + + if (ret < 0) + return ltr501_als_write_samp_freq(data, + freq_val, + freq_val2); + return ret; + case IIO_PROXIMITY: + ret = ltr501_ps_read_samp_freq(data, &freq_val, + &freq_val2); + if (ret < 0) + return ret; + + ret = ltr501_ps_write_samp_freq(data, val, val2); + if (ret < 0) + return ret; + + /* update persistence count when changing frequency */ + ret = ltr501_write_intr_prst(data, chan->type, + 0, data->ps_period); + + if (ret < 0) + return ltr501_ps_write_samp_freq(data, + freq_val, + freq_val2); + return ret; + default: + return -EINVAL; + } } return -EINVAL; } @@ -509,6 +821,55 @@ static int ltr501_write_thresh(struct iio_dev *indio_dev, return -EINVAL; } +static int ltr501_read_event(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + int ret; + + switch (info) { + case IIO_EV_INFO_VALUE: + return ltr501_read_thresh(indio_dev, chan, type, dir, + info, val, val2); + case IIO_EV_INFO_PERIOD: + ret = ltr501_read_intr_prst(iio_priv(indio_dev), + chan->type, val2); + *val = *val2 / 1000000; + *val2 = *val2 % 1000000; + return ret; + default: + return -EINVAL; + } + + return -EINVAL; +} + +static int ltr501_write_event(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + switch (info) { + case IIO_EV_INFO_VALUE: + if (val2 != 0) + return -EINVAL; + return ltr501_write_thresh(indio_dev, chan, type, dir, + info, val, val2); + case IIO_EV_INFO_PERIOD: + return ltr501_write_intr_prst(iio_priv(indio_dev), chan->type, + val, val2); + default: + return -EINVAL; + } + + return -EINVAL; +} + static int ltr501_read_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, @@ -568,11 +929,13 @@ static int ltr501_write_event_config(struct iio_dev *indio_dev, static IIO_CONST_ATTR(in_proximity_scale_available, "1 0.25 0.125 0.0625"); static IIO_CONST_ATTR(in_intensity_scale_available, "1 0.005"); static IIO_CONST_ATTR_INT_TIME_AVAIL("0.05 0.1 0.2 0.4"); +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("20 10 5 2 1 0.5"); static struct attribute *ltr501_attributes[] = { &iio_const_attr_in_proximity_scale_available.dev_attr.attr, &iio_const_attr_in_intensity_scale_available.dev_attr.attr, &iio_const_attr_integration_time_available.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, NULL }; @@ -591,8 +954,8 @@ static const struct iio_info ltr501_info = { .read_raw = ltr501_read_raw, .write_raw = ltr501_write_raw, .attrs = <r501_attribute_group, - .read_event_value = <r501_read_thresh, - .write_event_value = <r501_write_thresh, + .read_event_value = <r501_read_event, + .write_event_value = <r501_write_event, .read_event_config = <r501_read_event_config, .write_event_config = <r501_write_event_config, .driver_module = THIS_MODULE, @@ -706,6 +1069,14 @@ static int ltr501_init(struct ltr501_data *data) data->ps_contr = status | LTR501_CONTR_ACTIVE; + ret = ltr501_read_intr_prst(data, IIO_INTENSITY, &data->als_period); + if (ret < 0) + return ret; + + ret = ltr501_read_intr_prst(data, IIO_PROXIMITY, &data->ps_period); + if (ret < 0) + return ret; + return ltr501_write_contr(data, data->als_contr, data->ps_contr); } @@ -783,6 +1154,34 @@ static int ltr501_probe(struct i2c_client *client, return PTR_ERR(data->reg_ps_intr); } + data->reg_als_rate = devm_regmap_field_alloc(&client->dev, regmap, + reg_field_als_rate); + if (IS_ERR(data->reg_als_rate)) { + dev_err(&client->dev, "ALS samp rate field init failed.\n"); + return PTR_ERR(data->reg_als_rate); + } + + data->reg_ps_rate = devm_regmap_field_alloc(&client->dev, regmap, + reg_field_ps_rate); + if (IS_ERR(data->reg_ps_rate)) { + dev_err(&client->dev, "PS samp rate field init failed.\n"); + return PTR_ERR(data->reg_ps_rate); + } + + data->reg_als_prst = devm_regmap_field_alloc(&client->dev, regmap, + reg_field_als_prst); + if (IS_ERR(data->reg_als_prst)) { + dev_err(&client->dev, "ALS prst reg field init failed\n"); + return PTR_ERR(data->reg_als_prst); + } + + data->reg_ps_prst = devm_regmap_field_alloc(&client->dev, regmap, + reg_field_ps_prst); + if (IS_ERR(data->reg_ps_prst)) { + dev_err(&client->dev, "PS prst reg field init failed.\n"); + return PTR_ERR(data->reg_ps_prst); + } + ret = regmap_read(data->regmap, LTR501_PART_ID, &partid); if (ret < 0) return ret; From 772154d0ddde6b46a3866c73a16cfbfaf3053be4 Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Sun, 19 Apr 2015 02:10:04 -0700 Subject: [PATCH 0205/3798] iio: ltr501: Add ACPI enumeration support Added ACPI enumeration support for LTR501 chip. Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Jonathan Cameron --- drivers/iio/light/ltr501.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index d9b4536f006728..0162e865211860 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -1264,6 +1265,12 @@ static int ltr501_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(ltr501_pm_ops, ltr501_suspend, ltr501_resume); +static const struct acpi_device_id ltr_acpi_match[] = { + {"LTER0501", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, ltr_acpi_match); + static const struct i2c_device_id ltr501_id[] = { { "ltr501", 0 }, { } @@ -1274,6 +1281,7 @@ static struct i2c_driver ltr501_driver = { .driver = { .name = LTR501_DRV_NAME, .pm = <r501_pm_ops, + .acpi_match_table = ACPI_PTR(ltr_acpi_match), .owner = THIS_MODULE, }, .probe = ltr501_probe, From 8a0c39b1621adc0f2f1c25bd44645afeee5c1d99 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 13 Apr 2015 11:50:09 +0100 Subject: [PATCH 0206/3798] drm/i915: Simplify and fix object to display tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Purpose of this tracking is to know when to flush the cache between the CPU and the non-coherent display engine. Prior to: commit 121920faf2ccce9aa66a7e2588415c9647b66104 Author: Tvrtko Ursulin Date: Mon Mar 23 11:10:37 2015 +0000 drm/i915/skl: Query display address through a wrapper This worked by a mix of direct flag manipulation and checking for existence of a pinned GGTT VMA. With the introduction of rotated display mappings this approach is no longer correct. New simpler approach is to just keep this count over calls which pin and unpin objects to and from display, at the slight cost of extra space in every bo. (Inspired and extracted code from a larger rework by Chris Wilson.) v2: Remove the limit since it is not well defined. (Chris Wilson, Ville Syrjälä) v3: Commit message corrections. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Cc: Chris Wilson Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_gem.c | 30 ++++++------------------------ 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fd72f3f0cf84dc..93e9d36c2b683f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1969,7 +1969,6 @@ struct drm_i915_gem_object { * accurate mappable working set. */ unsigned int fault_mappable:1; - unsigned int pin_display:1; /* * Is the object to be mapped as read-only to the GPU @@ -1983,6 +1982,8 @@ struct drm_i915_gem_object { unsigned int frontbuffer_bits:INTEL_FRONTBUFFER_BITS; + unsigned int pin_display; + struct sg_table *pages; int pages_pin_count; struct get_page { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f7b8766e09fc8f..761f1b6b49428b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3914,24 +3914,6 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, return ret; } -static bool is_pin_display(struct drm_i915_gem_object *obj) -{ - struct i915_vma *vma; - - vma = i915_gem_obj_to_ggtt(obj); - if (!vma) - return false; - - /* There are 2 sources that pin objects: - * 1. The display engine (scanouts, sprites, cursors); - * 2. Reservations for execbuffer; - * - * We can ignore reservations as we hold the struct_mutex and - * are only called outside of the reservation path. - */ - return vma->pin_count; -} - /* * Prepare buffer for display plane (scanout, cursors, etc). * Can be called from an uninterruptible phase (modesetting) and allows @@ -3944,7 +3926,6 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, const struct i915_ggtt_view *view) { u32 old_read_domains, old_write_domain; - bool was_pin_display; int ret; if (pipelined != i915_gem_request_get_ring(obj->last_read_req)) { @@ -3956,8 +3937,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, /* Mark the pin_display early so that we account for the * display coherency whilst setting up the cache domains. */ - was_pin_display = obj->pin_display; - obj->pin_display = true; + obj->pin_display++; /* The display engine is not coherent with the LLC cache on gen6. As * a result, we make sure that the pinning that is about to occur is @@ -4001,8 +3981,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, return 0; err_unpin_display: - WARN_ON(was_pin_display != is_pin_display(obj)); - obj->pin_display = was_pin_display; + obj->pin_display--; return ret; } @@ -4010,9 +3989,12 @@ void i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj, const struct i915_ggtt_view *view) { + if (WARN_ON(obj->pin_display == 0)) + return; + i915_gem_object_ggtt_unpin_view(obj, view); - obj->pin_display = is_pin_display(obj); + obj->pin_display--; } int From c7e16f22e83775de96bf7585682d2e7be7f1c1dc Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:11 +0200 Subject: [PATCH 0207/3798] drm/i915: Move gen8 clear_range vfunc setup into common code Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 9041f3dfdfb403..1c8ef7c143aa19 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -994,6 +994,7 @@ static int gen8_ppgtt_init_common(struct i915_hw_ppgtt *ppgtt, uint64_t size) ppgtt->base.total = size; ppgtt->base.cleanup = gen8_ppgtt_cleanup; ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; + ppgtt->base.clear_range = gen8_ppgtt_clear_range; ppgtt->switch_mm = gen8_mm_switch; @@ -1022,7 +1023,6 @@ static int gen8_aliasing_ppgtt_init(struct i915_hw_ppgtt *ppgtt) } ppgtt->base.allocate_va_range = NULL; - ppgtt->base.clear_range = gen8_ppgtt_clear_range; ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true); return 0; @@ -1037,7 +1037,6 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) return ret; ppgtt->base.allocate_va_range = gen8_alloc_va_range; - ppgtt->base.clear_range = gen8_ppgtt_clear_range; return 0; } From 777dc5bb26a5aff916af1b6ee84ed7dc8cac1245 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:12 +0200 Subject: [PATCH 0208/3798] drm/i915: Move vma vfuns to adddress_space They change with the address space and not with each vma, so move them into the right pile of vfuncs. Save 2 pointers per vma and clarifies the code. Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 28 ++++++++++++---------------- drivers/gpu/drm/i915/i915_gem_gtt.h | 15 +++++++-------- 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 761f1b6b49428b..8698cff03fc1df 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3067,7 +3067,7 @@ int i915_vma_unbind(struct i915_vma *vma) trace_i915_vma_unbind(vma); - vma->unbind_vma(vma); + vma->vm->unbind_vma(vma); list_del_init(&vma->mm_list); if (i915_is_ggtt(vma->vm)) { diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 1c8ef7c143aa19..290db48faf278a 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -995,6 +995,8 @@ static int gen8_ppgtt_init_common(struct i915_hw_ppgtt *ppgtt, uint64_t size) ppgtt->base.cleanup = gen8_ppgtt_cleanup; ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; ppgtt->base.clear_range = gen8_ppgtt_clear_range; + ppgtt->base.unbind_vma = ppgtt_unbind_vma; + ppgtt->base.bind_vma = ppgtt_bind_vma; ppgtt->switch_mm = gen8_mm_switch; @@ -1579,6 +1581,8 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing) ppgtt->base.allocate_va_range = aliasing ? NULL : gen6_alloc_va_range; ppgtt->base.clear_range = gen6_ppgtt_clear_range; ppgtt->base.insert_entries = gen6_ppgtt_insert_entries; + ppgtt->base.unbind_vma = ppgtt_unbind_vma; + ppgtt->base.bind_vma = ppgtt_bind_vma; ppgtt->base.cleanup = gen6_ppgtt_cleanup; ppgtt->base.start = 0; ppgtt->base.total = I915_PDES * GEN6_PTES * PAGE_SIZE; @@ -2573,6 +2577,8 @@ static int gen8_gmch_probe(struct drm_device *dev, dev_priv->gtt.base.clear_range = gen8_ggtt_clear_range; dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries; + dev_priv->gtt.base.bind_vma = ggtt_bind_vma; + dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma; return ret; } @@ -2613,6 +2619,8 @@ static int gen6_gmch_probe(struct drm_device *dev, dev_priv->gtt.base.clear_range = gen6_ggtt_clear_range; dev_priv->gtt.base.insert_entries = gen6_ggtt_insert_entries; + dev_priv->gtt.base.bind_vma = ggtt_bind_vma; + dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma; return ret; } @@ -2645,6 +2653,8 @@ static int i915_gmch_probe(struct drm_device *dev, dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev); dev_priv->gtt.base.clear_range = i915_ggtt_clear_range; + dev_priv->gtt.base.bind_vma = i915_ggtt_bind_vma; + dev_priv->gtt.base.unbind_vma = i915_ggtt_unbind_vma; if (unlikely(dev_priv->gtt.do_idle_maps)) DRM_INFO("applying Ironlake quirks for intel_iommu\n"); @@ -2732,22 +2742,8 @@ __i915_gem_vma_create(struct drm_i915_gem_object *obj, vma->vm = vm; vma->obj = obj; - if (INTEL_INFO(vm->dev)->gen >= 6) { - if (i915_is_ggtt(vm)) { - vma->ggtt_view = *ggtt_view; - - vma->unbind_vma = ggtt_unbind_vma; - vma->bind_vma = ggtt_bind_vma; - } else { - vma->unbind_vma = ppgtt_unbind_vma; - vma->bind_vma = ppgtt_bind_vma; - } - } else { - BUG_ON(!i915_is_ggtt(vm)); + if (i915_is_ggtt(vm)) vma->ggtt_view = *ggtt_view; - vma->unbind_vma = i915_ggtt_unbind_vma; - vma->bind_vma = i915_ggtt_bind_vma; - } list_add_tail(&vma->vma_link, &obj->vma_list); if (!i915_is_ggtt(vm)) @@ -2957,7 +2953,7 @@ int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, return ret; } - vma->bind_vma(vma, cache_level, flags); + vma->vm->bind_vma(vma, cache_level, flags); return 0; } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 29de64d1164efb..12d0ded0d8236c 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -196,14 +196,6 @@ struct i915_vma { * bits with absolutely no headroom. So use 4 bits. */ unsigned int pin_count:4; #define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf - - /** Unmap an object from an address space. This usually consists of - * setting the valid PTE entries to a reserved scratch page. */ - void (*unbind_vma)(struct i915_vma *vma); - /* Map an object into an address space with the given cache flags. */ - void (*bind_vma)(struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags); }; struct i915_page_table { @@ -281,6 +273,13 @@ struct i915_address_space { uint64_t start, enum i915_cache_level cache_level, u32 flags); void (*cleanup)(struct i915_address_space *vm); + /** Unmap an object from an address space. This usually consists of + * setting the valid PTE entries to a reserved scratch page. */ + void (*unbind_vma)(struct i915_vma *vma); + /* Map an object into an address space with the given cache flags. */ + void (*bind_vma)(struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags); }; /* The Graphics Translation Table is the way in which GEN hardware translates a From 061dd493103f14f768475fa666f39377f41814bb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:13 +0200 Subject: [PATCH 0209/3798] drm/i915: Clean up aliasing ppgtt correctly on error paths While at it inline the free functions - they don't actually free the ppgtt, just clean up the allocations done for it. Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 30 ++++++++++------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 290db48faf278a..abb11f139d25df 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -672,8 +672,10 @@ static void gen8_free_page_tables(struct i915_page_directory *pd, struct drm_dev } } -static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt) +static void gen8_ppgtt_cleanup(struct i915_address_space *vm) { + struct i915_hw_ppgtt *ppgtt = + container_of(vm, struct i915_hw_ppgtt, base); int i; for_each_set_bit(i, ppgtt->pdp.used_pdpes, GEN8_LEGACY_PDPES) { @@ -688,14 +690,6 @@ static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt) unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev); } -static void gen8_ppgtt_cleanup(struct i915_address_space *vm) -{ - struct i915_hw_ppgtt *ppgtt = - container_of(vm, struct i915_hw_ppgtt, base); - - gen8_ppgtt_free(ppgtt); -} - /** * gen8_ppgtt_alloc_pagetabs() - Allocate page tables for VA range. * @ppgtt: Master ppgtt structure. @@ -1454,11 +1448,16 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, return ret; } -static void gen6_ppgtt_free(struct i915_hw_ppgtt *ppgtt) +static void gen6_ppgtt_cleanup(struct i915_address_space *vm) { + struct i915_hw_ppgtt *ppgtt = + container_of(vm, struct i915_hw_ppgtt, base); struct i915_page_table *pt; uint32_t pde; + + drm_mm_remove_node(&ppgtt->node); + gen6_for_all_pdes(pt, ppgtt, pde) { if (pt != ppgtt->scratch_pt) unmap_and_free_pt(pt, ppgtt->base.dev); @@ -1468,16 +1467,6 @@ static void gen6_ppgtt_free(struct i915_hw_ppgtt *ppgtt) unmap_and_free_pd(&ppgtt->pd, ppgtt->base.dev); } -static void gen6_ppgtt_cleanup(struct i915_address_space *vm) -{ - struct i915_hw_ppgtt *ppgtt = - container_of(vm, struct i915_hw_ppgtt, base); - - drm_mm_remove_node(&ppgtt->node); - - gen6_ppgtt_free(ppgtt); -} - static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt) { struct drm_device *dev = ppgtt->base.dev; @@ -2268,6 +2257,7 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, ret = __hw_ppgtt_init(dev, ppgtt, true); if (ret) { + ppgtt->base.cleanup(&ppgtt->base); kfree(ppgtt); return ret; } From 5c5f645773b6d147bf68c350674dc3ef4f8de83d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:14 +0200 Subject: [PATCH 0210/3798] drm/i915: Unify aliasing ppgtt handling With the dynamic pagetable alloc code aliasing ppgtt special-cases where again mixed in all over the place with the low-level init code. Extract the va preallocation and clearing again into the common code where aliasing ppgtt gets set up. Note that with this we don't set the size of the aliasing ppgtt to the size of the parent ggtt address space. Which isn't required at all since except for the ppgtt setup/cleanup code no one ever looks at this. Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 134 +++++----------------------- 1 file changed, 24 insertions(+), 110 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index abb11f139d25df..75787f1d275162 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -387,50 +387,6 @@ static struct i915_page_table *alloc_pt_single(struct drm_device *dev) return ERR_PTR(ret); } -/** - * alloc_pt_range() - Allocate a multiple page tables - * @pd: The page directory which will have at least @count entries - * available to point to the allocated page tables. - * @pde: First page directory entry for which we are allocating. - * @count: Number of pages to allocate. - * @dev: DRM device. - * - * Allocates multiple page table pages and sets the appropriate entries in the - * page table structure within the page directory. Function cleans up after - * itself on any failures. - * - * Return: 0 if allocation succeeded. - */ -static int alloc_pt_range(struct i915_page_directory *pd, uint16_t pde, size_t count, - struct drm_device *dev) -{ - int i, ret; - - /* 512 is the max page tables per page_directory on any platform. */ - if (WARN_ON(pde + count > I915_PDES)) - return -EINVAL; - - for (i = pde; i < pde + count; i++) { - struct i915_page_table *pt = alloc_pt_single(dev); - - if (IS_ERR(pt)) { - ret = PTR_ERR(pt); - goto err_out; - } - WARN(pd->page_table[i], - "Leaking page directory entry %d (%p)\n", - i, pd->page_table[i]); - pd->page_table[i] = pt; - } - - return 0; - -err_out: - while (i-- > pde) - unmap_and_free_pt(pd->page_table[i], dev); - return ret; -} - static void unmap_and_free_pd(struct i915_page_directory *pd, struct drm_device *dev) { @@ -971,7 +927,7 @@ static int gen8_alloc_va_range(struct i915_address_space *vm, * space. * */ -static int gen8_ppgtt_init_common(struct i915_hw_ppgtt *ppgtt, uint64_t size) +static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) { ppgtt->scratch_pt = alloc_pt_single(ppgtt->base.dev); if (IS_ERR(ppgtt->scratch_pt)) @@ -985,8 +941,9 @@ static int gen8_ppgtt_init_common(struct i915_hw_ppgtt *ppgtt, uint64_t size) gen8_initialize_pd(&ppgtt->base, ppgtt->scratch_pd); ppgtt->base.start = 0; - ppgtt->base.total = size; + ppgtt->base.total = 1ULL << 32; ppgtt->base.cleanup = gen8_ppgtt_cleanup; + ppgtt->base.allocate_va_range = gen8_alloc_va_range; ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; ppgtt->base.clear_range = gen8_ppgtt_clear_range; ppgtt->base.unbind_vma = ppgtt_unbind_vma; @@ -997,46 +954,6 @@ static int gen8_ppgtt_init_common(struct i915_hw_ppgtt *ppgtt, uint64_t size) return 0; } -static int gen8_aliasing_ppgtt_init(struct i915_hw_ppgtt *ppgtt) -{ - struct drm_device *dev = ppgtt->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - uint64_t start = 0, size = dev_priv->gtt.base.total; - int ret; - - ret = gen8_ppgtt_init_common(ppgtt, dev_priv->gtt.base.total); - if (ret) - return ret; - - /* Aliasing PPGTT has to always work and be mapped because of the way we - * use RESTORE_INHIBIT in the context switch. This will be fixed - * eventually. */ - ret = gen8_alloc_va_range(&ppgtt->base, start, size); - if (ret) { - unmap_and_free_pd(ppgtt->scratch_pd, ppgtt->base.dev); - unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev); - return ret; - } - - ppgtt->base.allocate_va_range = NULL; - ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true); - - return 0; -} - -static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) -{ - int ret; - - ret = gen8_ppgtt_init_common(ppgtt, (1ULL << 32)); - if (ret) - return ret; - - ppgtt->base.allocate_va_range = gen8_alloc_va_range; - - return 0; -} - static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) { struct i915_address_space *vm = &ppgtt->base; @@ -1533,7 +1450,7 @@ static void gen6_scratch_va_range(struct i915_hw_ppgtt *ppgtt, ppgtt->pd.page_table[pde] = ppgtt->scratch_pt; } -static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing) +static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) { struct drm_device *dev = ppgtt->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -1556,18 +1473,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing) if (ret) return ret; - if (aliasing) { - /* preallocate all pts */ - ret = alloc_pt_range(&ppgtt->pd, 0, I915_PDES, - ppgtt->base.dev); - - if (ret) { - gen6_ppgtt_cleanup(&ppgtt->base); - return ret; - } - } - - ppgtt->base.allocate_va_range = aliasing ? NULL : gen6_alloc_va_range; + ppgtt->base.allocate_va_range = gen6_alloc_va_range; ppgtt->base.clear_range = gen6_ppgtt_clear_range; ppgtt->base.insert_entries = gen6_ppgtt_insert_entries; ppgtt->base.unbind_vma = ppgtt_unbind_vma; @@ -1583,10 +1489,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing) ppgtt->pd_addr = (gen6_pte_t __iomem *)dev_priv->gtt.gsm + ppgtt->pd.pd_offset / sizeof(gen6_pte_t); - if (aliasing) - ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true); - else - gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total); + gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total); gen6_write_page_range(dev_priv, &ppgtt->pd, 0, ppgtt->base.total); @@ -1600,8 +1503,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing) return 0; } -static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt, - bool aliasing) +static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -1609,9 +1511,7 @@ static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt, ppgtt->base.scratch = dev_priv->gtt.base.scratch; if (INTEL_INFO(dev)->gen < 8) - return gen6_ppgtt_init(ppgtt, aliasing); - else if (aliasing) - return gen8_aliasing_ppgtt_init(ppgtt); + return gen6_ppgtt_init(ppgtt); else return gen8_ppgtt_init(ppgtt); } @@ -1620,7 +1520,7 @@ int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) struct drm_i915_private *dev_priv = dev->dev_private; int ret = 0; - ret = __hw_ppgtt_init(dev, ppgtt, false); + ret = __hw_ppgtt_init(dev, ppgtt); if (ret == 0) { kref_init(&ppgtt->ref); drm_mm_init(&ppgtt->base.mm, ppgtt->base.start, @@ -2255,13 +2155,27 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, if (!ppgtt) return -ENOMEM; - ret = __hw_ppgtt_init(dev, ppgtt, true); + ret = __hw_ppgtt_init(dev, ppgtt); + if (ret) { + ppgtt->base.cleanup(&ppgtt->base); + kfree(ppgtt); + return ret; + } + + if (ppgtt->base.allocate_va_range) + ret = ppgtt->base.allocate_va_range(&ppgtt->base, 0, + ppgtt->base.total); if (ret) { ppgtt->base.cleanup(&ppgtt->base); kfree(ppgtt); return ret; } + ppgtt->base.clear_range(&ppgtt->base, + ppgtt->base.start, + ppgtt->base.total, + true); + dev_priv->mm.aliasing_ppgtt = ppgtt; } From f329f5f6eb4fad8f2e9c62fe37ec01ae5ce0f212 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:15 +0200 Subject: [PATCH 0211/3798] drm/i915: Move PTE_READ_ONLY to ->pte_encode vfunc It's only used as a flag there, so unconfuse things a bit. Also separate the bind_vma flag space from the pte_encode flag space in the code. Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 15 +++++++++------ drivers/gpu/drm/i915/i915_gem_gtt.h | 3 ++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 75787f1d275162..4e2caef8377250 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1610,14 +1610,16 @@ void i915_ppgtt_release(struct kref *kref) static void ppgtt_bind_vma(struct i915_vma *vma, enum i915_cache_level cache_level, - u32 flags) + u32 unused) { + u32 pte_flags = 0; + /* Currently applicable only to VLV */ if (vma->obj->gt_ro) - flags |= PTE_READ_ONLY; + pte_flags |= PTE_READ_ONLY; vma->vm->insert_entries(vma->vm, vma->obj->pages, vma->node.start, - cache_level, flags); + cache_level, pte_flags); } static void ppgtt_unbind_vma(struct i915_vma *vma) @@ -1986,10 +1988,11 @@ static void ggtt_bind_vma(struct i915_vma *vma, struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj = vma->obj; struct sg_table *pages = obj->pages; + u32 pte_flags = 0; /* Currently applicable only to VLV */ if (obj->gt_ro) - flags |= PTE_READ_ONLY; + pte_flags |= PTE_READ_ONLY; if (i915_is_ggtt(vma->vm)) pages = vma->ggtt_view.pages; @@ -2010,7 +2013,7 @@ static void ggtt_bind_vma(struct i915_vma *vma, (cache_level != obj->cache_level)) { vma->vm->insert_entries(vma->vm, pages, vma->node.start, - cache_level, flags); + cache_level, pte_flags); vma->bound |= GLOBAL_BIND; } } @@ -2021,7 +2024,7 @@ static void ggtt_bind_vma(struct i915_vma *vma, struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt; appgtt->base.insert_entries(&appgtt->base, pages, vma->node.start, - cache_level, flags); + cache_level, pte_flags); vma->bound |= LOCAL_BIND; } } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 12d0ded0d8236c..fb0a04aa5363b5 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -158,7 +158,6 @@ struct i915_vma { /** Flags and address space this VMA is bound to */ #define GLOBAL_BIND (1<<0) #define LOCAL_BIND (1<<1) -#define PTE_READ_ONLY (1<<2) unsigned int bound : 4; /** @@ -261,6 +260,8 @@ struct i915_address_space { gen6_pte_t (*pte_encode)(dma_addr_t addr, enum i915_cache_level level, bool valid, u32 flags); /* Create a valid PTE */ + /* flags for pte_encode */ +#define PTE_READ_ONLY (1<<0) int (*allocate_va_range)(struct i915_address_space *vm, uint64_t start, uint64_t length); From 0229da324d23de67fa4af585b4ef134f721adc84 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 19:01:54 +0200 Subject: [PATCH 0212/3798] drm/i915: Dont clear PIN_GLOBAL in the execbuf pinning fallback PIN_GLOBAL is set only when userspace asked for it, and that is only the case for the gen6 PIPE_CONTROL workaround. We're not allowed to just clear this. The important part of the fallback is to drop the restriction to the mappable range. This issue has been introduced in commit edf4427b8055dc93eb5222d8174b07a75ba24fb5 Author: Chris Wilson Date: Wed Jan 14 11:20:56 2015 +0000 drm/i915: Fallback to using CPU relocations for large batch buffers v2: Chris pointed out that we also miss to set PIN_GLOBAL when the buffer is already bound. Fix this up too. Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 48ac5608481e4b..564425fce1a708 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -586,11 +586,12 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, int ret; flags = 0; + if (entry->flags & EXEC_OBJECT_NEEDS_GTT) + flags |= PIN_GLOBAL; + if (!drm_mm_node_allocated(&vma->node)) { if (entry->flags & __EXEC_OBJECT_NEEDS_MAP) flags |= PIN_GLOBAL | PIN_MAPPABLE; - if (entry->flags & EXEC_OBJECT_NEEDS_GTT) - flags |= PIN_GLOBAL; if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS) flags |= BATCH_OFFSET_BIAS | PIN_OFFSET_BIAS; } @@ -600,7 +601,7 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, only_mappable_for_reloc(entry->flags)) ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, - flags & ~(PIN_GLOBAL | PIN_MAPPABLE)); + flags & ~PIN_MAPPABLE); if (ret) return ret; From 070c1d059f43ce719f4e8a6528c7211197bad3b4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:17 +0200 Subject: [PATCH 0213/3798] drm/i915: Drop redundant GGTT rebinding Since commit bf3d149b25f67f241735b91a56b7f070bc0a5407 Author: Daniel Vetter Date: Fri Feb 14 14:01:12 2014 +0100 drm/i915: split PIN_GLOBAL out from PIN_MAPPABLE i915_gem_obj_ggtt_pin always binds into the ggtt, but I've forgotten to remove the now redundant additional bind call later on. Fix this up. Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index e4c57a3981b35e..dd5bff657c9c85 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -638,7 +638,6 @@ static int do_switch(struct intel_engine_cs *ring, struct intel_context *from = ring->last_context; u32 hw_flags = 0; bool uninitialized = false; - struct i915_vma *vma; int ret, i; if (from != NULL && ring == &dev_priv->ring[RCS]) { @@ -696,16 +695,6 @@ static int do_switch(struct intel_engine_cs *ring, if (ret) goto unpin_out; - vma = i915_gem_obj_to_ggtt(to->legacy_hw_ctx.rcs_state); - if (!(vma->bound & GLOBAL_BIND)) { - ret = i915_vma_bind(vma, - to->legacy_hw_ctx.rcs_state->cache_level, - GLOBAL_BIND); - /* This shouldn't ever fail. */ - if (WARN_ONCE(ret, "GGTT context bind failed!")) - goto unpin_out; - } - if (!to->legacy_hw_ctx.initialized) { hw_flags |= MI_RESTORE_INHIBIT; /* NB: If we inhibit the restore, the context is not allowed to From 7df113e47366e6bbc0dd02c9fa776ae52f4ef5c1 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 17 Apr 2015 12:49:07 +0100 Subject: [PATCH 0214/3798] drm/i915: Fixup kerneldoc for struct intel_context commit ae6c4806927b8b0781ecc187aa16b10c820fc430 Author: Daniel Vetter Date: Wed Aug 6 15:04:53 2014 +0200 drm/i915: Only track real ppgtt for a context Changed the code but didn't update kerneldoc. Signed-off-by: Tvrtko Ursulin Cc: "Thierry, Michel" Cc: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 93e9d36c2b683f..167e0bd79f98b9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -774,7 +774,7 @@ struct i915_ctx_hang_stats { * context). * @hang_stats: information about the role of this context in possible GPU * hangs. - * @vm: virtual memory space used by this context. + * @ppgtt: virtual memory space used by this context. * @legacy_hw_ctx: render context backing object and whether it is correctly * initialized (legacy ring submission mechanism only). * @link: link in the global list of contexts. From 396aa4451e865d1e36d6d4e0686a9303c038b606 Mon Sep 17 00:00:00 2001 From: Todd Previte Date: Sat, 18 Apr 2015 00:04:18 -0700 Subject: [PATCH 0215/3798] drm: Fix for DP CTS test 4.2.2.5 - I2C DEFER handling For test 4.2.2.5 to pass per the Link CTS Core 1.2 rev1.1 spec, the source device must attempt at least 7 times to read the EDID when it receives an I2C defer. The normal DRM code makes only 7 retries, regardless of whether or not the response is a native defer or an I2C defer. Test 4.2.2.5 fails since there are native defers interspersed with the I2C defers which results in less than 7 EDID read attempts. The solution is to add the numer of defers to the retry counter when an I2C DEFER is returned such that another read attempt will be made. This situation should normally only occur in compliance testing, however, as a worse case real-world scenario, it would result in 13 attempts ( 6 native defers, 7 I2C defers) for a single transaction to complete. The net result is a slightly slower response to an EDID read that shouldn't significantly impact overall performance. V2: - Added a check on the number of I2C Defers to limit the number of times that the retries variable will be decremented. This is to address review feedback regarding possible infinite loops from misbehaving sink devices. V3: - Fixed the limit value to 7 instead of 8 to get the correct retry count. - Combined the increment of the defer count into the if-statement V4: - Removed i915 tag from subject as the patch is not i915-specific V5: - Updated the for-loop to add the number of i2c defers to the retry counter such that the correct number of retry attempts will be made Signed-off-by: Todd Previte Cc: dri-devel@lists.freedesktop.org Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_dp_helper.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 575172ed6c3282..80a02a412607f9 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -432,7 +432,7 @@ static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter) */ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { - unsigned int retry; + unsigned int retry, defer_i2c; int ret; /* @@ -440,7 +440,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) * is required to retry at least seven times upon receiving AUX_DEFER * before giving up the AUX transaction. */ - for (retry = 0; retry < 7; retry++) { + for (retry = 0, defer_i2c = 0; retry < (7 + defer_i2c); retry++) { mutex_lock(&aux->hw_mutex); ret = aux->transfer(aux, msg); mutex_unlock(&aux->hw_mutex); @@ -499,7 +499,13 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) case DP_AUX_I2C_REPLY_DEFER: DRM_DEBUG_KMS("I2C defer\n"); + /* DP Compliance Test 4.2.2.5 Requirement: + * Must have at least 7 retries for I2C defers on the + * transaction to pass this test + */ aux->i2c_defer_count++; + if (defer_i2c < 7) + defer_i2c++; usleep_range(400, 500); continue; From a3c6d686443e912e33cebdf9cd80f94df3ded7b0 Mon Sep 17 00:00:00 2001 From: Josef Holzmayr Date: Thu, 16 Apr 2015 14:16:29 +0200 Subject: [PATCH 0216/3798] DRM: Don't re-poll connector for disconnect DRM probe should not repoll a connector if it is already connected and the DRM_CONNECTOR_POLL_DISCONNECT flag is not set. Signed-off-by: Josef Holzmayr Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_probe_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index d44437fc42b13b..2fb2fbe8c2de52 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -322,8 +322,6 @@ static void output_poll_execute(struct work_struct *work) if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) continue; - repoll = true; - old_status = connector->status; /* if we are connected and don't want to poll for disconnect skip it */ @@ -331,6 +329,8 @@ static void output_poll_execute(struct work_struct *work) !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) continue; + repoll = true; + connector->status = connector->funcs->detect(connector, false); if (old_status != connector->status) { const char *old, *new; From 2ebef630fd283642a11c48c0e0f054c3c5c59e86 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 20 Apr 2015 16:22:48 +0100 Subject: [PATCH 0217/3798] drm/i915/skl: Support Y tiling in MMIO flips Add Y tiling support to skl_do_mmio_flip. Signed-off-by: Tvrtko Ursulin Cc: Damien Lespiau Cc: Sonika Jindal Cc: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index be69e84399a495..30dfc73ac7b22b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10556,23 +10556,34 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc) struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_framebuffer *fb = intel_crtc->base.primary->fb; - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj = intel_fb->obj; const enum pipe pipe = intel_crtc->pipe; u32 ctl, stride; ctl = I915_READ(PLANE_CTL(pipe, 0)); ctl &= ~PLANE_CTL_TILED_MASK; - if (obj->tiling_mode == I915_TILING_X) + switch (fb->modifier[0]) { + case DRM_FORMAT_MOD_NONE: + break; + case I915_FORMAT_MOD_X_TILED: ctl |= PLANE_CTL_TILED_X; + break; + case I915_FORMAT_MOD_Y_TILED: + ctl |= PLANE_CTL_TILED_Y; + break; + case I915_FORMAT_MOD_Yf_TILED: + ctl |= PLANE_CTL_TILED_YF; + break; + default: + MISSING_CASE(fb->modifier[0]); + } /* * The stride is either expressed as a multiple of 64 bytes chunks for * linear buffers or in number of tiles for tiled buffers. */ - stride = fb->pitches[0] >> 6; - if (obj->tiling_mode == I915_TILING_X) - stride = fb->pitches[0] >> 9; /* X tiles are 512 bytes wide */ + stride = fb->pitches[0] / + intel_fb_stride_alignment(dev, fb->modifier[0], + fb->pixel_format); /* * Both PLANE_CTL and PLANE_STRIDE are not updated on vblank but on From d0f702e648dc365070f1868ec291264ad27e65d8 Mon Sep 17 00:00:00 2001 From: Chen Hanxiao Date: Thu, 23 Apr 2015 07:57:33 -0400 Subject: [PATCH 0218/3798] cgroup: fix some comment typos s/effctive/effective s/hierarhcy/hierarchy s/shoulid/should Signed-off-by: Chen Hanxiao Signed-off-by: Tejun Heo --- kernel/cgroup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 469dd547770ca3..cfa27f968e6f07 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -261,7 +261,7 @@ static struct cgroup_subsys_state *cgroup_css(struct cgroup *cgrp, * @cgrp: the cgroup of interest * @ss: the subsystem of interest (%NULL returns @cgrp->self) * - * Similar to cgroup_css() but returns the effctive css, which is defined + * Similar to cgroup_css() but returns the effective css, which is defined * as the matching css of the nearest ancestor including self which has @ss * enabled. If @ss is associated with the hierarchy @cgrp is on, this * function is guaranteed to return non-NULL css. @@ -882,7 +882,7 @@ static void cgroup_exit_root_id(struct cgroup_root *root) static void cgroup_free_root(struct cgroup_root *root) { if (root) { - /* hierarhcy ID shoulid already have been released */ + /* hierarchy ID should already have been released */ WARN_ON_ONCE(root->hierarchy_id); idr_destroy(&root->cgroup_idr); From 71b7e54f71b899db9f8def67a0e976969384e699 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:18 +0200 Subject: [PATCH 0219/3798] drm/i915: Don't look at pg_dirty_rings for aliasing ppgtt We load the ppgtt ptes once per gpu reset/driver load/resume and that's all that's needed. Note that this only blows up when we're using the allocate_va_range funcs and not the special-purpose ones used. With this change we can get rid of that duplication. Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 6 ------ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 --- 2 files changed, 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index dd5bff657c9c85..6b0962db2cf7bf 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -575,8 +575,6 @@ static inline bool should_skip_switch(struct intel_engine_cs *ring, struct intel_context *from, struct intel_context *to) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; - if (to->remap_slice) return false; @@ -584,10 +582,6 @@ static inline bool should_skip_switch(struct intel_engine_cs *ring, if (from == to && !test_bit(ring->id, &to->ppgtt->pd_dirty_rings)) return true; - } else if (dev_priv->mm.aliasing_ppgtt) { - if (from == to && !test_bit(ring->id, - &dev_priv->mm.aliasing_ppgtt->pd_dirty_rings)) - return true; } return false; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 564425fce1a708..1cf3468551a257 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1251,9 +1251,6 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, if (ctx->ppgtt) WARN(ctx->ppgtt->pd_dirty_rings & (1<id), "%s didn't clear reload\n", ring->name); - else if (dev_priv->mm.aliasing_ppgtt) - WARN(dev_priv->mm.aliasing_ppgtt->pd_dirty_rings & - (1<id), "%s didn't clear reload\n", ring->name); instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK; instp_mask = I915_EXEC_CONSTANTS_MASK; From 9258811c961879450502f767773227f5c0d79120 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:19 +0200 Subject: [PATCH 0220/3798] drm/i915: Don't use atomics for pg_dirty_rings It's already protected by the bkl^Wdev->struct_mutex. While at it realign some related code. Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 16 ++++++++-------- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 5 ++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 6b0962db2cf7bf..5a47eb5e3c5dca 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -578,11 +578,9 @@ static inline bool should_skip_switch(struct intel_engine_cs *ring, if (to->remap_slice) return false; - if (to->ppgtt) { - if (from == to && !test_bit(ring->id, - &to->ppgtt->pd_dirty_rings)) - return true; - } + if (to->ppgtt && from == to && + !(intel_ring_flag(ring) & to->ppgtt->pd_dirty_rings)) + return true; return false; } @@ -668,7 +666,7 @@ static int do_switch(struct intel_engine_cs *ring, goto unpin_out; /* Doing a PD load always reloads the page dirs */ - clear_bit(ring->id, &to->ppgtt->pd_dirty_rings); + to->ppgtt->pd_dirty_rings &= ~intel_ring_flag(ring); } if (ring != &dev_priv->ring[RCS]) { @@ -696,12 +694,14 @@ static int do_switch(struct intel_engine_cs *ring, * space. This means we must enforce that a page table load * occur when this occurs. */ } else if (to->ppgtt && - test_and_clear_bit(ring->id, &to->ppgtt->pd_dirty_rings)) + (intel_ring_flag(ring) & to->ppgtt->pd_dirty_rings)) { hw_flags |= MI_FORCE_RESTORE; + to->ppgtt->pd_dirty_rings &= ~intel_ring_flag(ring); + } /* We should never emit switch_mm more than once */ WARN_ON(needs_pd_load_pre(ring, to) && - needs_pd_load_post(ring, to, hw_flags)); + needs_pd_load_post(ring, to, hw_flags)); ret = mi_set_context(ring, to, hw_flags); if (ret) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 1cf3468551a257..7f69aa820458bb 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1248,9 +1248,8 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, if (ret) goto error; - if (ctx->ppgtt) - WARN(ctx->ppgtt->pd_dirty_rings & (1<id), - "%s didn't clear reload\n", ring->name); + WARN(ctx->ppgtt && ctx->ppgtt->pd_dirty_rings & (1<id), + "%s didn't clear reload\n", ring->name); instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK; instp_mask = I915_EXEC_CONSTANTS_MASK; From cd102a687beed1042824d5fa81c6ba8bfe78e6a4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:20 +0200 Subject: [PATCH 0221/3798] drm/i915: Remove misleading comment around bind_to_vm It's true that we might need to context switch, but both the signalling and implementation of the same are a few source files away. Remove it. Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8698cff03fc1df..b86da6fceb7680 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4197,10 +4197,6 @@ i915_gem_object_do_pin(struct drm_i915_gem_object *obj, bound = vma ? vma->bound : 0; if (vma == NULL || !drm_mm_node_allocated(&vma->node)) { - /* In true PPGTT, bind has possibly changed PDEs, which - * means we must do a context switch before the GPU can - * accurately read some of the VMAs. - */ vma = i915_gem_object_bind_to_vm(obj, vm, ggtt_view, alignment, flags); if (IS_ERR(vma)) From 0875546c5318c85c13d07014af5350e9000bc9e9 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 20 Apr 2015 09:04:05 -0700 Subject: [PATCH 0222/3798] drm/i915: Fix up the vma aliasing ppgtt binding Currently we have the problem that the decision whether ptes need to be (re)written is splattered all over the codebase. Move all that into i915_vma_bind. This needs a few changes: - Just reuse the PIN_* flags for i915_vma_bind and do the conversion to vma->bound in there to avoid duplicating the conversion code all over. - We need to make binding for EXECBUF (i.e. pick aliasing ppgtt if around) explicit, add PIN_USER for that. - Two callers want to update ptes, give them a PIN_UPDATE for that. Of course we still want to avoid double-binding, but that should be taken care of: - A ppgtt vma will only ever see PIN_USER, so no issue with double-binding. - A ggtt vma with aliasing ppgtt needs both types of binding, and we track that properly now. - A ggtt vma without aliasing ppgtt could be bound twice. In the lower-level ->bind_vma functions hence unconditionally set GLOBAL_BIND when writing the ggtt ptes. There's still a bit room for cleanup, but that's for follow-up patches. v2: Fixup fumbles. v3: s/PIN_EXECBUF/PIN_USER/ for clearer meaning, suggested by Chris. Cc: Chris Wilson Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 11 ++-- drivers/gpu/drm/i915/i915_gem.c | 11 ++-- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 7 +-- drivers/gpu/drm/i915/i915_gem_gtt.c | 65 +++++++++------------- 4 files changed, 40 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 167e0bd79f98b9..906f8851df4c7e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2645,10 +2645,13 @@ void i915_init_vm(struct drm_i915_private *dev_priv, void i915_gem_free_object(struct drm_gem_object *obj); void i915_gem_vma_destroy(struct i915_vma *vma); -#define PIN_MAPPABLE 0x1 -#define PIN_NONBLOCK 0x2 -#define PIN_GLOBAL 0x4 -#define PIN_OFFSET_BIAS 0x8 +/* Flags used by pin/bind&friends. */ +#define PIN_MAPPABLE (1<<0) +#define PIN_NONBLOCK (1<<1) +#define PIN_GLOBAL (1<<2) +#define PIN_OFFSET_BIAS (1<<3) +#define PIN_USER (1<<4) +#define PIN_UPDATE (1<<5) #define PIN_OFFSET_MASK (~4095) int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b86da6fceb7680..91aade7c9f6d5d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3589,8 +3589,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, goto err_remove_node; trace_i915_vma_bind(vma, flags); - ret = i915_vma_bind(vma, obj->cache_level, - flags & PIN_GLOBAL ? GLOBAL_BIND : 0); + ret = i915_vma_bind(vma, obj->cache_level, flags); if (ret) goto err_finish_gtt; @@ -3816,7 +3815,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, list_for_each_entry(vma, &obj->vma_list, vma_link) if (drm_mm_node_allocated(&vma->node)) { ret = i915_vma_bind(vma, cache_level, - vma->bound & GLOBAL_BIND); + PIN_UPDATE); if (ret) return ret; } @@ -4201,10 +4200,8 @@ i915_gem_object_do_pin(struct drm_i915_gem_object *obj, flags); if (IS_ERR(vma)) return PTR_ERR(vma); - } - - if (flags & PIN_GLOBAL && !(vma->bound & GLOBAL_BIND)) { - ret = i915_vma_bind(vma, obj->cache_level, GLOBAL_BIND); + } else { + ret = i915_vma_bind(vma, obj->cache_level, flags); if (ret) return ret; } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 7f69aa820458bb..cfdc8c6073aa87 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -400,10 +400,9 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, * pipe_control writes because the gpu doesn't properly redirect them * through the ppgtt for non_secure batchbuffers. */ if (unlikely(IS_GEN6(dev) && - reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && - !(target_vma->bound & GLOBAL_BIND))) { + reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION)) { ret = i915_vma_bind(target_vma, target_i915_obj->cache_level, - GLOBAL_BIND); + PIN_GLOBAL); if (WARN_ONCE(ret, "Unexpected failure to bind target VMA!")) return ret; } @@ -585,7 +584,7 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, uint64_t flags; int ret; - flags = 0; + flags = PIN_USER; if (entry->flags & EXEC_OBJECT_NEEDS_GTT) flags |= PIN_GLOBAL; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 4e2caef8377250..9e06180e206f5e 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1748,15 +1748,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) continue; i915_gem_clflush_object(obj, obj->pin_display); - /* The bind_vma code tries to be smart about tracking mappings. - * Unfortunately above, we've just wiped out the mappings - * without telling our object about it. So we need to fake it. - * - * Bind is not expected to fail since this is only called on - * resume and assumption is all requirements exist already. - */ - vma->bound &= ~GLOBAL_BIND; - WARN_ON(i915_vma_bind(vma, obj->cache_level, GLOBAL_BIND)); + WARN_ON(i915_vma_bind(vma, obj->cache_level, PIN_UPDATE)); } @@ -1957,7 +1949,8 @@ static void i915_ggtt_bind_vma(struct i915_vma *vma, BUG_ON(!i915_is_ggtt(vma->vm)); intel_gtt_insert_sg_entries(vma->ggtt_view.pages, entry, flags); - vma->bound = GLOBAL_BIND; + + vma->bound |= GLOBAL_BIND; } static void i915_ggtt_clear_range(struct i915_address_space *vm, @@ -1976,7 +1969,6 @@ static void i915_ggtt_unbind_vma(struct i915_vma *vma) const unsigned int size = vma->obj->base.size >> PAGE_SHIFT; BUG_ON(!i915_is_ggtt(vma->vm)); - vma->bound = 0; intel_gtt_clear_range(first, size); } @@ -1997,35 +1989,19 @@ static void ggtt_bind_vma(struct i915_vma *vma, if (i915_is_ggtt(vma->vm)) pages = vma->ggtt_view.pages; - /* If there is no aliasing PPGTT, or the caller needs a global mapping, - * or we have a global mapping already but the cacheability flags have - * changed, set the global PTEs. - * - * If there is an aliasing PPGTT it is anecdotally faster, so use that - * instead if none of the above hold true. - * - * NB: A global mapping should only be needed for special regions like - * "gtt mappable", SNB errata, or if specified via special execbuf - * flags. At all other times, the GPU will use the aliasing PPGTT. - */ if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) { - if (!(vma->bound & GLOBAL_BIND) || - (cache_level != obj->cache_level)) { - vma->vm->insert_entries(vma->vm, pages, - vma->node.start, - cache_level, pte_flags); - vma->bound |= GLOBAL_BIND; - } + vma->vm->insert_entries(vma->vm, pages, + vma->node.start, + cache_level, pte_flags); + + vma->bound |= GLOBAL_BIND; } - if (dev_priv->mm.aliasing_ppgtt && - (!(vma->bound & LOCAL_BIND) || - (cache_level != obj->cache_level))) { + if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) { struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt; appgtt->base.insert_entries(&appgtt->base, pages, vma->node.start, cache_level, pte_flags); - vma->bound |= LOCAL_BIND; } } @@ -2040,16 +2016,14 @@ static void ggtt_unbind_vma(struct i915_vma *vma) vma->node.start, obj->base.size, true); - vma->bound &= ~GLOBAL_BIND; } - if (vma->bound & LOCAL_BIND) { + if (dev_priv->mm.aliasing_ppgtt && vma->bound & LOCAL_BIND) { struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt; appgtt->base.clear_range(&appgtt->base, vma->node.start, obj->base.size, true); - vma->bound &= ~LOCAL_BIND; } } @@ -2839,6 +2813,7 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma) int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags) { + u32 bind_flags = 0; int ret; if (vma->vm->allocate_va_range) { @@ -2855,12 +2830,24 @@ int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, if (i915_is_ggtt(vma->vm)) { ret = i915_get_ggtt_vma_pages(vma); - if (ret) - return ret; + return 0; } - vma->vm->bind_vma(vma, cache_level, flags); + if (flags & PIN_GLOBAL) + bind_flags |= GLOBAL_BIND; + if (flags & PIN_USER) + bind_flags |= LOCAL_BIND; + + if (flags & PIN_UPDATE) + bind_flags |= vma->bound; + else + bind_flags &= ~vma->bound; + + if (bind_flags) + vma->vm->bind_vma(vma, cache_level, bind_flags); + + vma->bound |= bind_flags; return 0; } From fa42331b4cd961cecb3f6919116d2e6efeb2334b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:23 +0200 Subject: [PATCH 0223/3798] drm/i915: move i915_gem_restore_gtt_mappings around Avoids 2 forward declarations. Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 109 ++++++++++++++-------------- 1 file changed, 53 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 9e06180e206f5e..c36dcfeeadd034 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -97,9 +97,6 @@ const struct i915_ggtt_view i915_ggtt_view_rotated = { .type = I915_GGTT_VIEW_ROTATED }; -static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv); -static void chv_setup_private_ppat(struct drm_i915_private *dev_priv); - static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) { bool has_aliasing_ppgtt; @@ -1727,59 +1724,6 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev) i915_ggtt_flush(dev_priv); } -void i915_gem_restore_gtt_mappings(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj; - struct i915_address_space *vm; - - i915_check_and_clear_faults(dev); - - /* First fill our portion of the GTT with scratch pages */ - dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, - dev_priv->gtt.base.start, - dev_priv->gtt.base.total, - true); - - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { - struct i915_vma *vma = i915_gem_obj_to_vma(obj, - &dev_priv->gtt.base); - if (!vma) - continue; - - i915_gem_clflush_object(obj, obj->pin_display); - WARN_ON(i915_vma_bind(vma, obj->cache_level, PIN_UPDATE)); - } - - - if (INTEL_INFO(dev)->gen >= 8) { - if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) - chv_setup_private_ppat(dev_priv); - else - bdw_setup_private_ppat(dev_priv); - - return; - } - - if (USES_PPGTT(dev)) { - list_for_each_entry(vm, &dev_priv->vm_list, global_link) { - /* TODO: Perhaps it shouldn't be gen6 specific */ - - struct i915_hw_ppgtt *ppgtt = - container_of(vm, struct i915_hw_ppgtt, - base); - - if (i915_is_ggtt(vm)) - ppgtt = dev_priv->mm.aliasing_ppgtt; - - gen6_write_page_range(dev_priv, &ppgtt->pd, - 0, ppgtt->base.total); - } - } - - i915_ggtt_flush(dev_priv); -} - int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) { if (obj->has_dma_mapping) @@ -2603,6 +2547,59 @@ int i915_gem_gtt_init(struct drm_device *dev) return 0; } +void i915_gem_restore_gtt_mappings(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj; + struct i915_address_space *vm; + + i915_check_and_clear_faults(dev); + + /* First fill our portion of the GTT with scratch pages */ + dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, + dev_priv->gtt.base.start, + dev_priv->gtt.base.total, + true); + + list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { + struct i915_vma *vma = i915_gem_obj_to_vma(obj, + &dev_priv->gtt.base); + if (!vma) + continue; + + i915_gem_clflush_object(obj, obj->pin_display); + WARN_ON(i915_vma_bind(vma, obj->cache_level, PIN_UPDATE)); + } + + + if (INTEL_INFO(dev)->gen >= 8) { + if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) + chv_setup_private_ppat(dev_priv); + else + bdw_setup_private_ppat(dev_priv); + + return; + } + + if (USES_PPGTT(dev)) { + list_for_each_entry(vm, &dev_priv->vm_list, global_link) { + /* TODO: Perhaps it shouldn't be gen6 specific */ + + struct i915_hw_ppgtt *ppgtt = + container_of(vm, struct i915_hw_ppgtt, + base); + + if (i915_is_ggtt(vm)) + ppgtt = dev_priv->mm.aliasing_ppgtt; + + gen6_write_page_range(dev_priv, &ppgtt->pd, + 0, ppgtt->base.total); + } + } + + i915_ggtt_flush(dev_priv); +} + static struct i915_vma * __i915_gem_vma_create(struct drm_i915_gem_object *obj, struct i915_address_space *vm, From 4755265977159be0261972da2ba54917765b18ed Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:24 +0200 Subject: [PATCH 0224/3798] drm/i915: Move ppgtt_bind/unbind around Again avoids some forward declarations. Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 44 +++++++++++++---------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index c36dcfeeadd034..1abbc1f950848b 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -145,8 +145,25 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) static void ppgtt_bind_vma(struct i915_vma *vma, enum i915_cache_level cache_level, - u32 flags); -static void ppgtt_unbind_vma(struct i915_vma *vma); + u32 unused) +{ + u32 pte_flags = 0; + + /* Currently applicable only to VLV */ + if (vma->obj->gt_ro) + pte_flags |= PTE_READ_ONLY; + + vma->vm->insert_entries(vma->vm, vma->obj->pages, vma->node.start, + cache_level, pte_flags); +} + +static void ppgtt_unbind_vma(struct i915_vma *vma) +{ + vma->vm->clear_range(vma->vm, + vma->node.start, + vma->obj->base.size, + true); +} static inline gen8_pte_t gen8_pte_encode(dma_addr_t addr, enum i915_cache_level level, @@ -1604,29 +1621,6 @@ void i915_ppgtt_release(struct kref *kref) kfree(ppgtt); } -static void -ppgtt_bind_vma(struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 unused) -{ - u32 pte_flags = 0; - - /* Currently applicable only to VLV */ - if (vma->obj->gt_ro) - pte_flags |= PTE_READ_ONLY; - - vma->vm->insert_entries(vma->vm, vma->obj->pages, vma->node.start, - cache_level, pte_flags); -} - -static void ppgtt_unbind_vma(struct i915_vma *vma) -{ - vma->vm->clear_range(vma->vm, - vma->node.start, - vma->obj->base.size, - true); -} - extern int intel_iommu_gfx_mapped; /* Certain Gen5 chipsets require require idling the GPU before * unmapping anything from the GTT when VT-d is enabled. From d369d2d9683dd98afbc7a37c1119d7a317790c47 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:25 +0200 Subject: [PATCH 0225/3798] drm/i915: Unduplicate i915_ggtt_unbind/bind_vma ggtt_bind/unbind_vma already has checks for aliasing ppgtt or not, there's nothing else magic they do. Resurrect i915_ggtt_insert_entries to make the reuse possibel. Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 1abbc1f950848b..09430178049ee3 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1876,19 +1876,16 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, readl(gtt_base); } - -static void i915_ggtt_bind_vma(struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 unused) +static void i915_ggtt_insert_entries(struct i915_address_space *vm, + struct sg_table *pages, + uint64_t start, + enum i915_cache_level cache_level, u32 unused) { - const unsigned long entry = vma->node.start >> PAGE_SHIFT; unsigned int flags = (cache_level == I915_CACHE_NONE) ? AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY; - BUG_ON(!i915_is_ggtt(vma->vm)); - intel_gtt_insert_sg_entries(vma->ggtt_view.pages, entry, flags); + intel_gtt_insert_sg_entries(pages, start >> PAGE_SHIFT, flags); - vma->bound |= GLOBAL_BIND; } static void i915_ggtt_clear_range(struct i915_address_space *vm, @@ -1901,15 +1898,6 @@ static void i915_ggtt_clear_range(struct i915_address_space *vm, intel_gtt_clear_range(first_entry, num_entries); } -static void i915_ggtt_unbind_vma(struct i915_vma *vma) -{ - const unsigned int first = vma->node.start >> PAGE_SHIFT; - const unsigned int size = vma->obj->base.size >> PAGE_SHIFT; - - BUG_ON(!i915_is_ggtt(vma->vm)); - intel_gtt_clear_range(first, size); -} - static void ggtt_bind_vma(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags) @@ -2471,9 +2459,10 @@ static int i915_gmch_probe(struct drm_device *dev, intel_gtt_get(gtt_total, stolen, mappable_base, mappable_end); dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev); + dev_priv->gtt.base.insert_entries = i915_ggtt_insert_entries; dev_priv->gtt.base.clear_range = i915_ggtt_clear_range; - dev_priv->gtt.base.bind_vma = i915_ggtt_bind_vma; - dev_priv->gtt.base.unbind_vma = i915_ggtt_unbind_vma; + dev_priv->gtt.base.bind_vma = ggtt_bind_vma; + dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma; if (unlikely(dev_priv->gtt.do_idle_maps)) DRM_INFO("applying Ironlake quirks for intel_iommu\n"); From 2c642b07eba461a244c32279a00d98ffab39ec07 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:26 +0200 Subject: [PATCH 0226/3798] drm/i915: Don't try to outsmart gcc in i915_gem_gtt.c Sprinkling static inline all over the place is carg-culting. Remove it. Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 38 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 09430178049ee3..9a0bd95d35183f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -165,9 +165,9 @@ static void ppgtt_unbind_vma(struct i915_vma *vma) true); } -static inline gen8_pte_t gen8_pte_encode(dma_addr_t addr, - enum i915_cache_level level, - bool valid) +static gen8_pte_t gen8_pte_encode(dma_addr_t addr, + enum i915_cache_level level, + bool valid) { gen8_pte_t pte = valid ? _PAGE_PRESENT | _PAGE_RW : 0; pte |= addr; @@ -187,9 +187,9 @@ static inline gen8_pte_t gen8_pte_encode(dma_addr_t addr, return pte; } -static inline gen8_pde_t gen8_pde_encode(struct drm_device *dev, - dma_addr_t addr, - enum i915_cache_level level) +static gen8_pde_t gen8_pde_encode(struct drm_device *dev, + dma_addr_t addr, + enum i915_cache_level level) { gen8_pde_t pde = _PAGE_PRESENT | _PAGE_RW; pde |= addr; @@ -299,8 +299,8 @@ static gen6_pte_t iris_pte_encode(dma_addr_t addr, #define i915_dma_unmap_single(px, dev) \ __i915_dma_unmap_single((px)->daddr, dev) -static inline void __i915_dma_unmap_single(dma_addr_t daddr, - struct drm_device *dev) +static void __i915_dma_unmap_single(dma_addr_t daddr, + struct drm_device *dev) { struct device *device = &dev->pdev->dev; @@ -321,9 +321,9 @@ static inline void __i915_dma_unmap_single(dma_addr_t daddr, #define i915_dma_map_single(px, dev) \ i915_dma_map_page_single((px)->page, (dev), &(px)->daddr) -static inline int i915_dma_map_page_single(struct page *page, - struct drm_device *dev, - dma_addr_t *daddr) +static int i915_dma_map_page_single(struct page *page, + struct drm_device *dev, + dma_addr_t *daddr) { struct device *device = &dev->pdev->dev; @@ -1268,7 +1268,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, * are switching between contexts with the same LRCA, we also must do a force * restore. */ -static inline void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt) +static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt) { /* If current vm != vm, */ ppgtt->pd_dirty_rings = INTEL_INFO(ppgtt->base.dev)->ring_mask; @@ -1625,7 +1625,7 @@ extern int intel_iommu_gfx_mapped; /* Certain Gen5 chipsets require require idling the GPU before * unmapping anything from the GTT when VT-d is enabled. */ -static inline bool needs_idle_maps(struct drm_device *dev) +static bool needs_idle_maps(struct drm_device *dev) { #ifdef CONFIG_INTEL_IOMMU /* Query intel_iommu to see if we need the workaround. Presumably that @@ -1731,7 +1731,7 @@ int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) return 0; } -static inline void gen8_set_pte(void __iomem *addr, gen8_pte_t pte) +static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte) { #ifdef writeq writeq(pte, addr); @@ -2154,14 +2154,14 @@ static void teardown_scratch_page(struct drm_device *dev) __free_page(page); } -static inline unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) +static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) { snb_gmch_ctl >>= SNB_GMCH_GGMS_SHIFT; snb_gmch_ctl &= SNB_GMCH_GGMS_MASK; return snb_gmch_ctl << 20; } -static inline unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl) +static unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl) { bdw_gmch_ctl >>= BDW_GMCH_GGMS_SHIFT; bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK; @@ -2177,7 +2177,7 @@ static inline unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl) return bdw_gmch_ctl << 20; } -static inline unsigned int chv_get_total_gtt_size(u16 gmch_ctrl) +static unsigned int chv_get_total_gtt_size(u16 gmch_ctrl) { gmch_ctrl >>= SNB_GMCH_GGMS_SHIFT; gmch_ctrl &= SNB_GMCH_GGMS_MASK; @@ -2188,14 +2188,14 @@ static inline unsigned int chv_get_total_gtt_size(u16 gmch_ctrl) return 0; } -static inline size_t gen6_get_stolen_size(u16 snb_gmch_ctl) +static size_t gen6_get_stolen_size(u16 snb_gmch_ctl) { snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT; snb_gmch_ctl &= SNB_GMCH_GMS_MASK; return snb_gmch_ctl << 25; /* 32 MB units */ } -static inline size_t gen8_get_stolen_size(u16 bdw_gmch_ctl) +static size_t gen8_get_stolen_size(u16 bdw_gmch_ctl) { bdw_gmch_ctl >>= BDW_GMCH_GMS_SHIFT; bdw_gmch_ctl &= BDW_GMCH_GMS_MASK; From 70b9f6f8321f06788dc31783974750cb82745b65 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:27 +0200 Subject: [PATCH 0227/3798] rm/i915: Move i915_get_ggtt_vma_pages into ggtt_bind_vma We have this neat abstraction between ppgtt and ggtt for (un)bind_vma and didn't end up using it really. What a shame, so fix this and make the ->bind_vma hook a bit more useful. Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 41 +++++++++++++++++------------ drivers/gpu/drm/i915/i915_gem_gtt.h | 6 ++--- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 9a0bd95d35183f..6fae6bdde156f1 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -92,6 +92,9 @@ * */ +static int +i915_get_ggtt_vma_pages(struct i915_vma *vma); + const struct i915_ggtt_view i915_ggtt_view_normal; const struct i915_ggtt_view i915_ggtt_view_rotated = { .type = I915_GGTT_VIEW_ROTATED @@ -143,9 +146,9 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) return has_aliasing_ppgtt ? 1 : 0; } -static void ppgtt_bind_vma(struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 unused) +static int ppgtt_bind_vma(struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 unused) { u32 pte_flags = 0; @@ -155,6 +158,8 @@ static void ppgtt_bind_vma(struct i915_vma *vma, vma->vm->insert_entries(vma->vm, vma->obj->pages, vma->node.start, cache_level, pte_flags); + + return 0; } static void ppgtt_unbind_vma(struct i915_vma *vma) @@ -1898,22 +1903,26 @@ static void i915_ggtt_clear_range(struct i915_address_space *vm, intel_gtt_clear_range(first_entry, num_entries); } -static void ggtt_bind_vma(struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) +static int ggtt_bind_vma(struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags) { struct drm_device *dev = vma->vm->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj = vma->obj; struct sg_table *pages = obj->pages; u32 pte_flags = 0; + int ret; + + ret = i915_get_ggtt_vma_pages(vma); + if (ret) + return ret; + pages = vma->ggtt_view.pages; /* Currently applicable only to VLV */ if (obj->gt_ro) pte_flags |= PTE_READ_ONLY; - if (i915_is_ggtt(vma->vm)) - pages = vma->ggtt_view.pages; if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) { vma->vm->insert_entries(vma->vm, pages, @@ -1929,6 +1938,8 @@ static void ggtt_bind_vma(struct i915_vma *vma, vma->node.start, cache_level, pte_flags); } + + return 0; } static void ggtt_unbind_vma(struct i915_vma *vma) @@ -2749,7 +2760,7 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, return ERR_PTR(ret); } -static inline int +static int i915_get_ggtt_vma_pages(struct i915_vma *vma) { int ret = 0; @@ -2793,8 +2804,8 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma) int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags) { + int ret = 0; u32 bind_flags = 0; - int ret; if (vma->vm->allocate_va_range) { trace_i915_va_alloc(vma->vm, vma->node.start, @@ -2808,12 +2819,6 @@ int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, return ret; } - if (i915_is_ggtt(vma->vm)) { - ret = i915_get_ggtt_vma_pages(vma); - if (ret) - return 0; - } - if (flags & PIN_GLOBAL) bind_flags |= GLOBAL_BIND; if (flags & PIN_USER) @@ -2825,7 +2830,9 @@ int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, bind_flags &= ~vma->bound; if (bind_flags) - vma->vm->bind_vma(vma, cache_level, bind_flags); + ret = vma->vm->bind_vma(vma, cache_level, bind_flags); + if (ret) + return ret; vma->bound |= bind_flags; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index fb0a04aa5363b5..4e6cac575cd8e5 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -278,9 +278,9 @@ struct i915_address_space { * setting the valid PTE entries to a reserved scratch page. */ void (*unbind_vma)(struct i915_vma *vma); /* Map an object into an address space with the given cache flags. */ - void (*bind_vma)(struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags); + int (*bind_vma)(struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags); }; /* The Graphics Translation Table is the way in which GEN hardware translates a From 14f1fa2d0c86bcce0a66196acb32648c2f083b87 Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Thu, 23 Apr 2015 10:17:34 +0200 Subject: [PATCH 0228/3798] =?UTF-8?q?drm/i915:=C2=A0Enable=20dithering=20o?= =?UTF-8?q?n=20NatSemi=20DVO2501=20for=20Fujitsu=20S6010?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch enables the (unfortunately undocumented) scaler of the NatSemi 2501 DVO found in the Fujitsu-Siemens S6010 laptop and other machines of the same series and age. Parts of the DVO scaler logic have been revealed by reverse engineering and trial and error, so your milage may vary. The patch (and the whole ns2501 DVO code) is currently only good for the 1024x768 panel of the S6010, and may hopefully work on other machines with the same panel size. The mode-specific configuration of the scaler have been moved out into a separate class, the mode-agnostic settings remain as raw register list as their purpose remains unclear at this point. Signed-off-by: Daniel Vetter Signed-off-by: Thomas Richter [danvet: Make the thing apply and conform to kernel patch expectations.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/dvo_ns2501.c | 670 +++++++++++++++++------------- 1 file changed, 374 insertions(+), 296 deletions(-) diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c b/drivers/gpu/drm/i915/dvo_ns2501.c index 441630434d3474..97ae8aa157e9ad 100644 --- a/drivers/gpu/drm/i915/dvo_ns2501.c +++ b/drivers/gpu/drm/i915/dvo_ns2501.c @@ -60,6 +60,130 @@ #define NS2501_REGC 0x0c +/* + * The following registers are not part of the official datasheet + * and are the result of reverse engineering. + */ + +/* + * Register c0 controls how the DVO synchronizes with + * its input. + */ +#define NS2501_REGC0 0xc0 +#define NS2501_C0_ENABLE (1<<0) /* enable the DVO sync in general */ +#define NS2501_C0_HSYNC (1<<1) /* synchronize horizontal with input */ +#define NS2501_C0_VSYNC (1<<2) /* synchronize vertical with input */ +#define NS2501_C0_RESET (1<<7) /* reset the synchronization flip/flops */ + +/* + * Register 41 is somehow related to the sync register and sync + * configuration. It should be 0x32 whenever regC0 is 0x05 (hsync off) + * and 0x00 otherwise. + */ +#define NS2501_REG41 0x41 + +/* + * this register controls the dithering of the DVO + * One bit enables it, the other define the dithering depth. + * The higher the value, the lower the dithering depth. + */ +#define NS2501_F9_REG 0xf9 +#define NS2501_F9_ENABLE (1<<0) /* if set, dithering is enabled */ +#define NS2501_F9_DITHER_MASK (0x7f<<1) /* controls the dither depth */ +#define NS2501_F9_DITHER_SHIFT 1 /* shifts the dither mask */ + +/* + * PLL configuration register. This is a pair of registers, + * one single byte register at 1B, and a pair at 1C,1D. + * These registers are counters/dividers. + */ +#define NS2501_REG1B 0x1b /* one byte PLL control register */ +#define NS2501_REG1C 0x1c /* low-part of the second register */ +#define NS2501_REG1D 0x1d /* high-part of the second register */ + +/* + * Scaler control registers. Horizontal at b8,b9, + * vertical at 10,11. The scale factor is computed as + * 2^16/control-value. The low-byte comes first. + */ +#define NS2501_REG10 0x10 /* low-byte vertical scaler */ +#define NS2501_REG11 0x11 /* high-byte vertical scaler */ +#define NS2501_REGB8 0xb8 /* low-byte horizontal scaler */ +#define NS2501_REGB9 0xb9 /* high-byte horizontal scaler */ + +/* + * Display window definition. This consists of four registers + * per dimension. One register pair defines the start of the + * display, one the end. + * As far as I understand, this defines the window within which + * the scaler samples the input. + */ +#define NS2501_REGC1 0xc1 /* low-byte horizontal display start */ +#define NS2501_REGC2 0xc2 /* high-byte horizontal display start */ +#define NS2501_REGC3 0xc3 /* low-byte horizontal display stop */ +#define NS2501_REGC4 0xc4 /* high-byte horizontal display stop */ +#define NS2501_REGC5 0xc5 /* low-byte vertical display start */ +#define NS2501_REGC6 0xc6 /* high-byte vertical display start */ +#define NS2501_REGC7 0xc7 /* low-byte vertical display stop */ +#define NS2501_REGC8 0xc8 /* high-byte vertical display stop */ + +/* + * The following register pair seems to define the start of + * the vertical sync. If automatic syncing is enabled, and the + * register value defines a sync pulse that is later than the + * incoming sync, then the register value is ignored and the + * external hsync triggers the synchronization. + */ +#define NS2501_REG80 0x80 /* low-byte vsync-start */ +#define NS2501_REG81 0x81 /* high-byte vsync-start */ + +/* + * The following register pair seems to define the total number + * of lines created at the output side of the scaler. + * This is again a low-high register pair. + */ +#define NS2501_REG82 0x82 /* output display height, low byte */ +#define NS2501_REG83 0x83 /* output display height, high byte */ + +/* + * The following registers define the end of the front-porch + * in horizontal and vertical position and hence allow to shift + * the image left/right or up/down. + */ +#define NS2501_REG98 0x98 /* horizontal start of display + 256, low */ +#define NS2501_REG99 0x99 /* horizontal start of display + 256, high */ +#define NS2501_REG8E 0x8e /* vertical start of the display, low byte */ +#define NS2501_REG8F 0x8f /* vertical start of the display, high byte */ + +/* + * The following register pair control the function of the + * backlight and the DVO output. To enable the corresponding + * function, the corresponding bit must be set in both registers. + */ +#define NS2501_REG34 0x34 /* DVO enable functions, first register */ +#define NS2501_REG35 0x35 /* DVO enable functions, second register */ +#define NS2501_34_ENABLE_OUTPUT (1<<0) /* enable DVO output */ +#define NS2501_34_ENABLE_BACKLIGHT (1<<1) /* enable backlight */ + +/* + * Registers 9C and 9D define the vertical output offset + * of the visible region. + */ +#define NS2501_REG9C 0x9c +#define NS2501_REG9D 0x9d + +/* + * The register 9F defines the dithering. This requires the + * scaler to be ON. Bit 0 enables dithering, the remaining + * bits control the depth of the dither. The higher the value, + * the LOWER the dithering amplitude. A good value seems to be + * 15 (total register value). + */ +#define NS2501_REGF9 0xf9 +#define NS2501_F9_ENABLE_DITHER (1<<0) /* enable dithering */ +#define NS2501_F9_DITHER_MASK (0x7f<<1) /* dither masking */ +#define NS2501_F9_DITHER_SHIFT 1 /* upshift of the dither mask */ + enum { MODE_640x480, MODE_800x600, @@ -72,274 +196,178 @@ struct ns2501_reg { }; /* - * Magic values based on what the BIOS on - * Fujitsu-Siemens Lifebook S6010 programs (1024x768 panel). + * The following structure keeps the complete configuration of + * the DVO, given a specific output configuration. + * This is pretty much guess-work from reverse-engineering, so + * read all this with a grain of salt. + */ +struct ns2501_configuration { + uint8_t sync; /* configuration of the C0 register */ + uint8_t conf; /* configuration register 8 */ + uint8_t syncb; /* configuration register 41 */ + uint8_t dither; /* configuration of the dithering */ + uint8_t pll_a; /* PLL configuration, register A, 1B */ + uint16_t pll_b; /* PLL configuration, register B, 1C/1D */ + uint16_t hstart; /* horizontal start, registers C1/C2 */ + uint16_t hstop; /* horizontal total, registers C3/C4 */ + uint16_t vstart; /* vertical start, registers C5/C6 */ + uint16_t vstop; /* vertical total, registers C7/C8 */ + uint16_t vsync; /* manual vertical sync start, 80/81 */ + uint16_t vtotal; /* number of lines generated, 82/83 */ + uint16_t hpos; /* horizontal position + 256, 98/99 */ + uint16_t vpos; /* vertical position, 8e/8f */ + uint16_t voffs; /* vertical output offset, 9c/9d */ + uint16_t hscale; /* horizontal scaling factor, b8/b9 */ + uint16_t vscale; /* vertical scaling factor, 10/11 */ +}; + +/* + * DVO configuration values, partially based on what the BIOS + * of the Fujitsu Lifebook S6010 writes into registers, + * partially found by manual tweaking. These configurations assume + * a 1024x768 panel. */ -static const struct ns2501_reg regs_1024x768[][86] = { +static const struct ns2501_configuration ns2501_modes[] = { [MODE_640x480] = { - [0] = { .offset = 0x0a, .value = 0x81, }, - [1] = { .offset = 0x18, .value = 0x07, }, - [2] = { .offset = 0x19, .value = 0x00, }, - [3] = { .offset = 0x1a, .value = 0x00, }, - [4] = { .offset = 0x1b, .value = 0x11, }, - [5] = { .offset = 0x1c, .value = 0x54, }, - [6] = { .offset = 0x1d, .value = 0x03, }, - [7] = { .offset = 0x1e, .value = 0x02, }, - [8] = { .offset = 0xf3, .value = 0x90, }, - [9] = { .offset = 0xf9, .value = 0x00, }, - [10] = { .offset = 0xc1, .value = 0x90, }, - [11] = { .offset = 0xc2, .value = 0x00, }, - [12] = { .offset = 0xc3, .value = 0x0f, }, - [13] = { .offset = 0xc4, .value = 0x03, }, - [14] = { .offset = 0xc5, .value = 0x16, }, - [15] = { .offset = 0xc6, .value = 0x00, }, - [16] = { .offset = 0xc7, .value = 0x02, }, - [17] = { .offset = 0xc8, .value = 0x02, }, - [18] = { .offset = 0xf4, .value = 0x00, }, - [19] = { .offset = 0x80, .value = 0xff, }, - [20] = { .offset = 0x81, .value = 0x07, }, - [21] = { .offset = 0x82, .value = 0x3d, }, - [22] = { .offset = 0x83, .value = 0x05, }, - [23] = { .offset = 0x94, .value = 0x00, }, - [24] = { .offset = 0x95, .value = 0x00, }, - [25] = { .offset = 0x96, .value = 0x05, }, - [26] = { .offset = 0x97, .value = 0x00, }, - [27] = { .offset = 0x9a, .value = 0x88, }, - [28] = { .offset = 0x9b, .value = 0x00, }, - [29] = { .offset = 0x98, .value = 0x00, }, - [30] = { .offset = 0x99, .value = 0x00, }, - [31] = { .offset = 0xf7, .value = 0x88, }, - [32] = { .offset = 0xf8, .value = 0x0a, }, - [33] = { .offset = 0x9c, .value = 0x24, }, - [34] = { .offset = 0x9d, .value = 0x00, }, - [35] = { .offset = 0x9e, .value = 0x25, }, - [36] = { .offset = 0x9f, .value = 0x03, }, - [37] = { .offset = 0xa0, .value = 0x28, }, - [38] = { .offset = 0xa1, .value = 0x01, }, - [39] = { .offset = 0xa2, .value = 0x28, }, - [40] = { .offset = 0xa3, .value = 0x05, }, - [41] = { .offset = 0xb6, .value = 0x09, }, - [42] = { .offset = 0xb8, .value = 0x00, }, - [43] = { .offset = 0xb9, .value = 0xa0, }, - [44] = { .offset = 0xba, .value = 0x00, }, - [45] = { .offset = 0xbb, .value = 0x20, }, - [46] = { .offset = 0x10, .value = 0x00, }, - [47] = { .offset = 0x11, .value = 0xa0, }, - [48] = { .offset = 0x12, .value = 0x02, }, - [49] = { .offset = 0x20, .value = 0x00, }, - [50] = { .offset = 0x22, .value = 0x00, }, - [51] = { .offset = 0x23, .value = 0x00, }, - [52] = { .offset = 0x24, .value = 0x00, }, - [53] = { .offset = 0x25, .value = 0x00, }, - [54] = { .offset = 0x8c, .value = 0x10, }, - [55] = { .offset = 0x8d, .value = 0x02, }, - [56] = { .offset = 0x8e, .value = 0x10, }, - [57] = { .offset = 0x8f, .value = 0x00, }, - [58] = { .offset = 0x90, .value = 0xff, }, - [59] = { .offset = 0x91, .value = 0x07, }, - [60] = { .offset = 0x92, .value = 0xa0, }, - [61] = { .offset = 0x93, .value = 0x02, }, - [62] = { .offset = 0xa5, .value = 0x00, }, - [63] = { .offset = 0xa6, .value = 0x00, }, - [64] = { .offset = 0xa7, .value = 0x00, }, - [65] = { .offset = 0xa8, .value = 0x00, }, - [66] = { .offset = 0xa9, .value = 0x04, }, - [67] = { .offset = 0xaa, .value = 0x70, }, - [68] = { .offset = 0xab, .value = 0x4f, }, - [69] = { .offset = 0xac, .value = 0x00, }, - [70] = { .offset = 0xa4, .value = 0x84, }, - [71] = { .offset = 0x7e, .value = 0x18, }, - [72] = { .offset = 0x84, .value = 0x00, }, - [73] = { .offset = 0x85, .value = 0x00, }, - [74] = { .offset = 0x86, .value = 0x00, }, - [75] = { .offset = 0x87, .value = 0x00, }, - [76] = { .offset = 0x88, .value = 0x00, }, - [77] = { .offset = 0x89, .value = 0x00, }, - [78] = { .offset = 0x8a, .value = 0x00, }, - [79] = { .offset = 0x8b, .value = 0x00, }, - [80] = { .offset = 0x26, .value = 0x00, }, - [81] = { .offset = 0x27, .value = 0x00, }, - [82] = { .offset = 0xad, .value = 0x00, }, - [83] = { .offset = 0x08, .value = 0x30, }, /* 0x31 */ - [84] = { .offset = 0x41, .value = 0x00, }, - [85] = { .offset = 0xc0, .value = 0x05, }, + .sync = NS2501_C0_ENABLE | NS2501_C0_VSYNC, + .conf = NS2501_8_VEN | NS2501_8_HEN | NS2501_8_PD, + .syncb = 0x32, + .dither = 0x0f, + .pll_a = 17, + .pll_b = 852, + .hstart = 144, + .hstop = 783, + .vstart = 22, + .vstop = 514, + .vsync = 2047, /* actually, ignored with this config */ + .vtotal = 1341, + .hpos = 0, + .vpos = 16, + .voffs = 36, + .hscale = 40960, + .vscale = 40960 }, [MODE_800x600] = { - [0] = { .offset = 0x0a, .value = 0x81, }, - [1] = { .offset = 0x18, .value = 0x07, }, - [2] = { .offset = 0x19, .value = 0x00, }, - [3] = { .offset = 0x1a, .value = 0x00, }, - [4] = { .offset = 0x1b, .value = 0x19, }, - [5] = { .offset = 0x1c, .value = 0x64, }, - [6] = { .offset = 0x1d, .value = 0x02, }, - [7] = { .offset = 0x1e, .value = 0x02, }, - [8] = { .offset = 0xf3, .value = 0x90, }, - [9] = { .offset = 0xf9, .value = 0x00, }, - [10] = { .offset = 0xc1, .value = 0xd7, }, - [11] = { .offset = 0xc2, .value = 0x00, }, - [12] = { .offset = 0xc3, .value = 0xf8, }, - [13] = { .offset = 0xc4, .value = 0x03, }, - [14] = { .offset = 0xc5, .value = 0x1a, }, - [15] = { .offset = 0xc6, .value = 0x00, }, - [16] = { .offset = 0xc7, .value = 0x73, }, - [17] = { .offset = 0xc8, .value = 0x02, }, - [18] = { .offset = 0xf4, .value = 0x00, }, - [19] = { .offset = 0x80, .value = 0x27, }, - [20] = { .offset = 0x81, .value = 0x03, }, - [21] = { .offset = 0x82, .value = 0x41, }, - [22] = { .offset = 0x83, .value = 0x05, }, - [23] = { .offset = 0x94, .value = 0x00, }, - [24] = { .offset = 0x95, .value = 0x00, }, - [25] = { .offset = 0x96, .value = 0x05, }, - [26] = { .offset = 0x97, .value = 0x00, }, - [27] = { .offset = 0x9a, .value = 0x88, }, - [28] = { .offset = 0x9b, .value = 0x00, }, - [29] = { .offset = 0x98, .value = 0x00, }, - [30] = { .offset = 0x99, .value = 0x00, }, - [31] = { .offset = 0xf7, .value = 0x88, }, - [32] = { .offset = 0xf8, .value = 0x06, }, - [33] = { .offset = 0x9c, .value = 0x23, }, - [34] = { .offset = 0x9d, .value = 0x00, }, - [35] = { .offset = 0x9e, .value = 0x25, }, - [36] = { .offset = 0x9f, .value = 0x03, }, - [37] = { .offset = 0xa0, .value = 0x28, }, - [38] = { .offset = 0xa1, .value = 0x01, }, - [39] = { .offset = 0xa2, .value = 0x28, }, - [40] = { .offset = 0xa3, .value = 0x05, }, - [41] = { .offset = 0xb6, .value = 0x09, }, - [42] = { .offset = 0xb8, .value = 0x30, }, - [43] = { .offset = 0xb9, .value = 0xc8, }, - [44] = { .offset = 0xba, .value = 0x00, }, - [45] = { .offset = 0xbb, .value = 0x20, }, - [46] = { .offset = 0x10, .value = 0x20, }, - [47] = { .offset = 0x11, .value = 0xc8, }, - [48] = { .offset = 0x12, .value = 0x02, }, - [49] = { .offset = 0x20, .value = 0x00, }, - [50] = { .offset = 0x22, .value = 0x00, }, - [51] = { .offset = 0x23, .value = 0x00, }, - [52] = { .offset = 0x24, .value = 0x00, }, - [53] = { .offset = 0x25, .value = 0x00, }, - [54] = { .offset = 0x8c, .value = 0x10, }, - [55] = { .offset = 0x8d, .value = 0x02, }, - [56] = { .offset = 0x8e, .value = 0x04, }, - [57] = { .offset = 0x8f, .value = 0x00, }, - [58] = { .offset = 0x90, .value = 0xff, }, - [59] = { .offset = 0x91, .value = 0x07, }, - [60] = { .offset = 0x92, .value = 0xa0, }, - [61] = { .offset = 0x93, .value = 0x02, }, - [62] = { .offset = 0xa5, .value = 0x00, }, - [63] = { .offset = 0xa6, .value = 0x00, }, - [64] = { .offset = 0xa7, .value = 0x00, }, - [65] = { .offset = 0xa8, .value = 0x00, }, - [66] = { .offset = 0xa9, .value = 0x83, }, - [67] = { .offset = 0xaa, .value = 0x40, }, - [68] = { .offset = 0xab, .value = 0x32, }, - [69] = { .offset = 0xac, .value = 0x00, }, - [70] = { .offset = 0xa4, .value = 0x80, }, - [71] = { .offset = 0x7e, .value = 0x18, }, - [72] = { .offset = 0x84, .value = 0x00, }, - [73] = { .offset = 0x85, .value = 0x00, }, - [74] = { .offset = 0x86, .value = 0x00, }, - [75] = { .offset = 0x87, .value = 0x00, }, - [76] = { .offset = 0x88, .value = 0x00, }, - [77] = { .offset = 0x89, .value = 0x00, }, - [78] = { .offset = 0x8a, .value = 0x00, }, - [79] = { .offset = 0x8b, .value = 0x00, }, - [80] = { .offset = 0x26, .value = 0x00, }, - [81] = { .offset = 0x27, .value = 0x00, }, - [82] = { .offset = 0xad, .value = 0x00, }, - [83] = { .offset = 0x08, .value = 0x30, }, /* 0x31 */ - [84] = { .offset = 0x41, .value = 0x00, }, - [85] = { .offset = 0xc0, .value = 0x07, }, + .sync = NS2501_C0_ENABLE | + NS2501_C0_HSYNC | NS2501_C0_VSYNC, + .conf = NS2501_8_VEN | NS2501_8_HEN | NS2501_8_PD, + .syncb = 0x00, + .dither = 0x0f, + .pll_a = 25, + .pll_b = 612, + .hstart = 215, + .hstop = 1016, + .vstart = 26, + .vstop = 627, + .vsync = 807, + .vtotal = 1341, + .hpos = 0, + .vpos = 4, + .voffs = 35, + .hscale = 51248, + .vscale = 51232 }, [MODE_1024x768] = { - [0] = { .offset = 0x0a, .value = 0x81, }, - [1] = { .offset = 0x18, .value = 0x07, }, - [2] = { .offset = 0x19, .value = 0x00, }, - [3] = { .offset = 0x1a, .value = 0x00, }, - [4] = { .offset = 0x1b, .value = 0x11, }, - [5] = { .offset = 0x1c, .value = 0x54, }, - [6] = { .offset = 0x1d, .value = 0x03, }, - [7] = { .offset = 0x1e, .value = 0x02, }, - [8] = { .offset = 0xf3, .value = 0x90, }, - [9] = { .offset = 0xf9, .value = 0x00, }, - [10] = { .offset = 0xc1, .value = 0x90, }, - [11] = { .offset = 0xc2, .value = 0x00, }, - [12] = { .offset = 0xc3, .value = 0x0f, }, - [13] = { .offset = 0xc4, .value = 0x03, }, - [14] = { .offset = 0xc5, .value = 0x16, }, - [15] = { .offset = 0xc6, .value = 0x00, }, - [16] = { .offset = 0xc7, .value = 0x02, }, - [17] = { .offset = 0xc8, .value = 0x02, }, - [18] = { .offset = 0xf4, .value = 0x00, }, - [19] = { .offset = 0x80, .value = 0xff, }, - [20] = { .offset = 0x81, .value = 0x07, }, - [21] = { .offset = 0x82, .value = 0x3d, }, - [22] = { .offset = 0x83, .value = 0x05, }, - [23] = { .offset = 0x94, .value = 0x00, }, - [24] = { .offset = 0x95, .value = 0x00, }, - [25] = { .offset = 0x96, .value = 0x05, }, - [26] = { .offset = 0x97, .value = 0x00, }, - [27] = { .offset = 0x9a, .value = 0x88, }, - [28] = { .offset = 0x9b, .value = 0x00, }, - [29] = { .offset = 0x98, .value = 0x00, }, - [30] = { .offset = 0x99, .value = 0x00, }, - [31] = { .offset = 0xf7, .value = 0x88, }, - [32] = { .offset = 0xf8, .value = 0x0a, }, - [33] = { .offset = 0x9c, .value = 0x24, }, - [34] = { .offset = 0x9d, .value = 0x00, }, - [35] = { .offset = 0x9e, .value = 0x25, }, - [36] = { .offset = 0x9f, .value = 0x03, }, - [37] = { .offset = 0xa0, .value = 0x28, }, - [38] = { .offset = 0xa1, .value = 0x01, }, - [39] = { .offset = 0xa2, .value = 0x28, }, - [40] = { .offset = 0xa3, .value = 0x05, }, - [41] = { .offset = 0xb6, .value = 0x09, }, - [42] = { .offset = 0xb8, .value = 0x00, }, - [43] = { .offset = 0xb9, .value = 0xa0, }, - [44] = { .offset = 0xba, .value = 0x00, }, - [45] = { .offset = 0xbb, .value = 0x20, }, - [46] = { .offset = 0x10, .value = 0x00, }, - [47] = { .offset = 0x11, .value = 0xa0, }, - [48] = { .offset = 0x12, .value = 0x02, }, - [49] = { .offset = 0x20, .value = 0x00, }, - [50] = { .offset = 0x22, .value = 0x00, }, - [51] = { .offset = 0x23, .value = 0x00, }, - [52] = { .offset = 0x24, .value = 0x00, }, - [53] = { .offset = 0x25, .value = 0x00, }, - [54] = { .offset = 0x8c, .value = 0x10, }, - [55] = { .offset = 0x8d, .value = 0x02, }, - [56] = { .offset = 0x8e, .value = 0x10, }, - [57] = { .offset = 0x8f, .value = 0x00, }, - [58] = { .offset = 0x90, .value = 0xff, }, - [59] = { .offset = 0x91, .value = 0x07, }, - [60] = { .offset = 0x92, .value = 0xa0, }, - [61] = { .offset = 0x93, .value = 0x02, }, - [62] = { .offset = 0xa5, .value = 0x00, }, - [63] = { .offset = 0xa6, .value = 0x00, }, - [64] = { .offset = 0xa7, .value = 0x00, }, - [65] = { .offset = 0xa8, .value = 0x00, }, - [66] = { .offset = 0xa9, .value = 0x04, }, - [67] = { .offset = 0xaa, .value = 0x70, }, - [68] = { .offset = 0xab, .value = 0x4f, }, - [69] = { .offset = 0xac, .value = 0x00, }, - [70] = { .offset = 0xa4, .value = 0x84, }, - [71] = { .offset = 0x7e, .value = 0x18, }, - [72] = { .offset = 0x84, .value = 0x00, }, - [73] = { .offset = 0x85, .value = 0x00, }, - [74] = { .offset = 0x86, .value = 0x00, }, - [75] = { .offset = 0x87, .value = 0x00, }, - [76] = { .offset = 0x88, .value = 0x00, }, - [77] = { .offset = 0x89, .value = 0x00, }, - [78] = { .offset = 0x8a, .value = 0x00, }, - [79] = { .offset = 0x8b, .value = 0x00, }, - [80] = { .offset = 0x26, .value = 0x00, }, - [81] = { .offset = 0x27, .value = 0x00, }, - [82] = { .offset = 0xad, .value = 0x00, }, - [83] = { .offset = 0x08, .value = 0x34, }, /* 0x35 */ - [84] = { .offset = 0x41, .value = 0x00, }, - [85] = { .offset = 0xc0, .value = 0x01, }, - }, + .sync = NS2501_C0_ENABLE | NS2501_C0_VSYNC, + .conf = NS2501_8_VEN | NS2501_8_HEN | NS2501_8_PD, + .syncb = 0x32, + .dither = 0x0f, + .pll_a = 11, + .pll_b = 1350, + .hstart = 276, + .hstop = 1299, + .vstart = 15, + .vstop = 1056, + .vsync = 2047, + .vtotal = 1341, + .hpos = 0, + .vpos = 7, + .voffs = 27, + .hscale = 65535, + .vscale = 65535 + } +}; + +/* + * Other configuration values left by the BIOS of the + * Fujitsu S6010 in the DVO control registers. Their + * value does not depend on the BIOS and their meaning + * is unknown. + */ + +static const struct ns2501_reg mode_agnostic_values[] = { + /* 08 is mode specific */ + [0] = { .offset = 0x0a, .value = 0x81, }, + /* 10,11 are part of the mode specific configuration */ + [1] = { .offset = 0x12, .value = 0x02, }, + [2] = { .offset = 0x18, .value = 0x07, }, + [3] = { .offset = 0x19, .value = 0x00, }, + [4] = { .offset = 0x1a, .value = 0x00, }, /* PLL?, ignored */ + /* 1b,1c,1d are part of the mode specific configuration */ + [5] = { .offset = 0x1e, .value = 0x02, }, + [6] = { .offset = 0x1f, .value = 0x40, }, + [7] = { .offset = 0x20, .value = 0x00, }, + [8] = { .offset = 0x21, .value = 0x00, }, + [9] = { .offset = 0x22, .value = 0x00, }, + [10] = { .offset = 0x23, .value = 0x00, }, + [11] = { .offset = 0x24, .value = 0x00, }, + [12] = { .offset = 0x25, .value = 0x00, }, + [13] = { .offset = 0x26, .value = 0x00, }, + [14] = { .offset = 0x27, .value = 0x00, }, + [15] = { .offset = 0x7e, .value = 0x18, }, + /* 80-84 are part of the mode-specific configuration */ + [16] = { .offset = 0x84, .value = 0x00, }, + [17] = { .offset = 0x85, .value = 0x00, }, + [18] = { .offset = 0x86, .value = 0x00, }, + [19] = { .offset = 0x87, .value = 0x00, }, + [20] = { .offset = 0x88, .value = 0x00, }, + [21] = { .offset = 0x89, .value = 0x00, }, + [22] = { .offset = 0x8a, .value = 0x00, }, + [23] = { .offset = 0x8b, .value = 0x00, }, + [24] = { .offset = 0x8c, .value = 0x10, }, + [25] = { .offset = 0x8d, .value = 0x02, }, + /* 8e,8f are part of the mode-specific configuration */ + [26] = { .offset = 0x90, .value = 0xff, }, + [27] = { .offset = 0x91, .value = 0x07, }, + [28] = { .offset = 0x92, .value = 0xa0, }, + [29] = { .offset = 0x93, .value = 0x02, }, + [30] = { .offset = 0x94, .value = 0x00, }, + [31] = { .offset = 0x95, .value = 0x00, }, + [32] = { .offset = 0x96, .value = 0x05, }, + [33] = { .offset = 0x97, .value = 0x00, }, + /* 98,99 are part of the mode-specific configuration */ + [34] = { .offset = 0x9a, .value = 0x88, }, + [35] = { .offset = 0x9b, .value = 0x00, }, + /* 9c,9d are part of the mode-specific configuration */ + [36] = { .offset = 0x9e, .value = 0x25, }, + [37] = { .offset = 0x9f, .value = 0x03, }, + [38] = { .offset = 0xa0, .value = 0x28, }, + [39] = { .offset = 0xa1, .value = 0x01, }, + [40] = { .offset = 0xa2, .value = 0x28, }, + [41] = { .offset = 0xa3, .value = 0x05, }, + /* register 0xa4 is mode specific, but 0x80..0x84 works always */ + [42] = { .offset = 0xa4, .value = 0x84, }, + [43] = { .offset = 0xa5, .value = 0x00, }, + [44] = { .offset = 0xa6, .value = 0x00, }, + [45] = { .offset = 0xa7, .value = 0x00, }, + [46] = { .offset = 0xa8, .value = 0x00, }, + /* 0xa9 to 0xab are mode specific, but have no visible effect */ + [47] = { .offset = 0xa9, .value = 0x04, }, + [48] = { .offset = 0xaa, .value = 0x70, }, + [49] = { .offset = 0xab, .value = 0x4f, }, + [50] = { .offset = 0xac, .value = 0x00, }, + [51] = { .offset = 0xad, .value = 0x00, }, + [52] = { .offset = 0xb6, .value = 0x09, }, + [53] = { .offset = 0xb7, .value = 0x03, }, + /* b8,b9 are part of the mode-specific configuration */ + [54] = { .offset = 0xba, .value = 0x00, }, + [55] = { .offset = 0xbb, .value = 0x20, }, + [56] = { .offset = 0xf3, .value = 0x90, }, + [57] = { .offset = 0xf4, .value = 0x00, }, + [58] = { .offset = 0xf7, .value = 0x88, }, + /* f8 is mode specific, but the value does not matter */ + [59] = { .offset = 0xf8, .value = 0x0a, }, + [60] = { .offset = 0xf9, .value = 0x00, } }; static const struct ns2501_reg regs_init[] = { @@ -350,24 +378,11 @@ static const struct ns2501_reg regs_init[] = { struct ns2501_priv { bool quiet; - const struct ns2501_reg *regs; + const struct ns2501_configuration *conf; }; #define NSPTR(d) ((NS2501Ptr)(d->DriverPrivate.ptr)) -/* - * For reasons unclear to me, the ns2501 at least on the Fujitsu/Siemens - * laptops does not react on the i2c bus unless - * both the PLL is running and the display is configured in its native - * resolution. - * This function forces the DVO on, and stores the registers it touches. - * Afterwards, registers are restored to regular values. - * - * This is pretty much a hack, though it works. - * Without that, ns2501_readb and ns2501_writeb fail - * when switching the resolution. - */ - /* ** Read a register from the ns2501. ** Returns true if successful, false otherwise. @@ -534,6 +549,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { + const struct ns2501_configuration *conf; struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv); int mode_idx, i; @@ -541,6 +557,36 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo, ("set mode (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n", mode->hdisplay, mode->htotal, mode->vdisplay, mode->vtotal); + DRM_DEBUG_KMS("Detailed requested mode settings are:\n" + "clock : %d kHz\n" + "hdisplay : %d\n" + "hblank start : %d\n" + "hblank end : %d\n" + "hsync start : %d\n" + "hsync end : %d\n" + "htotal : %d\n" + "hskew : %d\n" + "vdisplay : %d\n" + "vblank start : %d\n" + "hblank end : %d\n" + "vsync start : %d\n" + "vsync end : %d\n" + "vtotal : %d\n", + adjusted_mode->crtc_clock, + adjusted_mode->crtc_hdisplay, + adjusted_mode->crtc_hblank_start, + adjusted_mode->crtc_hblank_end, + adjusted_mode->crtc_hsync_start, + adjusted_mode->crtc_hsync_end, + adjusted_mode->crtc_htotal, + adjusted_mode->crtc_hskew, + adjusted_mode->crtc_vdisplay, + adjusted_mode->crtc_vblank_start, + adjusted_mode->crtc_vblank_end, + adjusted_mode->crtc_vsync_start, + adjusted_mode->crtc_vsync_end, + adjusted_mode->crtc_vtotal); + if (mode->hdisplay == 640 && mode->vdisplay == 480) mode_idx = MODE_640x480; else if (mode->hdisplay == 800 && mode->vdisplay == 600) @@ -554,10 +600,44 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo, for (i = 0; i < ARRAY_SIZE(regs_init); i++) ns2501_writeb(dvo, regs_init[i].offset, regs_init[i].value); - ns->regs = regs_1024x768[mode_idx]; - - for (i = 0; i < 84; i++) - ns2501_writeb(dvo, ns->regs[i].offset, ns->regs[i].value); + /* Write the mode-agnostic values */ + for (i = 0; i < ARRAY_SIZE(mode_agnostic_values); i++) + ns2501_writeb(dvo, mode_agnostic_values[i].offset, + mode_agnostic_values[i].value); + + /* Write now the mode-specific configuration */ + conf = ns2501_modes + mode_idx; + ns->conf = conf; + + ns2501_writeb(dvo, NS2501_REG8, conf->conf); + ns2501_writeb(dvo, NS2501_REG1B, conf->pll_a); + ns2501_writeb(dvo, NS2501_REG1C, conf->pll_b & 0xff); + ns2501_writeb(dvo, NS2501_REG1D, conf->pll_b >> 8); + ns2501_writeb(dvo, NS2501_REGC1, conf->hstart & 0xff); + ns2501_writeb(dvo, NS2501_REGC2, conf->hstart >> 8); + ns2501_writeb(dvo, NS2501_REGC3, conf->hstop & 0xff); + ns2501_writeb(dvo, NS2501_REGC4, conf->hstop >> 8); + ns2501_writeb(dvo, NS2501_REGC5, conf->vstart & 0xff); + ns2501_writeb(dvo, NS2501_REGC6, conf->vstart >> 8); + ns2501_writeb(dvo, NS2501_REGC7, conf->vstop & 0xff); + ns2501_writeb(dvo, NS2501_REGC8, conf->vstop >> 8); + ns2501_writeb(dvo, NS2501_REG80, conf->vsync & 0xff); + ns2501_writeb(dvo, NS2501_REG81, conf->vsync >> 8); + ns2501_writeb(dvo, NS2501_REG82, conf->vtotal & 0xff); + ns2501_writeb(dvo, NS2501_REG83, conf->vtotal >> 8); + ns2501_writeb(dvo, NS2501_REG98, conf->hpos & 0xff); + ns2501_writeb(dvo, NS2501_REG99, conf->hpos >> 8); + ns2501_writeb(dvo, NS2501_REG8E, conf->vpos & 0xff); + ns2501_writeb(dvo, NS2501_REG8F, conf->vpos >> 8); + ns2501_writeb(dvo, NS2501_REG9C, conf->voffs & 0xff); + ns2501_writeb(dvo, NS2501_REG9D, conf->voffs >> 8); + ns2501_writeb(dvo, NS2501_REGB8, conf->hscale & 0xff); + ns2501_writeb(dvo, NS2501_REGB9, conf->hscale >> 8); + ns2501_writeb(dvo, NS2501_REG10, conf->vscale & 0xff); + ns2501_writeb(dvo, NS2501_REG11, conf->vscale >> 8); + ns2501_writeb(dvo, NS2501_REGF9, conf->dither); + ns2501_writeb(dvo, NS2501_REG41, conf->syncb); + ns2501_writeb(dvo, NS2501_REGC0, conf->sync); } /* set the NS2501 power state */ @@ -579,34 +659,32 @@ static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable) DRM_DEBUG_KMS("Trying set the dpms of the DVO to %i\n", enable); if (enable) { - if (WARN_ON(ns->regs[83].offset != 0x08 || - ns->regs[84].offset != 0x41 || - ns->regs[85].offset != 0xc0)) - return; - - ns2501_writeb(dvo, 0xc0, ns->regs[85].value | 0x08); + ns2501_writeb(dvo, NS2501_REGC0, ns->conf->sync | 0x08); - ns2501_writeb(dvo, 0x41, ns->regs[84].value); + ns2501_writeb(dvo, NS2501_REG41, ns->conf->syncb); - ns2501_writeb(dvo, 0x34, 0x01); + ns2501_writeb(dvo, NS2501_REG34, NS2501_34_ENABLE_OUTPUT); msleep(15); - ns2501_writeb(dvo, 0x08, 0x35); - if (!(ns->regs[83].value & NS2501_8_BPAS)) - ns2501_writeb(dvo, 0x08, 0x31); + ns2501_writeb(dvo, NS2501_REG8, + ns->conf->conf | NS2501_8_BPAS); + if (!(ns->conf->conf & NS2501_8_BPAS)) + ns2501_writeb(dvo, NS2501_REG8, ns->conf->conf); msleep(200); - ns2501_writeb(dvo, 0x34, 0x03); + ns2501_writeb(dvo, NS2501_REG34, + NS2501_34_ENABLE_OUTPUT | NS2501_34_ENABLE_BACKLIGHT); - ns2501_writeb(dvo, 0xc0, ns->regs[85].value); + ns2501_writeb(dvo, NS2501_REGC0, ns->conf->sync); } else { - ns2501_writeb(dvo, 0x34, 0x01); + ns2501_writeb(dvo, NS2501_REG34, NS2501_34_ENABLE_OUTPUT); msleep(200); - ns2501_writeb(dvo, 0x08, 0x34); + ns2501_writeb(dvo, NS2501_REG8, NS2501_8_VEN | NS2501_8_HEN | + NS2501_8_BPAS); msleep(15); - ns2501_writeb(dvo, 0x34, 0x00); + ns2501_writeb(dvo, NS2501_REG34, 0x00); } } From de4de566f84b87f4d5f8265b11932088adb19896 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 23 Apr 2015 22:02:54 +0200 Subject: [PATCH 0229/3798] drm/i915: Update DRIVER_DATE to 20150423 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 906f8851df4c7e..6c030639f8d9e0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -56,7 +56,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20150410" +#define DRIVER_DATE "20150423" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ From f4a3ae9308e34bcd704325a08879b2c1cfb74686 Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Wed, 19 Nov 2014 12:27:11 -0600 Subject: [PATCH 0230/3798] GFS2: Use average srttb value in congestion calculations This patch changes function gfs2_rgrp_congested so that it uses an average srttb (smoothed round trip time for blocking rgrp glocks) rather than the CPU-specific value. If we use the CPU-specific value it can incorrectly report no contention when there really is contention due to the glock processing occurring on a different CPU. Signed-off-by: Bob Peterson Acked-by: Steven Whitehouse --- fs/gfs2/rgrp.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 6af2396a317c3d..f39eedc1af7628 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -1850,14 +1850,19 @@ static bool gfs2_rgrp_congested(const struct gfs2_rgrpd *rgd, int loops) const struct gfs2_sbd *sdp = gl->gl_sbd; struct gfs2_lkstats *st; s64 r_dcount, l_dcount; - s64 r_srttb, l_srttb; + s64 l_srttb, a_srttb = 0; s64 srttb_diff; s64 sqr_diff; s64 var; + int cpu; preempt_disable(); + for_each_present_cpu(cpu) { + st = &per_cpu_ptr(sdp->sd_lkstats, cpu)->lkstats[LM_TYPE_RGRP]; + a_srttb += st->stats[GFS2_LKS_SRTTB]; + } st = &this_cpu_ptr(sdp->sd_lkstats)->lkstats[LM_TYPE_RGRP]; - r_srttb = st->stats[GFS2_LKS_SRTTB]; + a_srttb /= num_present_cpus(); r_dcount = st->stats[GFS2_LKS_DCOUNT]; var = st->stats[GFS2_LKS_SRTTVARB] + gl->gl_stats.stats[GFS2_LKS_SRTTVARB]; @@ -1866,10 +1871,10 @@ static bool gfs2_rgrp_congested(const struct gfs2_rgrpd *rgd, int loops) l_srttb = gl->gl_stats.stats[GFS2_LKS_SRTTB]; l_dcount = gl->gl_stats.stats[GFS2_LKS_DCOUNT]; - if ((l_dcount < 1) || (r_dcount < 1) || (r_srttb == 0)) + if ((l_dcount < 1) || (r_dcount < 1) || (a_srttb == 0)) return false; - srttb_diff = r_srttb - l_srttb; + srttb_diff = a_srttb - l_srttb; sqr_diff = srttb_diff * srttb_diff; var *= 2; From 0166b197c2ed2327bb7761ded8cba2cfd371a425 Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Wed, 22 Apr 2015 11:24:12 -0500 Subject: [PATCH 0231/3798] GFS2: Average in only non-zero round-trip times for congestion stats This patch changes function gfs2_rgrp_congested so that it only factors in non-zero values into its average round trip time. If the round-trip time is zero for a particular cpu, that cpu has obviously never dealt with bouncing the resource group in question, so factoring in a zero value will only skew the numbers. It also fixes a compile error on some arches related to division. Signed-off-by: Bob Peterson Acked-by: Steven Whitehouse --- fs/gfs2/rgrp.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index f39eedc1af7628..cb270651c613e7 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -1854,15 +1854,19 @@ static bool gfs2_rgrp_congested(const struct gfs2_rgrpd *rgd, int loops) s64 srttb_diff; s64 sqr_diff; s64 var; - int cpu; + int cpu, nonzero = 0; preempt_disable(); for_each_present_cpu(cpu) { st = &per_cpu_ptr(sdp->sd_lkstats, cpu)->lkstats[LM_TYPE_RGRP]; - a_srttb += st->stats[GFS2_LKS_SRTTB]; + if (st->stats[GFS2_LKS_SRTTB]) { + a_srttb += st->stats[GFS2_LKS_SRTTB]; + nonzero++; + } } st = &this_cpu_ptr(sdp->sd_lkstats)->lkstats[LM_TYPE_RGRP]; - a_srttb /= num_present_cpus(); + if (nonzero) + do_div(a_srttb, nonzero); r_dcount = st->stats[GFS2_LKS_DCOUNT]; var = st->stats[GFS2_LKS_SRTTVARB] + gl->gl_stats.stats[GFS2_LKS_SRTTVARB]; From 8592a7eefa540303dd9e60fa49340d09ca9376b4 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 21 Apr 2015 19:10:59 +0300 Subject: [PATCH 0232/3798] iio: ltr501: Add support for ltr559 chip This device is register compatible with LTR501, with a minor difference for ALS control register as showed below: ALS Control register for LTR501: 7 6 5 4 3 2 1 0 +------+------+------+------+------+------+------+------+ | | | | | | Reserved | Gain | SW | ALS Mode | | | | Reset| | +------+------+------+------+------+------+------+------+ ALS Control register for LTR559: 7 6 5 4 3 2 1 0 +------+------+------+------+------+------+------+------+ | | | | | | Reserved | Gain | SW | ALS | | | | Reset| Mode | +------+------+------+------+------+------+------+------+ We handle this difference by introducing ltr501_chip_info. Datasheet for LTR559 is at: http://optoelectronics.liteon.com/upload/download/DS86-2013-0003/S_110_LTR-559ALS-01_DS_V1.pdf Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 3 +- drivers/iio/light/ltr501.c | 218 +++++++++++++++++++++++++++++++------ 2 files changed, 186 insertions(+), 35 deletions(-) diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 01a1a16ab7be8f..16a0ba11ab6e60 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -169,7 +169,8 @@ config LTR501 select IIO_TRIGGERED_BUFFER help If you say yes here you get support for the Lite-On LTR-501ALS-01 - ambient light and proximity sensor. + ambient light and proximity sensor. This driver also supports LTR-559 + ALS/PS sensor. This driver can also be built as a module. If so, the module will be called ltr501. diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index 0162e865211860..92da5146bc1ce0 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -88,9 +88,63 @@ struct ltr501_samp_table { int time_val; /* repetition rate in micro seconds */ }; +#define LTR501_RESERVED_GAIN -1 + +enum { + ltr501 = 0, + ltr559, +}; + +struct ltr501_gain { + int scale; + int uscale; +}; + +static struct ltr501_gain ltr501_als_gain_tbl[] = { + {1, 0}, + {0, 5000}, +}; + +static struct ltr501_gain ltr559_als_gain_tbl[] = { + {1, 0}, + {0, 500000}, + {0, 250000}, + {0, 125000}, + {LTR501_RESERVED_GAIN, LTR501_RESERVED_GAIN}, + {LTR501_RESERVED_GAIN, LTR501_RESERVED_GAIN}, + {0, 20000}, + {0, 10000}, +}; + +static struct ltr501_gain ltr501_ps_gain_tbl[] = { + {1, 0}, + {0, 250000}, + {0, 125000}, + {0, 62500}, +}; + +static struct ltr501_gain ltr559_ps_gain_tbl[] = { + {0, 62500}, /* x16 gain */ + {0, 31250}, /* x32 gain */ + {0, 15625}, /* bits X1 are for x64 gain */ + {0, 15624}, +}; + +struct ltr501_chip_info { + u8 partid; + struct ltr501_gain *als_gain; + int als_gain_tbl_size; + struct ltr501_gain *ps_gain; + int ps_gain_tbl_size; + u8 als_mode_active; + u8 als_gain_mask; + u8 als_gain_shift; +}; + struct ltr501_data { struct i2c_client *client; struct mutex lock_als, lock_ps; + struct ltr501_chip_info *chip_info; u8 als_contr, ps_contr; int als_period, ps_period; /* period in micro seconds */ struct regmap *regmap; @@ -516,10 +570,6 @@ static const struct iio_chan_spec ltr501_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(3), }; -static const int ltr501_ps_gain[4][2] = { - {1, 0}, {0, 250000}, {0, 125000}, {0, 62500} -}; - static int ltr501_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -557,19 +607,16 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_INTENSITY: - if (data->als_contr & LTR501_CONTR_ALS_GAIN_MASK) { - *val = 0; - *val2 = 5000; - return IIO_VAL_INT_PLUS_MICRO; - } - *val = 1; - *val2 = 0; - return IIO_VAL_INT; + i = (data->als_contr & data->chip_info->als_gain_mask) + >> data->chip_info->als_gain_shift; + *val = data->chip_info->als_gain[i].scale; + *val2 = data->chip_info->als_gain[i].uscale; + return IIO_VAL_INT_PLUS_MICRO; case IIO_PROXIMITY: i = (data->ps_contr & LTR501_CONTR_PS_GAIN_MASK) >> LTR501_CONTR_PS_GAIN_SHIFT; - *val = ltr501_ps_gain[i][0]; - *val2 = ltr501_ps_gain[i][1]; + *val = data->chip_info->ps_gain[i].scale; + *val2 = data->chip_info->ps_gain[i].uscale; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; @@ -594,12 +641,13 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, return -EINVAL; } -static int ltr501_get_ps_gain_index(int val, int val2) +static int ltr501_get_gain_index(struct ltr501_gain *gain, int size, + int val, int val2) { int i; - for (i = 0; i < ARRAY_SIZE(ltr501_ps_gain); i++) - if (val == ltr501_ps_gain[i][0] && val2 == ltr501_ps_gain[i][1]) + for (i = 0; i < size; i++) + if (val == gain[i].scale && val2 == gain[i].uscale) return i; return -1; @@ -611,6 +659,7 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, { struct ltr501_data *data = iio_priv(indio_dev); int i, ret, freq_val, freq_val2; + struct ltr501_chip_info *info = data->chip_info; if (iio_buffer_enabled(indio_dev)) return -EBUSY; @@ -619,17 +668,21 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_INTENSITY: - if (val == 0 && val2 == 5000) - data->als_contr |= LTR501_CONTR_ALS_GAIN_MASK; - else if (val == 1 && val2 == 0) - data->als_contr &= ~LTR501_CONTR_ALS_GAIN_MASK; - else + i = ltr501_get_gain_index(info->als_gain, + info->als_gain_tbl_size, + val, val2); + if (i < 0) return -EINVAL; + data->als_contr &= ~info->als_gain_mask; + data->als_contr |= i << info->als_gain_shift; + return regmap_write(data->regmap, LTR501_ALS_CONTR, data->als_contr); case IIO_PROXIMITY: - i = ltr501_get_ps_gain_index(val, val2); + i = ltr501_get_gain_index(info->ps_gain, + info->ps_gain_tbl_size, + val, val2); if (i < 0) return -EINVAL; data->ps_contr &= ~LTR501_CONTR_PS_GAIN_MASK; @@ -927,14 +980,61 @@ static int ltr501_write_event_config(struct iio_dev *indio_dev, return -EINVAL; } -static IIO_CONST_ATTR(in_proximity_scale_available, "1 0.25 0.125 0.0625"); -static IIO_CONST_ATTR(in_intensity_scale_available, "1 0.005"); +static ssize_t ltr501_show_proximity_scale_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ltr501_data *data = iio_priv(dev_to_iio_dev(dev)); + struct ltr501_chip_info *info = data->chip_info; + ssize_t len = 0; + int i; + + for (i = 0; i < info->ps_gain_tbl_size; i++) { + if (info->ps_gain[i].scale == LTR501_RESERVED_GAIN) + continue; + len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06d ", + info->ps_gain[i].scale, + info->ps_gain[i].uscale); + } + + buf[len - 1] = '\n'; + + return len; +} + +static ssize_t ltr501_show_intensity_scale_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ltr501_data *data = iio_priv(dev_to_iio_dev(dev)); + struct ltr501_chip_info *info = data->chip_info; + ssize_t len = 0; + int i; + + for (i = 0; i < info->als_gain_tbl_size; i++) { + if (info->als_gain[i].scale == LTR501_RESERVED_GAIN) + continue; + len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06d ", + info->als_gain[i].scale, + info->als_gain[i].uscale); + } + + buf[len - 1] = '\n'; + + return len; +} + static IIO_CONST_ATTR_INT_TIME_AVAIL("0.05 0.1 0.2 0.4"); static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("20 10 5 2 1 0.5"); +static IIO_DEVICE_ATTR(in_proximity_scale_available, S_IRUGO, + ltr501_show_proximity_scale_avail, NULL, 0); +static IIO_DEVICE_ATTR(in_intensity_scale_available, S_IRUGO, + ltr501_show_intensity_scale_avail, NULL, 0); + static struct attribute *ltr501_attributes[] = { - &iio_const_attr_in_proximity_scale_available.dev_attr.attr, - &iio_const_attr_in_intensity_scale_available.dev_attr.attr, + &iio_dev_attr_in_proximity_scale_available.dev_attr.attr, + &iio_dev_attr_in_intensity_scale_available.dev_attr.attr, &iio_const_attr_integration_time_available.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, NULL @@ -962,6 +1062,29 @@ static const struct iio_info ltr501_info = { .driver_module = THIS_MODULE, }; +static struct ltr501_chip_info ltr501_chip_info_tbl[] = { + [ltr501] = { + .partid = 0x08, + .als_gain = ltr501_als_gain_tbl, + .als_gain_tbl_size = ARRAY_SIZE(ltr501_als_gain_tbl), + .ps_gain = ltr501_ps_gain_tbl, + .ps_gain_tbl_size = ARRAY_SIZE(ltr501_ps_gain_tbl), + .als_mode_active = BIT(0) | BIT(1), + .als_gain_mask = BIT(3), + .als_gain_shift = 3, + }, + [ltr559] = { + .partid = 0x09, + .als_gain = ltr559_als_gain_tbl, + .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl), + .ps_gain = ltr559_ps_gain_tbl, + .ps_gain_tbl_size = ARRAY_SIZE(ltr559_ps_gain_tbl), + .als_mode_active = BIT(1), + .als_gain_mask = BIT(2) | BIT(3) | BIT(4), + .als_gain_shift = 2, + }, +}; + static int ltr501_write_contr(struct ltr501_data *data, u8 als_val, u8 ps_val) { int ret; @@ -1062,7 +1185,7 @@ static int ltr501_init(struct ltr501_data *data) if (ret < 0) return ret; - data->als_contr = status | LTR501_CONTR_ACTIVE; + data->als_contr = ret | data->chip_info->als_mode_active; ret = regmap_read(data->regmap, LTR501_PS_CONTR, &status); if (ret < 0) @@ -1105,17 +1228,30 @@ static struct regmap_config ltr501_regmap_config = { static int ltr501_powerdown(struct ltr501_data *data) { - return ltr501_write_contr(data, data->als_contr & ~LTR501_CONTR_ACTIVE, + return ltr501_write_contr(data, data->als_contr & + ~data->chip_info->als_mode_active, data->ps_contr & ~LTR501_CONTR_ACTIVE); } +static const char *ltr501_match_acpi_device(struct device *dev, int *chip_idx) +{ + const struct acpi_device_id *id; + + id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!id) + return NULL; + *chip_idx = id->driver_data; + return dev_name(dev); +} + static int ltr501_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ltr501_data *data; struct iio_dev *indio_dev; struct regmap *regmap; - int ret, partid; + int ret, partid, chip_idx = 0; + const char *name = NULL; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) @@ -1186,13 +1322,25 @@ static int ltr501_probe(struct i2c_client *client, ret = regmap_read(data->regmap, LTR501_PART_ID, &partid); if (ret < 0) return ret; - if ((partid >> 4) != 0x8) + + if (id) { + name = id->name; + chip_idx = id->driver_data; + } else if (ACPI_HANDLE(&client->dev)) { + name = ltr501_match_acpi_device(&client->dev, &chip_idx); + } else { + return -ENODEV; + } + + data->chip_info = <r501_chip_info_tbl[chip_idx]; + + if ((partid >> 4) != data->chip_info->partid) return -ENODEV; indio_dev->dev.parent = &client->dev; indio_dev->channels = ltr501_channels; indio_dev->num_channels = ARRAY_SIZE(ltr501_channels); - indio_dev->name = LTR501_DRV_NAME; + indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; ret = ltr501_init(data); @@ -1266,13 +1414,15 @@ static int ltr501_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(ltr501_pm_ops, ltr501_suspend, ltr501_resume); static const struct acpi_device_id ltr_acpi_match[] = { - {"LTER0501", 0}, + {"LTER0501", ltr501}, + {"LTER0559", ltr559}, { }, }; MODULE_DEVICE_TABLE(acpi, ltr_acpi_match); static const struct i2c_device_id ltr501_id[] = { - { "ltr501", 0 }, + { "ltr501", ltr501}, + { "ltr559", ltr559}, { } }; MODULE_DEVICE_TABLE(i2c, ltr501_id); From 035ebb15101c0f5c58d6ff8b343c6eae9ddca9c6 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 21 Apr 2015 19:11:00 +0300 Subject: [PATCH 0233/3798] iio: ltr501: Add support for ltr301 chip Added support for Liteon 301 Ambient light sensor. Since LTR-301 and LTR-501 are register compatible(and even have same part id), LTR-501 driver has been extended to support both devices. LTR-501 is similar to LTR-301 in ALS sensing, But the only difference is, LTR-501 also supports proximity sensing. LTR-501 - ALS + Proximity combo LTR-301 - ALS sensor. Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 2 +- drivers/iio/light/ltr501.c | 76 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 16a0ba11ab6e60..a437bad466864d 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -170,7 +170,7 @@ config LTR501 help If you say yes here you get support for the Lite-On LTR-501ALS-01 ambient light and proximity sensor. This driver also supports LTR-559 - ALS/PS sensor. + ALS/PS or LTR-301 ALS sensors. This driver can also be built as a module. If so, the module will be called ltr501. diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index 92da5146bc1ce0..ca4bf470a3325a 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -93,6 +93,7 @@ struct ltr501_samp_table { enum { ltr501 = 0, ltr559, + ltr301, }; struct ltr501_gain { @@ -139,6 +140,10 @@ struct ltr501_chip_info { u8 als_mode_active; u8 als_gain_mask; u8 als_gain_shift; + struct iio_chan_spec const *channels; + const int no_channels; + const struct iio_info *info; + const struct iio_info *info_no_irq; }; struct ltr501_data { @@ -570,6 +575,18 @@ static const struct iio_chan_spec ltr501_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(3), }; +static const struct iio_chan_spec ltr301_channels[] = { + LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0, + ltr501_als_event_spec, + ARRAY_SIZE(ltr501_als_event_spec)), + LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR, + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_SAMP_FREQ), + NULL, 0), + IIO_CHAN_SOFT_TIMESTAMP(2), +}; + static int ltr501_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -1040,10 +1057,21 @@ static struct attribute *ltr501_attributes[] = { NULL }; +static struct attribute *ltr301_attributes[] = { + &iio_dev_attr_in_intensity_scale_available.dev_attr.attr, + &iio_const_attr_integration_time_available.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL +}; + static const struct attribute_group ltr501_attribute_group = { .attrs = ltr501_attributes, }; +static const struct attribute_group ltr301_attribute_group = { + .attrs = ltr301_attributes, +}; + static const struct iio_info ltr501_info_no_irq = { .read_raw = ltr501_read_raw, .write_raw = ltr501_write_raw, @@ -1062,6 +1090,24 @@ static const struct iio_info ltr501_info = { .driver_module = THIS_MODULE, }; +static const struct iio_info ltr301_info_no_irq = { + .read_raw = ltr501_read_raw, + .write_raw = ltr501_write_raw, + .attrs = <r301_attribute_group, + .driver_module = THIS_MODULE, +}; + +static const struct iio_info ltr301_info = { + .read_raw = ltr501_read_raw, + .write_raw = ltr501_write_raw, + .attrs = <r301_attribute_group, + .read_event_value = <r501_read_event, + .write_event_value = <r501_write_event, + .read_event_config = <r501_read_event_config, + .write_event_config = <r501_write_event_config, + .driver_module = THIS_MODULE, +}; + static struct ltr501_chip_info ltr501_chip_info_tbl[] = { [ltr501] = { .partid = 0x08, @@ -1072,6 +1118,10 @@ static struct ltr501_chip_info ltr501_chip_info_tbl[] = { .als_mode_active = BIT(0) | BIT(1), .als_gain_mask = BIT(3), .als_gain_shift = 3, + .info = <r501_info, + .info_no_irq = <r501_info_no_irq, + .channels = ltr501_channels, + .no_channels = ARRAY_SIZE(ltr501_channels), }, [ltr559] = { .partid = 0x09, @@ -1082,6 +1132,22 @@ static struct ltr501_chip_info ltr501_chip_info_tbl[] = { .als_mode_active = BIT(1), .als_gain_mask = BIT(2) | BIT(3) | BIT(4), .als_gain_shift = 2, + .info = <r501_info, + .info_no_irq = <r501_info_no_irq, + .channels = ltr501_channels, + .no_channels = ARRAY_SIZE(ltr501_channels), + }, + [ltr301] = { + .partid = 0x08, + .als_gain = ltr501_als_gain_tbl, + .als_gain_tbl_size = ARRAY_SIZE(ltr501_als_gain_tbl), + .als_mode_active = BIT(0) | BIT(1), + .als_gain_mask = BIT(3), + .als_gain_shift = 3, + .info = <r301_info, + .info_no_irq = <r301_info_no_irq, + .channels = ltr301_channels, + .no_channels = ARRAY_SIZE(ltr301_channels), }, }; @@ -1338,8 +1404,9 @@ static int ltr501_probe(struct i2c_client *client, return -ENODEV; indio_dev->dev.parent = &client->dev; - indio_dev->channels = ltr501_channels; - indio_dev->num_channels = ARRAY_SIZE(ltr501_channels); + indio_dev->info = data->chip_info->info; + indio_dev->channels = data->chip_info->channels; + indio_dev->num_channels = data->chip_info->no_channels; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; @@ -1348,7 +1415,6 @@ static int ltr501_probe(struct i2c_client *client, return ret; if (client->irq > 0) { - indio_dev->info = <r501_info; ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, ltr501_interrupt_handler, IRQF_TRIGGER_FALLING | @@ -1361,7 +1427,7 @@ static int ltr501_probe(struct i2c_client *client, return ret; } } else { - indio_dev->info = <r501_info_no_irq; + indio_dev->info = data->chip_info->info_no_irq; } ret = iio_triggered_buffer_setup(indio_dev, NULL, @@ -1416,6 +1482,7 @@ static SIMPLE_DEV_PM_OPS(ltr501_pm_ops, ltr501_suspend, ltr501_resume); static const struct acpi_device_id ltr_acpi_match[] = { {"LTER0501", ltr501}, {"LTER0559", ltr559}, + {"LTER0301", ltr301}, { }, }; MODULE_DEVICE_TABLE(acpi, ltr_acpi_match); @@ -1423,6 +1490,7 @@ MODULE_DEVICE_TABLE(acpi, ltr_acpi_match); static const struct i2c_device_id ltr501_id[] = { { "ltr501", ltr501}, { "ltr559", ltr559}, + { "ltr301", ltr301}, { } }; MODULE_DEVICE_TABLE(i2c, ltr501_id); From b39f0c945c0dc39763a76e2f54fb9eea0e49e876 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 13 Apr 2015 18:40:52 +0300 Subject: [PATCH 0234/3798] iio: accel: mma9551_core: wrong doc fixes Fix docummentation for mma9553_read_* functions. Signed-off-by: Irina Tirdea Reported-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma9551_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/mma9551_core.c b/drivers/iio/accel/mma9551_core.c index 7f55a6d7cd035d..2543167c0f7c2c 100644 --- a/drivers/iio/accel/mma9551_core.c +++ b/drivers/iio/accel/mma9551_core.c @@ -374,7 +374,7 @@ EXPORT_SYMBOL(mma9551_read_status_word); * @app_id: Application ID * @reg: Application register * @len: Length of array to read in bytes - * @val: Array of words to read + * @buf: Array of words to read * * Read multiple configuration registers (word-sized registers). * @@ -409,7 +409,7 @@ EXPORT_SYMBOL(mma9551_read_config_words); * @app_id: Application ID * @reg: Application register * @len: Length of array to read in bytes - * @val: Array of words to read + * @buf: Array of words to read * * Read multiple status registers (word-sized registers). * @@ -444,7 +444,7 @@ EXPORT_SYMBOL(mma9551_read_status_words); * @app_id: Application ID * @reg: Application register * @len: Length of array to write in bytes - * @val: Array of words to write + * @buf: Array of words to write * * Write multiple configuration registers (word-sized registers). * From 476c41a73eee708101495d2202c82060d0fc787d Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 13 Apr 2015 18:40:53 +0300 Subject: [PATCH 0235/3798] iio: accel: mma9551_core: typo fix in RSC APP ID Fix typo in Reset/Suspend/Clear Application ID definition. Signed-off-by: Irina Tirdea Reported-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma9551_core.c | 2 +- drivers/iio/accel/mma9551_core.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/accel/mma9551_core.c b/drivers/iio/accel/mma9551_core.c index 2543167c0f7c2c..54b3ae615a1458 100644 --- a/drivers/iio/accel/mma9551_core.c +++ b/drivers/iio/accel/mma9551_core.c @@ -785,7 +785,7 @@ EXPORT_SYMBOL(mma9551_read_accel_scale); */ int mma9551_app_reset(struct i2c_client *client, u32 app_mask) { - return mma9551_write_config_byte(client, MMA9551_APPID_RCS, + return mma9551_write_config_byte(client, MMA9551_APPID_RSC, MMA9551_RSC_RESET + MMA9551_RSC_OFFSET(app_mask), MMA9551_RSC_VAL(app_mask)); diff --git a/drivers/iio/accel/mma9551_core.h b/drivers/iio/accel/mma9551_core.h index edaa56b1078e10..79939e40805a00 100644 --- a/drivers/iio/accel/mma9551_core.h +++ b/drivers/iio/accel/mma9551_core.h @@ -22,7 +22,7 @@ #define MMA9551_APPID_TILT 0x0B #define MMA9551_APPID_SLEEP_WAKE 0x12 #define MMA9551_APPID_PEDOMETER 0x15 -#define MMA9551_APPID_RCS 0x17 +#define MMA9551_APPID_RSC 0x17 #define MMA9551_APPID_NONE 0xff /* Reset/Suspend/Clear application app masks */ From 1d052931c689d14397d05ac705cf386955bcf813 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 13 Apr 2015 18:40:54 +0300 Subject: [PATCH 0236/3798] iio: accel: mma9553: check for error in reading initial activity and stepcnt When configuring gpio, we need to read initial values for activity and step count. This function may fail due to i2c read errors. Check the error code returned by mma9553_read_activity_stepcnt and return the appropriate error in gpio config function. Signed-off-by: Irina Tirdea Reported-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma9553.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index 2df1af7d43fc6d..04a4bb99b269e6 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -365,9 +365,12 @@ static int mma9553_conf_gpio(struct mma9553_data *data) return 0; /* Save initial values for activity and stepcnt */ - if (activity_enabled || ev_step_detect->enabled) - mma9553_read_activity_stepcnt(data, &data->activity, - &data->stepcnt); + if (activity_enabled || ev_step_detect->enabled) { + ret = mma9553_read_activity_stepcnt(data, &data->activity, + &data->stepcnt); + if (ret < 0) + return ret; + } ret = mma9551_gpio_config(data->client, MMA9553_DEFAULT_GPIO_PIN, From 04aff96ad49d297fa530bb01aa09f1f39e65189a Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 13 Apr 2015 18:40:55 +0300 Subject: [PATCH 0237/3798] iio: accel: mma9553: return 0 as indication of success Use return 0 instead of return ret to mark clearly the success return path. Signed-off-by: Irina Tirdea Suggested-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma9553.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index 04a4bb99b269e6..f2118b1a7010e4 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -794,7 +794,7 @@ static int mma9553_write_event_config(struct iio_dev *indio_dev, mutex_unlock(&data->mutex); - return ret; + return 0; err_conf_gpio: if (state) { From c105ac6a039242e847d6b770ec2f4fa2c9f20a1b Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 13 Apr 2015 18:40:56 +0300 Subject: [PATCH 0238/3798] iio: accel: mma9553: comment and error message fixes Use "GPIO" instead of "gpio" and "ACPI" instead of "acpi". Includes a couple of small style fixes in comments (missing full stop, whitespace, paranthesis). Signed-off-by: Irina Tirdea Suggested-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma9553.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index f2118b1a7010e4..7c87ec41b8d05a 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -75,14 +75,14 @@ #define MMA9553_DEFAULT_GPIO_PIN mma9551_gpio6 #define MMA9553_DEFAULT_GPIO_POLARITY 0 -/* Bitnum used for gpio configuration = bit number in high status byte */ #define STATUS_TO_BITNUM(bit) (ffs(bit) - 9) +/* Bitnum used for GPIO configuration = bit number in high status byte */ #define MMA9553_DEFAULT_SAMPLE_RATE 30 /* Hz */ /* * The internal activity level must be stable for ACTTHD samples before - * ACTIVITY is updated.The ACTIVITY variable contains the current activity + * ACTIVITY is updated. The ACTIVITY variable contains the current activity * level and is updated every time a step is detected or once a second * if there are no steps. */ @@ -401,13 +401,13 @@ static int mma9553_init(struct mma9553_data *data) sizeof(data->conf), (u16 *) &data->conf); if (ret < 0) { dev_err(&data->client->dev, - "device is not MMA9553L: failed to read cfg regs\n"); + "failed to read configuration registers\n"); return ret; } - /* Reset gpio */ data->gpio_bitnum = -1; + /* Reset GPIO */ ret = mma9553_conf_gpio(data); if (ret < 0) return ret; @@ -459,7 +459,8 @@ static int mma9553_read_raw(struct iio_dev *indio_dev, * The HW only counts steps and other dependent * parameters (speed, distance, calories, activity) * if power is on (from enabling an event or the - * step counter */ + * step counter). + */ powered_on = mma9553_is_any_event_enabled(data, false, 0) || data->stepcnt_enabled; @@ -899,7 +900,7 @@ static int mma9553_get_calibgender_mode(struct iio_dev *indio_dev, gender = mma9553_get_bits(data->conf.filter, MMA9553_MASK_CONF_MALE); /* * HW expects 0 for female and 1 for male, - * while iio index is 0 for male and 1 for female + * while iio index is 0 for male and 1 for female. */ return !gender; } @@ -1111,16 +1112,16 @@ static int mma9553_gpio_probe(struct i2c_client *client) dev = &client->dev; - /* data ready gpio interrupt pin */ + /* data ready GPIO interrupt pin */ gpio = devm_gpiod_get_index(dev, MMA9553_GPIO_NAME, 0, GPIOD_IN); if (IS_ERR(gpio)) { - dev_err(dev, "acpi gpio get index failed\n"); + dev_err(dev, "ACPI GPIO get index failed\n"); return PTR_ERR(gpio); } ret = gpiod_to_irq(gpio); - dev_dbg(dev, "gpio resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); + dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); return ret; } From 43c30937c300bc30abb6368a71d4e17e37509a07 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 13 Apr 2015 18:40:57 +0300 Subject: [PATCH 0239/3798] iio: accel: mma9553: use GENMASK Use GENMASK instead of BIT or direct value to define a mask. Signed-off-by: Irina Tirdea Suggested-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma9553.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index 7c87ec41b8d05a..dcbf04fa3d05bc 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -62,8 +62,8 @@ #define MMA9553_MASK_STATUS_STEPCHG BIT(13) #define MMA9553_MASK_STATUS_ACTCHG BIT(12) #define MMA9553_MASK_STATUS_SUSP BIT(11) -#define MMA9553_MASK_STATUS_ACTIVITY (BIT(10) | BIT(9) | BIT(8)) -#define MMA9553_MASK_STATUS_VERSION 0x00FF +#define MMA9553_MASK_STATUS_ACTIVITY GENMASK(10, 8) +#define MMA9553_MASK_STATUS_VERSION GENMASK(7, 0) #define MMA9553_REG_STEPCNT 0x02 #define MMA9553_REG_DISTANCE 0x04 From 996ba514591cd89c5555e143f6ad893f3f5e6824 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 13 Apr 2015 18:40:58 +0300 Subject: [PATCH 0240/3798] iio: accel: mma9553: prefix naming fixes Add mma9553_ prefix to all local functions/declarations. Signed-off-by: Irina Tirdea Suggested-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma9553.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index dcbf04fa3d05bc..b17848eae9ce88 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -75,8 +75,8 @@ #define MMA9553_DEFAULT_GPIO_PIN mma9551_gpio6 #define MMA9553_DEFAULT_GPIO_POLARITY 0 -#define STATUS_TO_BITNUM(bit) (ffs(bit) - 9) /* Bitnum used for GPIO configuration = bit number in high status byte */ +#define MMA9553_STATUS_TO_BITNUM(bit) (ffs(bit) - 9) #define MMA9553_DEFAULT_SAMPLE_RATE 30 /* Hz */ @@ -353,11 +353,11 @@ static int mma9553_conf_gpio(struct mma9553_data *data) * This bit is the logical OR of the SUSPCHG, STEPCHG, and ACTCHG flags. */ if (activity_enabled && ev_step_detect->enabled) - bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_MRGFL); + bitnum = MMA9553_STATUS_TO_BITNUM(MMA9553_MASK_STATUS_MRGFL); else if (ev_step_detect->enabled) - bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_STEPCHG); + bitnum = MMA9553_STATUS_TO_BITNUM(MMA9553_MASK_STATUS_STEPCHG); else if (activity_enabled) - bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_ACTCHG); + bitnum = MMA9553_STATUS_TO_BITNUM(MMA9553_MASK_STATUS_ACTCHG); else /* Reset */ appid = MMA9551_APPID_NONE; @@ -947,11 +947,11 @@ static const struct iio_event_spec mma9553_activity_events[] = { }, }; -static const char * const calibgender_modes[] = { "male", "female" }; +static const char * const mma9553_calibgender_modes[] = { "male", "female" }; static const struct iio_enum mma9553_calibgender_enum = { - .items = calibgender_modes, - .num_items = ARRAY_SIZE(calibgender_modes), + .items = mma9553_calibgender_modes, + .num_items = ARRAY_SIZE(mma9553_calibgender_modes), .get = mma9553_get_calibgender_mode, .set = mma9553_set_calibgender_mode, }; From 334efd076dc5bde5c579c0cf1c2b5d3dcd8839f7 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 13 Apr 2015 18:41:00 +0300 Subject: [PATCH 0241/3798] iio: accel: mma9553: refactor mma9553_read_raw Refactor code for simplicity and clarity. Signed-off-by: Irina Tirdea Suggested-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma9553.c | 101 ++++++++++++------------------------ 1 file changed, 33 insertions(+), 68 deletions(-) diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index b17848eae9ce88..032537fc2c561a 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -441,6 +441,32 @@ static int mma9553_init(struct mma9553_data *data) return mma9551_set_device_state(data->client, true); } +static int mma9553_read_status_word(struct mma9553_data *data, u16 reg, + u16 *tmp) +{ + bool powered_on; + int ret; + + /* + * The HW only counts steps and other dependent + * parameters (speed, distance, calories, activity) + * if power is on (from enabling an event or the + * step counter). + */ + powered_on = mma9553_is_any_event_enabled(data, false, 0) || + data->stepcnt_enabled; + if (!powered_on) { + dev_err(&data->client->dev, "No channels enabled\n"); + return -EINVAL; + } + + mutex_lock(&data->mutex); + ret = mma9551_read_status_word(data->client, MMA9551_APPID_PEDOMETER, + reg, tmp); + mutex_unlock(&data->mutex); + return ret; +} + static int mma9553_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -449,70 +475,30 @@ static int mma9553_read_raw(struct iio_dev *indio_dev, int ret; u16 tmp; u8 activity; - bool powered_on; switch (mask) { case IIO_CHAN_INFO_PROCESSED: switch (chan->type) { case IIO_STEPS: - /* - * The HW only counts steps and other dependent - * parameters (speed, distance, calories, activity) - * if power is on (from enabling an event or the - * step counter). - */ - powered_on = - mma9553_is_any_event_enabled(data, false, 0) || - data->stepcnt_enabled; - if (!powered_on) { - dev_err(&data->client->dev, - "No channels enabled\n"); - return -EINVAL; - } - mutex_lock(&data->mutex); - ret = mma9551_read_status_word(data->client, - MMA9551_APPID_PEDOMETER, + ret = mma9553_read_status_word(data, MMA9553_REG_STEPCNT, &tmp); - mutex_unlock(&data->mutex); if (ret < 0) return ret; *val = tmp; return IIO_VAL_INT; case IIO_DISTANCE: - powered_on = - mma9553_is_any_event_enabled(data, false, 0) || - data->stepcnt_enabled; - if (!powered_on) { - dev_err(&data->client->dev, - "No channels enabled\n"); - return -EINVAL; - } - mutex_lock(&data->mutex); - ret = mma9551_read_status_word(data->client, - MMA9551_APPID_PEDOMETER, + ret = mma9553_read_status_word(data, MMA9553_REG_DISTANCE, &tmp); - mutex_unlock(&data->mutex); if (ret < 0) return ret; *val = tmp; return IIO_VAL_INT; case IIO_ACTIVITY: - powered_on = - mma9553_is_any_event_enabled(data, false, 0) || - data->stepcnt_enabled; - if (!powered_on) { - dev_err(&data->client->dev, - "No channels enabled\n"); - return -EINVAL; - } - mutex_lock(&data->mutex); - ret = mma9551_read_status_word(data->client, - MMA9551_APPID_PEDOMETER, + ret = mma9553_read_status_word(data, MMA9553_REG_STATUS, &tmp); - mutex_unlock(&data->mutex); if (ret < 0) return ret; @@ -537,38 +523,17 @@ static int mma9553_read_raw(struct iio_dev *indio_dev, case IIO_VELOCITY: /* m/h */ if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) return -EINVAL; - powered_on = - mma9553_is_any_event_enabled(data, false, 0) || - data->stepcnt_enabled; - if (!powered_on) { - dev_err(&data->client->dev, - "No channels enabled\n"); - return -EINVAL; - } - mutex_lock(&data->mutex); - ret = mma9551_read_status_word(data->client, - MMA9551_APPID_PEDOMETER, - MMA9553_REG_SPEED, &tmp); - mutex_unlock(&data->mutex); + ret = mma9553_read_status_word(data, + MMA9553_REG_SPEED, + &tmp); if (ret < 0) return ret; *val = tmp; return IIO_VAL_INT; case IIO_ENERGY: /* Cal or kcal */ - powered_on = - mma9553_is_any_event_enabled(data, false, 0) || - data->stepcnt_enabled; - if (!powered_on) { - dev_err(&data->client->dev, - "No channels enabled\n"); - return -EINVAL; - } - mutex_lock(&data->mutex); - ret = mma9551_read_status_word(data->client, - MMA9551_APPID_PEDOMETER, + ret = mma9553_read_status_word(data, MMA9553_REG_CALORIES, &tmp); - mutex_unlock(&data->mutex); if (ret < 0) return ret; *val = tmp; From ef8307a21ac79823b8a4f977eac42329328af384 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 13 Apr 2015 18:40:59 +0300 Subject: [PATCH 0242/3798] iio: accel: mma9553: fix gpio bitnum init value Initial value of gpio bitnum is set to -1, but the variable is declared as unsigned. Use a positive invalid value for initial gpio bitnum. Signed-off-by: Irina Tirdea Suggested-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma9553.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index 032537fc2c561a..9d649c4a21fd0e 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -77,6 +77,7 @@ /* Bitnum used for GPIO configuration = bit number in high status byte */ #define MMA9553_STATUS_TO_BITNUM(bit) (ffs(bit) - 9) +#define MMA9553_MAX_BITNUM MMA9553_STATUS_TO_BITNUM(BIT(16)) #define MMA9553_DEFAULT_SAMPLE_RATE 30 /* Hz */ @@ -406,8 +407,8 @@ static int mma9553_init(struct mma9553_data *data) } - data->gpio_bitnum = -1; /* Reset GPIO */ + data->gpio_bitnum = MMA9553_MAX_BITNUM; ret = mma9553_conf_gpio(data); if (ret < 0) return ret; From e98ceca076bb37d42116c5395ba40d7e31ba869c Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Thu, 16 Apr 2015 22:20:57 +0300 Subject: [PATCH 0243/3798] staging: iio: light: isl29018: Remove non-standard sysfs attributes This patch removes non-standard sysfs attributes range, range_available, adc_resolution and adc_resolution_available. It also removes the corresponding show and store functions. This is in preparation for using standard IIO attributes in order to move the code out of staging. Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 94 ---------------------------- 1 file changed, 94 deletions(-) diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index a3489187aeb0c5..d3d0611d0cb436 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -230,87 +230,6 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, } /* Sysfs interface */ -/* range */ -static ssize_t show_range(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct isl29018_chip *chip = iio_priv(indio_dev); - - return sprintf(buf, "%u\n", chip->range); -} - -static ssize_t store_range(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct isl29018_chip *chip = iio_priv(indio_dev); - int status; - unsigned long lval; - unsigned int new_range; - - if (kstrtoul(buf, 10, &lval)) - return -EINVAL; - - if (!(lval == 1000UL || lval == 4000UL || - lval == 16000UL || lval == 64000UL)) { - dev_err(dev, "The range is not supported\n"); - return -EINVAL; - } - - mutex_lock(&chip->lock); - status = isl29018_set_range(chip, lval, &new_range); - if (status < 0) { - mutex_unlock(&chip->lock); - dev_err(dev, - "Error in setting max range with err %d\n", status); - return status; - } - chip->range = new_range; - mutex_unlock(&chip->lock); - - return count; -} - -/* resolution */ -static ssize_t show_resolution(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct isl29018_chip *chip = iio_priv(indio_dev); - - return sprintf(buf, "%u\n", chip->adc_bit); -} - -static ssize_t store_resolution(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct isl29018_chip *chip = iio_priv(indio_dev); - int status; - unsigned int val; - unsigned int new_adc_bit; - - if (kstrtouint(buf, 10, &val)) - return -EINVAL; - if (!(val == 4 || val == 8 || val == 12 || val == 16)) { - dev_err(dev, "The resolution is not supported\n"); - return -EINVAL; - } - - mutex_lock(&chip->lock); - status = isl29018_set_resolution(chip, val, &new_adc_bit); - if (status < 0) { - mutex_unlock(&chip->lock); - dev_err(dev, "Error in setting resolution\n"); - return status; - } - chip->adc_bit = new_adc_bit; - mutex_unlock(&chip->lock); - - return count; -} - /* proximity scheme */ static ssize_t show_prox_infrared_suppression(struct device *dev, struct device_attribute *attr, char *buf) @@ -447,11 +366,6 @@ static const struct iio_chan_spec isl29023_channels[] = { ISL29018_IR_CHANNEL, }; -static IIO_DEVICE_ATTR(range, S_IRUGO | S_IWUSR, show_range, store_range, 0); -static IIO_CONST_ATTR(range_available, "1000 4000 16000 64000"); -static IIO_CONST_ATTR(adc_resolution_available, "4 8 12 16"); -static IIO_DEVICE_ATTR(adc_resolution, S_IRUGO | S_IWUSR, - show_resolution, store_resolution, 0); static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression, S_IRUGO | S_IWUSR, show_prox_infrared_suppression, @@ -460,19 +374,11 @@ static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression, #define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) #define ISL29018_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr) static struct attribute *isl29018_attributes[] = { - ISL29018_DEV_ATTR(range), - ISL29018_CONST_ATTR(range_available), - ISL29018_DEV_ATTR(adc_resolution), - ISL29018_CONST_ATTR(adc_resolution_available), ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_suppression), NULL }; static struct attribute *isl29023_attributes[] = { - ISL29018_DEV_ATTR(range), - ISL29018_CONST_ATTR(range_available), - ISL29018_DEV_ATTR(adc_resolution), - ISL29018_CONST_ATTR(adc_resolution_available), NULL }; From 809a591b16781cc69f1f3ff2cc9a790e3ae8ec8f Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Thu, 16 Apr 2015 22:20:58 +0300 Subject: [PATCH 0244/3798] staging: iio: light: isl29018: Rename lux_scale to calibscale This patch renames lux_scale to calibscale and lux_uscale to ucalibscale. This is done in order to avoid confusion since these parameters are used for hardware applied calibration. Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index d3d0611d0cb436..ffc3d1b2ee9a72 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -71,8 +71,8 @@ struct isl29018_chip { struct regmap *regmap; struct mutex lock; int type; - unsigned int lux_scale; - unsigned int lux_uscale; + unsigned int calibscale; + unsigned int ucalibscale; unsigned int range; unsigned int adc_bit; int prox_scheme; @@ -165,12 +165,12 @@ static int isl29018_read_lux(struct isl29018_chip *chip, int *lux) /* To support fractional scaling, separate the unshifted lux * into two calculations: int scaling and micro-scaling. - * lux_uscale ranges from 0-999999, so about 20 bits. Split + * ucalibscale ranges from 0-999999, so about 20 bits. Split * the /1,000,000 in two to reduce the risk of over/underflow. */ data_x_range = lux_data * chip->range; - lux_unshifted = data_x_range * chip->lux_scale; - lux_unshifted += data_x_range / 1000 * chip->lux_uscale / 1000; + lux_unshifted = data_x_range * chip->calibscale; + lux_unshifted += data_x_range / 1000 * chip->ucalibscale / 1000; *lux = lux_unshifted >> chip->adc_bit; return 0; @@ -277,9 +277,9 @@ static int isl29018_write_raw(struct iio_dev *indio_dev, mutex_lock(&chip->lock); if (mask == IIO_CHAN_INFO_CALIBSCALE && chan->type == IIO_LIGHT) { - chip->lux_scale = val; + chip->calibscale = val; /* With no write_raw_get_fmt(), val2 is a MICRO fraction. */ - chip->lux_uscale = val2; + chip->ucalibscale = val2; ret = 0; } mutex_unlock(&chip->lock); @@ -323,8 +323,8 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, break; case IIO_CHAN_INFO_CALIBSCALE: if (chan->type == IIO_LIGHT) { - *val = chip->lux_scale; - *val2 = chip->lux_uscale; + *val = chip->calibscale; + *val2 = chip->ucalibscale; ret = IIO_VAL_INT_PLUS_MICRO; } break; @@ -607,8 +607,8 @@ static int isl29018_probe(struct i2c_client *client, mutex_init(&chip->lock); chip->type = dev_id; - chip->lux_scale = 1; - chip->lux_uscale = 0; + chip->calibscale = 1; + chip->ucalibscale = 0; chip->range = 1000; chip->adc_bit = 16; chip->suspended = false; From c7d1f08a0c91ad9796d6d1fac8eb913e8a6d4288 Mon Sep 17 00:00:00 2001 From: Ryo Kataoka Date: Sun, 5 Apr 2015 01:54:31 +0900 Subject: [PATCH 0245/3798] ARM: shmobile: r8a7790: Remove MSIOF address from device tree MSIOF Base Address H'E6xx can be accessed by CPU and DMAC. MSIOF Base Address H'E7xx for DMAC was removed from H/W manual. Signed-off-by: Ryo Kataoka Signed-off-by: Yoshihiro Kaneko Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 4bb2f4c17321bd..f3b8430070b6e4 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1273,7 +1273,7 @@ msiof0: spi@e6e20000 { compatible = "renesas,msiof-r8a7790"; - reg = <0 0xe6e20000 0 0x0064>, <0 0xe7e20000 0 0x0064>; + reg = <0 0xe6e20000 0 0x0064>; interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp0_clks R8A7790_CLK_MSIOF0>; dmas = <&dmac0 0x51>, <&dmac0 0x52>; @@ -1285,7 +1285,7 @@ msiof1: spi@e6e10000 { compatible = "renesas,msiof-r8a7790"; - reg = <0 0xe6e10000 0 0x0064>, <0 0xe7e10000 0 0x0064>; + reg = <0 0xe6e10000 0 0x0064>; interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7790_CLK_MSIOF1>; dmas = <&dmac0 0x55>, <&dmac0 0x56>; @@ -1297,7 +1297,7 @@ msiof2: spi@e6e00000 { compatible = "renesas,msiof-r8a7790"; - reg = <0 0xe6e00000 0 0x0064>, <0 0xe7e00000 0 0x0064>; + reg = <0 0xe6e00000 0 0x0064>; interrupts = <0 158 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7790_CLK_MSIOF2>; dmas = <&dmac0 0x41>, <&dmac0 0x42>; @@ -1309,7 +1309,7 @@ msiof3: spi@e6c90000 { compatible = "renesas,msiof-r8a7790"; - reg = <0 0xe6c90000 0 0x0064>, <0 0xe7c90000 0 0x0064>; + reg = <0 0xe6c90000 0 0x0064>; interrupts = <0 159 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7790_CLK_MSIOF3>; dmas = <&dmac0 0x45>, <&dmac0 0x46>; From cb6d08a2b61fc0025a0148d06b71b8a7d0920e98 Mon Sep 17 00:00:00 2001 From: Ryo Kataoka Date: Sun, 5 Apr 2015 01:55:12 +0900 Subject: [PATCH 0246/3798] ARM: shmobile: r8a7791: Remove MSIOF address from device tree MSIOF Base Address H'E6xx can be accessed by CPU and DMAC. MSIOF Base Address H'E7xx for DMAC was removed from H/W manual. Signed-off-by: Ryo Kataoka Signed-off-by: Yoshihiro Kaneko Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- Documentation/devicetree/bindings/spi/sh-msiof.txt | 2 +- arch/arm/boot/dts/r8a7791.dtsi | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/sh-msiof.txt b/Documentation/devicetree/bindings/spi/sh-msiof.txt index 4c388bb2f0a224..8f771441be6055 100644 --- a/Documentation/devicetree/bindings/spi/sh-msiof.txt +++ b/Documentation/devicetree/bindings/spi/sh-msiof.txt @@ -60,7 +60,7 @@ Example: msiof0: spi@e6e20000 { compatible = "renesas,msiof-r8a7791"; - reg = <0 0xe6e20000 0 0x0064>, <0 0xe7e20000 0 0x0064>; + reg = <0 0xe6e20000 0 0x0064>; interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>; dmas = <&dmac0 0x51>, <&dmac0 0x52>; diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 4696062f6ddeaa..3e9f824797e75a 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1288,7 +1288,7 @@ msiof0: spi@e6e20000 { compatible = "renesas,msiof-r8a7791"; - reg = <0 0xe6e20000 0 0x0064>, <0 0xe7e20000 0 0x0064>; + reg = <0 0xe6e20000 0 0x0064>; interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>; dmas = <&dmac0 0x51>, <&dmac0 0x52>; @@ -1300,7 +1300,7 @@ msiof1: spi@e6e10000 { compatible = "renesas,msiof-r8a7791"; - reg = <0 0xe6e10000 0 0x0064>, <0 0xe7e10000 0 0x0064>; + reg = <0 0xe6e10000 0 0x0064>; interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7791_CLK_MSIOF1>; dmas = <&dmac0 0x55>, <&dmac0 0x56>; @@ -1312,7 +1312,7 @@ msiof2: spi@e6e00000 { compatible = "renesas,msiof-r8a7791"; - reg = <0 0xe6e00000 0 0x0064>, <0 0xe7e00000 0 0x0064>; + reg = <0 0xe6e00000 0 0x0064>; interrupts = <0 158 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7791_CLK_MSIOF2>; dmas = <&dmac0 0x41>, <&dmac0 0x42>; From 7917d14129a5a7241289f06d2c5299c5d03ed529 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 18 Mar 2015 11:24:01 +0800 Subject: [PATCH 0247/3798] ARM: sun8i: Add SMP support for the Allwinner A23 The A23 is a dual Cortex-A7. Add the logic to use the IPs used to control the CPU configuration and the CPU power so that we can bring up secondary CPUs at boot. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- .../devicetree/bindings/arm/cpus.txt | 1 + arch/arm/mach-sunxi/platsmp.c | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt index 6aa331d11c5e3e..d6b794cef0b8b9 100644 --- a/Documentation/devicetree/bindings/arm/cpus.txt +++ b/Documentation/devicetree/bindings/arm/cpus.txt @@ -188,6 +188,7 @@ nodes to be present and contain the properties described below. # On ARM 32-bit systems this property is optional and can be one of: "allwinner,sun6i-a31" + "allwinner,sun8i-a23" "arm,psci" "brcm,brahma-b15" "marvell,armada-375-smp" diff --git a/arch/arm/mach-sunxi/platsmp.c b/arch/arm/mach-sunxi/platsmp.c index 587b0468efcc30..e8483ec79d6706 100644 --- a/arch/arm/mach-sunxi/platsmp.c +++ b/arch/arm/mach-sunxi/platsmp.c @@ -121,3 +121,72 @@ static struct smp_operations sun6i_smp_ops __initdata = { .smp_boot_secondary = sun6i_smp_boot_secondary, }; CPU_METHOD_OF_DECLARE(sun6i_a31_smp, "allwinner,sun6i-a31", &sun6i_smp_ops); + +static void __init sun8i_smp_prepare_cpus(unsigned int max_cpus) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "allwinner,sun8i-a23-prcm"); + if (!node) { + pr_err("Missing A23 PRCM node in the device tree\n"); + return; + } + + prcm_membase = of_iomap(node, 0); + if (!prcm_membase) { + pr_err("Couldn't map A23 PRCM registers\n"); + return; + } + + node = of_find_compatible_node(NULL, NULL, + "allwinner,sun8i-a23-cpuconfig"); + if (!node) { + pr_err("Missing A23 CPU config node in the device tree\n"); + return; + } + + cpucfg_membase = of_iomap(node, 0); + if (!cpucfg_membase) + pr_err("Couldn't map A23 CPU config registers\n"); + +} + +static int sun8i_smp_boot_secondary(unsigned int cpu, + struct task_struct *idle) +{ + u32 reg; + + if (!(prcm_membase && cpucfg_membase)) + return -EFAULT; + + spin_lock(&cpu_lock); + + /* Set CPU boot address */ + writel(virt_to_phys(secondary_startup), + cpucfg_membase + CPUCFG_PRIVATE0_REG); + + /* Assert the CPU core in reset */ + writel(0, cpucfg_membase + CPUCFG_CPU_RST_CTRL_REG(cpu)); + + /* Assert the L1 cache in reset */ + reg = readl(cpucfg_membase + CPUCFG_GEN_CTRL_REG); + writel(reg & ~BIT(cpu), cpucfg_membase + CPUCFG_GEN_CTRL_REG); + + /* Clear CPU power-off gating */ + reg = readl(prcm_membase + PRCM_CPU_PWROFF_REG); + writel(reg & ~BIT(cpu), prcm_membase + PRCM_CPU_PWROFF_REG); + mdelay(1); + + /* Deassert the CPU core reset */ + writel(3, cpucfg_membase + CPUCFG_CPU_RST_CTRL_REG(cpu)); + + spin_unlock(&cpu_lock); + + return 0; +} + +struct smp_operations sun8i_smp_ops __initdata = { + .smp_prepare_cpus = sun8i_smp_prepare_cpus, + .smp_boot_secondary = sun8i_smp_boot_secondary, +}; +CPU_METHOD_OF_DECLARE(sun8i_a23_smp, "allwinner,sun8i-a23", &sun8i_smp_ops); From 033ba3d759db1ae913ad87f59554958a1fbc6fcd Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 2 Sep 2014 19:25:26 +0200 Subject: [PATCH 0248/3798] ARM: sun4i: Relicense the A10 DTSI under GPLv2/X11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current GPL only licensing on the DTSI makes it very impractical for other software components licensed under another license. In order to make it easier for them to reuse our device trees, relicense our DTSI first under a GPL/X11 dual-license. Hopefully, the DTS will follow soon. Signed-off-by: Maxime Ripard Acked-by: Alexandre Belloni Acked-by: Arnd Bergmann Acked-by: Carlo Caione Acked-by: Chen-Yu Tsai Acked-by: David Lanzendörfer Acked-by: Emilio López Acked-by: Hans de Goede Acked-by: Lorenzo Pieralisi Acked-by: Oliver Schinagl Acked-by: Roman Byshko Acked-by: Stefan Roese --- arch/arm/boot/dts/sun4i-a10.dtsi | 46 ++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index eebb7853e00bba..17e4598db1761b 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -2,12 +2,48 @@ * Copyright 2012 Stefan Roese * Stefan Roese * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ #include "skeleton.dtsi" From 1d86b4b52c94867529f4c61d950f77298ddeb85e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 2 Sep 2014 19:25:26 +0200 Subject: [PATCH 0249/3798] ARM: sun5i: Relicense the A10s/A13 DTSI under GPLv2/X11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current GPL only licensing on the DTSI makes it very impractical for other software components licensed under another license. In order to make it easier for them to reuse our device trees, relicense our DTSI first under a GPL/X11 dual-license. Hopefully, the DTS will follow soon. Signed-off-by: Maxime Ripard Acked-by: Arnd Bergmann Acked-by: Chen-Yu Tsai Acked-by: David Lanzendörfer Acked-by: Emilio López Acked-by: Hans de Goede Acked-by: Lorenzo Pieralisi Acked-by: Oliver Schinagl Acked-by: Roman Byshko --- arch/arm/boot/dts/sun5i-a10s.dtsi | 46 +++++++++++++++++++++++++++---- arch/arm/boot/dts/sun5i-a13.dtsi | 46 +++++++++++++++++++++++++++---- 2 files changed, 82 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index 2fd8988f310c6e..3733fc1ed4c7cc 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi @@ -3,12 +3,48 @@ * * Maxime Ripard * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ #include "skeleton.dtsi" diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index 883cb4873688f2..efea2f48e09807 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi @@ -3,12 +3,48 @@ * * Maxime Ripard * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ #include "skeleton.dtsi" From 17a35943458cf9463cd53e88ba3b68d75eb152b1 Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Mon, 26 Jan 2015 20:00:06 +0200 Subject: [PATCH 0250/3798] ARM: dts: sun4i: Add initial dts for Gemei G9 tablet Gemei G9 is an A10 based tablet, with 1G RAM, 16G NAND, 1024x768 IPS LCD display, stereo speakers, 1.3MP front camera and 5 MP rear camera, 8000mAh battery, GT901 2+1 touchscreen, Bosch BMA250 accelerometer and RTL8188CUS USB wifi. It also has MicroSD slot, miniHDMI, 1 x MicroUSB OTG port and 1 x MicroUSB host port and 3.5mm headphone jack. Changes since v2: * Fix syntax error (brown paper bag release) Changes since v1: * Added sun4i-lradc keymap * Added TODO note about missing IRQ pins for bma250 * Fixed formatting issues and removed external URLs Signed-off-by: Priit Laes Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 7 +- arch/arm/boot/dts/sun4i-a10-gemei-g9.dts | 168 +++++++++++++++++++++++ 2 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 arch/arm/boot/dts/sun4i-a10-gemei-g9.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 86217db2937ab3..b3b29104d59ef4 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -525,13 +525,14 @@ dtb-$(CONFIG_MACH_SUN4I) += \ sun4i-a10-ba10-tvbox.dtb \ sun4i-a10-chuwi-v7-cw0825.dtb \ sun4i-a10-cubieboard.dtb \ + sun4i-a10-gemei-g9.dtb \ + sun4i-a10-hackberry.dtb \ + sun4i-a10-hyundai-a7hd.dtb \ + sun4i-a10-inet97fv2.dtb \ sun4i-a10-marsboard.dtb \ sun4i-a10-mini-xplus.dtb \ sun4i-a10-mk802.dtb \ sun4i-a10-mk802ii.dtb \ - sun4i-a10-hackberry.dtb \ - sun4i-a10-hyundai-a7hd.dtb \ - sun4i-a10-inet97fv2.dtb \ sun4i-a10-olinuxino-lime.dtb \ sun4i-a10-pcduino.dtb dtb-$(CONFIG_MACH_SUN5I) += \ diff --git a/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts b/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts new file mode 100644 index 00000000000000..0c734538079383 --- /dev/null +++ b/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts @@ -0,0 +1,168 @@ +/* + * Copyright 2015 Priit Laes + * + * Priit Laes + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun4i-a10.dtsi" +#include "sunxi-common-regulators.dtsi" +#include +#include + +/ { + model = "Gemei G9 Tablet"; + compatible = "gemei,g9", "allwinner,sun4i-a10"; +}; + +/* + * TODO: + * 2x cameras via CSI + * bma250 IRQs + * AXP battery management + * NAND + * OTG + * Touchscreen - gt801_2plus1 @ i2c adapter 2 @ 0x48 + */ + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupts = <0>; + + interrupt-controller; + #interrupt-cells = <1>; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; + + /* Accelerometer */ + bma250@18 { + compatible = "bosch,bma250"; + reg = <0x18>; + + /* + * TODO: interrupt pins: + * int1 - PH00 + * int2 - PI10 + */ + }; +}; + +&lradc { + vref-supply = <®_vcc3v0>; + + status = "okay"; + + button@158 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <158730>; + }; + + button@349 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <349206>; + }; + + button@1142 { + label = "Esc"; + linux,code = ; + channel = <0>; + voltage = <1142856>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH01 */ + cd-inverted; + status = "okay"; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From 061035d456c9902d31a3b7d98b8a7ee0f3b20a99 Mon Sep 17 00:00:00 2001 From: Adam Sampson Date: Tue, 27 Jan 2015 18:27:45 +0000 Subject: [PATCH 0251/3798] ARM: dts: sun7i: Add dts file for pcDuino 3 Nano board Add support for the LinkSprite pcDuino 3 Nano board. This is a low-cost Allwinner A20 board with Arduino-style GPIO headers; it features 1G RAM, 4G NAND flash, 1 micro-SD, 2 USB sockets, 1 micro USB socket for OTG and another for power in, HDMI, SATA, 5V power for SATA devices, gigabit Ethernet, an IR receiver, 3.5mm audio out and a MIPI camera connector. For more details, see: http://linux-sunxi.org/LinkSprite_pcDuino3_Nano Changes in v3: - rename LEDs to pcduino3-nano:green:usr[12] - remove optional features on Arduino headers (i2c2, spi0, uart2) Signed-off-by: Adam Sampson Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 3 +- arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts | 191 ++++++++++++++++++ 2 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index b3b29104d59ef4..8c9c62ba65993d 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -559,7 +559,8 @@ dtb-$(CONFIG_MACH_SUN7I) += \ sun7i-a20-olinuxino-lime.dtb \ sun7i-a20-olinuxino-lime2.dtb \ sun7i-a20-olinuxino-micro.dtb \ - sun7i-a20-pcduino3.dtb + sun7i-a20-pcduino3.dtb \ + sun7i-a20-pcduino3-nano.dtb dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-a23-ippo-q8h-v5.dtb \ sun8i-a23-ippo-q8h-v1.2.dtb diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts new file mode 100644 index 00000000000000..632b8a9e092f79 --- /dev/null +++ b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts @@ -0,0 +1,191 @@ +/* + * Copyright 2015 Adam Sampson + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun7i-a20.dtsi" +#include "sunxi-common-regulators.dtsi" +#include +#include + +/ { + model = "LinkSprite pcDuino3 Nano"; + compatible = "linksprite,pcduino3-nano", "allwinner,sun7i-a20"; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_pcduino3_nano>; + + /* Marked "LED3" on the PCB. */ + usr1 { + label = "pcduino3-nano:green:usr1"; + gpios = <&pio 7 16 GPIO_ACTIVE_LOW>; /* PH16 */ + }; + + /* Marked "LED4" on the PCB. */ + usr2 { + label = "pcduino3-nano:green:usr2"; + gpios = <&pio 7 15 GPIO_ACTIVE_LOW>; /* PH15 */ + }; + }; +}; + +&ahci { + target-supply = <®_ahci_5v>; + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + + interrupt-controller; + #interrupt-cells = <1>; + }; +}; + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pio { + ahci_pwr_pin_pcduino3_nano: ahci_pwr_pin@0 { + allwinner,pins = "PH2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_pcduino3_nano: led_pins@0 { + allwinner,pins = "PH16", "PH15"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb1_vbus_pin_pcduino3_nano: usb1_vbus_pin@0 { + allwinner,pins = "PH11"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_ahci_5v { + pinctrl-0 = <&ahci_pwr_pin_pcduino3_nano>; + gpio = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ + status = "okay"; +}; + +®_usb1_vbus { + pinctrl-0 = <&usb1_vbus_pin_pcduino3_nano>; + gpio = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */ + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From d67b984be92927c1bbab3e391616e51937e26438 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 2 Sep 2014 19:25:26 +0200 Subject: [PATCH 0252/3798] ARM: sun7i: hummingbird: Relicense the device tree under GPLv2/X11 The current GPL only licensing on the DTSI makes it very impractical for other software components licensed under another license. In order to make it easier for them to reuse our device trees, relicense our device trees under a GPL/X11 dual-license. Signed-off-by: Maxime Ripard Acked-by: Wills Wang --- arch/arm/boot/dts/sun7i-a20-hummingbird.dts | 46 ++++++++++++++++++--- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts index 86a944ce19f8c6..2a9ee72b2b4aad 100644 --- a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts +++ b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts @@ -3,12 +3,48 @@ * * Wills Wang * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; From bc8ffc2de87855f91b376dca4597ca0b9254cabc Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 28 Jan 2015 03:54:08 +0800 Subject: [PATCH 0253/3798] ARM: dts: sun9i: Add usb clock nodes to a80 dtsi The USB controller and phy clocks and resets have a separate address block and driver. Add the nodes to represent them. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun9i-a80.dtsi | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi index f0f6fb91f8c36c..0ffecf6f91a9c2 100644 --- a/arch/arm/boot/dts/sun9i-a80.dtsi +++ b/arch/arm/boot/dts/sun9i-a80.dtsi @@ -137,6 +137,28 @@ clock-output-names = "osc32k"; }; + usb_mod_clk: clk@00a08000 { + #clock-cells = <1>; + #reset-cells = <1>; + compatible = "allwinner,sun9i-a80-usb-mod-clk"; + reg = <0x00a08000 0x4>; + clocks = <&ahb1_gates 1>; + clock-output-names = "usb0_ahb", "usb_ohci0", + "usb1_ahb", "usb_ohci1", + "usb2_ahb", "usb_ohci2"; + }; + + usb_phy_clk: clk@00a08004 { + #clock-cells = <1>; + #reset-cells = <1>; + compatible = "allwinner,sun9i-a80-usb-phy-clk"; + reg = <0x00a08004 0x4>; + clocks = <&ahb1_gates 1>; + clock-output-names = "usb_phy0", "usb_hsic1_480M", + "usb_phy1", "usb_hsic2_480M", + "usb_phy2", "usb_hsic_12M"; + }; + pll4: clk@0600000c { #clock-cells = <0>; compatible = "allwinner,sun9i-a80-pll4-clk"; From 1af5d19269c122b7882b26132d2cad05b455e3c7 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 28 Jan 2015 03:54:10 +0800 Subject: [PATCH 0254/3798] ARM: dts: sun9i: Add usb phy nodes to a80 dtsi On sun9i, there are 3 independent usb phys for EHCI/OHCI. Add device nodes for them. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun9i-a80.dtsi | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi index 0ffecf6f91a9c2..7e7a369737b02a 100644 --- a/arch/arm/boot/dts/sun9i-a80.dtsi +++ b/arch/arm/boot/dts/sun9i-a80.dtsi @@ -345,6 +345,43 @@ */ ranges = <0 0 0 0x20000000>; + usbphy1: phy@00a00800 { + compatible = "allwinner,sun9i-a80-usb-phy"; + reg = <0x00a00800 0x4>; + clocks = <&usb_phy_clk 1>; + clock-names = "phy"; + resets = <&usb_phy_clk 17>; + reset-names = "phy"; + status = "disabled"; + #phy-cells = <0>; + }; + + usbphy2: phy@00a01800 { + compatible = "allwinner,sun9i-a80-usb-phy"; + reg = <0x00a01800 0x4>; + clocks = <&usb_phy_clk 2>, <&usb_phy_clk 10>, + <&usb_phy_clk 3>; + clock-names = "hsic_480M", "hsic_12M", "phy"; + resets = <&usb_phy_clk 18>, <&usb_phy_clk 19>; + reset-names = "hsic", "phy"; + status = "disabled"; + #phy-cells = <0>; + /* usb1 is always used with HSIC */ + phy_type = "hsic"; + }; + + usbphy3: phy@00a02800 { + compatible = "allwinner,sun9i-a80-usb-phy"; + reg = <0x00a02800 0x4>; + clocks = <&usb_phy_clk 4>, <&usb_phy_clk 10>, + <&usb_phy_clk 5>; + clock-names = "hsic_480M", "hsic_12M", "phy"; + resets = <&usb_phy_clk 20>, <&usb_phy_clk 21>; + reset-names = "hsic", "phy"; + status = "disabled"; + #phy-cells = <0>; + }; + mmc0: mmc@01c0f000 { compatible = "allwinner,sun5i-a13-mmc"; reg = <0x01c0f000 0x1000>; From c0188c40c2eac2bfc1305240120e568985f17c52 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 2 Sep 2014 19:25:26 +0200 Subject: [PATCH 0255/3798] ARM: sun7i: olinuxino micro: Relicense the device tree under GPLv2/X11 The current GPL only licensing on the DTSI makes it very impractical for other software components licensed under another license. In order to make it easier for them to reuse our device trees, relicense our device trees under a GPL/X11 dual-license. Signed-off-by: Maxime Ripard Acked-by: Carlo Caione Acked-by: Chen-Yu Tsai Acked-by: Hans de Goede Acked-by: Zalan Blenessy --- .../boot/dts/sun7i-a20-olinuxino-micro.dts | 46 +++++++++++++++++-- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts index 714e15ac5416b7..5c548cfda0e496 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts @@ -3,12 +3,48 @@ * * Maxime Ripard * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; From 70472163a7471e1ae37cbdebe2c7bfffc45ebd1f Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 3 Feb 2015 06:22:02 +0800 Subject: [PATCH 0256/3798] ARM: dts: sun9i: Add USB host controller nodes to a80 dtsi The A80 has 3 EHCI/OHCI USB controllers. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun9i-a80.dtsi | 55 ++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi index 7e7a369737b02a..2f7f82cc86ba11 100644 --- a/arch/arm/boot/dts/sun9i-a80.dtsi +++ b/arch/arm/boot/dts/sun9i-a80.dtsi @@ -345,6 +345,28 @@ */ ranges = <0 0 0 0x20000000>; + ehci0: usb@00a00000 { + compatible = "allwinner,sun9i-a80-ehci", "generic-ehci"; + reg = <0x00a00000 0x100>; + interrupts = ; + clocks = <&usb_mod_clk 1>; + resets = <&usb_mod_clk 17>; + phys = <&usbphy1>; + phy-names = "usb"; + status = "disabled"; + }; + + ohci0: usb@00a00400 { + compatible = "allwinner,sun9i-a80-ohci", "generic-ohci"; + reg = <0x00a00400 0x100>; + interrupts = ; + clocks = <&usb_mod_clk 1>, <&usb_mod_clk 2>; + resets = <&usb_mod_clk 17>; + phys = <&usbphy1>; + phy-names = "usb"; + status = "disabled"; + }; + usbphy1: phy@00a00800 { compatible = "allwinner,sun9i-a80-usb-phy"; reg = <0x00a00800 0x4>; @@ -356,6 +378,17 @@ #phy-cells = <0>; }; + ehci1: usb@00a01000 { + compatible = "allwinner,sun9i-a80-ehci", "generic-ehci"; + reg = <0x00a01000 0x100>; + interrupts = ; + clocks = <&usb_mod_clk 3>; + resets = <&usb_mod_clk 18>; + phys = <&usbphy2>; + phy-names = "usb"; + status = "disabled"; + }; + usbphy2: phy@00a01800 { compatible = "allwinner,sun9i-a80-usb-phy"; reg = <0x00a01800 0x4>; @@ -370,6 +403,28 @@ phy_type = "hsic"; }; + ehci2: usb@00a02000 { + compatible = "allwinner,sun9i-a80-ehci", "generic-ehci"; + reg = <0x00a02000 0x100>; + interrupts = ; + clocks = <&usb_mod_clk 5>; + resets = <&usb_mod_clk 19>; + phys = <&usbphy3>; + phy-names = "usb"; + status = "disabled"; + }; + + ohci2: usb@00a02400 { + compatible = "allwinner,sun9i-a80-ohci", "generic-ohci"; + reg = <0x00a02400 0x100>; + interrupts = ; + clocks = <&usb_mod_clk 5>, <&usb_mod_clk 6>; + resets = <&usb_mod_clk 19>; + phys = <&usbphy3>; + phy-names = "usb"; + status = "disabled"; + }; + usbphy3: phy@00a02800 { compatible = "allwinner,sun9i-a80-usb-phy"; reg = <0x00a02800 0x4>; From fa86885b6bc75e73d2f24ada02ccb74cab9c73c1 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 3 Feb 2015 06:22:03 +0800 Subject: [PATCH 0257/3798] ARM: dts: sun9i: Enable USB support on A80 Optimus board On the Optimus board, all three USB hosts can be used. HCI0 and HCI2 are available through the USB connector. HCI1 is available with HSIC through 2 pins on the GPIO expansion header. This patch also adds a regulator for HCI2/USB3's VBUS. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun9i-a80-optimus.dts | 65 +++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts index a3fed2bdf62032..e53f2656c2d0ff 100644 --- a/arch/arm/boot/dts/sun9i-a80-optimus.dts +++ b/arch/arm/boot/dts/sun9i-a80-optimus.dts @@ -86,6 +86,29 @@ gpios = <&pio 7 0 GPIO_ACTIVE_HIGH>; }; }; + + reg_usb3_vbus: usb3-vbus { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&usb3_vbus_pin_optimus>; + regulator-name = "usb3-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */ + }; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&ehci2 { + status = "okay"; }; &i2c3 { @@ -99,6 +122,14 @@ allwinner,pull = ; }; +&ohci0 { + status = "okay"; +}; + +&ohci2 { + status = "okay"; +}; + &pio { led_pins_optimus: led-pins@0 { allwinner,pins = "PH0", "PH1"; @@ -113,6 +144,20 @@ allwinner,drive = ; allwinner,pull = ; }; + + usb1_vbus_pin_optimus: usb1_vbus_pin@1 { + allwinner,pins = "PH4"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb3_vbus_pin_optimus: usb3_vbus_pin@1 { + allwinner,pins = "PH5"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; }; &mmc0 { @@ -134,6 +179,12 @@ status = "okay"; }; +®_usb1_vbus { + pinctrl-0 = <&usb1_vbus_pin_optimus>; + gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_pins_a>; @@ -150,3 +201,17 @@ /* Enable internal pull-up */ allwinner,pull = ; }; + +&usbphy1 { + vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; + +&usbphy2 { + status = "okay"; +}; + +&usbphy3 { + vbus-supply = <®_usb3_vbus>; + status = "okay"; +}; From fbfa7367724339334f8076f6bf03697060f4e9f3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 30 Jan 2015 16:30:48 +0100 Subject: [PATCH 0258/3798] ARM: sun5i: Add a DTSI common to A10s and A13 The A10s and the A13 are very similar SoCs, the only difference being the number of pins and the number of devices available (number of UARTs, EMAC only in the A10s, etc.), and the clocks and pinctrl functions obviously. Create a common DTSI that will be included by the A10s and A13 DTSI, that will add their SoC differences in there. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i.dtsi | 532 +++++++++++++++++++++++++++++++++++ 1 file changed, 532 insertions(+) create mode 100644 arch/arm/boot/dts/sun5i.dtsi diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi new file mode 100644 index 00000000000000..24c29c27fc6d97 --- /dev/null +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -0,0 +1,532 @@ +/* + * Copyright 2012-2015 Maxime Ripard + * + * Maxime Ripard + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "skeleton.dtsi" + +#include +#include + +/ { + interrupt-parent = <&intc>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a8"; + reg = <0x0>; + clocks = <&cpu>; + }; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* + * This is a dummy clock, to be used as placeholder on + * other mux clocks when a specific parent clock is not + * yet implemented. It should be dropped when the driver + * is complete. + */ + dummy: dummy { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <0>; + }; + + osc24M: clk@01c20050 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-osc-clk"; + reg = <0x01c20050 0x4>; + clock-frequency = <24000000>; + clock-output-names = "osc24M"; + }; + + osc32k: clk@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + clock-output-names = "osc32k"; + }; + + pll1: clk@01c20000 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-pll1-clk"; + reg = <0x01c20000 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll1"; + }; + + pll4: clk@01c20018 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-pll1-clk"; + reg = <0x01c20018 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll4"; + }; + + pll5: clk@01c20020 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-pll5-clk"; + reg = <0x01c20020 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll5_ddr", "pll5_other"; + }; + + pll6: clk@01c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-pll6-clk"; + reg = <0x01c20028 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll6_sata", "pll6_other", "pll6"; + }; + + /* dummy is 200M */ + cpu: cpu@01c20054 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-cpu-clk"; + reg = <0x01c20054 0x4>; + clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>; + clock-output-names = "cpu"; + }; + + axi: axi@01c20054 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-axi-clk"; + reg = <0x01c20054 0x4>; + clocks = <&cpu>; + clock-output-names = "axi"; + }; + + ahb: ahb@01c20054 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-ahb-clk"; + reg = <0x01c20054 0x4>; + clocks = <&axi>; + clock-output-names = "ahb"; + }; + + apb0: apb0@01c20054 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-apb0-clk"; + reg = <0x01c20054 0x4>; + clocks = <&ahb>; + clock-output-names = "apb0"; + }; + + apb1: clk@01c20058 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-apb1-clk"; + reg = <0x01c20058 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&osc32k>; + clock-output-names = "apb1"; + }; + + axi_gates: clk@01c2005c { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-axi-gates-clk"; + reg = <0x01c2005c 0x4>; + clocks = <&axi>; + clock-output-names = "axi_dram"; + }; + + nand_clk: clk@01c20080 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; + reg = <0x01c20080 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "nand"; + }; + + ms_clk: clk@01c20084 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; + reg = <0x01c20084 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ms"; + }; + + mmc0_clk: clk@01c20088 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-mmc-clk"; + reg = <0x01c20088 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc0", + "mmc0_output", + "mmc0_sample"; + }; + + mmc1_clk: clk@01c2008c { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-mmc-clk"; + reg = <0x01c2008c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc1", + "mmc1_output", + "mmc1_sample"; + }; + + mmc2_clk: clk@01c20090 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-mmc-clk"; + reg = <0x01c20090 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc2", + "mmc2_output", + "mmc2_sample"; + }; + + ts_clk: clk@01c20098 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; + reg = <0x01c20098 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ts"; + }; + + ss_clk: clk@01c2009c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; + reg = <0x01c2009c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ss"; + }; + + spi0_clk: clk@01c200a0 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; + reg = <0x01c200a0 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi0"; + }; + + spi1_clk: clk@01c200a4 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; + reg = <0x01c200a4 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi1"; + }; + + spi2_clk: clk@01c200a8 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; + reg = <0x01c200a8 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi2"; + }; + + ir0_clk: clk@01c200b0 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; + reg = <0x01c200b0 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ir0"; + }; + + usb_clk: clk@01c200cc { + #clock-cells = <1>; + #reset-cells = <1>; + compatible = "allwinner,sun5i-a13-usb-clk"; + reg = <0x01c200cc 0x4>; + clocks = <&pll6 1>; + clock-output-names = "usb_ohci0", "usb_phy"; + }; + + mbus_clk: clk@01c2015c { + #clock-cells = <0>; + compatible = "allwinner,sun5i-a13-mbus-clk"; + reg = <0x01c2015c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mbus"; + }; + }; + + soc@01c00000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + dma: dma-controller@01c02000 { + compatible = "allwinner,sun4i-a10-dma"; + reg = <0x01c02000 0x1000>; + interrupts = <27>; + clocks = <&ahb_gates 6>; + #dma-cells = <2>; + }; + + spi0: spi@01c05000 { + compatible = "allwinner,sun4i-a10-spi"; + reg = <0x01c05000 0x1000>; + interrupts = <10>; + clocks = <&ahb_gates 20>, <&spi0_clk>; + clock-names = "ahb", "mod"; + dmas = <&dma SUN4I_DMA_DEDICATED 27>, + <&dma SUN4I_DMA_DEDICATED 26>; + dma-names = "rx", "tx"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + spi1: spi@01c06000 { + compatible = "allwinner,sun4i-a10-spi"; + reg = <0x01c06000 0x1000>; + interrupts = <11>; + clocks = <&ahb_gates 21>, <&spi1_clk>; + clock-names = "ahb", "mod"; + dmas = <&dma SUN4I_DMA_DEDICATED 9>, + <&dma SUN4I_DMA_DEDICATED 8>; + dma-names = "rx", "tx"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + mmc0: mmc@01c0f000 { + compatible = "allwinner,sun5i-a13-mmc"; + reg = <0x01c0f000 0x1000>; + clocks = <&ahb_gates 8>, + <&mmc0_clk 0>, + <&mmc0_clk 1>, + <&mmc0_clk 2>; + clock-names = "ahb", + "mmc", + "output", + "sample"; + interrupts = <32>; + status = "disabled"; + }; + + mmc1: mmc@01c10000 { + compatible = "allwinner,sun5i-a13-mmc"; + reg = <0x01c10000 0x1000>; + clocks = <&ahb_gates 9>, + <&mmc1_clk 0>, + <&mmc1_clk 1>, + <&mmc1_clk 2>; + clock-names = "ahb", + "mmc", + "output", + "sample"; + interrupts = <33>; + status = "disabled"; + }; + + mmc2: mmc@01c11000 { + compatible = "allwinner,sun5i-a13-mmc"; + reg = <0x01c11000 0x1000>; + clocks = <&ahb_gates 10>, + <&mmc2_clk 0>, + <&mmc2_clk 1>, + <&mmc2_clk 2>; + clock-names = "ahb", + "mmc", + "output", + "sample"; + interrupts = <34>; + status = "disabled"; + }; + + usbphy: phy@01c13400 { + #phy-cells = <1>; + compatible = "allwinner,sun5i-a13-usb-phy"; + reg = <0x01c13400 0x10 0x01c14800 0x4>; + reg-names = "phy_ctrl", "pmu1"; + clocks = <&usb_clk 8>; + clock-names = "usb_phy"; + resets = <&usb_clk 0>, <&usb_clk 1>; + reset-names = "usb0_reset", "usb1_reset"; + status = "disabled"; + }; + + ehci0: usb@01c14000 { + reg = <0x01c14000 0x100>; + interrupts = <39>; + clocks = <&ahb_gates 1>; + phys = <&usbphy 1>; + phy-names = "usb"; + status = "disabled"; + }; + + ohci0: usb@01c14400 { + reg = <0x01c14400 0x100>; + interrupts = <40>; + clocks = <&usb_clk 6>, <&ahb_gates 2>; + phys = <&usbphy 1>; + phy-names = "usb"; + status = "disabled"; + }; + + spi2: spi@01c17000 { + compatible = "allwinner,sun4i-a10-spi"; + reg = <0x01c17000 0x1000>; + interrupts = <12>; + clocks = <&ahb_gates 22>, <&spi2_clk>; + clock-names = "ahb", "mod"; + dmas = <&dma SUN4I_DMA_DEDICATED 29>, + <&dma SUN4I_DMA_DEDICATED 28>; + dma-names = "rx", "tx"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + intc: interrupt-controller@01c20400 { + compatible = "allwinner,sun4i-a10-ic"; + reg = <0x01c20400 0x400>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + pio: pinctrl@01c20800 { + reg = <0x01c20800 0x400>; + interrupts = <28>; + clocks = <&apb0_gates 5>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + #size-cells = <0>; + #gpio-cells = <3>; + }; + + timer@01c20c00 { + compatible = "allwinner,sun4i-a10-timer"; + reg = <0x01c20c00 0x90>; + interrupts = <22>; + clocks = <&osc24M>; + }; + + wdt: watchdog@01c20c90 { + compatible = "allwinner,sun4i-a10-wdt"; + reg = <0x01c20c90 0x10>; + }; + + lradc: lradc@01c22800 { + compatible = "allwinner,sun4i-a10-lradc-keys"; + reg = <0x01c22800 0x100>; + interrupts = <31>; + status = "disabled"; + }; + + sid: eeprom@01c23800 { + compatible = "allwinner,sun4i-a10-sid"; + reg = <0x01c23800 0x10>; + }; + + rtp: rtp@01c25000 { + compatible = "allwinner,sun4i-a10-ts"; + reg = <0x01c25000 0x100>; + interrupts = <29>; + #thermal-sensor-cells = <0>; + }; + + uart1: serial@01c28400 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c28400 0x400>; + interrupts = <2>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&apb1_gates 17>; + status = "disabled"; + }; + + uart3: serial@01c28c00 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c28c00 0x400>; + interrupts = <4>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&apb1_gates 19>; + status = "disabled"; + }; + + i2c0: i2c@01c2ac00 { + compatible = "allwinner,sun4i-a10-i2c"; + reg = <0x01c2ac00 0x400>; + interrupts = <7>; + clocks = <&apb1_gates 0>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c1: i2c@01c2b000 { + compatible = "allwinner,sun4i-a10-i2c"; + reg = <0x01c2b000 0x400>; + interrupts = <8>; + clocks = <&apb1_gates 1>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c2: i2c@01c2b400 { + compatible = "allwinner,sun4i-a10-i2c"; + reg = <0x01c2b400 0x400>; + interrupts = <9>; + clocks = <&apb1_gates 2>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + timer@01c60000 { + compatible = "allwinner,sun5i-a13-hstimer"; + reg = <0x01c60000 0x1000>; + interrupts = <82>, <83>; + clocks = <&ahb_gates 28>; + }; + }; +}; From 51fbba421261f13f215848c49ec8e3a169e0f1a2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 30 Jan 2015 16:31:19 +0100 Subject: [PATCH 0259/3798] ARM: sun5i: a13: Move to the common sun5i DTSI Now that we have a common DTSI for the sun5i family, move the A13 to use it. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i-a13.dtsi | 552 +++---------------------------- arch/arm/boot/dts/sun5i.dtsi | 28 ++ 2 files changed, 65 insertions(+), 515 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index efea2f48e09807..39264f7c7ae602 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi @@ -49,10 +49,10 @@ #include "skeleton.dtsi" -#include +#include "sun5i.dtsi" -#include #include +#include / { interrupt-parent = <&intc>; @@ -71,31 +71,6 @@ }; }; - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a8"; - reg = <0x0>; - clocks = <&cpu>; - clock-latency = <244144>; /* 8 32k periods */ - operating-points = < - /* kHz uV */ - 1008000 1400000 - 912000 1350000 - 864000 1300000 - 624000 1200000 - 576000 1200000 - 432000 1200000 - >; - #cooling-cells = <2>; - cooling-min-level = <0>; - cooling-max-level = <5>; - }; - }; - thermal-zones { cpu_thermal { /* milliseconds */ @@ -128,107 +103,7 @@ }; }; - memory { - reg = <0x40000000 0x20000000>; - }; - clocks { - #address-cells = <1>; - #size-cells = <1>; - ranges; - - /* - * This is a dummy clock, to be used as placeholder on - * other mux clocks when a specific parent clock is not - * yet implemented. It should be dropped when the driver - * is complete. - */ - dummy: dummy { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <0>; - }; - - osc24M: clk@01c20050 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-osc-clk"; - reg = <0x01c20050 0x4>; - clock-frequency = <24000000>; - clock-output-names = "osc24M"; - }; - - osc32k: clk@0 { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <32768>; - clock-output-names = "osc32k"; - }; - - pll1: clk@01c20000 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-pll1-clk"; - reg = <0x01c20000 0x4>; - clocks = <&osc24M>; - clock-output-names = "pll1"; - }; - - pll4: clk@01c20018 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-pll1-clk"; - reg = <0x01c20018 0x4>; - clocks = <&osc24M>; - clock-output-names = "pll4"; - }; - - pll5: clk@01c20020 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-pll5-clk"; - reg = <0x01c20020 0x4>; - clocks = <&osc24M>; - clock-output-names = "pll5_ddr", "pll5_other"; - }; - - pll6: clk@01c20028 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-pll6-clk"; - reg = <0x01c20028 0x4>; - clocks = <&osc24M>; - clock-output-names = "pll6_sata", "pll6_other", "pll6"; - }; - - /* dummy is 200M */ - cpu: cpu@01c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-cpu-clk"; - reg = <0x01c20054 0x4>; - clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>; - clock-output-names = "cpu"; - }; - - axi: axi@01c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-axi-clk"; - reg = <0x01c20054 0x4>; - clocks = <&cpu>; - clock-output-names = "axi"; - }; - - axi_gates: clk@01c2005c { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-axi-gates-clk"; - reg = <0x01c2005c 0x4>; - clocks = <&axi>; - clock-output-names = "axi_dram"; - }; - - ahb: ahb@01c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-ahb-clk"; - reg = <0x01c20054 0x4>; - clocks = <&axi>; - clock-output-names = "ahb"; - }; - ahb_gates: clk@01c20060 { #clock-cells = <1>; compatible = "allwinner,sun5i-a13-ahb-gates-clk"; @@ -242,14 +117,6 @@ "ahb_de_fe", "ahb_iep", "ahb_mali400"; }; - apb0: apb0@01c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-apb0-clk"; - reg = <0x01c20054 0x4>; - clocks = <&ahb>; - clock-output-names = "apb0"; - }; - apb0_gates: clk@01c20068 { #clock-cells = <1>; compatible = "allwinner,sun5i-a13-apb0-gates-clk"; @@ -258,14 +125,6 @@ clock-output-names = "apb0_codec", "apb0_pio", "apb0_ir"; }; - apb1: clk@01c20058 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-apb1-clk"; - reg = <0x01c20058 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&osc32k>; - clock-output-names = "apb1"; - }; - apb1_gates: clk@01c2006c { #clock-cells = <1>; compatible = "allwinner,sun5i-a13-apb1-gates-clk"; @@ -274,384 +133,47 @@ clock-output-names = "apb1_i2c0", "apb1_i2c1", "apb1_i2c2", "apb1_uart1", "apb1_uart3"; }; - - nand_clk: clk@01c20080 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c20080 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "nand"; - }; - - ms_clk: clk@01c20084 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c20084 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "ms"; - }; - - mmc0_clk: clk@01c20088 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-mmc-clk"; - reg = <0x01c20088 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "mmc0", - "mmc0_output", - "mmc0_sample"; - }; - - mmc1_clk: clk@01c2008c { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-mmc-clk"; - reg = <0x01c2008c 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "mmc1", - "mmc1_output", - "mmc1_sample"; - }; - - mmc2_clk: clk@01c20090 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-mmc-clk"; - reg = <0x01c20090 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "mmc2", - "mmc2_output", - "mmc2_sample"; - }; - - ts_clk: clk@01c20098 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c20098 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "ts"; - }; - - ss_clk: clk@01c2009c { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c2009c 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "ss"; - }; - - spi0_clk: clk@01c200a0 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c200a0 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "spi0"; - }; - - spi1_clk: clk@01c200a4 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c200a4 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "spi1"; - }; - - spi2_clk: clk@01c200a8 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c200a8 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "spi2"; - }; - - ir0_clk: clk@01c200b0 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c200b0 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "ir0"; - }; - - usb_clk: clk@01c200cc { - #clock-cells = <1>; - #reset-cells = <1>; - compatible = "allwinner,sun5i-a13-usb-clk"; - reg = <0x01c200cc 0x4>; - clocks = <&pll6 1>; - clock-output-names = "usb_ohci0", "usb_phy"; - }; - - mbus_clk: clk@01c2015c { - #clock-cells = <0>; - compatible = "allwinner,sun5i-a13-mbus-clk"; - reg = <0x01c2015c 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "mbus"; - }; }; +}; - soc@01c00000 { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - dma: dma-controller@01c02000 { - compatible = "allwinner,sun4i-a10-dma"; - reg = <0x01c02000 0x1000>; - interrupts = <27>; - clocks = <&ahb_gates 6>; - #dma-cells = <2>; - }; - - spi0: spi@01c05000 { - compatible = "allwinner,sun4i-a10-spi"; - reg = <0x01c05000 0x1000>; - interrupts = <10>; - clocks = <&ahb_gates 20>, <&spi0_clk>; - clock-names = "ahb", "mod"; - dmas = <&dma SUN4I_DMA_DEDICATED 27>, - <&dma SUN4I_DMA_DEDICATED 26>; - dma-names = "rx", "tx"; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - }; - - spi1: spi@01c06000 { - compatible = "allwinner,sun4i-a10-spi"; - reg = <0x01c06000 0x1000>; - interrupts = <11>; - clocks = <&ahb_gates 21>, <&spi1_clk>; - clock-names = "ahb", "mod"; - dmas = <&dma SUN4I_DMA_DEDICATED 9>, - <&dma SUN4I_DMA_DEDICATED 8>; - dma-names = "rx", "tx"; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - }; - - mmc0: mmc@01c0f000 { - compatible = "allwinner,sun5i-a13-mmc"; - reg = <0x01c0f000 0x1000>; - clocks = <&ahb_gates 8>, - <&mmc0_clk 0>, - <&mmc0_clk 1>, - <&mmc0_clk 2>; - clock-names = "ahb", - "mmc", - "output", - "sample"; - interrupts = <32>; - status = "disabled"; - }; - - mmc2: mmc@01c11000 { - compatible = "allwinner,sun5i-a13-mmc"; - reg = <0x01c11000 0x1000>; - clocks = <&ahb_gates 10>, - <&mmc2_clk 0>, - <&mmc2_clk 1>, - <&mmc2_clk 2>; - clock-names = "ahb", - "mmc", - "output", - "sample"; - interrupts = <34>; - status = "disabled"; - }; - - usbphy: phy@01c13400 { - #phy-cells = <1>; - compatible = "allwinner,sun5i-a13-usb-phy"; - reg = <0x01c13400 0x10 0x01c14800 0x4>; - reg-names = "phy_ctrl", "pmu1"; - clocks = <&usb_clk 8>; - clock-names = "usb_phy"; - resets = <&usb_clk 0>, <&usb_clk 1>; - reset-names = "usb0_reset", "usb1_reset"; - status = "disabled"; - }; - - ehci0: usb@01c14000 { - compatible = "allwinner,sun5i-a13-ehci", "generic-ehci"; - reg = <0x01c14000 0x100>; - interrupts = <39>; - clocks = <&ahb_gates 1>; - phys = <&usbphy 1>; - phy-names = "usb"; - status = "disabled"; - }; - - ohci0: usb@01c14400 { - compatible = "allwinner,sun5i-a13-ohci", "generic-ohci"; - reg = <0x01c14400 0x100>; - interrupts = <40>; - clocks = <&usb_clk 6>, <&ahb_gates 2>; - phys = <&usbphy 1>; - phy-names = "usb"; - status = "disabled"; - }; - - spi2: spi@01c17000 { - compatible = "allwinner,sun4i-a10-spi"; - reg = <0x01c17000 0x1000>; - interrupts = <12>; - clocks = <&ahb_gates 22>, <&spi2_clk>; - clock-names = "ahb", "mod"; - dmas = <&dma SUN4I_DMA_DEDICATED 29>, - <&dma SUN4I_DMA_DEDICATED 28>; - dma-names = "rx", "tx"; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - }; - - intc: interrupt-controller@01c20400 { - compatible = "allwinner,sun4i-a10-ic"; - reg = <0x01c20400 0x400>; - interrupt-controller; - #interrupt-cells = <1>; - }; - - pio: pinctrl@01c20800 { - compatible = "allwinner,sun5i-a13-pinctrl"; - reg = <0x01c20800 0x400>; - interrupts = <28>; - clocks = <&apb0_gates 5>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - #size-cells = <0>; - #gpio-cells = <3>; - - uart1_pins_a: uart1@0 { - allwinner,pins = "PE10", "PE11"; - allwinner,function = "uart1"; - allwinner,drive = ; - allwinner,pull = ; - }; - - uart1_pins_b: uart1@1 { - allwinner,pins = "PG3", "PG4"; - allwinner,function = "uart1"; - allwinner,drive = ; - allwinner,pull = ; - }; - - i2c0_pins_a: i2c0@0 { - allwinner,pins = "PB0", "PB1"; - allwinner,function = "i2c0"; - allwinner,drive = ; - allwinner,pull = ; - }; - - i2c1_pins_a: i2c1@0 { - allwinner,pins = "PB15", "PB16"; - allwinner,function = "i2c1"; - allwinner,drive = ; - allwinner,pull = ; - }; - - i2c2_pins_a: i2c2@0 { - allwinner,pins = "PB17", "PB18"; - allwinner,function = "i2c2"; - allwinner,drive = ; - allwinner,pull = ; - }; - - mmc0_pins_a: mmc0@0 { - allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; - allwinner,function = "mmc0"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; - - timer@01c20c00 { - compatible = "allwinner,sun4i-a10-timer"; - reg = <0x01c20c00 0x90>; - interrupts = <22>; - clocks = <&osc24M>; - }; - - wdt: watchdog@01c20c90 { - compatible = "allwinner,sun4i-a10-wdt"; - reg = <0x01c20c90 0x10>; - }; - - lradc: lradc@01c22800 { - compatible = "allwinner,sun4i-a10-lradc-keys"; - reg = <0x01c22800 0x100>; - interrupts = <31>; - status = "disabled"; - }; - - sid: eeprom@01c23800 { - compatible = "allwinner,sun4i-a10-sid"; - reg = <0x01c23800 0x10>; - }; - - rtp: rtp@01c25000 { - compatible = "allwinner,sun4i-a10-ts"; - reg = <0x01c25000 0x100>; - interrupts = <29>; - #thermal-sensor-cells = <0>; - }; - - uart1: serial@01c28400 { - compatible = "snps,dw-apb-uart"; - reg = <0x01c28400 0x400>; - interrupts = <2>; - reg-shift = <2>; - reg-io-width = <4>; - clocks = <&apb1_gates 17>; - status = "disabled"; - }; +&cpu0 { + clock-latency = <244144>; /* 8 32k periods */ + operating-points = < + /* kHz uV */ + 1008000 1400000 + 912000 1350000 + 864000 1300000 + 624000 1200000 + 576000 1200000 + 432000 1200000 + >; + #cooling-cells = <2>; + cooling-min-level = <0>; + cooling-max-level = <5>; +}; - uart3: serial@01c28c00 { - compatible = "snps,dw-apb-uart"; - reg = <0x01c28c00 0x400>; - interrupts = <4>; - reg-shift = <2>; - reg-io-width = <4>; - clocks = <&apb1_gates 19>; - status = "disabled"; - }; +&ehci0 { + compatible = "allwinner,sun5i-a13-ehci", "generic-ehci"; +}; - i2c0: i2c@01c2ac00 { - compatible = "allwinner,sun5i-a13-i2c", "allwinner,sun4i-a10-i2c"; - reg = <0x01c2ac00 0x400>; - interrupts = <7>; - clocks = <&apb1_gates 0>; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - }; +&ohci0 { + compatible = "allwinner,sun5i-a13-ohci", "generic-ohci"; +}; - i2c1: i2c@01c2b000 { - compatible = "allwinner,sun5i-a13-i2c", "allwinner,sun4i-a10-i2c"; - reg = <0x01c2b000 0x400>; - interrupts = <8>; - clocks = <&apb1_gates 1>; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - }; +&pio { + compatible = "allwinner,sun5i-a13-pinctrl"; - i2c2: i2c@01c2b400 { - compatible = "allwinner,sun5i-a13-i2c", "allwinner,sun4i-a10-i2c"; - reg = <0x01c2b400 0x400>; - interrupts = <9>; - clocks = <&apb1_gates 2>; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - }; + uart1_pins_a: uart1@0 { + allwinner,pins = "PE10", "PE11"; + allwinner,function = "uart1"; + allwinner,drive = ; + allwinner,pull = ; + }; - timer@01c60000 { - compatible = "allwinner,sun5i-a13-hstimer"; - reg = <0x01c60000 0x1000>; - interrupts = <82>, <83>; - clocks = <&ahb_gates 28>; - }; + uart1_pins_b: uart1@1 { + allwinner,pins = "PG3", "PG4"; + allwinner,function = "uart1"; + allwinner,drive = ; + allwinner,pull = ; }; }; diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index 24c29c27fc6d97..e42cbb03620f9f 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -439,6 +439,34 @@ #interrupt-cells = <2>; #size-cells = <0>; #gpio-cells = <3>; + + i2c0_pins_a: i2c0@0 { + allwinner,pins = "PB0", "PB1"; + allwinner,function = "i2c0"; + allwinner,drive = ; + allwinner,pull = ; + }; + + i2c1_pins_a: i2c1@0 { + allwinner,pins = "PB15", "PB16"; + allwinner,function = "i2c1"; + allwinner,drive = ; + allwinner,pull = ; + }; + + i2c2_pins_a: i2c2@0 { + allwinner,pins = "PB17", "PB18"; + allwinner,function = "i2c2"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc0_pins_a: mmc0@0 { + allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; + allwinner,function = "mmc0"; + allwinner,drive = ; + allwinner,pull = ; + }; }; timer@01c20c00 { From 903b2d75159fe1d5eca7e7e911c824268fe6c9f1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 30 Jan 2015 16:42:13 +0100 Subject: [PATCH 0260/3798] ARM: sun5i: a10s: Move to the common sun5i DTSI Now that we have a common DTSI for the sun5i family, move the A10s to use it. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i-a10s.dtsi | 582 +++--------------------------- 1 file changed, 48 insertions(+), 534 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index 3733fc1ed4c7cc..ef516db5852d2d 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi @@ -49,6 +49,8 @@ #include "skeleton.dtsi" +#include "sun5i.dtsi" + #include #include @@ -81,113 +83,7 @@ }; }; - cpus { - cpu@0 { - compatible = "arm,cortex-a8"; - }; - }; - - memory { - reg = <0x40000000 0x20000000>; - }; - clocks { - #address-cells = <1>; - #size-cells = <1>; - ranges; - - /* - * This is a dummy clock, to be used as placeholder on - * other mux clocks when a specific parent clock is not - * yet implemented. It should be dropped when the driver - * is complete. - */ - dummy: dummy { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <0>; - }; - - osc24M: clk@01c20050 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-osc-clk"; - reg = <0x01c20050 0x4>; - clock-frequency = <24000000>; - clock-output-names = "osc24M"; - }; - - osc32k: clk@0 { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <32768>; - clock-output-names = "osc32k"; - }; - - pll1: clk@01c20000 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-pll1-clk"; - reg = <0x01c20000 0x4>; - clocks = <&osc24M>; - clock-output-names = "pll1"; - }; - - pll4: clk@01c20018 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-pll1-clk"; - reg = <0x01c20018 0x4>; - clocks = <&osc24M>; - clock-output-names = "pll4"; - }; - - pll5: clk@01c20020 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-pll5-clk"; - reg = <0x01c20020 0x4>; - clocks = <&osc24M>; - clock-output-names = "pll5_ddr", "pll5_other"; - }; - - pll6: clk@01c20028 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-pll6-clk"; - reg = <0x01c20028 0x4>; - clocks = <&osc24M>; - clock-output-names = "pll6_sata", "pll6_other", "pll6"; - }; - - /* dummy is 200M */ - cpu: cpu@01c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-cpu-clk"; - reg = <0x01c20054 0x4>; - clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>; - clock-output-names = "cpu"; - }; - - axi: axi@01c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-axi-clk"; - reg = <0x01c20054 0x4>; - clocks = <&cpu>; - clock-output-names = "axi"; - }; - - axi_gates: clk@01c2005c { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-axi-gates-clk"; - reg = <0x01c2005c 0x4>; - clocks = <&axi>; - clock-output-names = "axi_dram"; - }; - - ahb: ahb@01c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-ahb-clk"; - reg = <0x01c20054 0x4>; - clocks = <&axi>; - clock-output-names = "ahb"; - }; - ahb_gates: clk@01c20060 { #clock-cells = <1>; compatible = "allwinner,sun5i-a10s-ahb-gates-clk"; @@ -202,14 +98,6 @@ "ahb_de_be", "ahb_de_fe", "ahb_iep", "ahb_mali400"; }; - apb0: apb0@01c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-apb0-clk"; - reg = <0x01c20054 0x4>; - clocks = <&ahb>; - clock-output-names = "apb0"; - }; - apb0_gates: clk@01c20068 { #clock-cells = <1>; compatible = "allwinner,sun5i-a10s-apb0-gates-clk"; @@ -219,14 +107,6 @@ "apb0_ir", "apb0_keypad"; }; - apb1: clk@01c20058 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-apb1-clk"; - reg = <0x01c20058 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&osc32k>; - clock-output-names = "apb1"; - }; - apb1_gates: clk@01c2006c { #clock-cells = <1>; compatible = "allwinner,sun5i-a10s-apb1-gates-clk"; @@ -236,161 +116,9 @@ "apb1_i2c2", "apb1_uart0", "apb1_uart1", "apb1_uart2", "apb1_uart3"; }; - - nand_clk: clk@01c20080 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c20080 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "nand"; - }; - - ms_clk: clk@01c20084 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c20084 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "ms"; - }; - - mmc0_clk: clk@01c20088 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-mmc-clk"; - reg = <0x01c20088 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "mmc0", - "mmc0_output", - "mmc0_sample"; - }; - - mmc1_clk: clk@01c2008c { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-mmc-clk"; - reg = <0x01c2008c 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "mmc1", - "mmc1_output", - "mmc1_sample"; - }; - - mmc2_clk: clk@01c20090 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-mmc-clk"; - reg = <0x01c20090 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "mmc2", - "mmc2_output", - "mmc2_sample"; - }; - - ts_clk: clk@01c20098 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c20098 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "ts"; - }; - - ss_clk: clk@01c2009c { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c2009c 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "ss"; - }; - - spi0_clk: clk@01c200a0 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c200a0 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "spi0"; - }; - - spi1_clk: clk@01c200a4 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c200a4 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "spi1"; - }; - - spi2_clk: clk@01c200a8 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c200a8 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "spi2"; - }; - - ir0_clk: clk@01c200b0 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-mod0-clk"; - reg = <0x01c200b0 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "ir0"; - }; - - usb_clk: clk@01c200cc { - #clock-cells = <1>; - #reset-cells = <1>; - compatible = "allwinner,sun5i-a13-usb-clk"; - reg = <0x01c200cc 0x4>; - clocks = <&pll6 1>; - clock-output-names = "usb_ohci0", "usb_phy"; - }; - - mbus_clk: clk@01c2015c { - #clock-cells = <0>; - compatible = "allwinner,sun5i-a13-mbus-clk"; - reg = <0x01c2015c 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "mbus"; - }; }; soc@01c00000 { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - dma: dma-controller@01c02000 { - compatible = "allwinner,sun4i-a10-dma"; - reg = <0x01c02000 0x1000>; - interrupts = <27>; - clocks = <&ahb_gates 6>; - #dma-cells = <2>; - }; - - spi0: spi@01c05000 { - compatible = "allwinner,sun4i-a10-spi"; - reg = <0x01c05000 0x1000>; - interrupts = <10>; - clocks = <&ahb_gates 20>, <&spi0_clk>; - clock-names = "ahb", "mod"; - dmas = <&dma SUN4I_DMA_DEDICATED 27>, - <&dma SUN4I_DMA_DEDICATED 26>; - dma-names = "rx", "tx"; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - }; - - spi1: spi@01c06000 { - compatible = "allwinner,sun4i-a10-spi"; - reg = <0x01c06000 0x1000>; - interrupts = <11>; - clocks = <&ahb_gates 21>, <&spi1_clk>; - clock-names = "ahb", "mod"; - dmas = <&dma SUN4I_DMA_DEDICATED 9>, - <&dma SUN4I_DMA_DEDICATED 8>; - dma-names = "rx", "tx"; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - }; - emac: ethernet@01c0b000 { compatible = "allwinner,sun4i-a10-emac"; reg = <0x01c0b000 0x1000>; @@ -407,214 +135,6 @@ #size-cells = <0>; }; - mmc0: mmc@01c0f000 { - compatible = "allwinner,sun5i-a13-mmc"; - reg = <0x01c0f000 0x1000>; - clocks = <&ahb_gates 8>, - <&mmc0_clk 0>, - <&mmc0_clk 1>, - <&mmc0_clk 2>; - clock-names = "ahb", - "mmc", - "output", - "sample"; - interrupts = <32>; - status = "disabled"; - }; - - mmc1: mmc@01c10000 { - compatible = "allwinner,sun5i-a13-mmc"; - reg = <0x01c10000 0x1000>; - clocks = <&ahb_gates 9>, - <&mmc1_clk 0>, - <&mmc1_clk 1>, - <&mmc1_clk 2>; - clock-names = "ahb", - "mmc", - "output", - "sample"; - interrupts = <33>; - status = "disabled"; - }; - - mmc2: mmc@01c11000 { - compatible = "allwinner,sun5i-a13-mmc"; - reg = <0x01c11000 0x1000>; - clocks = <&ahb_gates 10>, - <&mmc2_clk 0>, - <&mmc2_clk 1>, - <&mmc2_clk 2>; - clock-names = "ahb", - "mmc", - "output", - "sample"; - interrupts = <34>; - status = "disabled"; - }; - - usbphy: phy@01c13400 { - #phy-cells = <1>; - compatible = "allwinner,sun5i-a13-usb-phy"; - reg = <0x01c13400 0x10 0x01c14800 0x4>; - reg-names = "phy_ctrl", "pmu1"; - clocks = <&usb_clk 8>; - clock-names = "usb_phy"; - resets = <&usb_clk 0>, <&usb_clk 1>; - reset-names = "usb0_reset", "usb1_reset"; - status = "disabled"; - }; - - ehci0: usb@01c14000 { - compatible = "allwinner,sun5i-a10s-ehci", "generic-ehci"; - reg = <0x01c14000 0x100>; - interrupts = <39>; - clocks = <&ahb_gates 1>; - phys = <&usbphy 1>; - phy-names = "usb"; - status = "disabled"; - }; - - ohci0: usb@01c14400 { - compatible = "allwinner,sun5i-a10s-ohci", "generic-ohci"; - reg = <0x01c14400 0x100>; - interrupts = <40>; - clocks = <&usb_clk 6>, <&ahb_gates 2>; - phys = <&usbphy 1>; - phy-names = "usb"; - status = "disabled"; - }; - - spi2: spi@01c17000 { - compatible = "allwinner,sun4i-a10-spi"; - reg = <0x01c17000 0x1000>; - interrupts = <12>; - clocks = <&ahb_gates 22>, <&spi2_clk>; - clock-names = "ahb", "mod"; - dmas = <&dma SUN4I_DMA_DEDICATED 29>, - <&dma SUN4I_DMA_DEDICATED 28>; - dma-names = "rx", "tx"; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - }; - - intc: interrupt-controller@01c20400 { - compatible = "allwinner,sun4i-a10-ic"; - reg = <0x01c20400 0x400>; - interrupt-controller; - #interrupt-cells = <1>; - }; - - pio: pinctrl@01c20800 { - compatible = "allwinner,sun5i-a10s-pinctrl"; - reg = <0x01c20800 0x400>; - interrupts = <28>; - clocks = <&apb0_gates 5>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - #size-cells = <0>; - #gpio-cells = <3>; - - uart0_pins_a: uart0@0 { - allwinner,pins = "PB19", "PB20"; - allwinner,function = "uart0"; - allwinner,drive = ; - allwinner,pull = ; - }; - - uart2_pins_a: uart2@0 { - allwinner,pins = "PC18", "PC19"; - allwinner,function = "uart2"; - allwinner,drive = ; - allwinner,pull = ; - }; - - uart3_pins_a: uart3@0 { - allwinner,pins = "PG9", "PG10"; - allwinner,function = "uart3"; - allwinner,drive = ; - allwinner,pull = ; - }; - - emac_pins_a: emac0@0 { - allwinner,pins = "PA0", "PA1", "PA2", - "PA3", "PA4", "PA5", "PA6", - "PA7", "PA8", "PA9", "PA10", - "PA11", "PA12", "PA13", "PA14", - "PA15", "PA16"; - allwinner,function = "emac"; - allwinner,drive = ; - allwinner,pull = ; - }; - - i2c0_pins_a: i2c0@0 { - allwinner,pins = "PB0", "PB1"; - allwinner,function = "i2c0"; - allwinner,drive = ; - allwinner,pull = ; - }; - - i2c1_pins_a: i2c1@0 { - allwinner,pins = "PB15", "PB16"; - allwinner,function = "i2c1"; - allwinner,drive = ; - allwinner,pull = ; - }; - - i2c2_pins_a: i2c2@0 { - allwinner,pins = "PB17", "PB18"; - allwinner,function = "i2c2"; - allwinner,drive = ; - allwinner,pull = ; - }; - - mmc0_pins_a: mmc0@0 { - allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; - allwinner,function = "mmc0"; - allwinner,drive = ; - allwinner,pull = ; - }; - - mmc1_pins_a: mmc1@0 { - allwinner,pins = "PG3","PG4","PG5","PG6","PG7","PG8"; - allwinner,function = "mmc1"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; - - timer@01c20c00 { - compatible = "allwinner,sun4i-a10-timer"; - reg = <0x01c20c00 0x90>; - interrupts = <22>; - clocks = <&osc24M>; - }; - - wdt: watchdog@01c20c90 { - compatible = "allwinner,sun4i-a10-wdt"; - reg = <0x01c20c90 0x10>; - }; - - lradc: lradc@01c22800 { - compatible = "allwinner,sun4i-a10-lradc-keys"; - reg = <0x01c22800 0x100>; - interrupts = <31>; - status = "disabled"; - }; - - sid: eeprom@01c23800 { - compatible = "allwinner,sun4i-a10-sid"; - reg = <0x01c23800 0x10>; - }; - - rtp: rtp@01c25000 { - compatible = "allwinner,sun4i-a10-ts"; - reg = <0x01c25000 0x100>; - interrupts = <29>; - #thermal-sensor-cells = <0>; - }; - uart0: serial@01c28000 { compatible = "snps,dw-apb-uart"; reg = <0x01c28000 0x400>; @@ -625,16 +145,6 @@ status = "disabled"; }; - uart1: serial@01c28400 { - compatible = "snps,dw-apb-uart"; - reg = <0x01c28400 0x400>; - interrupts = <2>; - reg-shift = <2>; - reg-io-width = <4>; - clocks = <&apb1_gates 17>; - status = "disabled"; - }; - uart2: serial@01c28800 { compatible = "snps,dw-apb-uart"; reg = <0x01c28800 0x400>; @@ -644,52 +154,56 @@ clocks = <&apb1_gates 18>; status = "disabled"; }; + }; +}; - uart3: serial@01c28c00 { - compatible = "snps,dw-apb-uart"; - reg = <0x01c28c00 0x400>; - interrupts = <4>; - reg-shift = <2>; - reg-io-width = <4>; - clocks = <&apb1_gates 19>; - status = "disabled"; - }; +&ehci0 { + compatible = "allwinner,sun5i-a10s-ehci", "generic-ehci"; +}; - i2c0: i2c@01c2ac00 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "allwinner,sun5i-a10s-i2c", "allwinner,sun4i-a10-i2c"; - reg = <0x01c2ac00 0x400>; - interrupts = <7>; - clocks = <&apb1_gates 0>; - status = "disabled"; - }; +&ohci0 { + compatible = "allwinner,sun5i-a10s-ohci", "generic-ohci"; +}; - i2c1: i2c@01c2b000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "allwinner,sun5i-a10s-i2c", "allwinner,sun4i-a10-i2c"; - reg = <0x01c2b000 0x400>; - interrupts = <8>; - clocks = <&apb1_gates 1>; - status = "disabled"; - }; +&pio { + compatible = "allwinner,sun5i-a10s-pinctrl"; - i2c2: i2c@01c2b400 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "allwinner,sun5i-a10s-i2c", "allwinner,sun4i-a10-i2c"; - reg = <0x01c2b400 0x400>; - interrupts = <9>; - clocks = <&apb1_gates 2>; - status = "disabled"; - }; + uart0_pins_a: uart0@0 { + allwinner,pins = "PB19", "PB20"; + allwinner,function = "uart0"; + allwinner,drive = ; + allwinner,pull = ; + }; - timer@01c60000 { - compatible = "allwinner,sun5i-a13-hstimer"; - reg = <0x01c60000 0x1000>; - interrupts = <82>, <83>; - clocks = <&ahb_gates 28>; - }; + uart2_pins_a: uart2@0 { + allwinner,pins = "PC18", "PC19"; + allwinner,function = "uart2"; + allwinner,drive = ; + allwinner,pull = ; + }; + + uart3_pins_a: uart3@0 { + allwinner,pins = "PG9", "PG10"; + allwinner,function = "uart3"; + allwinner,drive = ; + allwinner,pull = ; + }; + + emac_pins_a: emac0@0 { + allwinner,pins = "PA0", "PA1", "PA2", + "PA3", "PA4", "PA5", "PA6", + "PA7", "PA8", "PA9", "PA10", + "PA11", "PA12", "PA13", "PA14", + "PA15", "PA16"; + allwinner,function = "emac"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc1_pins_a: mmc1@0 { + allwinner,pins = "PG3","PG4","PG5","PG6","PG7","PG8"; + allwinner,function = "mmc1"; + allwinner,drive = ; + allwinner,pull = ; }; }; From 84bdea6e5ed64211be4f8f1773186f1f5c9401f3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0261/3798] ARM: sun4i: a1000: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10-a1000.dts | 200 +++++++++++++------------- 1 file changed, 99 insertions(+), 101 deletions(-) diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts index b67e5be618cfd4..648626bc58a139 100644 --- a/arch/arm/boot/dts/sun4i-a10-a1000.dts +++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts @@ -58,103 +58,6 @@ model = "Mele A1000"; compatible = "mele,a1000", "allwinner,sun4i-a10"; - soc@01c00000 { - emac: ethernet@01c0b000 { - pinctrl-names = "default"; - pinctrl-0 = <&emac_pins_a>; - phy = <&phy1>; - status = "okay"; - }; - - mdio@01c0b080 { - phy-supply = <®_emac_3v3>; - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; - - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - - ehci0: usb@01c14000 { - status = "okay"; - }; - - ohci0: usb@01c14400 { - status = "okay"; - }; - - ahci: sata@01c18000 { - status = "okay"; - }; - - ehci1: usb@01c1c000 { - status = "okay"; - }; - - ohci1: usb@01c1c400 { - status = "okay"; - }; - - pinctrl@01c20800 { - emac_power_pin_a1000: emac_power_pin@0 { - allwinner,pins = "PH15"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - led_pins_a1000: led_pins@0 { - allwinner,pins = "PH10", "PH20"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; - - ir0: ir@01c21800 { - pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; - status = "okay"; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupts = <0>; - - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - }; - leds { compatible = "gpio-leds"; pinctrl-names = "default"; @@ -181,12 +84,107 @@ enable-active-high; gpio = <&pio 7 15 GPIO_ACTIVE_HIGH>; }; +}; + +&ahci { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&emac_pins_a>; + phy = <&phy1>; + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupts = <0>; + + interrupt-controller; + #interrupt-cells = <1>; + }; +}; + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&mdio { + phy-supply = <®_emac_3v3>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; - reg_usb1_vbus: usb1-vbus { - status = "okay"; +&pio { + emac_power_pin_a1000: emac_power_pin@0 { + allwinner,pins = "PH15"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; - reg_usb2_vbus: usb2-vbus { - status = "okay"; + led_pins_a1000: led_pins@0 { + allwinner,pins = "PH10", "PH20"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; }; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From b6ef4c2c66c3afa621722f31fd2542393051a894 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0262/3798] ARM: sun4i: ba10 tvbox: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts | 168 ++++++++++----------- 1 file changed, 83 insertions(+), 85 deletions(-) diff --git a/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts b/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts index 490b77c9bb3675..bebb803a9456dc 100644 --- a/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts +++ b/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts @@ -54,95 +54,93 @@ / { model = "BA10 tvbox"; compatible = "allwinner,ba10-tvbox", "allwinner,sun4i-a10"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&emac_pins_a>; + phy = <&phy1>; + status = "okay"; +}; - soc@01c00000 { - emac: ethernet@01c0b000 { - pinctrl-names = "default"; - pinctrl-0 = <&emac_pins_a>; - phy = <&phy1>; - status = "okay"; - }; - - mdio@01c0b080 { - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; - - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - - ehci0: usb@01c14000 { - status = "okay"; - }; - - ohci0: usb@01c14400 { - status = "okay"; - }; - - ehci1: usb@01c1c000 { - status = "okay"; - }; - - ohci1: usb@01c1c400 { - status = "okay"; - }; - - pinctrl@01c20800 { - usb2_vbus_pin_a: usb2_vbus_pin@0 { - allwinner,pins = "PH12"; - }; - }; - - ir0: ir@01c21800 { - pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; - status = "okay"; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupts = <0>; - - interrupt-controller; - #interrupt-cells = <1>; - }; - }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupts = <0>; + + interrupt-controller; + #interrupt-cells = <1>; }; +}; - reg_usb1_vbus: usb1-vbus { - status = "okay"; +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&mdio { + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; }; +}; - reg_usb2_vbus: usb2-vbus { - gpio = <&pio 7 12 GPIO_ACTIVE_HIGH>; - status = "okay"; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pio { + usb2_vbus_pin_a: usb2_vbus_pin@0 { + allwinner,pins = "PH12"; }; }; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + gpio = <&pio 7 12 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From 8fd5cfc7e4d62c1378c7afecdf2176b44502236a Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0263/3798] ARM: sun4i: cubieboard: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 214 ++++++++++----------- 1 file changed, 106 insertions(+), 108 deletions(-) diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts index 4260c2b476073d..07c2f64b14ee5c 100644 --- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts @@ -57,104 +57,6 @@ model = "Cubietech Cubieboard"; compatible = "cubietech,a10-cubieboard", "allwinner,sun4i-a10"; - soc@01c00000 { - emac: ethernet@01c0b000 { - pinctrl-names = "default"; - pinctrl-0 = <&emac_pins_a>; - phy = <&phy1>; - status = "okay"; - }; - - mdio@01c0b080 { - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; - - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - - ehci0: usb@01c14000 { - status = "okay"; - }; - - ohci0: usb@01c14400 { - status = "okay"; - }; - - ahci: sata@01c18000 { - target-supply = <®_ahci_5v>; - status = "okay"; - }; - - ehci1: usb@01c1c000 { - status = "okay"; - }; - - ohci1: usb@01c1c400 { - status = "okay"; - }; - - pinctrl@01c20800 { - led_pins_cubieboard: led_pins@0 { - allwinner,pins = "PH20", "PH21"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; - - ir0: ir@01c21800 { - pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; - status = "okay"; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - - axp209: pmic@34 { - reg = <0x34>; - interrupts = <0>; - }; - }; - - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - }; - - spi0: spi@01c05000 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins_a>; - status = "okay"; - }; - }; - leds { compatible = "gpio-leds"; pinctrl-names = "default"; @@ -171,26 +73,96 @@ linux,default-trigger = "heartbeat"; }; }; +}; - reg_ahci_5v: ahci-5v { - status = "okay"; - }; +&ahci { + target-supply = <®_ahci_5v>; + status = "okay"; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&emac_pins_a>; + phy = <&phy1>; + status = "okay"; +}; - reg_usb1_vbus: usb1-vbus { - status = "okay"; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupts = <0>; }; +}; - reg_usb2_vbus: usb2-vbus { - status = "okay"; +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&mdio { + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; }; }; -#include "axp209.dtsi" +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; -&cpu0 { - cpu-supply = <®_dcdc2>; +&ohci0 { + status = "okay"; }; +&ohci1 { + status = "okay"; +}; + +&pio { + led_pins_cubieboard: led_pins@0 { + allwinner,pins = "PH20", "PH21"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_ahci_5v { + status = "okay"; +}; + +#include "axp209.dtsi" + ®_dcdc2 { regulator-always-on; regulator-min-microvolt = <1000000>; @@ -215,3 +187,29 @@ regulator-max-microvolt = <3000000>; regulator-name = "avcc"; }; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins_a>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From 4218f450e8dd5d309ad153079dcbb57eb7465622 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0264/3798] ARM: sun4i: hackberry: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10-hackberry.dts | 187 ++++++++++------------ 1 file changed, 85 insertions(+), 102 deletions(-) diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/sun4i-a10-hackberry.dts index d3f73ea25567a4..3cb067ed8715f7 100644 --- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts +++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts @@ -58,102 +58,6 @@ model = "Miniand Hackberry"; compatible = "miniand,hackberry", "allwinner,sun4i-a10"; - soc@01c00000 { - emac: ethernet@01c0b000 { - pinctrl-names = "default"; - pinctrl-0 = <&emac_pins_a>; - phy = <&phy0>; - status = "okay"; - }; - - mdio@01c0b080 { - phy-supply = <®_emac_3v3>; - status = "okay"; - - phy0: ethernet-phy@0 { - reg = <0>; - }; - }; - - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; - - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - - ehci0: usb@01c14000 { - status = "okay"; - }; - - ohci0: usb@01c14400 { - status = "okay"; - }; - - ehci1: usb@01c1c000 { - status = "okay"; - }; - - ohci1: usb@01c1c400 { - status = "okay"; - }; - - pio: pinctrl@01c20800 { - pinctrl-names = "default"; - pinctrl-0 = <&hackberry_hogs>; - - hackberry_hogs: hogs@0 { - allwinner,pins = "PH19"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - usb2_vbus_pin_hackberry: usb2_vbus_pin@0 { - allwinner,pins = "PH12"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; - - ir0: ir@01c21800 { - pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; - status = "okay"; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupts = <0>; - - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - }; - reg_emac_3v3: emac-3v3 { compatible = "regulator-fixed"; regulator-name = "emac-3v3"; @@ -162,14 +66,93 @@ enable-active-high; gpio = <&pio 7 19 GPIO_ACTIVE_HIGH>; }; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&emac_pins_a>; + phy = <&phy0>; + status = "okay"; +}; + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&mdio { + phy-supply = <®_emac_3v3>; + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; +}; - reg_usb1_vbus: usb1-vbus { - status = "okay"; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pio { + pinctrl-names = "default"; + pinctrl-0 = <&hackberry_hogs>; + + hackberry_hogs: hogs@0 { + allwinner,pins = "PH19"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; - reg_usb2_vbus: usb2-vbus { - pinctrl-0 = <&usb2_vbus_pin_hackberry>; - gpio = <&pio 7 12 GPIO_ACTIVE_HIGH>; - status = "okay"; + usb2_vbus_pin_hackberry: usb2_vbus_pin@0 { + allwinner,pins = "PH12"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; }; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + pinctrl-0 = <&usb2_vbus_pin_hackberry>; + gpio = <&pio 7 12 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; From 82c8364b66f9f7e5f2e70d5ad15beff63973786f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0265/3798] ARM: sun4i: inet97fv2: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10-inet97fv2.dts | 104 ++++++++++------------ 1 file changed, 49 insertions(+), 55 deletions(-) diff --git a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts index 482914333bba27..ab3bbc13db1ca3 100644 --- a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts +++ b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts @@ -56,71 +56,65 @@ / { model = "INet-97F Rev 02"; compatible = "primux,inet97fv2", "allwinner,sun4i-a10"; +}; - aliases { - serial0 = &uart0; - }; - - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; +&ehci0 { + status = "okay"; +}; - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; +&ehci1 { + status = "okay"; +}; - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; - ehci0: usb@01c14000 { - status = "okay"; - }; + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupts = <0>; - ohci0: usb@01c14400 { - status = "okay"; - }; + interrupt-controller; + #interrupt-cells = <1>; + }; +}; - ehci1: usb@01c1c000 { - status = "okay"; - }; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; - ohci1: usb@01c1c400 { - status = "okay"; - }; +&ohci0 { + status = "okay"; +}; - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; +&ohci1 { + status = "okay"; +}; - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupts = <0>; +®_usb1_vbus { + status = "okay"; +}; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - }; +®_usb2_vbus { + status = "okay"; +}; - reg_usb1_vbus: usb1-vbus { - status = "okay"; - }; +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; - reg_usb2_vbus: usb2-vbus { - status = "okay"; - }; +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; }; From c2e046419f47d10fcd1c427fc45ce6a19c7119ae Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0266/3798] ARM: sun4i: mini xplus: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10-mini-xplus.dts | 140 ++++++++++----------- 1 file changed, 68 insertions(+), 72 deletions(-) diff --git a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts index eb5fd6904a69c1..dce9a341516b85 100644 --- a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts +++ b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts @@ -57,80 +57,76 @@ / { model = "PineRiver Mini X-Plus"; compatible = "pineriver,mini-xplus", "allwinner,sun4i-a10"; +}; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; - - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - - ehci0: usb@01c14000 { - status = "okay"; - }; - - ohci0: usb@01c14400 { - status = "okay"; - }; - - ehci1: usb@01c1c000 { - status = "okay"; - }; - - ohci1: usb@01c1c400 { - status = "okay"; - }; - - pinctrl@01c20800 { - ir0_pins_a: ir0@0 { - /* The ir receiver is not always populated */ - allwinner,pull = ; - }; - }; - - ir0: ir@01c21800 { - pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; - status = "okay"; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupts = <0>; - - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - }; +&ehci0 { + status = "okay"; +}; - reg_usb1_vbus: usb1-vbus { - status = "okay"; - }; +&ehci1 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupts = <0>; - reg_usb2_vbus: usb2-vbus { - status = "okay"; + interrupt-controller; + #interrupt-cells = <1>; }; }; + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&ir0_pins_a { + /* The ir receiver is not always populated */ + allwinner,pull = ; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From a86d26c85a414d4ec69ff1b1fb66b14d5c3046bd Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0267/3798] ARM: sun4i: olinuxino lime: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- .../arm/boot/dts/sun4i-a10-olinuxino-lime.dts | 213 +++++++++--------- 1 file changed, 104 insertions(+), 109 deletions(-) diff --git a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts index 75742f8f96f3d1..03350dff42b18b 100644 --- a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts +++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts @@ -56,136 +56,131 @@ model = "Olimex A10-OLinuXino-LIME"; compatible = "olimex,a10-olinuxino-lime", "allwinner,sun4i-a10"; - cpus { - cpu0: cpu@0 { - /* - * The A10-Lime is known to be unstable - * when running at 1008 MHz - */ - operating-points = < - /* kHz uV */ - 912000 1350000 - 864000 1300000 - 624000 1250000 - >; - cooling-max-level = <2>; + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_olinuxinolime>; + + green { + label = "a10-olinuxino-lime:green:usr"; + gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; + default-state = "on"; }; }; +}; - soc@01c00000 { - emac: ethernet@01c0b000 { - pinctrl-names = "default"; - pinctrl-0 = <&emac_pins_a>; - phy = <&phy1>; - status = "okay"; - }; +&ahci { + target-supply = <®_ahci_5v>; + status = "okay"; +}; - mdio@01c0b080 { - status = "okay"; +&cpu0 { + /* + * The A10-Lime is known to be unstable when running at 1008 MHz + */ + operating-points = < + /* kHz uV */ + 912000 1350000 + 864000 1300000 + 624000 1250000 + >; + cooling-max-level = <2>; +}; - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; +&ehci0 { + status = "okay"; +}; - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; +&ehci1 { + status = "okay"; +}; - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&emac_pins_a>; + phy = <&phy1>; + status = "okay"; +}; - ehci0: usb@01c14000 { - status = "okay"; - }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; - ohci0: usb@01c14400 { - status = "okay"; - }; + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupts = <0>; - ahci: sata@01c18000 { - target-supply = <®_ahci_5v>; - status = "okay"; - }; + interrupt-controller; + #interrupt-cells = <1>; + }; +}; - ehci1: usb@01c1c000 { - status = "okay"; - }; +&mdio { + status = "okay"; - ohci1: usb@01c1c400 { - status = "okay"; - }; + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; - pinctrl@01c20800 { - ahci_pwr_pin_olinuxinolime: ahci_pwr_pin@1 { - allwinner,pins = "PC3"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - led_pins_olinuxinolime: led_pins@0 { - allwinner,pins = "PH2"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; +&ohci0 { + status = "okay"; +}; - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; +&ohci1 { + status = "okay"; +}; - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupts = <0>; +&pio { + ahci_pwr_pin_olinuxinolime: ahci_pwr_pin@1 { + allwinner,pins = "PC3"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; + led_pins_olinuxinolime: led_pins@0 { + allwinner,pins = "PH2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; +}; - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_olinuxinolime>; +®_ahci_5v { + pinctrl-0 = <&ahci_pwr_pin_olinuxinolime>; + gpio = <&pio 2 3 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; - green { - label = "a10-olinuxino-lime:green:usr"; - gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; - default-state = "on"; - }; - }; +®_usb1_vbus { + status = "okay"; +}; - reg_ahci_5v: ahci-5v { - pinctrl-0 = <&ahci_pwr_pin_olinuxinolime>; - gpio = <&pio 2 3 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; +®_usb2_vbus { + status = "okay"; +}; - reg_usb1_vbus: usb1-vbus { - status = "okay"; - }; +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; - reg_usb2_vbus: usb2-vbus { - status = "okay"; - }; +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; }; From 5e8773694937784003216bd147d5dd969e2cd091 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0268/3798] ARM: sun4i: pcduino: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10-pcduino.dts | 177 ++++++++++++------------ 1 file changed, 88 insertions(+), 89 deletions(-) diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/sun4i-a10-pcduino.dts index 9d1e5482cf82de..6923ca75eb4ac9 100644 --- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts +++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts @@ -58,91 +58,6 @@ model = "LinkSprite pcDuino"; compatible = "linksprite,a10-pcduino", "allwinner,sun4i-a10"; - soc@01c00000 { - emac: ethernet@01c0b000 { - pinctrl-names = "default"; - pinctrl-0 = <&emac_pins_a>; - phy = <&phy1>; - status = "okay"; - }; - - pinctrl@01c20800 { - led_pins_pcduino: led_pins@0 { - allwinner,pins = "PH15", "PH16"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - key_pins_pcduino: key_pins@0 { - allwinner,pins = "PH17", "PH18", "PH19"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; - - mdio@01c0b080 { - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; - - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - - ehci0: usb@01c14000 { - status = "okay"; - }; - - ohci0: usb@01c14400 { - status = "okay"; - }; - - ehci1: usb@01c1c000 { - status = "okay"; - }; - - ohci1: usb@01c1c400 { - status = "okay"; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupts = <0>; - - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - }; leds { compatible = "gpio-leds"; @@ -185,12 +100,96 @@ gpios = <&pio 7 19 GPIO_ACTIVE_LOW>; }; }; +}; + +&ehci0 { + status = "okay"; +}; - reg_usb1_vbus: usb1-vbus { - status = "okay"; +&ehci1 { + status = "okay"; +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&emac_pins_a>; + phy = <&phy1>; + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupts = <0>; + + interrupt-controller; + #interrupt-cells = <1>; }; +}; - reg_usb2_vbus: usb2-vbus { - status = "okay"; +&mdio { + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; }; }; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pio { + led_pins_pcduino: led_pins@0 { + allwinner,pins = "PH15", "PH16"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + key_pins_pcduino: key_pins@0 { + allwinner,pins = "PH17", "PH18", "PH19"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From b96b3b224e872ba33e404fe8770e1ae34a1b58be Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 30 Jan 2015 16:51:03 +0100 Subject: [PATCH 0269/3798] ARM: sun5i: a10s: olinuxino micro: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- .../boot/dts/sun5i-a10s-olinuxino-micro.dts | 315 +++++++++--------- 1 file changed, 157 insertions(+), 158 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts index 2bbc93b935ca5b..aa88ee88738182 100644 --- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts @@ -65,184 +65,183 @@ serial2 = &uart3; }; - soc@01c00000 { - emac: ethernet@01c0b000 { - pinctrl-names = "default"; - pinctrl-0 = <&emac_pins_a>; - phy = <&phy1>; - status = "okay"; + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_olinuxino>; + + green { + label = "a10s-olinuxino-micro:green:usr"; + gpios = <&pio 4 3 GPIO_ACTIVE_HIGH>; + default-state = "on"; }; + }; +}; - mdio@01c0b080 { - status = "okay"; +&ehci0 { + status = "okay"; +}; - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&emac_pins_a>; + phy = <&phy1>; + status = "okay"; +}; - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_olinuxino_micro>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */ - cd-inverted; - status = "okay"; - }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; +}; - mmc1: mmc@01c10000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc1_pins_a>, <&mmc1_cd_pin_olinuxino_micro>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 6 13 GPIO_ACTIVE_HIGH>; /* PG13 */ - cd-inverted; - status = "okay"; - }; +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - status = "okay"; - }; + at24@50 { + compatible = "at,24c16"; + pagesize = <16>; + reg = <0x50>; + read-only; + }; +}; - ehci0: usb@01c14000 { - status = "okay"; - }; +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; - ohci0: usb@01c14400 { - status = "okay"; - }; +&lradc { + vref-supply = <®_vcc3v0>; + status = "okay"; - pinctrl@01c20800 { - mmc0_cd_pin_olinuxino_micro: mmc0_cd_pin@0 { - allwinner,pins = "PG1"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - - mmc1_cd_pin_olinuxino_micro: mmc1_cd_pin@0 { - allwinner,pins = "PG13"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - - led_pins_olinuxino: led_pins@0 { - allwinner,pins = "PE3"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - usb1_vbus_pin_olinuxino_m: usb1_vbus_pin@0 { - allwinner,pins = "PB10"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; + button@191 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <191274>; + }; - lradc: lradc@01c22800 { - vref-supply = <®_vcc3v0>; - status = "okay"; - - button@191 { - label = "Volume Up"; - linux,code = ; - channel = <0>; - voltage = <191274>; - }; - - button@392 { - label = "Volume Down"; - linux,code = ; - channel = <0>; - voltage = <392644>; - }; - - button@601 { - label = "Menu"; - linux,code = ; - channel = <0>; - voltage = <601151>; - }; - - button@795 { - label = "Enter"; - linux,code = ; - channel = <0>; - voltage = <795090>; - }; - - button@987 { - label = "Home"; - linux,code = ; - channel = <0>; - voltage = <987387>; - }; - }; + button@392 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <392644>; + }; - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; + button@601 { + label = "Menu"; + linux,code = ; + channel = <0>; + voltage = <601151>; + }; - uart2: serial@01c28800 { - pinctrl-names = "default"; - pinctrl-0 = <&uart2_pins_a>; - status = "okay"; - }; + button@795 { + label = "Enter"; + linux,code = ; + channel = <0>; + voltage = <795090>; + }; - uart3: serial@01c28c00 { - pinctrl-names = "default"; - pinctrl-0 = <&uart3_pins_a>; - status = "okay"; - }; + button@987 { + label = "Home"; + linux,code = ; + channel = <0>; + voltage = <987387>; + }; +}; - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - }; +&mdio { + status = "okay"; - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - - at24@50 { - compatible = "at,24c16"; - pagesize = <16>; - reg = <0x50>; - read-only; - }; - }; + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; - i2c2: i2c@01c2b400 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_pins_a>; - status = "okay"; - }; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_olinuxino_micro>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */ + cd-inverted; + status = "okay"; +}; + +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins_a>, <&mmc1_cd_pin_olinuxino_micro>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 13 GPIO_ACTIVE_HIGH>; /* PG13 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&pio { + mmc0_cd_pin_olinuxino_micro: mmc0_cd_pin@0 { + allwinner,pins = "PG1"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; }; - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_olinuxino>; + mmc1_cd_pin_olinuxino_micro: mmc1_cd_pin@0 { + allwinner,pins = "PG13"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; - green { - label = "a10s-olinuxino-micro:green:usr"; - gpios = <&pio 4 3 GPIO_ACTIVE_HIGH>; - default-state = "on"; - }; + led_pins_olinuxino: led_pins@0 { + allwinner,pins = "PE3"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; - reg_usb1_vbus: usb1-vbus { - pinctrl-0 = <&usb1_vbus_pin_olinuxino_m>; - gpio = <&pio 1 10 GPIO_ACTIVE_HIGH>; - status = "okay"; + usb1_vbus_pin_olinuxino_m: usb1_vbus_pin@0 { + allwinner,pins = "PB10"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; }; + +®_usb1_vbus { + pinctrl-0 = <&usb1_vbus_pin_olinuxino_m>; + gpio = <&pio 1 10 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins_a>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; + From 420e6f25df16322fecaa4de7d20ae6fa3a7363a2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 30 Jan 2015 16:58:45 +0100 Subject: [PATCH 0270/3798] ARM: sun5i: a10s: r7 tv dongle: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts | 132 +++++++++--------- 1 file changed, 65 insertions(+), 67 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts b/arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts index 7deddfc9df8b52..d42ce170e6404d 100644 --- a/arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts +++ b/arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts @@ -56,69 +56,6 @@ model = "R7 A10s hdmi tv-stick"; compatible = "allwinner,r7-tv-dongle", "allwinner,sun5i-a10s"; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_r7>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */ - cd-inverted; - status = "okay"; - }; - - mmc1: mmc@01c10000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc1_pins_a>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - non-removable; - status = "okay"; - }; - - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - status = "okay"; - }; - - ehci0: usb@01c14000 { - status = "okay"; - }; - - ohci0: usb@01c14400 { - status = "okay"; - }; - - pinctrl@01c20800 { - mmc0_cd_pin_r7: mmc0_cd_pin@0 { - allwinner,pins = "PG1"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - - led_pins_r7: led_pins@0 { - allwinner,pins = "PB2"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - usb1_vbus_pin_r7: usb1_vbus_pin@0 { - allwinner,pins = "PG13"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - }; - leds { compatible = "gpio-leds"; pinctrl-names = "default"; @@ -130,10 +67,71 @@ default-state = "on"; }; }; +}; + +&ehci0 { + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_r7>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */ + cd-inverted; + status = "okay"; +}; + +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins_a>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + non-removable; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&pio { + mmc0_cd_pin_r7: mmc0_cd_pin@0 { + allwinner,pins = "PG1"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_r7: led_pins@0 { + allwinner,pins = "PB2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; - reg_usb1_vbus: usb1-vbus { - pinctrl-0 = <&usb1_vbus_pin_r7>; - gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>; - status = "okay"; + usb1_vbus_pin_r7: usb1_vbus_pin@0 { + allwinner,pins = "PG13"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; }; + +®_usb1_vbus { + pinctrl-0 = <&usb1_vbus_pin_r7>; + gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; From f5d89ab5ba954b5ddcfc99c737da4f92b76b2da9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 11:59:48 +0100 Subject: [PATCH 0271/3798] ARM: sun5i: a13: hsg h702: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i-a13-hsg-h702.dts | 136 +++++++++++------------ 1 file changed, 67 insertions(+), 69 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a13-hsg-h702.dts b/arch/arm/boot/dts/sun5i-a13-hsg-h702.dts index 03aa04555630ed..b59255a445bc76 100644 --- a/arch/arm/boot/dts/sun5i-a13-hsg-h702.dts +++ b/arch/arm/boot/dts/sun5i-a13-hsg-h702.dts @@ -59,82 +59,69 @@ aliases { serial0 = &uart1; }; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&ehci0 { + status = "okay"; +}; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_h702>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 6 0 GPIO_ACTIVE_HIGH>; /* PG0 */ - cd-inverted; - status = "okay"; - }; - - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_ldo3>; - status = "okay"; - }; - - ehci0: usb@01c14000 { - status = "okay"; - }; - - ohci0: usb@01c14400 { - status = "okay"; - }; - - pinctrl@01c20800 { - mmc0_cd_pin_h702: mmc0_cd_pin@0 { - allwinner,pins = "PG0"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; - - uart1: serial@01c28400 { - pinctrl-names = "default"; - pinctrl-0 = <&uart1_pins_b>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - - axp209: pmic@34 { - reg = <0x34>; - interrupts = <0>; - }; - }; - - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - - pcf8563: rtc@51 { - compatible = "nxp,pcf8563"; - reg = <0x51>; - }; - }; - - i2c2: i2c@01c2b400 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_pins_a>; - status = "okay"; - }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupts = <0>; }; }; -#include "axp209.dtsi" +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; -&cpu0 { - cpu-supply = <®_dcdc2>; + pcf8563: rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; }; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_h702>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 0 GPIO_ACTIVE_HIGH>; /* PG0 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&pio { + mmc0_cd_pin_h702: mmc0_cd_pin@0 { + allwinner,pins = "PG0"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +#include "axp209.dtsi" + ®_dcdc2 { regulator-always-on; regulator-min-microvolt = <1000000>; @@ -165,3 +152,14 @@ regulator-max-microvolt = <3300000>; regulator-name = "vcc-wifi"; }; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins_b>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_ldo3>; + status = "okay"; +}; From c999303bfc26644b0ab66b3f905ff46b4c76a82d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:04:17 +0100 Subject: [PATCH 0272/3798] ARM: sun5i: a13: olinuxino micro: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- .../boot/dts/sun5i-a13-olinuxino-micro.dts | 148 +++++++++--------- 1 file changed, 73 insertions(+), 75 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts index 03deb84268ceba..bdb0a094223f52 100644 --- a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts @@ -61,93 +61,91 @@ serial0 = &uart1; }; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_olinuxinom>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 6 0 GPIO_ACTIVE_HIGH>; /* PG0 */ - cd-inverted; - status = "okay"; - }; + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_olinuxinom>; - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - status = "okay"; + power { + label = "a13-olinuxino-micro:green:power"; + gpios = <&pio 6 9 GPIO_ACTIVE_HIGH>; + default-state = "on"; }; + }; +}; - ehci0: usb@01c14000 { - status = "okay"; - }; +&ehci0 { + status = "okay"; +}; - ohci0: usb@01c14400 { - status = "okay"; - }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; +}; - pinctrl@01c20800 { - mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 { - allwinner,pins = "PG0"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - - led_pins_olinuxinom: led_pins@0 { - allwinner,pins = "PG9"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - usb1_vbus_pin_olinuxinom: usb1_vbus_pin@0 { - allwinner,pins = "PG11"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; - uart1: serial@01c28400 { - pinctrl-names = "default"; - pinctrl-0 = <&uart1_pins_b>; - status = "okay"; - }; +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - }; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_olinuxinom>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 0 GPIO_ACTIVE_HIGH>; /* PG0 */ + cd-inverted; + status = "okay"; +}; - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - }; +&ohci0 { + status = "okay"; +}; - i2c2: i2c@01c2b400 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_pins_a>; - status = "okay"; - }; +&pio { + mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 { + allwinner,pins = "PG0"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; }; - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_olinuxinom>; - - power { - label = "a13-olinuxino-micro:green:power"; - gpios = <&pio 6 9 GPIO_ACTIVE_HIGH>; - default-state = "on"; - }; + led_pins_olinuxinom: led_pins@0 { + allwinner,pins = "PG9"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; - reg_usb1_vbus: usb1-vbus { - pinctrl-0 = <&usb1_vbus_pin_olinuxinom>; - gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>; - status = "okay"; + usb1_vbus_pin_olinuxinom: usb1_vbus_pin@0 { + allwinner,pins = "PG11"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; }; + +®_usb1_vbus { + pinctrl-0 = <&usb1_vbus_pin_olinuxinom>; + gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins_b>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; From b2547166a69a2878d4e152a5b2143507db8bd381 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0273/3798] ARM: sun5i: a13: olinuxino: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 236 +++++++++++----------- 1 file changed, 117 insertions(+), 119 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts index 6b24876ed46290..d09c57b4905b2e 100644 --- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts +++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts @@ -63,141 +63,139 @@ serial0 = &uart1; }; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_olinuxino>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 6 0 GPIO_ACTIVE_HIGH>; /* PG0 */ - cd-inverted; - status = "okay"; - }; + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_olinuxino>; - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - status = "okay"; + power { + gpios = <&pio 6 9 GPIO_ACTIVE_HIGH>; + default-state = "on"; }; + }; +}; - ehci0: usb@01c14000 { - status = "okay"; - }; +&ehci0 { + status = "okay"; +}; - ohci0: usb@01c14400 { - status = "okay"; - }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; - pinctrl@01c20800 { - mmc0_cd_pin_olinuxino: mmc0_cd_pin@0 { - allwinner,pins = "PG0"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - - led_pins_olinuxino: led_pins@0 { - allwinner,pins = "PG9"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - usb1_vbus_pin_olinuxino: usb1_vbus_pin@0 { - allwinner,pins = "PG11"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupts = <0>; - lradc: lradc@01c22800 { - vref-supply = <®_vcc3v0>; - status = "okay"; - - button@191 { - label = "Volume Up"; - linux,code = ; - channel = <0>; - voltage = <191274>; - }; - - button@392 { - label = "Volume Down"; - linux,code = ; - channel = <0>; - voltage = <392644>; - }; - - button@601 { - label = "Menu"; - linux,code = ; - channel = <0>; - voltage = <601151>; - }; - - button@795 { - label = "Enter"; - linux,code = ; - channel = <0>; - voltage = <795090>; - }; - - button@987 { - label = "Home"; - linux,code = ; - channel = <0>; - voltage = <987387>; - }; - }; + interrupt-controller; + #interrupt-cells = <1>; + }; +}; - uart1: serial@01c28400 { - pinctrl-names = "default"; - pinctrl-0 = <&uart1_pins_b>; - status = "okay"; - }; +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupts = <0>; +&lradc { + vref-supply = <®_vcc3v0>; + status = "okay"; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; + button@191 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <191274>; + }; - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - }; + button@392 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <392644>; + }; - i2c2: i2c@01c2b400 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_pins_a>; - status = "okay"; - }; + button@601 { + label = "Menu"; + linux,code = ; + channel = <0>; + voltage = <601151>; }; - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_olinuxino>; + button@795 { + label = "Enter"; + linux,code = ; + channel = <0>; + voltage = <795090>; + }; - power { - gpios = <&pio 6 9 GPIO_ACTIVE_HIGH>; - default-state = "on"; - }; + button@987 { + label = "Home"; + linux,code = ; + channel = <0>; + voltage = <987387>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_olinuxino>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 0 GPIO_ACTIVE_HIGH>; /* PG0 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&pio { + mmc0_cd_pin_olinuxino: mmc0_cd_pin@0 { + allwinner,pins = "PG0"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_olinuxino: led_pins@0 { + allwinner,pins = "PG9"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; - reg_usb1_vbus: usb1-vbus { - pinctrl-0 = <&usb1_vbus_pin_olinuxino>; - gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>; - status = "okay"; + usb1_vbus_pin_olinuxino: usb1_vbus_pin@0 { + allwinner,pins = "PG11"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; }; + +®_usb1_vbus { + pinctrl-0 = <&usb1_vbus_pin_olinuxino>; + gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins_b>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; From df839aeb8042e5041dd4bba8acc5e8332cb3e5bc Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0274/3798] ARM: sun6i: app4 evb1: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31-app4-evb1.dts | 52 +++++++++++------------ 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/arch/arm/boot/dts/sun6i-a31-app4-evb1.dts b/arch/arm/boot/dts/sun6i-a31-app4-evb1.dts index be9f5ee6b59e13..98a74da02fd7d1 100644 --- a/arch/arm/boot/dts/sun6i-a31-app4-evb1.dts +++ b/arch/arm/boot/dts/sun6i-a31-app4-evb1.dts @@ -61,36 +61,34 @@ chosen { bootargs = "earlyprintk console=ttyS0,115200"; }; +}; - soc@01c00000 { - pio: pinctrl@01c20800 { - usb1_vbus_pin_a: usb1_vbus_pin@0 { - allwinner,pins = "PH27"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; +&ehci0 { + status = "okay"; +}; - usbphy: phy@01c19400 { - usb1_vbus-supply = <®_usb1_vbus>; - status = "okay"; - }; +&pio { + usb1_vbus_pin_a: usb1_vbus_pin@0 { + allwinner,pins = "PH27"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; - ehci0: usb@01c1a000 { - status = "okay"; - }; +®_usb1_vbus { + pinctrl-0 = <&usb1_vbus_pin_a>; + gpio = <&pio 7 27 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - }; +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; - reg_usb1_vbus: usb1-vbus { - pinctrl-0 = <&usb1_vbus_pin_a>; - gpio = <&pio 7 27 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; }; From 6f1b57f57d4dfc8033763c02d4e17131d1aa08ab Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0275/3798] ARM: sun6i: colombus: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31-colombus.dts | 120 +++++++++++------------ 1 file changed, 59 insertions(+), 61 deletions(-) diff --git a/arch/arm/boot/dts/sun6i-a31-colombus.dts b/arch/arm/boot/dts/sun6i-a31-colombus.dts index 84630e56acd75f..d6e925c381a345 100644 --- a/arch/arm/boot/dts/sun6i-a31-colombus.dts +++ b/arch/arm/boot/dts/sun6i-a31-colombus.dts @@ -61,76 +61,74 @@ chosen { bootargs = "earlyprintk console=ttyS0,115200"; }; +}; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_colombus>; - vmmc-supply = <®_vcc3v0>; - bus-width = <4>; - cd-gpios = <&pio 0 8 GPIO_ACTIVE_HIGH>; /* PA8 */ - cd-inverted; - status = "okay"; - }; +&ehci1 { + status = "okay"; +}; - usbphy: phy@01c19400 { - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "fail"; +}; - ehci1: usb@01c1b000 { - status = "okay"; - }; +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; - pio: pinctrl@01c20800 { - mmc0_pins_a: mmc0@0 { - allwinner,pull = ; - }; +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; - mmc0_cd_pin_colombus: mmc0_cd_pin@0 { - allwinner,pins = "PA8"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_colombus>; + vmmc-supply = <®_vcc3v0>; + bus-width = <4>; + cd-gpios = <&pio 0 8 GPIO_ACTIVE_HIGH>; /* PA8 */ + cd-inverted; + status = "okay"; +}; - usb2_vbus_pin_colombus: usb2_vbus_pin@0 { - allwinner,pins = "PH24"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; +&mmc0_pins_a { + allwinner,pull = ; +}; - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; +&pio { + mmc0_cd_pin_colombus: mmc0_cd_pin@0 { + allwinner,pins = "PA8"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "fail"; - }; + usb2_vbus_pin_colombus: usb2_vbus_pin@0 { + allwinner,pins = "PH24"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - }; +®_usb2_vbus { + pinctrl-names = "default"; + pinctrl-0 = <&usb2_vbus_pin_colombus>; + gpio = <&pio 7 24 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; - i2c2: i2c@01c2b400 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_pins_a>; - status = "okay"; - }; - }; +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; - reg_usb2_vbus: usb2-vbus { - pinctrl-names = "default"; - pinctrl-0 = <&usb2_vbus_pin_colombus>; - gpio = <&pio 7 24 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; +&usbphy { + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; }; From ece44e41fad62a4e4964540aa31cebb4b89a0b43 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0276/3798] ARM: sun6i: m9: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31-m9.dts | 148 ++++++++++++++--------------- 1 file changed, 73 insertions(+), 75 deletions(-) diff --git a/arch/arm/boot/dts/sun6i-a31-m9.dts b/arch/arm/boot/dts/sun6i-a31-m9.dts index 139a21e6b695f1..5cbbbd696b0026 100644 --- a/arch/arm/boot/dts/sun6i-a31-m9.dts +++ b/arch/arm/boot/dts/sun6i-a31-m9.dts @@ -60,93 +60,91 @@ bootargs = "earlyprintk console=ttyS0,115200"; }; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_m9>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 22 GPIO_ACTIVE_HIGH>; /* PH22 */ - cd-inverted; - status = "okay"; - }; + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_m9>; - usbphy: phy@01c19400 { - usb1_vbus-supply = <®_usb1_vbus>; - status = "okay"; + blue { + label = "m9:blue:usr"; + gpios = <&pio 7 13 GPIO_ACTIVE_HIGH>; }; + }; +}; - ehci0: usb@01c1a000 { - status = "okay"; - }; +&ehci0 { + status = "okay"; +}; - ehci1: usb@01c1b000 { - status = "okay"; - }; +&ehci1 { + status = "okay"; +}; - pio: pinctrl@01c20800 { - led_pins_m9: led_pins@0 { - allwinner,pins = "PH13"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - mmc0_cd_pin_m9: mmc0_cd_pin@0 { - allwinner,pins = "PH22"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - - usb1_vbus_pin_m9: usb1_vbus_pin@0 { - allwinner,pins = "PC27"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_mii_a>; + phy = <&phy1>; + phy-mode = "mii"; + status = "okay"; - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; - gmac: ethernet@01c30000 { - pinctrl-names = "default"; - pinctrl-0 = <&gmac_pins_mii_a>; - phy = <&phy1>; - phy-mode = "mii"; - status = "okay"; +&ir { + pinctrl-names = "default"; + pinctrl-0 = <&ir_pins_a>; + status = "okay"; +}; - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_m9>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 22 GPIO_ACTIVE_HIGH>; /* PH22 */ + cd-inverted; + status = "okay"; +}; - ir@01f02000 { - pinctrl-names = "default"; - pinctrl-0 = <&ir_pins_a>; - status = "okay"; - }; +&pio { + led_pins_m9: led_pins@0 { + allwinner,pins = "PH13"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_m9>; - - blue { - label = "m9:blue:usr"; - gpios = <&pio 7 13 GPIO_ACTIVE_HIGH>; - }; + mmc0_cd_pin_m9: mmc0_cd_pin@0 { + allwinner,pins = "PH22"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; }; - reg_usb1_vbus: usb1-vbus { - pinctrl-names = "default"; - pinctrl-0 = <&usb1_vbus_pin_m9>; - gpio = <&pio 2 27 GPIO_ACTIVE_HIGH>; - status = "okay"; + usb1_vbus_pin_m9: usb1_vbus_pin@0 { + allwinner,pins = "PC27"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; }; + +®_usb1_vbus { + pinctrl-names = "default"; + pinctrl-0 = <&usb1_vbus_pin_m9>; + gpio = <&pio 2 27 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; From d540b7cc69ace442959c5754d62b755d63603697 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0277/3798] ARM: sun7i: bananapi: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20-bananapi.dts | 262 +++++++++++------------ 1 file changed, 130 insertions(+), 132 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi.dts b/arch/arm/boot/dts/sun7i-a20-bananapi.dts index 5dd139e7792e12..6d1faf069e7ee3 100644 --- a/arch/arm/boot/dts/sun7i-a20-bananapi.dts +++ b/arch/arm/boot/dts/sun7i-a20-bananapi.dts @@ -65,160 +65,158 @@ serial2 = &uart7; }; - soc@01c00000 { - spi0: spi@01c05000 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins_a>; - status = "okay"; - }; - - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_bananapi>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */ - cd-inverted; - status = "okay"; - }; + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_bananapi>; - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; + green { + label = "bananapi:green:usr"; + gpios = <&pio 7 24 GPIO_ACTIVE_HIGH>; }; + }; - ehci0: usb@01c14000 { - status = "okay"; - }; + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac_power_pin_bananapi>; + regulator-name = "gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + enable-active-high; + gpio = <&pio 7 23 GPIO_ACTIVE_HIGH>; + }; +}; - ohci0: usb@01c14400 { - status = "okay"; - }; +&ahci { + status = "okay"; +}; - ahci: sata@01c18000 { - status = "okay"; - }; +&ehci0 { + status = "okay"; +}; - ehci1: usb@01c1c000 { - status = "okay"; - }; +&ehci1 { + status = "okay"; +}; - ohci1: usb@01c1c400 { - status = "okay"; - }; +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + phy-supply = <®_gmac_3v3>; + status = "okay"; - pinctrl@01c20800 { - mmc0_cd_pin_bananapi: mmc0_cd_pin@0 { - allwinner,pins = "PH10"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - - gmac_power_pin_bananapi: gmac_power_pin@0 { - allwinner,pins = "PH23"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - led_pins_bananapi: led_pins@0 { - allwinner,pins = "PH24"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; - ir0: ir@01c21800 { - pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; - status = "okay"; - }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; - uart3: serial@01c28c00 { - pinctrl-names = "default"; - pinctrl-0 = <&uart3_pins_b>; - status = "okay"; - }; + interrupt-controller; + #interrupt-cells = <1>; + }; +}; - uart7: serial@01c29c00 { - pinctrl-names = "default"; - pinctrl-0 = <&uart7_pins_a>; - status = "okay"; - }; +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupt-parent = <&nmi_intc>; - interrupts = <0 IRQ_TYPE_LEVEL_LOW>; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_bananapi>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */ + cd-inverted; + status = "okay"; +}; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; +&ohci0 { + status = "okay"; +}; - i2c2: i2c@01c2b400 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_pins_a>; - status = "okay"; - }; +&ohci1 { + status = "okay"; +}; - gmac: ethernet@01c50000 { - pinctrl-names = "default"; - pinctrl-0 = <&gmac_pins_rgmii_a>; - phy = <&phy1>; - phy-mode = "rgmii"; - phy-supply = <®_gmac_3v3>; - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; +&pio { + mmc0_cd_pin_bananapi: mmc0_cd_pin@0 { + allwinner,pins = "PH10"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; }; - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_bananapi>; - - green { - label = "bananapi:green:usr"; - gpios = <&pio 7 24 GPIO_ACTIVE_HIGH>; - }; + gmac_power_pin_bananapi: gmac_power_pin@0 { + allwinner,pins = "PH23"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; - reg_usb1_vbus: usb1-vbus { - status = "okay"; + led_pins_bananapi: led_pins@0 { + allwinner,pins = "PH24"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; +}; - reg_usb2_vbus: usb2-vbus { - status = "okay"; - }; +®_usb1_vbus { + status = "okay"; +}; - reg_gmac_3v3: gmac-3v3 { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&gmac_power_pin_bananapi>; - regulator-name = "gmac-3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - startup-delay-us = <100000>; - enable-active-high; - gpio = <&pio 7 23 GPIO_ACTIVE_HIGH>; - }; +®_usb2_vbus { + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins_a>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins_b>; + status = "okay"; +}; + +&uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&uart7_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; }; From b5ec9938b544c47f5cb536faa5637fde4b4b6156 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0278/3798] ARM: sun7i: cubieboard2: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 198 ++++++++++---------- 1 file changed, 98 insertions(+), 100 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts index c4ab6edb6f1567..8c847eb70cadbd 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts @@ -59,96 +59,6 @@ model = "Cubietech Cubieboard2"; compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20"; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; - - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - - ehci0: usb@01c14000 { - status = "okay"; - }; - - ohci0: usb@01c14400 { - status = "okay"; - }; - - ahci: sata@01c18000 { - target-supply = <®_ahci_5v>; - status = "okay"; - }; - - ehci1: usb@01c1c000 { - status = "okay"; - }; - - ohci1: usb@01c1c400 { - status = "okay"; - }; - - pinctrl@01c20800 { - led_pins_cubieboard2: led_pins@0 { - allwinner,pins = "PH20", "PH21"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; - - ir0: ir@01c21800 { - pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; - status = "okay"; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - - axp209: pmic@34 { - reg = <0x34>; - interrupt-parent = <&nmi_intc>; - interrupts = <0 IRQ_TYPE_LEVEL_LOW>; - }; - }; - - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - }; - - gmac: ethernet@01c50000 { - pinctrl-names = "default"; - pinctrl-0 = <&gmac_pins_mii_a>; - phy = <&phy1>; - phy-mode = "mii"; - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - }; - leds { compatible = "gpio-leds"; pinctrl-names = "default"; @@ -164,26 +74,94 @@ gpios = <&pio 7 20 GPIO_ACTIVE_HIGH>; }; }; +}; - reg_ahci_5v: ahci-5v { - status = "okay"; - }; +&ahci { + target-supply = <®_ahci_5v>; + status = "okay"; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; - reg_usb1_vbus: usb1-vbus { - status = "okay"; +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_mii_a>; + phy = <&phy1>; + phy-mode = "mii"; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; - reg_usb2_vbus: usb2-vbus { - status = "okay"; + axp209: pmic@34 { + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; }; }; -#include "axp209.dtsi" +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; -&cpu0 { - cpu-supply = <®_dcdc2>; +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; }; +&ohci1 { + status = "okay"; +}; + +&pio { + led_pins_cubieboard2: led_pins@0 { + allwinner,pins = "PH20", "PH21"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_ahci_5v { + status = "okay"; +}; + +#include "axp209.dtsi" + ®_dcdc2 { regulator-always-on; regulator-min-microvolt = <1000000>; @@ -208,3 +186,23 @@ regulator-max-microvolt = <3000000>; regulator-name = "avcc"; }; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From 712a9fa2af03fefbb172e85c9b7930e78e7f634f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0279/3798] ARM: sun7i: cubietruck: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 316 ++++++++++----------- 1 file changed, 157 insertions(+), 159 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts index 8f74a649576da7..0c219a419f4908 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts @@ -59,144 +59,6 @@ model = "Cubietech Cubietruck"; compatible = "cubietech,cubietruck", "allwinner,sun7i-a20"; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; - - mmc3: mmc@01c12000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc3_pins_a>; - vmmc-supply = <®_vmmc3>; - bus-width = <4>; - non-removable; - status = "okay"; - }; - - usbphy: phy@01c13400 { - usb0_vbus-supply = <®_usb0_vbus>; - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - - ehci0: usb@01c14000 { - status = "okay"; - }; - - ohci0: usb@01c14400 { - status = "okay"; - }; - - ahci: sata@01c18000 { - target-supply = <®_ahci_5v>; - status = "okay"; - }; - - ehci1: usb@01c1c000 { - status = "okay"; - }; - - ohci1: usb@01c1c400 { - status = "okay"; - }; - - pinctrl@01c20800 { - mmc3_pins_a: mmc3@0 { - /* AP6210 requires pull-up */ - allwinner,pull = ; - }; - - vmmc3_pin_cubietruck: vmmc3_pin@0 { - allwinner,pins = "PH9"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - ahci_pwr_pin_cubietruck: ahci_pwr_pin@1 { - allwinner,pins = "PH12"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - led_pins_cubietruck: led_pins@0 { - allwinner,pins = "PH7", "PH11", "PH20", "PH21"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - usb0_vbus_pin_a: usb0_vbus_pin@0 { - allwinner,pins = "PH17"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; - - pwm: pwm@01c20e00 { - pinctrl-names = "default"; - pinctrl-0 = <&pwm0_pins_a>, <&pwm1_pins_a>; - status = "okay"; - }; - - ir0: ir@01c21800 { - pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; - status = "okay"; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - - axp209: pmic@34 { - reg = <0x34>; - interrupt-parent = <&nmi_intc>; - interrupts = <0 IRQ_TYPE_LEVEL_LOW>; - }; - }; - - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - }; - - i2c2: i2c@01c2b400 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_pins_a>; - status = "okay"; - }; - - gmac: ethernet@01c50000 { - pinctrl-names = "default"; - pinctrl-0 = <&gmac_pins_rgmii_a>; - phy = <&phy1>; - phy-mode = "rgmii"; - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - }; - leds { compatible = "gpio-leds"; pinctrl-names = "default"; @@ -223,26 +85,6 @@ }; }; - reg_ahci_5v: ahci-5v { - pinctrl-0 = <&ahci_pwr_pin_cubietruck>; - gpio = <&pio 7 12 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; - - reg_usb0_vbus: usb0-vbus { - pinctrl-0 = <&usb0_vbus_pin_a>; - gpio = <&pio 7 17 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; - - reg_usb1_vbus: usb1-vbus { - status = "okay"; - }; - - reg_usb2_vbus: usb2-vbus { - status = "okay"; - }; - reg_vmmc3: vmmc3 { compatible = "regulator-fixed"; pinctrl-names = "default"; @@ -255,12 +97,141 @@ }; }; -#include "axp209.dtsi" +&ahci { + target-supply = <®_ahci_5v>; + status = "okay"; +}; &cpu0 { cpu-supply = <®_dcdc2>; }; +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&mmc3 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc3_pins_a>; + vmmc-supply = <®_vmmc3>; + bus-width = <4>; + non-removable; + status = "okay"; +}; + +&mmc3_pins_a { + /* AP6210 requires pull-up */ + allwinner,pull = ; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pio { + vmmc3_pin_cubietruck: vmmc3_pin@0 { + allwinner,pins = "PH9"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + ahci_pwr_pin_cubietruck: ahci_pwr_pin@1 { + allwinner,pins = "PH12"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_cubietruck: led_pins@0 { + allwinner,pins = "PH7", "PH11", "PH20", "PH21"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_pin_a: usb0_vbus_pin@0 { + allwinner,pins = "PH17"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pins_a>, <&pwm1_pins_a>; + status = "okay"; +}; + +®_ahci_5v { + pinctrl-0 = <&ahci_pwr_pin_cubietruck>; + gpio = <&pio 7 12 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +#include "axp209.dtsi" + ®_dcdc2 { regulator-always-on; regulator-min-microvolt = <1000000>; @@ -285,3 +256,30 @@ regulator-max-microvolt = <3000000>; regulator-name = "avcc"; }; + +®_usb0_vbus { + pinctrl-0 = <&usb0_vbus_pin_a>; + gpio = <&pio 7 17 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb0_vbus-supply = <®_usb0_vbus>; + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From 9bb082547e46e7414aa84588b61b40e082f8bec9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0280/3798] ARM: sun7i: hummingbird: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20-hummingbird.dts | 384 ++++++++++---------- 1 file changed, 191 insertions(+), 193 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts index 2a9ee72b2b4aad..8c30e126abe6bb 100644 --- a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts +++ b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts @@ -67,199 +67,6 @@ serial4 = &uart5; }; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v0>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; - - mmc3: mmc@01c12000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc3_pins_a>; - vmmc-supply = <®_mmc3_vdd>; - bus-width = <4>; - non-removable; - status = "okay"; - }; - - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - - ehci0: usb@01c14000 { - status = "okay"; - }; - - ohci0: usb@01c14400 { - status = "okay"; - }; - - ahci: sata@01c18000 { - target-supply = <®_ahci_5v>; - status = "okay"; - }; - - ehci1: usb@01c1c000 { - status = "okay"; - }; - - ohci1: usb@01c1c400 { - status = "okay"; - }; - - pio: pinctrl@01c20800 { - ahci_pwr_pin_a20_hummingbird: ahci_pwr_pin@0 { - allwinner,pins = "PH15"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - usb1_vbus_pin_a20_hummingbird: usb1_vbus_pin@0 { - allwinner,pins = "PH2"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - mmc3_vdd_pin_a20_hummingbird: mmc3_vdd_pin@0 { - allwinner,pins = "PH9"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - gmac_vdd_pin_a20_hummingbird: gmac_vdd_pin@0 { - allwinner,pins = "PH16"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; - - pwm: pwm@01c20e00 { - pinctrl-names = "default"; - pinctrl-0 = <&pwm0_pins_a>; - status = "okay"; - }; - - ir0: ir@01c21800 { - pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; - status = "okay"; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - - uart2: serial@01c28800 { - pinctrl-names = "default"; - pinctrl-0 = <&uart2_pins_a>; - status = "okay"; - }; - - uart3: serial@01c28c00 { - pinctrl-names = "default"; - pinctrl-0 = <&uart3_pins_a>; - status = "okay"; - }; - - uart4: serial@01c29000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart4_pins_a>; - status = "okay"; - }; - - uart5: serial@01c29400 { - pinctrl-names = "default"; - pinctrl-0 = <&uart5_pins_a>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupt-parent = <&nmi_intc>; - interrupts = <0 IRQ_TYPE_LEVEL_LOW>; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - }; - - i2c2: i2c@01c2b400 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_pins_a>; - status = "okay"; - }; - - i2c3: i2c@01c2b800 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c3_pins_a>; - status = "okay"; - }; - - spi2: spi@01c17000 { - pinctrl-names = "default"; - pinctrl-0 = <&spi2_pins_b>; - status = "okay"; - }; - - gmac: ethernet@01c50000 { - pinctrl-names = "default"; - pinctrl-0 = <&gmac_pins_rgmii_a>; - phy = <&phy1>; - phy-mode = "rgmii"; - phy-supply = <®_gmac_vdd>; - /* phy reset config */ - snps,reset-gpio = <&pio 0 17 GPIO_ACTIVE_HIGH>; /* PA17 */ - snps,reset-active-low; - /* wait 1s after reset, otherwise fail to read phy id */ - snps,reset-delays-us = <0 10000 1000000>; - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - }; - - reg_ahci_5v: ahci-5v { - pinctrl-0 = <&ahci_pwr_pin_a20_hummingbird>; - gpio = <&pio 7 15 GPIO_ACTIVE_HIGH>; /* PH15 */ - status = "okay"; - }; - - reg_usb1_vbus: usb1-vbus { - pinctrl-0 = <&usb1_vbus_pin_a20_hummingbird>; - gpio = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ - status = "okay"; - }; - - reg_usb2_vbus: usb2-vbus { - status = "okay"; - }; - reg_mmc3_vdd: mmc3_vdd { compatible = "regulator-fixed"; pinctrl-names = "default"; @@ -282,3 +89,194 @@ gpio = <&pio 7 16 GPIO_ACTIVE_HIGH>; /* PH16 */ }; }; + +&ahci { + target-supply = <®_ahci_5v>; + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + phy-supply = <®_gmac_vdd>; + /* phy reset config */ + snps,reset-gpio = <&pio 0 17 GPIO_ACTIVE_HIGH>; /* PA17 */ + snps,reset-active-low; + /* wait 1s after reset, otherwise fail to read phy id */ + snps,reset-delays-us = <0 10000 1000000>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + #interrupt-cells = <1>; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins_a>; + status = "okay"; +}; + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v0>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&mmc3 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc3_pins_a>; + vmmc-supply = <®_mmc3_vdd>; + bus-width = <4>; + non-removable; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pio { + ahci_pwr_pin_a20_hummingbird: ahci_pwr_pin@0 { + allwinner,pins = "PH15"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb1_vbus_pin_a20_hummingbird: usb1_vbus_pin@0 { + allwinner,pins = "PH2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc3_vdd_pin_a20_hummingbird: mmc3_vdd_pin@0 { + allwinner,pins = "PH9"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + gmac_vdd_pin_a20_hummingbird: gmac_vdd_pin@0 { + allwinner,pins = "PH16"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pins_a>; + status = "okay"; +}; + +®_ahci_5v { + pinctrl-0 = <&ahci_pwr_pin_a20_hummingbird>; + gpio = <&pio 7 15 GPIO_ACTIVE_HIGH>; /* PH15 */ + status = "okay"; +}; + +®_usb1_vbus { + pinctrl-0 = <&usb1_vbus_pin_a20_hummingbird>; + gpio = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_pins_b>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins_a>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins_a>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; + +&uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&uart5_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From 598699d073243eec4c9880a6b8c95ac092f560bd Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0281/3798] ARM: sun7i: i12 tvbox: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts | 252 +++++++++++----------- 1 file changed, 125 insertions(+), 127 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts index 06148b4d000fd2..baee563a0051f6 100644 --- a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts +++ b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts @@ -57,125 +57,6 @@ model = "I12 / Q5 / QT840A A20 tvbox"; compatible = "allwinner,i12-tvbox", "allwinner,sun7i-a20"; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; - - mmc3: mmc@01c12000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc3_pins_a>; - vmmc-supply = <®_vmmc3>; - bus-width = <4>; - non-removable; - status = "okay"; - }; - - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - - ehci0: usb@01c14000 { - status = "okay"; - }; - - ohci0: usb@01c14400 { - status = "okay"; - }; - - ehci1: usb@01c1c000 { - status = "okay"; - }; - - ohci1: usb@01c1c400 { - status = "okay"; - }; - - pinctrl@01c20800 { - mmc3_pins_a: mmc3@0 { - /* AP6210 / AP6330 requires pull-up */ - allwinner,pull = ; - }; - - vmmc3_pin_i12_tvbox: vmmc3_pin@0 { - allwinner,pins = "PH2"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - vmmc3_io_pin_i12_tvbox: vmmc3_io_pin@0 { - allwinner,pins = "PH12"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - gmac_power_pin_i12_tvbox: gmac_power_pin@0 { - allwinner,pins = "PH21"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - led_pins_i12_tvbox: led_pins@0 { - allwinner,pins = "PH9", "PH20"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; - - ir0: ir@01c21800 { - pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; - status = "okay"; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupt-parent = <&nmi_intc>; - interrupts = <0 IRQ_TYPE_LEVEL_LOW>; - - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - - gmac: ethernet@01c50000 { - pinctrl-names = "default"; - pinctrl-0 = <&gmac_pins_mii_a>; - phy = <&phy1>; - phy-mode = "mii"; - phy-supply = <®_gmac_3v3>; - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - }; - leds { compatible = "gpio-leds"; pinctrl-names = "default"; @@ -192,14 +73,6 @@ }; }; - reg_usb1_vbus: usb1-vbus { - status = "okay"; - }; - - reg_usb2_vbus: usb2-vbus { - status = "okay"; - }; - reg_vmmc3: vmmc3 { compatible = "regulator-fixed"; pinctrl-names = "default"; @@ -236,3 +109,128 @@ gpio = <&pio 7 21 GPIO_ACTIVE_HIGH>; }; }; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_mii_a>; + phy = <&phy1>; + phy-mode = "mii"; + phy-supply = <®_gmac_3v3>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + + interrupt-controller; + #interrupt-cells = <1>; + }; +}; + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&mmc3 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc3_pins_a>; + vmmc-supply = <®_vmmc3>; + bus-width = <4>; + non-removable; + status = "okay"; +}; + +&mmc3_pins_a { + /* AP6210 / AP6330 requires pull-up */ + allwinner,pull = ; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pio { + vmmc3_pin_i12_tvbox: vmmc3_pin@0 { + allwinner,pins = "PH2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + vmmc3_io_pin_i12_tvbox: vmmc3_io_pin@0 { + allwinner,pins = "PH12"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + gmac_power_pin_i12_tvbox: gmac_power_pin@0 { + allwinner,pins = "PH21"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_i12_tvbox: led_pins@0 { + allwinner,pins = "PH9", "PH20"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From 22b10010cdf1d145320aa6aa91c9d9c2929333e8 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0282/3798] ARM: sun7i: m3: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20-m3.dts | 178 ++++++++++++++--------------- 1 file changed, 88 insertions(+), 90 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20-m3.dts b/arch/arm/boot/dts/sun7i-a20-m3.dts index 5add9f243ec392..44ba67dfb49497 100644 --- a/arch/arm/boot/dts/sun7i-a20-m3.dts +++ b/arch/arm/boot/dts/sun7i-a20-m3.dts @@ -59,114 +59,112 @@ model = "Mele M3"; compatible = "mele,m3", "allwinner,sun7i-a20"; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_m3>; - mmc2: mmc@01c11000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc2_pins_a>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - non-removable; - status = "okay"; + blue { + label = "m3:blue:usr"; + gpios = <&pio 7 20 GPIO_ACTIVE_HIGH>; }; + }; +}; - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; +&ehci0 { + status = "okay"; +}; - ehci0: usb@01c14000 { - status = "okay"; - }; +&ehci1 { + status = "okay"; +}; - ohci0: usb@01c14400 { - status = "okay"; - }; +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_mii_a>; + phy = <&phy1>; + phy-mode = "mii"; + status = "okay"; - ehci1: usb@01c1c000 { - status = "okay"; - }; + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; - ohci1: usb@01c1c400 { - status = "okay"; - }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; - pinctrl@01c20800 { - led_pins_m3: led_pins@0 { - allwinner,pins = "PH20"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; - ir0: ir@01c21800 { - pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; - status = "okay"; - }; + interrupt-controller; + #interrupt-cells = <1>; + }; +}; - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupt-parent = <&nmi_intc>; - interrupts = <0 IRQ_TYPE_LEVEL_LOW>; +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins_a>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + non-removable; + status = "okay"; +}; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; +&ohci0 { + status = "okay"; +}; - gmac: ethernet@01c50000 { - pinctrl-names = "default"; - pinctrl-0 = <&gmac_pins_mii_a>; - phy = <&phy1>; - phy-mode = "mii"; - status = "okay"; +&ohci1 { + status = "okay"; +}; - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; +&pio { + led_pins_m3: led_pins@0 { + allwinner,pins = "PH20"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; +}; - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_m3>; +®_usb1_vbus { + status = "okay"; +}; - blue { - label = "m3:blue:usr"; - gpios = <&pio 7 20 GPIO_ACTIVE_HIGH>; - }; - }; +®_usb2_vbus { + status = "okay"; +}; - reg_usb1_vbus: usb1-vbus { - status = "okay"; - }; +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; - reg_usb2_vbus: usb2-vbus { - status = "okay"; - }; +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; }; From 5b178791a9a7817e691cb0fac9625826d5bea1e6 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0283/3798] ARM: sun7i: olinuxino lime: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- .../arm/boot/dts/sun7i-a20-olinuxino-lime.dts | 186 +++++++++--------- 1 file changed, 92 insertions(+), 94 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts index 12ded69d61ebc3..68efd2f33307ea 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts @@ -60,118 +60,116 @@ model = "Olimex A20-OLinuXino-LIME"; compatible = "olimex,a20-olinuxino-lime", "allwinner,sun7i-a20"; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_olinuxinolime>; - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; + green { + label = "a20-olinuxino-lime:green:usr"; + gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; + default-state = "on"; }; + }; +}; - ehci0: usb@01c14000 { - status = "okay"; - }; +&ahci { + target-supply = <®_ahci_5v>; + status = "okay"; +}; - ohci0: usb@01c14400 { - status = "okay"; - }; +&ehci0 { + status = "okay"; +}; - ahci: sata@01c18000 { - target-supply = <®_ahci_5v>; - status = "okay"; - }; +&ehci1 { + status = "okay"; +}; - ehci1: usb@01c1c000 { - status = "okay"; - }; +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_mii_a>; + phy = <&phy1>; + phy-mode = "mii"; + status = "okay"; - ohci1: usb@01c1c400 { - status = "okay"; - }; + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; - pinctrl@01c20800 { - ahci_pwr_pin_olinuxinolime: ahci_pwr_pin@1 { - allwinner,pins = "PC3"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - led_pins_olinuxinolime: led_pins@0 { - allwinner,pins = "PH2"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + + interrupt-controller; + #interrupt-cells = <1>; + }; +}; - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupt-parent = <&nmi_intc>; - interrupts = <0 IRQ_TYPE_LEVEL_LOW>; +&ohci0 { + status = "okay"; +}; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; +&ohci1 { + status = "okay"; +}; - gmac: ethernet@01c50000 { - pinctrl-names = "default"; - pinctrl-0 = <&gmac_pins_mii_a>; - phy = <&phy1>; - phy-mode = "mii"; - status = "okay"; +&pio { + ahci_pwr_pin_olinuxinolime: ahci_pwr_pin@1 { + allwinner,pins = "PC3"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; + led_pins_olinuxinolime: led_pins@0 { + allwinner,pins = "PH2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; +}; - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_olinuxinolime>; +®_ahci_5v { + pinctrl-0 = <&ahci_pwr_pin_olinuxinolime>; + gpio = <&pio 2 3 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; - green { - label = "a20-olinuxino-lime:green:usr"; - gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; - default-state = "on"; - }; - }; +®_usb1_vbus { + status = "okay"; +}; - reg_ahci_5v: ahci-5v { - pinctrl-0 = <&ahci_pwr_pin_olinuxinolime>; - gpio = <&pio 2 3 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; +®_usb2_vbus { + status = "okay"; +}; - reg_usb1_vbus: usb1-vbus { - status = "okay"; - }; +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; - reg_usb2_vbus: usb2-vbus { - status = "okay"; - }; +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; }; From 6bd0027ee14aa13c3d23583c3d29f1a02dd7ad80 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0284/3798] ARM: sun7i: olinuxino lime2: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- .../boot/dts/sun7i-a20-olinuxino-lime2.dts | 288 +++++++++--------- 1 file changed, 143 insertions(+), 145 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts index 260dbd3bf29d5f..5e57157f742d1a 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts @@ -57,176 +57,174 @@ model = "Olimex A20-OLinuXino-LIME2"; compatible = "olimex,a20-olinuxino-lime2", "allwinner,sun7i-a20"; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_olinuxinolime>; - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; + green { + label = "a20-olinuxino-lime2:green:usr"; + gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; + default-state = "on"; }; + }; - ehci0: usb@01c14000 { - status = "okay"; - }; + reg_axp_ipsout: axp_ipsout { + compatible = "regulator-fixed"; + regulator-name = "axp-ipsout"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; +}; - ohci0: usb@01c14400 { - status = "okay"; - }; +&ahci { + target-supply = <®_ahci_5v>; + status = "okay"; +}; - ahci: sata@01c18000 { - target-supply = <®_ahci_5v>; - status = "okay"; - }; +&ehci0 { + status = "okay"; +}; - ehci1: usb@01c1c000 { - status = "okay"; - }; +&ehci1 { + status = "okay"; +}; - ohci1: usb@01c1c400 { - status = "okay"; - }; +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + status = "okay"; - pinctrl@01c20800 { - ahci_pwr_pin_olinuxinolime: ahci_pwr_pin@1 { - allwinner,pins = "PC3"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; - led_pins_olinuxinolime: led_pins@0 { - allwinner,pins = "PH2"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + + interrupt-controller; + #interrupt-cells = <1>; + + acin-supply = <®_axp_ipsout>; + vin2-supply = <®_axp_ipsout>; + vin3-supply = <®_axp_ipsout>; + ldo24in-supply = <®_axp_ipsout>; + ldo3in-supply = <®_axp_ipsout>; + + regulators { + vdd_rtc: ldo1 { + regulator-min-microvolt = <1300000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; }; - }; - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; + avcc: ldo2 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupt-parent = <&nmi_intc>; - interrupts = <0 IRQ_TYPE_LEVEL_LOW>; - - interrupt-controller; - #interrupt-cells = <1>; - - acin-supply = <®_axp_ipsout>; - vin2-supply = <®_axp_ipsout>; - vin3-supply = <®_axp_ipsout>; - ldo24in-supply = <®_axp_ipsout>; - ldo3in-supply = <®_axp_ipsout>; - - regulators { - vdd_rtc: ldo1 { - regulator-min-microvolt = <1300000>; - regulator-max-microvolt = <1300000>; - regulator-always-on; - }; - - avcc: ldo2 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vcc_csi0: ldo3 { - regulator-min-microvolt = <700000>; - regulator-max-microvolt = <3500000>; - regulator-always-on; - }; - - vcc_csi1: ldo4 { - regulator-min-microvolt = <1250000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vdd_cpu: dcdc2 { - regulator-min-microvolt = <700000>; - regulator-max-microvolt = <2275000>; - regulator-always-on; - }; - - vdd_int: dcdc3 { - regulator-min-microvolt = <700000>; - regulator-max-microvolt = <3500000>; - regulator-always-on; - }; - }; + vcc_csi0: ldo3 { + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <3500000>; + regulator-always-on; }; - }; - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - }; + vcc_csi1: ldo4 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; - gmac: ethernet@01c50000 { - pinctrl-names = "default"; - pinctrl-0 = <&gmac_pins_rgmii_a>; - phy = <&phy1>; - phy-mode = "rgmii"; - status = "okay"; + vdd_cpu: dcdc2 { + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <2275000>; + regulator-always-on; + }; - phy1: ethernet-phy@1 { - reg = <1>; + vdd_int: dcdc3 { + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <3500000>; + regulator-always-on; }; }; }; +}; - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_olinuxinolime>; +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; - green { - label = "a20-olinuxino-lime2:green:usr"; - gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; - default-state = "on"; - }; - }; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; - reg_ahci_5v: ahci-5v { - pinctrl-0 = <&ahci_pwr_pin_olinuxinolime>; - gpio = <&pio 2 3 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; +&ohci0 { + status = "okay"; +}; - reg_usb1_vbus: usb1-vbus { - status = "okay"; - }; +&ohci1 { + status = "okay"; +}; - reg_usb2_vbus: usb2-vbus { - status = "okay"; +&pio { + ahci_pwr_pin_olinuxinolime: ahci_pwr_pin@1 { + allwinner,pins = "PC3"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; - reg_axp_ipsout: axp_ipsout { - compatible = "regulator-fixed"; - regulator-name = "axp-ipsout"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-always-on; + led_pins_olinuxinolime: led_pins@0 { + allwinner,pins = "PH2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; }; + +®_ahci_5v { + pinctrl-0 = <&ahci_pwr_pin_olinuxinolime>; + gpio = <&pio 2 3 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From 581b19e5592c77cf041906d431f7734c3e7b6578 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0285/3798] ARM: sun7i: olinuxino micro: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- .../boot/dts/sun7i-a20-olinuxino-micro.dts | 364 +++++++++--------- 1 file changed, 181 insertions(+), 183 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts index 5c548cfda0e496..f6f06311e25b09 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts @@ -68,216 +68,214 @@ spi1 = &spi2; }; - soc@01c00000 { - spi1: spi@01c06000 { - pinctrl-names = "default"; - pinctrl-0 = <&spi1_pins_a>; - status = "okay"; - }; + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_olinuxino>; - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; + green { + label = "a20-olinuxino-micro:green:usr"; + gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; + default-state = "on"; }; + }; +}; - mmc3: mmc@01c12000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc3_pins_a>, <&mmc3_cd_pin_olinuxinom>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */ - cd-inverted; - status = "okay"; - }; +&ahci { + target-supply = <®_ahci_5v>; + status = "okay"; +}; - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; +&ehci0 { + status = "okay"; +}; - ehci0: usb@01c14000 { - status = "okay"; - }; +&ehci1 { + status = "okay"; +}; - ohci0: usb@01c14400 { - status = "okay"; - }; +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_mii_a>; + phy = <&phy1>; + phy-mode = "mii"; + status = "okay"; - spi2: spi@01c17000 { - pinctrl-names = "default"; - pinctrl-0 = <&spi2_pins_a>; - status = "okay"; - }; + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; - ahci: sata@01c18000 { - target-supply = <®_ahci_5v>; - status = "okay"; - }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; - ehci1: usb@01c1c000 { - status = "okay"; - }; + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; - ohci1: usb@01c1c400 { - status = "okay"; - }; + interrupt-controller; + #interrupt-cells = <1>; + }; +}; - pinctrl@01c20800 { - mmc3_cd_pin_olinuxinom: mmc3_cd_pin@0 { - allwinner,pins = "PH11"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - - led_pins_olinuxino: led_pins@0 { - allwinner,pins = "PH2"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; - lradc: lradc@01c22800 { - vref-supply = <®_vcc3v0>; - status = "okay"; - - button@191 { - label = "Volume Up"; - linux,code = ; - channel = <0>; - voltage = <191274>; - }; - - button@392 { - label = "Volume Down"; - linux,code = ; - channel = <0>; - voltage = <392644>; - }; - - button@601 { - label = "Menu"; - linux,code = ; - channel = <0>; - voltage = <601151>; - }; - - button@795 { - label = "Search"; - linux,code = ; - channel = <0>; - voltage = <795090>; - }; - - button@987 { - label = "Home"; - linux,code = ; - channel = <0>; - voltage = <987387>; - }; - - button@1184 { - label = "Esc"; - linux,code = ; - channel = <0>; - voltage = <1184678>; - }; - - button@1398 { - label = "Enter"; - linux,code = ; - channel = <0>; - voltage = <1398804>; - }; - }; +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; +&lradc { + vref-supply = <®_vcc3v0>; + status = "okay"; - uart6: serial@01c29800 { - pinctrl-names = "default"; - pinctrl-0 = <&uart6_pins_a>; - status = "okay"; - }; + button@191 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <191274>; + }; - uart7: serial@01c29c00 { - pinctrl-names = "default"; - pinctrl-0 = <&uart7_pins_a>; - status = "okay"; - }; + button@392 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <392644>; + }; - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; + button@601 { + label = "Menu"; + linux,code = ; + channel = <0>; + voltage = <601151>; + }; - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupt-parent = <&nmi_intc>; - interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + button@795 { + label = "Search"; + linux,code = ; + channel = <0>; + voltage = <795090>; + }; - interrupt-controller; - #interrupt-cells = <1>; - }; - }; + button@987 { + label = "Home"; + linux,code = ; + channel = <0>; + voltage = <987387>; + }; - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - }; + button@1184 { + label = "Esc"; + linux,code = ; + channel = <0>; + voltage = <1184678>; + }; - i2c2: i2c@01c2b400 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_pins_a>; - status = "okay"; - }; + button@1398 { + label = "Enter"; + linux,code = ; + channel = <0>; + voltage = <1398804>; + }; +}; - gmac: ethernet@01c50000 { - pinctrl-names = "default"; - pinctrl-0 = <&gmac_pins_mii_a>; - phy = <&phy1>; - phy-mode = "mii"; - status = "okay"; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - }; +&mmc3 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc3_pins_a>, <&mmc3_cd_pin_olinuxinom>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */ + cd-inverted; + status = "okay"; +}; - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_olinuxino>; +&ohci0 { + status = "okay"; +}; - green { - label = "a20-olinuxino-micro:green:usr"; - gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; - default-state = "on"; - }; - }; +&ohci1 { + status = "okay"; +}; - reg_ahci_5v: ahci-5v { - status = "okay"; +&pio { + mmc3_cd_pin_olinuxinom: mmc3_cd_pin@0 { + allwinner,pins = "PH11"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; }; - reg_usb1_vbus: usb1-vbus { - status = "okay"; + led_pins_olinuxino: led_pins@0 { + allwinner,pins = "PH2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; +}; - reg_usb2_vbus: usb2-vbus { - status = "okay"; - }; +®_ahci_5v { + status = "okay"; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins_a>; + status = "okay"; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_pins_a>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&uart6 { + pinctrl-names = "default"; + pinctrl-0 = <&uart6_pins_a>; + status = "okay"; +}; + +&uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&uart7_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; }; From 1366e357f2b2a26fe2e3ee014c193d65fc2ed74e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0286/3798] ARM: sun7i: pcduino3: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20-pcduino3.dts | 210 +++++++++++------------ 1 file changed, 104 insertions(+), 106 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts index 0a2c2aeb4687ea..09ec96b2b7d758 100644 --- a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts +++ b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts @@ -59,105 +59,6 @@ model = "LinkSprite pcDuino3"; compatible = "linksprite,pcduino3", "allwinner,sun7i-a20"; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ - cd-inverted; - status = "okay"; - }; - - usbphy: phy@01c13400 { - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - - ehci0: usb@01c14000 { - status = "okay"; - }; - - ohci0: usb@01c14400 { - status = "okay"; - }; - - ahci: sata@01c18000 { - target-supply = <®_ahci_5v>; - status = "okay"; - }; - - ehci1: usb@01c1c000 { - status = "okay"; - }; - - ohci1: usb@01c1c400 { - status = "okay"; - }; - - pinctrl@01c20800 { - ahci_pwr_pin_a: ahci_pwr_pin@0 { - allwinner,pins = "PH2"; - }; - - led_pins_pcduino3: led_pins@0 { - allwinner,pins = "PH15", "PH16"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; - - key_pins_pcduino3: key_pins@0 { - allwinner,pins = "PH17", "PH18", "PH19"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; - - ir0: ir@01c21800 { - pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; - status = "okay"; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - - axp209: pmic@34 { - compatible = "x-powers,axp209"; - reg = <0x34>; - interrupt-parent = <&nmi_intc>; - interrupts = <0 IRQ_TYPE_LEVEL_LOW>; - - interrupt-controller; - #interrupt-cells = <1>; - }; - }; - - gmac: ethernet@01c50000 { - pinctrl-names = "default"; - pinctrl-0 = <&gmac_pins_mii_a>; - phy = <&phy1>; - phy-mode = "mii"; - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - }; - leds { compatible = "gpio-leds"; pinctrl-names = "default"; @@ -196,17 +97,114 @@ gpios = <&pio 7 19 GPIO_ACTIVE_LOW>; }; }; +}; + +&ahci { + target-supply = <®_ahci_5v>; + status = "okay"; +}; + +&ahci_pwr_pin_a { + allwinner,pins = "PH2"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_mii_a>; + phy = <&phy1>; + phy-mode = "mii"; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; - reg_usb1_vbus: usb1-vbus { - status = "okay"; + interrupt-controller; + #interrupt-cells = <1>; }; +}; + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; - reg_usb2_vbus: usb2-vbus { - status = "okay"; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pio { + led_pins_pcduino3: led_pins@0 { + allwinner,pins = "PH15", "PH16"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; }; - reg_ahci_5v: ahci-5v { - gpio = <&pio 7 2 GPIO_ACTIVE_HIGH>; - status = "okay"; + key_pins_pcduino3: key_pins@0 { + allwinner,pins = "PH17", "PH18", "PH19"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; }; }; + +®_ahci_5v { + gpio = <&pio 7 2 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From 1e9d5530932b614a5c01118b18fe710ea106fb72 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sat, 31 Jan 2015 12:11:54 +0100 Subject: [PATCH 0287/3798] ARM: sun8i: ippo q8h v5: Convert to DT label based syntax In order to lessen the amount of duplication of the DT tree, ease the new and follow the trend that prefers to use label based references when overriding DTSI nodes, convert the board to this syntax Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts | 110 ++++++++++---------- 1 file changed, 54 insertions(+), 56 deletions(-) diff --git a/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts b/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts index 623573e4608059..4cb25f8267c819 100644 --- a/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts +++ b/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts @@ -66,69 +66,67 @@ chosen { bootargs = "earlyprintk console=ttyS0,115200"; }; +}; - soc@01c00000 { - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_q8h>; - vmmc-supply = <®_vcc3v0>; - bus-width = <4>; - cd-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */ - cd-inverted; - status = "okay"; - }; - - pinctrl@01c20800 { - mmc0_cd_pin_q8h: mmc0_cd_pin@0 { - allwinner,pins = "PB4"; - allwinner,function = "gpio_in"; - allwinner,drive = ; - allwinner,pull = ; - }; - }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; +}; - lradc: lradc@01c22800 { - vref-supply = <®_vcc3v0>; - status = "okay"; +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; - button@200 { - label = "Volume Up"; - linux,code = ; - channel = <0>; - voltage = <200000>; - }; +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + /* pull-ups and devices require PMIC regulator */ + status = "failed"; +}; - button@400 { - label = "Volume Down"; - linux,code = ; - channel = <0>; - voltage = <400000>; - }; - }; +&lradc { + vref-supply = <®_vcc3v0>; + status = "okay"; - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - }; + button@200 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <200000>; + }; - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - }; + button@400 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <400000>; + }; +}; - i2c2: i2c@01c2b400 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_pins_a>; - /* pull-ups and devices require PMIC regulator */ - status = "failed"; - }; +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_q8h>; + vmmc-supply = <®_vcc3v0>; + bus-width = <4>; + cd-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */ + cd-inverted; + status = "okay"; +}; - r_uart: serial@01f02800 { - pinctrl-names = "default"; - pinctrl-0 = <&r_uart_pins_a>; - status = "okay"; - }; +&pio { + mmc0_cd_pin_q8h: mmc0_cd_pin@0 { + allwinner,pins = "PB4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; }; }; + +&r_uart { + pinctrl-names = "default"; + pinctrl-0 = <&r_uart_pins_a>; + status = "okay"; +}; From d3da93d47959c2a9ef399958ed1376809c388471 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Sat, 28 Feb 2015 14:48:05 +0100 Subject: [PATCH 0288/3798] ARM: sun6i: dt: Add new Mele I7 device The Mele I7 is a Allwinner A31 based Android TV box, with 1G RAM, 8GB NAND flash, a RTL8188etv wifi chip, 3 USB Host ports using USB-A receptacles, a micro USB-B receptacle for USB OTG, HDMI out, a TRS connector for A/V, SPDIF and IrDA. This patch adds basic support for the device, more information can be found here (http://linux-sunxi.org/Mele_I7). Signed-off-by: Marcus Cooper Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/sun6i-a31-i7.dts | 150 +++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 arch/arm/boot/dts/sun6i-a31-i7.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 8c9c62ba65993d..878afeca754e42 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -546,6 +546,7 @@ dtb-$(CONFIG_MACH_SUN6I) += \ sun6i-a31-app4-evb1.dtb \ sun6i-a31-colombus.dtb \ sun6i-a31-hummingbird.dtb \ + sun6i-a31-i7.dtb \ sun6i-a31-m9.dtb \ sun6i-a31s-cs908.dtb dtb-$(CONFIG_MACH_SUN7I) += \ diff --git a/arch/arm/boot/dts/sun6i-a31-i7.dts b/arch/arm/boot/dts/sun6i-a31-i7.dts new file mode 100644 index 00000000000000..049d3a6c09f232 --- /dev/null +++ b/arch/arm/boot/dts/sun6i-a31-i7.dts @@ -0,0 +1,150 @@ +/* + * Copyright 2015 Marcus Cooper + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun6i-a31.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include + +/ { + model = "Mele I7 Quad top set box"; + compatible = "mele,i7", "allwinner,sun6i-a31"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_i7>; + + blue { + label = "i7:blue:usr"; + gpios = <&pio 7 13 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_mii_a>; + phy = <&phy1>; + phy-mode = "mii"; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&ir { + pinctrl-names = "default"; + pinctrl-0 = <&ir_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_i7>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 22 GPIO_ACTIVE_HIGH>; /* PH22 */ + cd-inverted; + status = "okay"; +}; + +&pio { + led_pins_i7: led_pins@0 { + allwinner,pins = "PH13"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc0_cd_pin_i7: mmc0_cd_pin@0 { + allwinner,pins = "PH22"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb1_vbus_pin_i7: usb1_vbus_pin@0 { + allwinner,pins = "PC27"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_usb1_vbus { + pinctrl-names = "default"; + pinctrl-0 = <&usb1_vbus_pin_i7>; + gpio = <&pio 2 27 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; From ef1ac7c9631f58e1ee2f444942713324fddd86bb Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 3 Mar 2015 11:52:01 +0800 Subject: [PATCH 0289/3798] ARM: dts: sun6i: hummingbird: Enable IR receiver The A31 Hummingbird has an IR receiver. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts index 8b61b1b342e0a1..65ddaf4c72d2a8 100644 --- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts +++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts @@ -106,6 +106,12 @@ }; }; +&ir { + pinctrl-names = "default"; + pinctrl-0 = <&ir_pins_a>; + status = "okay"; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_hummingbird>; From cbc8107b3e44d86dc7a569c5ae42423cb95bc4a5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 7 Mar 2015 20:01:18 +0100 Subject: [PATCH 0290/3798] ARM: dts: sun4i: Enable tablet keys on Chuwi V7 CW0825 Enable the lradc controlled tablet keys on the Chuwi V7 CW0825 tablet. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- .../boot/dts/sun4i-a10-chuwi-v7-cw0825.dts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts b/arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts index 58214f2495984f..97fca89eb92b3d 100644 --- a/arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts +++ b/arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts @@ -49,6 +49,7 @@ #include "sun4i-a10.dtsi" #include "sunxi-common-regulators.dtsi" #include +#include / { model = "Chuwi V7 CW0825"; @@ -74,6 +75,32 @@ }; }; +&lradc { + vref-supply = <®_vcc3v0>; + status = "okay"; + + button@800 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <800000>; + }; + + button@1000 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <1000000>; + }; + + button@1200 { + label = "Back"; + linux,code = ; + channel = <0>; + voltage = <1200000>; + }; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; From 3727ed3bb3c531650e4e65a46b4b5eb3176c5da9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 7 Mar 2015 20:01:19 +0100 Subject: [PATCH 0291/3798] ARM: dts: sun5i: Stop using different compatibles for ehci/ohci on a13 vs a10s The A13 and the A10s use the same die (this has been confirmed by Allwinner), as such there is no need to differentiate between the ehci/ohci parts of both, the only reasons there were different allwinner,sun5i-a*-foo compatible between these 2 parts is costemetically and because we could when we still had 2 completely different dtsi files. The allwinner,sun5i-a*-foo compatible strings are not used for binding at all, the actual driver binds to the generic-?hci compatible, so we can safely remove this cosmetical difference and simplify the dtsi files. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i-a10s.dtsi | 8 -------- arch/arm/boot/dts/sun5i-a13.dtsi | 8 -------- arch/arm/boot/dts/sun5i.dtsi | 2 ++ 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index ef516db5852d2d..a78c95dfb33fdb 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi @@ -157,14 +157,6 @@ }; }; -&ehci0 { - compatible = "allwinner,sun5i-a10s-ehci", "generic-ehci"; -}; - -&ohci0 { - compatible = "allwinner,sun5i-a10s-ohci", "generic-ohci"; -}; - &pio { compatible = "allwinner,sun5i-a10s-pinctrl"; diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index 39264f7c7ae602..0188deed6f7571 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi @@ -152,14 +152,6 @@ cooling-max-level = <5>; }; -&ehci0 { - compatible = "allwinner,sun5i-a13-ehci", "generic-ehci"; -}; - -&ohci0 { - compatible = "allwinner,sun5i-a13-ohci", "generic-ohci"; -}; - &pio { compatible = "allwinner,sun5i-a13-pinctrl"; diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index e42cbb03620f9f..343ba1133bda0a 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -392,6 +392,7 @@ }; ehci0: usb@01c14000 { + compatible = "allwinner,sun5i-a13-ehci", "generic-ehci"; reg = <0x01c14000 0x100>; interrupts = <39>; clocks = <&ahb_gates 1>; @@ -401,6 +402,7 @@ }; ohci0: usb@01c14400 { + compatible = "allwinner,sun5i-a13-ohci", "generic-ohci"; reg = <0x01c14400 0x100>; interrupts = <40>; clocks = <&usb_clk 6>, <&ahb_gates 2>; From e1fe9f8c0ce77208fd7da4585641cfc8c892e5c8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 7 Mar 2015 20:01:20 +0100 Subject: [PATCH 0292/3798] ARM: dts: sun5i: Add mmc2 pinmux settings Add A13 mmc2 pinmux settings, note these are for a 8bit bus. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index 343ba1133bda0a..212da88ccc3984 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -469,6 +469,15 @@ allwinner,drive = ; allwinner,pull = ; }; + + mmc2_pins_a: mmc2@0 { + allwinner,pins = "PC6", "PC7", "PC8", "PC9", + "PC10", "PC11", "PC12", "PC13", + "PC14", "PC15"; + allwinner,function = "mmc2"; + allwinner,drive = ; + allwinner,pull = ; + }; }; timer@01c20c00 { From 0332e7dfe613259d8046e4b88704de43f17789a9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 7 Mar 2015 20:01:21 +0100 Subject: [PATCH 0293/3798] ARM: dts: sun5i: Add new Auxtek-t004 board The auxtek-t004: http://www.fasttech.com/products/1110/10004200/1318603-auxtek-t004-allwinner-a10s-single-core-android-ics Is an Allwinner A10s based hdmi tv stick with with 512M RAM, 4G nand flash, toc9002 (bcm43362) sdio wifi, 1 USB host ports using an USB-A receptacle and a 2 micro-usb receptacles, one for power and one for USB OTG. The sdio wifi appears to not have an oob irq hooked up, so we rely on sdio-irq support for it. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts | 151 +++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 878afeca754e42..50b36476781a23 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -536,6 +536,7 @@ dtb-$(CONFIG_MACH_SUN4I) += \ sun4i-a10-olinuxino-lime.dtb \ sun4i-a10-pcduino.dtb dtb-$(CONFIG_MACH_SUN5I) += \ + sun5i-a10s-auxtek-t004.dtb \ sun5i-a10s-mk802.dtb \ sun5i-a10s-olinuxino-micro.dtb \ sun5i-a10s-r7-tv-dongle.dtb \ diff --git a/arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts b/arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts new file mode 100644 index 00000000000000..6c6fef780984f4 --- /dev/null +++ b/arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts @@ -0,0 +1,151 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun5i-a10s.dtsi" +#include "sunxi-common-regulators.dtsi" +#include +#include + +/ { + model = "Auxtek t004 A10s hdmi tv-stick"; + compatible = "allwinner,auxtek-t004", "allwinner,sun5i-a10s"; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_t004>; + + red { + label = "t004-tv-dongle:red:usr"; + gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2 */ + default-state = "on"; + }; + }; + + reg_vmmc1: vmmc1 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_vcc_en_pin_t004>; + regulator-name = "vmmc1"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpio = <&pio 1 18 GPIO_ACTIVE_HIGH>; /* PB18 */ + }; +}; + +&ehci0 { + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_t004>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */ + cd-inverted; + status = "okay"; +}; + +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins_a>; + vmmc-supply = <®_vmmc1>; + bus-width = <4>; + non-removable; + cap-sdio-irq; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&pio { + mmc0_cd_pin_t004: mmc0_cd_pin@0 { + allwinner,pins = "PG1"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc1_vcc_en_pin_t004: mmc1_vcc_en_pin@0 { + allwinner,pins = "PB18"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_t004: led_pins@0 { + allwinner,pins = "PB2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_usb1_vbus { + gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>; /* PG13 */ + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usb1_vbus_pin_a { + allwinner,pins = "PG13"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; From 144cf39875b43ff0f4e281c31116b575c6f41f52 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 7 Mar 2015 20:01:22 +0100 Subject: [PATCH 0294/3798] ARM: dts: sun5i: Add new Utoo P66 board The UTOO P66 is a 6" A13 tablet / lcd ereader. It features a 6" 480x800 ips lcd screen, 512MB RAM & 4GB emmc. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 3 +- arch/arm/boot/dts/sun5i-a13-utoo-p66.dts | 203 +++++++++++++++++++++++ 2 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/sun5i-a13-utoo-p66.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 50b36476781a23..70d1ba682df736 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -542,7 +542,8 @@ dtb-$(CONFIG_MACH_SUN5I) += \ sun5i-a10s-r7-tv-dongle.dtb \ sun5i-a13-hsg-h702.dtb \ sun5i-a13-olinuxino.dtb \ - sun5i-a13-olinuxino-micro.dtb + sun5i-a13-olinuxino-micro.dtb \ + sun5i-a13-utoo-p66.dtb dtb-$(CONFIG_MACH_SUN6I) += \ sun6i-a31-app4-evb1.dtb \ sun6i-a31-colombus.dtb \ diff --git a/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts b/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts new file mode 100644 index 00000000000000..0f0a4112a0e309 --- /dev/null +++ b/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts @@ -0,0 +1,203 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun5i-a13.dtsi" +#include "sunxi-common-regulators.dtsi" +#include +#include +#include + +/ { + model = "Utoo P66"; + compatible = "utoo,p66", "allwinner,sun5i-a13"; + + i2c_lcd: i2c@0 { + /* The lcd panel i2c interface is hooked up via gpios */ + compatible = "i2c-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c_lcd_pins>; + gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>, /* PG12, sda */ + <&pio 6 10 GPIO_ACTIVE_HIGH>; /* PG10, scl */ + i2c-gpio,delay-us = <5>; + }; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&ehci0 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupts = <0>; + }; +}; + +#include "axp209.dtsi" + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; + + pcf8563: rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; +}; + +&lradc { + vref-supply = <®_ldo2>; + status = "okay"; + + button@200 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <200000>; + }; + + button@400 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <400000>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_p66>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 0 GPIO_ACTIVE_HIGH>; /* PG0 */ + cd-inverted; + status = "okay"; +}; + +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins_a>; + vmmc-supply = <®_vcc3v3>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&pio { + mmc0_cd_pin_p66: mmc0_cd_pin@0 { + allwinner,pins = "PG0"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + i2c_lcd_pins: i2c_lcd_pin@0 { + allwinner,pins = "PG10", "PG12"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb0_vbus_pin_a: usb0_vbus_pin@0 { + allwinner,pins = "PB4"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-int-pll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_ldo3 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-wifi"; +}; + +®_usb0_vbus { + gpio = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */ + status = "okay"; +}; + +&usbphy { + usb0_vbus-supply = <®_usb0_vbus>; + usb1_vbus-supply = <®_ldo3>; + status = "okay"; +}; From 8a9cbf5ead43b6b23e11d74d10ac79904d5bc57d Mon Sep 17 00:00:00 2001 From: Tyler Baker Date: Fri, 6 Mar 2015 15:35:05 -0800 Subject: [PATCH 0295/3798] ARM: dts: add vendor prefix for cubietech Add a cubietech vendor prefix, as it is missing. The cubietruck, cubieboard2, and cubieboard all already reference this prefix. Signed-off-by: Tyler Baker Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 80339192c93e26..9aa8abd4cee4c2 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -52,6 +52,7 @@ cnxt Conexant Systems, Inc. cortina Cortina Systems, Inc. cosmic Cosmic Circuits crystalfontz Crystalfontz America, Inc. +cubietech Cubietech, Ltd. dallas Maxim Integrated Products (formerly Dallas Semiconductor) davicom DAVICOM Semiconductor, Inc. denx Denx Software Engineering From 8bf1b9b3d90194a174493febc731f7783f2adf1a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 8 Mar 2015 21:53:42 +0100 Subject: [PATCH 0296/3798] ARM: dts: sunxi: Adjust touchscreen compatible for sun5i and later The touchscreen controller in the A13 and later has a different temperature curve than the one in the original A10, change the compatible for the A13 and later so that the kernel will use the correct curve. Reported-by: Tong Zhang Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i.dtsi | 2 +- arch/arm/boot/dts/sun7i-a20.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index 212da88ccc3984..244d8969757a65 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -505,7 +505,7 @@ }; rtp: rtp@01c25000 { - compatible = "allwinner,sun4i-a10-ts"; + compatible = "allwinner,sun5i-a13-ts"; reg = <0x01c25000 0x100>; interrupts = <29>; #thermal-sensor-cells = <0>; diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index fdd181792b4bee..2b4847c7cbd415 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -1042,7 +1042,7 @@ }; rtp: rtp@01c25000 { - compatible = "allwinner,sun4i-a10-ts"; + compatible = "allwinner,sun5i-a13-ts"; reg = <0x01c25000 0x100>; interrupts = ; #thermal-sensor-cells = <0>; From a486d0b2e9b9a09b9f873eb48bb1a9ac54ad5660 Mon Sep 17 00:00:00 2001 From: Aleksei Mamlin Date: Sun, 8 Mar 2015 14:57:33 +0300 Subject: [PATCH 0297/3798] ARM: dts: sun7i: Add dts file for Wexler TAB7200 This patch add support for Wexler TAB7200 tablet. The Wexler TAB7200 is a A20 based tablet with 7 inch display(800x480), capacitive touchscreen(5 fingers), 1G RAM, 4G NAND, micro SD card slot, mini HDMI port, 3.5mm audio plug, 1 USB OTG port and 1 USB 2.0 port. Signed-off-by: Aleksei Mamlin Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 3 +- .../arm/boot/dts/sun7i-a20-wexler-tab7200.dts | 180 ++++++++++++++++++ 2 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 70d1ba682df736..92b3c85553ad79 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -563,7 +563,8 @@ dtb-$(CONFIG_MACH_SUN7I) += \ sun7i-a20-olinuxino-lime2.dtb \ sun7i-a20-olinuxino-micro.dtb \ sun7i-a20-pcduino3.dtb \ - sun7i-a20-pcduino3-nano.dtb + sun7i-a20-pcduino3-nano.dtb \ + sun7i-a20-wexler-tab7200.dtb dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-a23-ippo-q8h-v5.dtb \ sun8i-a23-ippo-q8h-v1.2.dtb diff --git a/arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts b/arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts new file mode 100644 index 00000000000000..ea133bd3dd87fe --- /dev/null +++ b/arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts @@ -0,0 +1,180 @@ +/* + * Copyright 2015 Aleksei Mamlin + * Aleksei Mamlin + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun7i-a20.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "Wexler TAB7200"; + compatible = "wexler,tab7200", "allwinner,sun7i-a20"; +}; + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + +&lradc { + vref-supply = <®_vcc3v0>; + status = "okay"; + + button@571 { + label = "Volume Up"; + linux,code = ; + channel = <0>; + voltage = <571428>; + }; + + button@761 { + label = "Volume Down"; + linux,code = ; + channel = <0>; + voltage = <761904>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +#include "axp209.dtsi" + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1450000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-int-dll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From 6554afd218f931021c5e9fbd7b5a236c0d08f4ed Mon Sep 17 00:00:00 2001 From: Aleksei Mamlin Date: Sun, 8 Mar 2015 14:58:16 +0300 Subject: [PATCH 0298/3798] dt-bindings: Add vendor-prefix for Wexler This patch adds vendor-prefix for Wexler. WEXLER trademark owned by AVIRSA Electronics, a member of the diversified holding AVIRSA. Signed-off-by: Aleksei Mamlin Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 9aa8abd4cee4c2..6a99ddaf212b55 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -203,6 +203,7 @@ variscite Variscite Ltd. via VIA Technologies, Inc. virtio Virtual I/O Device Specification, developed by the OASIS consortium voipac Voipac Technologies s.r.o. +wexler Wexler winbond Winbond Electronics corp. wlf Wolfson Microelectronics wm Wondermedia Technologies, Inc. From 6d11c8e2b3aa0993a3cc6e65dc942dd348db5882 Mon Sep 17 00:00:00 2001 From: Tyler Baker Date: Mon, 9 Mar 2015 13:19:57 -0700 Subject: [PATCH 0299/3798] ARM: dts: add cubietech cubieboard4 Add a Cubietech Cubieboard4 device tree and instruct make to build it. This device tree has been derived from the sun9i-a80-optimus.dts as they are very similar in design[1]. Notably, I2C3 is not used on Cubieboard4 and the LED/PWM definitions will need to be updated in the future. [1] http://dl.cubieboard.org/model/cc-a80/Hardware/CC-A80-HW-V1.1.pdf Signed-off-by: Tyler Baker Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 3 +- arch/arm/boot/dts/sun9i-a80-cubieboard4.dts | 99 +++++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/sun9i-a80-cubieboard4.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 92b3c85553ad79..c6e95ab4e568e8 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -569,7 +569,8 @@ dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-a23-ippo-q8h-v5.dtb \ sun8i-a23-ippo-q8h-v1.2.dtb dtb-$(CONFIG_MACH_SUN9I) += \ - sun9i-a80-optimus.dtb + sun9i-a80-optimus.dtb \ + sun9i-a80-cubieboard4.dtb dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += \ tegra20-harmony.dtb \ tegra20-iris-512.dtb \ diff --git a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts new file mode 100644 index 00000000000000..6484dcf6987300 --- /dev/null +++ b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts @@ -0,0 +1,99 @@ +/* + * Copyright 2015 Tyler Baker + * + * Tyler Baker + * Chen-Yu Tsai + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun9i-a80.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include + +/ { + model = "Cubietech Cubieboard4"; + compatible = "cubietech,a80-cubieboard4", "allwinner,sun9i-a80"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + +}; + +&pio { + mmc0_cd_pin_cubieboard4: mmc0_cd_pin@0 { + allwinner,pins = "PH18"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>, <&mmc0_cd_pin_cubieboard4>; + vmmc-supply = <®_vcc3v0>; + bus-width = <4>; + cd-gpios = <&pio 7 18 GPIO_ACTIVE_HIGH>; /* PH18 */ + cd-inverted; + status = "okay"; +}; + +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_8bit_pins>; + vmmc-supply = <®_vcc3v0>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; From fcd601387d70db31ac5e0a17ca584f088821b459 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Tue, 10 Mar 2015 19:59:12 +0800 Subject: [PATCH 0300/3798] ARM: dts: sun6i: add p2wi controller node to dtsi The p2wi controller has only one possible pinmux setting. Use it by default in the dtsi, instead of having to set it in each board's dts. Signed-off-by: Boris BREZILLON [wens@csie.org: reformat commit title; rename p2wi pins and use as default] Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31.dtsi | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index fa2f403ccf28ad..92abea20b946d5 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -973,6 +973,27 @@ allwinner,drive = ; allwinner,pull = ; }; + + p2wi_pins: p2wi { + allwinner,pins = "PL0", "PL1"; + allwinner,function = "s_p2wi"; + allwinner,drive = ; + allwinner,pull = ; + }; + }; + + p2wi: i2c@01f03400 { + compatible = "allwinner,sun6i-a31-p2wi"; + reg = <0x01f03400 0x400>; + interrupts = ; + clocks = <&apb0_gates 3>; + clock-frequency = <100000>; + resets = <&apb0_rst 3>; + pinctrl-names = "default"; + pinctrl-0 = <&p2wi_pins>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; }; }; From 252619aedd616d7358d96877a467d74d19791e69 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 10 Mar 2015 19:59:13 +0800 Subject: [PATCH 0301/3798] ARM: dts: sun6i: hummingbird: Enable P2WI controller The Hummingbird A31 has an AXP221 PMIC hooked up to the P2WI controller. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts index 65ddaf4c72d2a8..533bedc5dd95ac 100644 --- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts +++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts @@ -140,6 +140,10 @@ }; }; +&p2wi { + status = "okay"; +}; + ®_usb1_vbus { gpio = <&pio 7 24 GPIO_ACTIVE_HIGH>; /* PH24 */ status = "okay"; From 81bc1d38a4f83aa3bee0795c212f829b3cd23ae1 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 10 Mar 2015 19:59:16 +0800 Subject: [PATCH 0302/3798] ARM: dts: sun6i: hummingbird: Add AXP221 PMIC device node The Hummingbird A31 has an AXP221 PMIC hooked up to the P2WI controller. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts index 533bedc5dd95ac..486ffc69ac9642 100644 --- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts +++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts @@ -142,6 +142,15 @@ &p2wi { status = "okay"; + + axp221: pmic@68 { + compatible = "x-powers,axp221"; + reg = <0x68>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + #interrupt-cells = <1>; + }; }; ®_usb1_vbus { From bab03561224baa536b98f1d137d2b6b5dd159763 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 10 Mar 2015 19:59:21 +0800 Subject: [PATCH 0303/3798] ARM: dts: sun6i: hummingbird: Add AXP221 regulator nodes This patch adds the AXP221 regulators. Only the ones directly used on the board are added. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 56 ++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts index 486ffc69ac9642..d13c88c6509ac6 100644 --- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts +++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts @@ -115,7 +115,7 @@ &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_hummingbird>; - vmmc-supply = <®_vcc3v0>; + vmmc-supply = <&vcc_3v0>; bus-width = <4>; cd-gpios = <&pio 0 8 GPIO_ACTIVE_HIGH>; /* PA8 */ cd-inverted; @@ -150,6 +150,60 @@ interrupts = <0 IRQ_TYPE_LEVEL_LOW>; interrupt-controller; #interrupt-cells = <1>; + dcdc1-supply = <&vcc_3v0>; + dcdc5-supply = <&vcc_dram>; + + regulators { + x-powers,dcdc-freq = <3000>; + + vcc_3v0: dcdc1 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "vcc-3v0"; + }; + + vdd_cpu: dcdc2 { + regulator-always-on; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1320000>; + regulator-name = "vdd-cpu"; + }; + + vdd_gpu: dcdc3 { + regulator-always-on; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1320000>; + regulator-name = "vdd-gpu"; + }; + + vdd_sys_dll: dcdc4 { + regulator-always-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-name = "vdd-sys-dll"; + }; + + vcc_dram: dcdc5 { + regulator-always-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vcc-dram"; + }; + + vcc_wifi: aldo1 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_wifi"; + }; + + avcc: aldo3 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; + }; + }; }; }; From 4c1bb9c31877d58c5d6f5c92327566fc8a5f99ac Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 10 Mar 2015 16:27:09 +0100 Subject: [PATCH 0304/3798] ARM: dts: sunxi: Add address- and size-cells properties to the mmc ctrl nodes Sometimes we need to specify non-probably information for sdio devices in the devicetree, this is done through child nodes addressed by the reg property, whereby the reg property refers to the sdio function number, see; Documentation/devicetree/bindings/mmc/mmc.txt This commit adds the necessary address- and size-cells properties to the mmc controller nodes in the dtsi files, so that dts files needing such a child node do not need to specify these themselves. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10.dtsi | 8 ++++++++ arch/arm/boot/dts/sun5i.dtsi | 6 ++++++ arch/arm/boot/dts/sun6i-a31.dtsi | 8 ++++++++ arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++ arch/arm/boot/dts/sun8i-a23.dtsi | 6 ++++++ arch/arm/boot/dts/sun9i-a80.dtsi | 8 ++++++++ 6 files changed, 44 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 17e4598db1761b..dcc357b42ae93b 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -521,6 +521,8 @@ "sample"; interrupts = <32>; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc1: mmc@01c10000 { @@ -536,6 +538,8 @@ "sample"; interrupts = <33>; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc2: mmc@01c11000 { @@ -551,6 +555,8 @@ "sample"; interrupts = <34>; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc3: mmc@01c12000 { @@ -566,6 +572,8 @@ "sample"; interrupts = <35>; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; usbphy: phy@01c13400 { diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index 244d8969757a65..df5f2fbf69749c 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -347,6 +347,8 @@ "sample"; interrupts = <32>; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc1: mmc@01c10000 { @@ -362,6 +364,8 @@ "sample"; interrupts = <33>; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc2: mmc@01c11000 { @@ -377,6 +381,8 @@ "sample"; interrupts = <34>; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; usbphy: phy@01c13400 { diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 92abea20b946d5..d9ccae7376ad78 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -402,6 +402,8 @@ reset-names = "ahb"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc1: mmc@01c10000 { @@ -419,6 +421,8 @@ reset-names = "ahb"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc2: mmc@01c11000 { @@ -436,6 +440,8 @@ reset-names = "ahb"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc3: mmc@01c12000 { @@ -453,6 +459,8 @@ reset-names = "ahb"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; usbphy: phy@01c19400 { diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 2b4847c7cbd415..24eae39eefa68f 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -600,6 +600,8 @@ "sample"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc1: mmc@01c10000 { @@ -615,6 +617,8 @@ "sample"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc2: mmc@01c11000 { @@ -630,6 +634,8 @@ "sample"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc3: mmc@01c12000 { @@ -645,6 +651,8 @@ "sample"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; usbphy: phy@01c13400 { diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi index 382ebd137ee4fb..85e7b2b9b11bfb 100644 --- a/arch/arm/boot/dts/sun8i-a23.dtsi +++ b/arch/arm/boot/dts/sun8i-a23.dtsi @@ -286,6 +286,8 @@ reset-names = "ahb"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc1: mmc@01c10000 { @@ -303,6 +305,8 @@ reset-names = "ahb"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc2: mmc@01c11000 { @@ -320,6 +324,8 @@ reset-names = "ahb"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; pio: pinctrl@01c20800 { diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi index 2f7f82cc86ba11..abe7bbf8aa8325 100644 --- a/arch/arm/boot/dts/sun9i-a80.dtsi +++ b/arch/arm/boot/dts/sun9i-a80.dtsi @@ -447,6 +447,8 @@ reset-names = "ahb"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc1: mmc@01c10000 { @@ -459,6 +461,8 @@ reset-names = "ahb"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc2: mmc@01c11000 { @@ -471,6 +475,8 @@ reset-names = "ahb"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc3: mmc@01c12000 { @@ -483,6 +489,8 @@ reset-names = "ahb"; interrupts = ; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; }; mmc_config_clk: clk@01c13000 { From 7862eb1b59eef343343dbdd0136fbf175184e538 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 10 Mar 2015 16:27:10 +0100 Subject: [PATCH 0305/3798] ARM: dts: sun7i: Add OOB irq support to boards with broadcom sdio wifi Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 8 ++++++++ arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts index 0c219a419f4908..5af1df795f3cf6 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts @@ -173,6 +173,14 @@ bus-width = <4>; non-removable; status = "okay"; + + brcmf: bcrmf@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + interrupt-parent = <&pio>; + interrupts = <10 IRQ_TYPE_LEVEL_LOW>; /* PH10 / EINT10 */ + interrupt-names = "host-wake"; + }; }; &mmc3_pins_a { diff --git a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts index baee563a0051f6..c11574c2b93163 100644 --- a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts +++ b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts @@ -170,6 +170,14 @@ bus-width = <4>; non-removable; status = "okay"; + + brcmf: bcrmf@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + interrupt-parent = <&pio>; + interrupts = <10 IRQ_TYPE_LEVEL_LOW>; /* PH10 / EINT10 */ + interrupt-names = "host-wake"; + }; }; &mmc3_pins_a { From 878c4ded1f15e6c2231b5d05bc8f21920f8a777f Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 10 Mar 2015 19:59:22 +0800 Subject: [PATCH 0306/3798] ARM: dts: sun6i: Add pinmux settings for mmc1 to dtsi mmc1 is used to connect to the WiFi chip on the Hummingbird A31. Signed-off-by: Chen-Yu Tsai [maxime: Changed the drive and pull values for their defines] Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index d9ccae7376ad78..2a37ee93265e52 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -589,6 +589,14 @@ allwinner,pull = ; }; + mmc1_pins_a: mmc1@0 { + allwinner,pins = "PG0", "PG1", "PG2", "PG3", + "PG4", "PG5"; + allwinner,function = "mmc1"; + allwinner,drive = ; + allwinner,pull = ; + }; + gmac_pins_mii_a: gmac_mii@0 { allwinner,pins = "PA0", "PA1", "PA2", "PA3", "PA8", "PA9", "PA11", From b5c26d66a4bba25b3a7f1c6ff599975f448e54bd Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 10 Mar 2015 19:59:24 +0800 Subject: [PATCH 0307/3798] ARM: dts: sun6i: hummingbird: Enable the onboard WiFi module The Hummingbird A31 has an AMPAK AP6210 WiFi+Bluetooth module. The WiFi part is a BCM43362 IC connected to MMC1 in the A31 SoC via SDIO. The IC also takes a power enable signal via GPIO. This is supported with the new power sequencing bindings. The WiFi module supports out-of-band interrupt signaling via GPIO, but this is not enabled yet. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts index d13c88c6509ac6..25a3ef49bb71a7 100644 --- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts +++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts @@ -61,6 +61,11 @@ chosen { bootargs = "earlyprintk console=ttyS0,115200"; }; + + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&pio 6 10 GPIO_ACTIVE_LOW>; /* PG10 */ + }; }; &ehci0 { @@ -127,6 +132,16 @@ allwinner,pull = ; }; +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins_a>, <&wifi_reset_pin_hummingbird>; + vmmc-supply = <&vcc_wifi>; + mmc-pwrseq = <&wifi_pwrseq>; + bus-width = <4>; + non-removable; + status = "okay"; +}; + &ohci0 { status = "okay"; }; @@ -138,6 +153,13 @@ allwinner,drive = ; allwinner,pull = ; }; + + wifi_reset_pin_hummingbird: wifi_reset_pin@0 { + allwinner,pins = "PG10"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; }; &p2wi { From 65ef564f06c30f779a7472ab441fd1964a5f0e47 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 18 Mar 2015 11:24:00 +0800 Subject: [PATCH 0308/3798] ARM: dts: sun8i: Enable ARM architected timer on A23 The A23 SoC has the architected timer, but the existing firmware from Allwinner does not set CNTFRQ at all. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a23.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi index 85e7b2b9b11bfb..9ff9227e2ab7a1 100644 --- a/arch/arm/boot/dts/sun8i-a23.dtsi +++ b/arch/arm/boot/dts/sun8i-a23.dtsi @@ -70,6 +70,16 @@ }; }; + timer { + compatible = "arm,armv7-timer"; + interrupts = , + , + , + ; + clock-frequency = <24000000>; + arm,cpu-registers-not-fw-configured; + }; + cpus { #address-cells = <1>; #size-cells = <0>; From 51e9f5ffc5b88ea0d2626edef737e582fe7039d8 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 18 Mar 2015 16:00:28 +0800 Subject: [PATCH 0309/3798] ARM: dts: sun9i: Enable ARM architected timer on A80 The A80 SoC has the architected timer, but the existing firmware from Allwinner does not set CNTFRQ at all. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun9i-a80.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi index abe7bbf8aa8325..d3dece2eea7213 100644 --- a/arch/arm/boot/dts/sun9i-a80.dtsi +++ b/arch/arm/boot/dts/sun9i-a80.dtsi @@ -114,6 +114,16 @@ reg = <0 0x20000000 0x02 0>; }; + timer { + compatible = "arm,armv7-timer"; + interrupts = , + , + , + ; + clock-frequency = <24000000>; + arm,cpu-registers-not-fw-configured; + }; + clocks { #address-cells = <1>; #size-cells = <1>; From f1bf2b9b3d4b2bd4a49a2e3ddf4c947d366a150c Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 14 Mar 2015 11:57:17 +0800 Subject: [PATCH 0310/3798] ARM: dts: sun9i: optimus: Switch to phy core regulator bindings for usb phys Since the phy core already supports specifying a regulator to handle during power up/down, it was decided to drop the regulator support in the sun9i usb phy driver. This patch switches the DT to the core bindings. This and the phy driver would be in the same release and should not be a problem as far as DT stability goes. Signed-off-by: Chen-Yu Tsai Acked-by: Kishon Vijay Abraham I Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun9i-a80-optimus.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts index e53f2656c2d0ff..c6ca116c59d295 100644 --- a/arch/arm/boot/dts/sun9i-a80-optimus.dts +++ b/arch/arm/boot/dts/sun9i-a80-optimus.dts @@ -203,7 +203,7 @@ }; &usbphy1 { - vbus-supply = <®_usb1_vbus>; + phy-supply = <®_usb1_vbus>; status = "okay"; }; @@ -212,6 +212,6 @@ }; &usbphy3 { - vbus-supply = <®_usb3_vbus>; + phy-supply = <®_usb3_vbus>; status = "okay"; }; From b14c112344996c3400bd588982e61fef7fe0ea64 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 21 Mar 2015 14:23:01 +0100 Subject: [PATCH 0311/3798] ARM: dts: sun6i: csq cs908 dts cleanup Remove the unused usb1_vbus_pin_csq908 node (vbus is always on on the cs908), and sort the remaining nodes alphabetically. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31s-cs908.dts | 37 ++++++++++---------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/arch/arm/boot/dts/sun6i-a31s-cs908.dts b/arch/arm/boot/dts/sun6i-a31s-cs908.dts index bc3734f67cf058..3f0cc8c58df8be 100644 --- a/arch/arm/boot/dts/sun6i-a31s-cs908.dts +++ b/arch/arm/boot/dts/sun6i-a31s-cs908.dts @@ -55,10 +55,6 @@ compatible = "csq,cs908", "allwinner,sun6i-a31s"; }; -&usbphy { - status = "okay"; -}; - &ehci0 { status = "okay"; }; @@ -67,25 +63,6 @@ status = "okay"; }; -&ohci1 { - status = "okay"; -}; - -&pio { - usb1_vbus_pin_csq908: usb1_vbus_pin@0 { - allwinner,pins = "PC27"; - allwinner,function = "gpio_out"; - allwinner,drive = ; - allwinner,pull = ; - }; -}; - -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; -}; - &gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_pins_mii_a>; @@ -102,3 +79,17 @@ pinctrl-0 = <&ir_pins_a>; status = "okay"; }; + +&ohci1 { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + status = "okay"; +}; From 59ebbe88a6431d0bd99c792f413ecf69273f2e9d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sun, 15 Mar 2015 20:47:31 +0100 Subject: [PATCH 0312/3798] ARM: sunxi: DT: Add stdout-path property Add UART aliases and stdout-path property for all the Allwinner boards so that we won't have to rely on the bootargs' console= value, while working with legacy bootloaders. While we're at it, also remove the mentions of earlyprintk in the bootargs, that will remove our default bootargs entirely, and allow the kernel to boot on a system even if DEBUG_LL is configured for another system. Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10-a1000.dts | 8 ++++++++ arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts | 8 ++++++++ arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts | 8 ++++++++ arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 8 ++++++++ arch/arm/boot/dts/sun4i-a10-gemei-g9.dts | 8 ++++++++ arch/arm/boot/dts/sun4i-a10-hackberry.dts | 8 ++++++++ arch/arm/boot/dts/sun4i-a10-hyundai-a7hd.dts | 8 ++++++++ arch/arm/boot/dts/sun4i-a10-inet97fv2.dts | 8 ++++++++ arch/arm/boot/dts/sun4i-a10-marsboard.dts | 8 ++++++++ arch/arm/boot/dts/sun4i-a10-mini-xplus.dts | 8 ++++++++ arch/arm/boot/dts/sun4i-a10-mk802.dts | 8 ++++++++ arch/arm/boot/dts/sun4i-a10-mk802ii.dts | 8 ++++++++ arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts | 8 ++++++++ arch/arm/boot/dts/sun4i-a10-pcduino.dts | 7 +++++++ arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts | 8 ++++++++ arch/arm/boot/dts/sun5i-a10s-mk802.dts | 8 ++++++++ arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 4 ++++ arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts | 8 ++++++++ arch/arm/boot/dts/sun5i-a13-hsg-h702.dts | 4 ++++ arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 4 ++++ arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 4 ++++ arch/arm/boot/dts/sun6i-a31-app4-evb1.dts | 6 +++++- arch/arm/boot/dts/sun6i-a31-colombus.dts | 6 +++++- arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 6 +++++- arch/arm/boot/dts/sun6i-a31-i7.dts | 6 +++++- arch/arm/boot/dts/sun6i-a31-m9.dts | 6 +++++- arch/arm/boot/dts/sun6i-a31s-cs908.dts | 8 ++++++++ arch/arm/boot/dts/sun7i-a20-bananapi.dts | 4 ++++ arch/arm/boot/dts/sun7i-a20-bananapro.dts | 10 ++++++++++ arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 8 ++++++++ arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 8 ++++++++ arch/arm/boot/dts/sun7i-a20-hummingbird.dts | 4 ++++ arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts | 8 ++++++++ arch/arm/boot/dts/sun7i-a20-m3.dts | 8 ++++++++ arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts | 8 ++++++++ arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts | 8 ++++++++ arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 4 ++++ arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts | 8 ++++++++ arch/arm/boot/dts/sun7i-a20-pcduino3.dts | 8 ++++++++ arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts | 8 ++++++++ arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts | 2 +- arch/arm/boot/dts/sun9i-a80-optimus.dts | 2 +- 42 files changed, 280 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts index 648626bc58a139..f03281434e593f 100644 --- a/arch/arm/boot/dts/sun4i-a10-a1000.dts +++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts @@ -58,6 +58,14 @@ model = "Mele A1000"; compatible = "mele,a1000", "allwinner,sun4i-a10"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts b/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts index bebb803a9456dc..1a3c7ddc538a9d 100644 --- a/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts +++ b/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts @@ -54,6 +54,14 @@ / { model = "BA10 tvbox"; compatible = "allwinner,ba10-tvbox", "allwinner,sun4i-a10"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; }; &ehci0 { diff --git a/arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts b/arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts index 97fca89eb92b3d..35fb163827decf 100644 --- a/arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts +++ b/arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts @@ -54,6 +54,14 @@ / { model = "Chuwi V7 CW0825"; compatible = "chuwi,v7-cw0825", "allwinner,sun4i-a10"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; }; &ehci1 { diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts index 07c2f64b14ee5c..0ba67d79c2b4a8 100644 --- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts @@ -57,6 +57,14 @@ model = "Cubietech Cubieboard"; compatible = "cubietech,a10-cubieboard", "allwinner,sun4i-a10"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts b/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts index 0c734538079383..fbd638a38018bf 100644 --- a/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts +++ b/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts @@ -56,6 +56,14 @@ / { model = "Gemei G9 Tablet"; compatible = "gemei,g9", "allwinner,sun4i-a10"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; }; /* diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/sun4i-a10-hackberry.dts index 3cb067ed8715f7..f4437883fba7a5 100644 --- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts +++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts @@ -58,6 +58,14 @@ model = "Miniand Hackberry"; compatible = "miniand,hackberry", "allwinner,sun4i-a10"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + reg_emac_3v3: emac-3v3 { compatible = "regulator-fixed"; regulator-name = "emac-3v3"; diff --git a/arch/arm/boot/dts/sun4i-a10-hyundai-a7hd.dts b/arch/arm/boot/dts/sun4i-a10-hyundai-a7hd.dts index c88382aacc36b6..9f06b180505815 100644 --- a/arch/arm/boot/dts/sun4i-a10-hyundai-a7hd.dts +++ b/arch/arm/boot/dts/sun4i-a10-hyundai-a7hd.dts @@ -53,6 +53,14 @@ / { model = "Hyundai A7HD"; compatible = "hyundai,a7hd", "allwinner,sun4i-a10"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; }; &ehci1 { diff --git a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts index ab3bbc13db1ca3..e19ef52f357946 100644 --- a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts +++ b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts @@ -56,6 +56,14 @@ / { model = "INet-97F Rev 02"; compatible = "primux,inet97fv2", "allwinner,sun4i-a10"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; }; &ehci0 { diff --git a/arch/arm/boot/dts/sun4i-a10-marsboard.dts b/arch/arm/boot/dts/sun4i-a10-marsboard.dts index 9ee86a700c2b46..00c54d2a182432 100644 --- a/arch/arm/boot/dts/sun4i-a10-marsboard.dts +++ b/arch/arm/boot/dts/sun4i-a10-marsboard.dts @@ -57,6 +57,14 @@ model = "HAOYU Electronics Marsboard A10"; compatible = "haoyu,a10-marsboard", "allwinner,sun4i-a10"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts index dce9a341516b85..0f24914c1a6e44 100644 --- a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts +++ b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts @@ -57,6 +57,14 @@ / { model = "PineRiver Mini X-Plus"; compatible = "pineriver,mini-xplus", "allwinner,sun4i-a10"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; }; &ehci0 { diff --git a/arch/arm/boot/dts/sun4i-a10-mk802.dts b/arch/arm/boot/dts/sun4i-a10-mk802.dts index e9a6886f0d5135..0f1c99133c9c59 100644 --- a/arch/arm/boot/dts/sun4i-a10-mk802.dts +++ b/arch/arm/boot/dts/sun4i-a10-mk802.dts @@ -53,6 +53,14 @@ / { model = "MK802"; compatible = "allwinner,mk802", "allwinner,sun4i-a10"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; }; &ehci0 { diff --git a/arch/arm/boot/dts/sun4i-a10-mk802ii.dts b/arch/arm/boot/dts/sun4i-a10-mk802ii.dts index 802eda494d1c4d..f97aa6f523f4ca 100644 --- a/arch/arm/boot/dts/sun4i-a10-mk802ii.dts +++ b/arch/arm/boot/dts/sun4i-a10-mk802ii.dts @@ -53,6 +53,14 @@ / { model = "MK802ii"; compatible = "allwinner,mk802ii", "allwinner,sun4i-a10"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; }; &ehci0 { diff --git a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts index 03350dff42b18b..5840d5e16b99b2 100644 --- a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts +++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts @@ -56,6 +56,14 @@ model = "Olimex A10-OLinuXino-LIME"; compatible = "olimex,a10-olinuxino-lime", "allwinner,sun4i-a10"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/sun4i-a10-pcduino.dts index 6923ca75eb4ac9..be6948e4164809 100644 --- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts +++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts @@ -58,6 +58,13 @@ model = "LinkSprite pcDuino"; compatible = "linksprite,a10-pcduino", "allwinner,sun4i-a10"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; leds { compatible = "gpio-leds"; diff --git a/arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts b/arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts index 6c6fef780984f4..ceb0582ac90d0c 100644 --- a/arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts +++ b/arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts @@ -55,6 +55,14 @@ model = "Auxtek t004 A10s hdmi tv-stick"; compatible = "allwinner,auxtek-t004", "allwinner,sun5i-a10s"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun5i-a10s-mk802.dts b/arch/arm/boot/dts/sun5i-a10s-mk802.dts index b21af87d9eae4e..e1a11e1d967de5 100644 --- a/arch/arm/boot/dts/sun5i-a10s-mk802.dts +++ b/arch/arm/boot/dts/sun5i-a10s-mk802.dts @@ -54,6 +54,14 @@ model = "MK802-A10s"; compatible = "allwinner,a10s-mk802", "allwinner,sun5i-a10s"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts index aa88ee88738182..85a8745fffb3d9 100644 --- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts @@ -65,6 +65,10 @@ serial2 = &uart3; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts b/arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts index d42ce170e6404d..9980969d09862b 100644 --- a/arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts +++ b/arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts @@ -56,6 +56,14 @@ model = "R7 A10s hdmi tv-stick"; compatible = "allwinner,r7-tv-dongle", "allwinner,sun5i-a10s"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun5i-a13-hsg-h702.dts b/arch/arm/boot/dts/sun5i-a13-hsg-h702.dts index b59255a445bc76..adf78a234ffb13 100644 --- a/arch/arm/boot/dts/sun5i-a13-hsg-h702.dts +++ b/arch/arm/boot/dts/sun5i-a13-hsg-h702.dts @@ -59,6 +59,10 @@ aliases { serial0 = &uart1; }; + + chosen { + stdout-path = "serial0:115200n8"; + }; }; &cpu0 { diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts index bdb0a094223f52..4a00bcee9272ac 100644 --- a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts @@ -61,6 +61,10 @@ serial0 = &uart1; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts index d09c57b4905b2e..44401565533fa3 100644 --- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts +++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts @@ -63,6 +63,10 @@ serial0 = &uart1; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun6i-a31-app4-evb1.dts b/arch/arm/boot/dts/sun6i-a31-app4-evb1.dts index 98a74da02fd7d1..b7b1df4be4603c 100644 --- a/arch/arm/boot/dts/sun6i-a31-app4-evb1.dts +++ b/arch/arm/boot/dts/sun6i-a31-app4-evb1.dts @@ -58,8 +58,12 @@ model = "Allwinner A31 APP4 EVB1 Evaluation Board"; compatible = "allwinner,app4-evb1", "allwinner,sun6i-a31"; + aliases { + serial0 = &uart0; + }; + chosen { - bootargs = "earlyprintk console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; }; diff --git a/arch/arm/boot/dts/sun6i-a31-colombus.dts b/arch/arm/boot/dts/sun6i-a31-colombus.dts index d6e925c381a345..95d7ec2b2955a0 100644 --- a/arch/arm/boot/dts/sun6i-a31-colombus.dts +++ b/arch/arm/boot/dts/sun6i-a31-colombus.dts @@ -58,8 +58,12 @@ model = "WITS A31 Colombus Evaluation Board"; compatible = "wits,colombus", "allwinner,sun6i-a31"; + aliases { + serial0 = &uart0; + }; + chosen { - bootargs = "earlyprintk console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; }; diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts index 25a3ef49bb71a7..1e820bc0c76814 100644 --- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts +++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts @@ -58,8 +58,12 @@ model = "Merrii A31 Hummingbird"; compatible = "merrii,a31-hummingbird", "allwinner,sun6i-a31"; + aliases { + serial0 = &uart0; + }; + chosen { - bootargs = "earlyprintk console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; wifi_pwrseq: wifi_pwrseq { diff --git a/arch/arm/boot/dts/sun6i-a31-i7.dts b/arch/arm/boot/dts/sun6i-a31-i7.dts index 049d3a6c09f232..ce37d69d34165f 100644 --- a/arch/arm/boot/dts/sun6i-a31-i7.dts +++ b/arch/arm/boot/dts/sun6i-a31-i7.dts @@ -56,8 +56,12 @@ model = "Mele I7 Quad top set box"; compatible = "mele,i7", "allwinner,sun6i-a31"; + aliases { + serial0 = &uart0; + }; + chosen { - bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; leds { diff --git a/arch/arm/boot/dts/sun6i-a31-m9.dts b/arch/arm/boot/dts/sun6i-a31-m9.dts index 5cbbbd696b0026..29f5fc717b4f8d 100644 --- a/arch/arm/boot/dts/sun6i-a31-m9.dts +++ b/arch/arm/boot/dts/sun6i-a31-m9.dts @@ -56,8 +56,12 @@ model = "Mele M9 / A1000G Quad top set box"; compatible = "mele,m9", "allwinner,sun6i-a31"; + aliases { + serial0 = &uart0; + }; + chosen { - bootargs = "earlyprintk console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; leds { diff --git a/arch/arm/boot/dts/sun6i-a31s-cs908.dts b/arch/arm/boot/dts/sun6i-a31s-cs908.dts index 3f0cc8c58df8be..68cb2bf3998886 100644 --- a/arch/arm/boot/dts/sun6i-a31s-cs908.dts +++ b/arch/arm/boot/dts/sun6i-a31s-cs908.dts @@ -53,6 +53,14 @@ / { model = "CSQ CS908 top set box"; compatible = "csq,cs908", "allwinner,sun6i-a31s"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; }; &ehci0 { diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi.dts b/arch/arm/boot/dts/sun7i-a20-bananapi.dts index 6d1faf069e7ee3..b952ac445504c2 100644 --- a/arch/arm/boot/dts/sun7i-a20-bananapi.dts +++ b/arch/arm/boot/dts/sun7i-a20-bananapi.dts @@ -65,6 +65,10 @@ serial2 = &uart7; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun7i-a20-bananapro.dts b/arch/arm/boot/dts/sun7i-a20-bananapro.dts index fb89fe7ed21b61..9d9027f25a4401 100644 --- a/arch/arm/boot/dts/sun7i-a20-bananapro.dts +++ b/arch/arm/boot/dts/sun7i-a20-bananapro.dts @@ -55,6 +55,16 @@ model = "LeMaker Banana Pro"; compatible = "lemaker,bananapro", "allwinner,sun7i-a20"; + aliases { + serial0 = &uart0; + serial1 = &uart2; + serial2 = &uart7; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts index 8c847eb70cadbd..3c817ac9360bd2 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts @@ -59,6 +59,14 @@ model = "Cubietech Cubieboard2"; compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts index 5af1df795f3cf6..613a19e63e5895 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts @@ -59,6 +59,14 @@ model = "Cubietech Cubietruck"; compatible = "cubietech,cubietruck", "allwinner,sun7i-a20"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts index 8c30e126abe6bb..d3f15c2e721eb5 100644 --- a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts +++ b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts @@ -67,6 +67,10 @@ serial4 = &uart5; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + reg_mmc3_vdd: mmc3_vdd { compatible = "regulator-fixed"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts index c11574c2b93163..3f99b3f222a7f4 100644 --- a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts +++ b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts @@ -57,6 +57,14 @@ model = "I12 / Q5 / QT840A A20 tvbox"; compatible = "allwinner,i12-tvbox", "allwinner,sun7i-a20"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun7i-a20-m3.dts b/arch/arm/boot/dts/sun7i-a20-m3.dts index 44ba67dfb49497..f2fb26e7d6e5e0 100644 --- a/arch/arm/boot/dts/sun7i-a20-m3.dts +++ b/arch/arm/boot/dts/sun7i-a20-m3.dts @@ -59,6 +59,14 @@ model = "Mele M3"; compatible = "mele,m3", "allwinner,sun7i-a20"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts index 68efd2f33307ea..6592cb21e32c8d 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts @@ -60,6 +60,14 @@ model = "Olimex A20-OLinuXino-LIME"; compatible = "olimex,a20-olinuxino-lime", "allwinner,sun7i-a20"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts index 5e57157f742d1a..3a7a2c2b488cdf 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts @@ -57,6 +57,14 @@ model = "Olimex A20-OLinuXino-LIME2"; compatible = "olimex,a20-olinuxino-lime2", "allwinner,sun7i-a20"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts index f6f06311e25b09..82802b6cb192a9 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts @@ -68,6 +68,10 @@ spi1 = &spi2; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts index 632b8a9e092f79..810c5f76459519 100644 --- a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts +++ b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts @@ -55,6 +55,14 @@ model = "LinkSprite pcDuino3 Nano"; compatible = "linksprite,pcduino3-nano", "allwinner,sun7i-a20"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts index 09ec96b2b7d758..cd05267781fb22 100644 --- a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts +++ b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts @@ -59,6 +59,14 @@ model = "LinkSprite pcDuino3"; compatible = "linksprite,pcduino3", "allwinner,sun7i-a20"; + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts b/arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts index ea133bd3dd87fe..2ad3b09dcb6f59 100644 --- a/arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts +++ b/arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts @@ -57,6 +57,14 @@ / { model = "Wexler TAB7200"; compatible = "wexler,tab7200", "allwinner,sun7i-a20"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; }; &cpu0 { diff --git a/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts b/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts index 4cb25f8267c819..f5658d123f9ba5 100644 --- a/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts +++ b/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts @@ -64,7 +64,7 @@ }; chosen { - bootargs = "earlyprintk console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; }; diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts index c6ca116c59d295..e463138a4d0407 100644 --- a/arch/arm/boot/dts/sun9i-a80-optimus.dts +++ b/arch/arm/boot/dts/sun9i-a80-optimus.dts @@ -64,7 +64,7 @@ }; chosen { - bootargs = "earlyprintk console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; }; leds { From 3a2bc642abee100511021b263032329f94e3a1e4 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 26 Mar 2015 05:04:48 +0800 Subject: [PATCH 0313/3798] ARM: dts: sun6i: Add cpu clock reference and operating points to dtsi The cpu core is clocked from the "cpu" clock. Add a reference to it in the first cpu node. Also add "cpu0" label to the node. The operating points were taken from the a list compiled by Maxime Ripard, which is based on A31 FEX files from the sunxi-boards repository. Not all boards have the same settings. The settings in this patch are the ones shared by A/B/C revisions, plus the default clock setting from u-boot. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31.dtsi | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 2a37ee93265e52..9ea0edb9684c81 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -96,10 +96,22 @@ #address-cells = <1>; #size-cells = <0>; - cpu@0 { + cpu0: cpu@0 { compatible = "arm,cortex-a7"; device_type = "cpu"; reg = <0>; + clocks = <&cpu>; + clock-latency = <244144>; /* 8 32k periods */ + operating-points = < + /* kHz uV */ + 1008000 1200000 + 864000 1200000 + 720000 1100000 + 480000 1000000 + >; + #cooling-cells = <2>; + cooling-min-level = <0>; + cooling-max-level = <3>; }; cpu@1 { From eb58b40fb62413d820407c8210acb6c2f1ac1d9b Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 26 Mar 2015 05:04:49 +0800 Subject: [PATCH 0314/3798] ARM: dts: sun6i: Add cpu thermal zones to dtsi The core temperature sensor now supports thermal zones. Add a thermal zone mapping for the cpus with passive cooling (cpufreq throttling). Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31.dtsi | 33 ++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 9ea0edb9684c81..25a97f08d94b30 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -50,6 +50,7 @@ #include "skeleton.dtsi" #include +#include #include @@ -133,6 +134,38 @@ }; }; + thermal-zones { + cpu_thermal { + /* milliseconds */ + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&rtp>; + + cooling-maps { + map0 { + trip = <&cpu_alert0>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + + trips { + cpu_alert0: cpu_alert0 { + /* milliCelsius */ + temperature = <70000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit: cpu_crit { + /* milliCelsius */ + temperature = <100000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + }; + memory { reg = <0x40000000 0x80000000>; }; From f2641d2a9126846dd2d9e8c3910d7134e1bfbbda Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 18 Mar 2015 11:24:02 +0800 Subject: [PATCH 0315/3798] ARM: sun8i: dt: Enable A23 SMP support Add enable-method property to enable SMP support. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a23.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi index 9ff9227e2ab7a1..6d6eda398e31b2 100644 --- a/arch/arm/boot/dts/sun8i-a23.dtsi +++ b/arch/arm/boot/dts/sun8i-a23.dtsi @@ -81,6 +81,7 @@ }; cpus { + enable-method = "allwinner,sun8i-a23"; #address-cells = <1>; #size-cells = <0>; @@ -593,6 +594,11 @@ }; }; + cpucfg@01f01c00 { + compatible = "allwinner,sun8i-a23-cpuconfig"; + reg = <0x01f01c00 0x300>; + }; + r_uart: serial@01f02800 { compatible = "snps,dw-apb-uart"; reg = <0x01f02800 0x400>; From dd2fd84ffd00f529bf1fbb546779db3834417b8a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 1 Apr 2015 17:26:24 +0200 Subject: [PATCH 0316/3798] ARM: dts: sun5i: Add broken-hpi property for Utoo-P66 eMMC The eMMC on the A13 based Utoo-P66 tablet does not properly support hpi, and trying to enable it results in the eMMC not working, so add a child-node describing the eMMC, and set the broken-hpi property on it. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i-a13-utoo-p66.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts b/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts index 0f0a4112a0e309..f2476eaecce206 100644 --- a/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts +++ b/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts @@ -135,6 +135,12 @@ bus-width = <8>; non-removable; status = "okay"; + + mmccard: mmccard@0 { + reg = <0>; + compatible = "mmc-card"; + broken-hpi; + }; }; &pio { From 6d92b80f356f35b48b1fcec22a4562536aa03dbb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 26 Mar 2015 15:53:42 +0100 Subject: [PATCH 0317/3798] ARM: dts: sun4i: Add A10 SRAM and SRAM controller The A10 has a few SRAM that can be mapped either to a device or to the CPU, with the mapping being controlled by a SRAM controller. Since most of the time these SRAM won't be accessible by the CPU, we can't use the mmio-sram driver and compatible. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10.dtsi | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index dcc357b42ae93b..1d7fd68bea1dc0 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -450,12 +450,46 @@ }; }; + /* + * Note we use the address where the mmio registers start, not where + * the SRAM blocks start, this cannot be changed because that would be + * a devicetree ABI change. + */ soc@01c00000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges; + sram@00000000 { + compatible = "allwinner,sun4i-a10-sram"; + reg = <0x00000000 0x4000>; + allwinner,sram-name = "A1"; + }; + + sram@00004000 { + compatible = "allwinner,sun4i-a10-sram"; + reg = <0x00004000 0x4000>; + allwinner,sram-name = "A2"; + }; + + sram@00008000 { + compatible = "allwinner,sun4i-a10-sram"; + reg = <0x00008000 0x4000>; + allwinner,sram-name = "A3-A4"; + }; + + sram@00010000 { + compatible = "allwinner,sun4i-a10-sram"; + reg = <0x00010000 0x1000>; + allwinner,sram-name = "D"; + }; + + sram-controller@01c00000 { + compatible = "allwinner,sun4i-a10-sram-controller"; + reg = <0x01c00000 0x30>; + }; + dma: dma-controller@01c02000 { compatible = "allwinner,sun4i-a10-dma"; reg = <0x01c02000 0x1000>; From e6f51e4bd2a5bb12678330033dc995192507426f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 26 Mar 2015 15:53:43 +0100 Subject: [PATCH 0318/3798] ARM: dts: sun5i: Add A13 and A10s SRAM and SRAM controller The A13 / A10s has a few SRAM that can be mapped either to a device or to the CPU, with the mapping being controlled by a SRAM controller. Since most of the time these SRAM won't be accessible by the CPU, we can't use the mmio-sram driver and compatible. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i.dtsi | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index df5f2fbf69749c..96b20d646b3fa2 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -292,12 +292,46 @@ }; }; + /* + * Note we use the address where the mmio registers start, not where + * the SRAM blocks start, this cannot be changed because that would be + * a devicetree ABI change. + */ soc@01c00000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges; + sram@00000000 { + compatible = "allwinner,sun4i-a10-sram"; + reg = <0x00000000 0x4000>; + allwinner,sram-name = "A1"; + }; + + sram@00004000 { + compatible = "allwinner,sun4i-a10-sram"; + reg = <0x00004000 0x4000>; + allwinner,sram-name = "A2"; + }; + + sram@00008000 { + compatible = "allwinner,sun4i-a10-sram"; + reg = <0x00008000 0x4000>; + allwinner,sram-name = "A3-A4"; + }; + + sram@00010000 { + compatible = "allwinner,sun4i-a10-sram"; + reg = <0x00010000 0x1000>; + allwinner,sram-name = "D"; + }; + + sram-controller@01c00000 { + compatible = "allwinner,sun4i-a10-sram-controller"; + reg = <0x01c00000 0x30>; + }; + dma: dma-controller@01c02000 { compatible = "allwinner,sun4i-a10-dma"; reg = <0x01c02000 0x1000>; From ccb4ada2f193c7d5dc944cc925d1f58e5a007c0c Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 26 Mar 2015 15:53:44 +0100 Subject: [PATCH 0319/3798] ARM: dts: sun7i: Add A20 SRAM and SRAM controller The A20 has a few SRAM that can be mapped either to a device or to the CPU, with the mapping being controlled by a SRAM controller. Since most of the time these SRAM won't be accessible by the CPU, we can't use the mmio-sram driver and compatible. Signed-off-by: Maxime Ripard [hdegoede@redhat.com: Do not change soc node name, change compatible to sun4i-a10-sram-controller to match the driver change] Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20.dtsi | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 24eae39eefa68f..d4ba77202d7afb 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -521,12 +521,46 @@ }; }; + /* + * Note we use the address where the mmio registers start, not where + * the SRAM blocks start, this cannot be changed because that would be + * a devicetree ABI change. + */ soc@01c00000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges; + sram@00000000 { + compatible = "allwinner,sun4i-a10-sram"; + reg = <0x00000000 0x4000>; + allwinner,sram-name = "A1"; + }; + + sram@00004000 { + compatible = "allwinner,sun4i-a10-sram"; + reg = <0x00004000 0x4000>; + allwinner,sram-name = "A2"; + }; + + sram@00008000 { + compatible = "allwinner,sun4i-a10-sram"; + reg = <0x00008000 0x4000>; + allwinner,sram-name = "A3-A4"; + }; + + sram@00010000 { + compatible = "allwinner,sun4i-a10-sram"; + reg = <0x00010000 0x1000>; + allwinner,sram-name = "D"; + }; + + sram-controller@01c00000 { + compatible = "allwinner,sun4i-a10-sram-controller"; + reg = <0x01c00000 0x30>; + }; + nmi_intc: interrupt-controller@01c00030 { compatible = "allwinner,sun7i-a20-sc-nmi"; interrupt-controller; From 69ddea353287ea0cc866239d7ee70c378c3cbe81 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 4 Apr 2015 10:59:53 +0200 Subject: [PATCH 0320/3798] ARM: dts: sun7i: Add dts file for the Orangepi SBC The Orangepi is a development board using the Allwinner A20 SoC, with 1G RAM, microsd slot, HDMI, 1Gbit ethernet, USB wifi, Micro USB (otg), sata, 4 USB A ports, ir receiver and a headphones jack. Also see: http://linux-sunxi.org/Xunlong_Orange_Pi http://www.orangepi.org/ Signed-off-by: Hans de Goede [maxime: Added /chosen/stdout-path] Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/sun7i-a20-orangepi.dts | 233 +++++++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 arch/arm/boot/dts/sun7i-a20-orangepi.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index c6e95ab4e568e8..25f3db729f8db5 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -562,6 +562,7 @@ dtb-$(CONFIG_MACH_SUN7I) += \ sun7i-a20-olinuxino-lime.dtb \ sun7i-a20-olinuxino-lime2.dtb \ sun7i-a20-olinuxino-micro.dtb \ + sun7i-a20-orangepi.dtb \ sun7i-a20-pcduino3.dtb \ sun7i-a20-pcduino3-nano.dtb \ sun7i-a20-wexler-tab7200.dtb diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi.dts b/arch/arm/boot/dts/sun7i-a20-orangepi.dts new file mode 100644 index 00000000000000..7e6405c5448f23 --- /dev/null +++ b/arch/arm/boot/dts/sun7i-a20-orangepi.dts @@ -0,0 +1,233 @@ +/* + * Copyright 2015 Hans de Goede + * + * Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun7i-a20.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "Orange Pi"; + compatible = "xunlong,orangepi", "allwinner,sun7i-a20"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_orangepi>; + + green { + label = "orangepi:green:usr"; + gpios = <&pio 7 24 GPIO_ACTIVE_HIGH>; /* PH24 */ + }; + }; + + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac_power_pin_orangepi>; + regulator-name = "gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + enable-active-high; + gpio = <&pio 7 23 GPIO_ACTIVE_HIGH>; /* PH23 */ + }; +}; + +&ahci { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + phy-supply = <®_gmac_3v3>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +#include "axp209.dtsi" + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_orangepi>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */ + cd-inverted; + status = "okay"; +}; + +&pio { + mmc0_cd_pin_orangepi: mmc0_cd_pin@0 { + allwinner,pins = "PH10"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb2_vbus_pin_bananapro: usb2_vbus_pin@0 { + allwinner,pins = "PH22"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + gmac_power_pin_orangepi: gmac_power_pin@0 { + allwinner,pins = "PH23"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_orangepi: led_pins@0 { + allwinner,pins = "PH24"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb1_vbus_pin_bananapro: usb1_vbus_pin@0 { + allwinner,pins = "PH26"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-int-pll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_usb1_vbus { + pinctrl-0 = <&usb1_vbus_pin_bananapro>; + gpio = <&pio 7 26 GPIO_ACTIVE_HIGH>; /* PH26 */ + status = "okay"; +}; + +®_usb2_vbus { + pinctrl-0 = <&usb2_vbus_pin_bananapro>; + gpio = <&pio 7 22 GPIO_ACTIVE_HIGH>; /* PH22 */ + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From fe0807c57e2b4d6c4f900bd554ea33fafbb49c51 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 4 Apr 2015 10:59:54 +0200 Subject: [PATCH 0321/3798] ARM: dts: sun7i: Add dts file for the Orangepi mini SBC The Orangepi mini is a development board using the Allwinner A20 SoC, with 1G RAM, 2 microsd slots (use the top side one for booting), HDMI, 1Gbit ethernet, USB wifi, Micro USB (otg), sata, 4 USB A ports, ir receiver and a headphones jack. Also see: http://linux-sunxi.org/Xunlong_Orange_Pi_Mini http://www.orangepi.org/ Signed-off-by: Hans de Goede [maxime: Added /chosen/stdout-path] Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts | 255 ++++++++++++++++++ 2 files changed, 256 insertions(+) create mode 100644 arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 25f3db729f8db5..a71d3c77f87d6f 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -563,6 +563,7 @@ dtb-$(CONFIG_MACH_SUN7I) += \ sun7i-a20-olinuxino-lime2.dtb \ sun7i-a20-olinuxino-micro.dtb \ sun7i-a20-orangepi.dtb \ + sun7i-a20-orangepi-mini.dtb \ sun7i-a20-pcduino3.dtb \ sun7i-a20-pcduino3-nano.dtb \ sun7i-a20-wexler-tab7200.dtb diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts b/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts new file mode 100644 index 00000000000000..0556938a5d4d63 --- /dev/null +++ b/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts @@ -0,0 +1,255 @@ +/* + * Copyright 2015 Hans de Goede + * + * Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun7i-a20.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "Orange Pi Mini"; + compatible = "xunlong,orangepi-mini", "allwinner,sun7i-a20"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_orangepi>; + + green { + label = "orangepi:green:usr"; + gpios = <&pio 7 24 GPIO_ACTIVE_HIGH>; /* PH24 */ + }; + + blue { + label = "orangepi:blue:usr"; + gpios = <&pio 7 25 GPIO_ACTIVE_HIGH>; /* PH25 */ + }; + }; + + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac_power_pin_orangepi>; + regulator-name = "gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + enable-active-high; + gpio = <&pio 7 23 GPIO_ACTIVE_HIGH>; /* PH23 */ + }; +}; + +&ahci { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + phy-supply = <®_gmac_3v3>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +#include "axp209.dtsi" + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_orangepi>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */ + cd-inverted; + status = "okay"; +}; + +&mmc3 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc3_pins_a>, <&mmc3_cd_pin_orangepi>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */ + cd-inverted; + status = "okay"; +}; + +&pio { + mmc0_cd_pin_orangepi: mmc0_cd_pin@0 { + allwinner,pins = "PH10"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc3_cd_pin_orangepi: mmc3_cd_pin@0 { + allwinner,pins = "PH11"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb2_vbus_pin_bananapro: usb2_vbus_pin@0 { + allwinner,pins = "PH22"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + gmac_power_pin_orangepi: gmac_power_pin@0 { + allwinner,pins = "PH23"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_orangepi: led_pins@0 { + allwinner,pins = "PH24", "PH25"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb1_vbus_pin_bananapro: usb1_vbus_pin@0 { + allwinner,pins = "PH26"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-int-pll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_usb1_vbus { + pinctrl-0 = <&usb1_vbus_pin_bananapro>; + gpio = <&pio 7 26 GPIO_ACTIVE_HIGH>; /* PH26 */ + status = "okay"; +}; + +®_usb2_vbus { + pinctrl-0 = <&usb2_vbus_pin_bananapro>; + gpio = <&pio 7 22 GPIO_ACTIVE_HIGH>; /* PH22 */ + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From 2a53aff2723676a873406403be5370074ed86fc3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 1 Apr 2015 17:29:37 +0200 Subject: [PATCH 0322/3798] ARM: dts: sun5i: Enable touchscreen on Utoo P66 Add a node for the chipone-icn8318 touchscreen found on the Utoo P66 tablet. Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i-a13-utoo-p66.dts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts b/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts index f2476eaecce206..d2303da6915d69 100644 --- a/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts +++ b/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts @@ -50,6 +50,7 @@ #include "sunxi-common-regulators.dtsi" #include #include +#include #include / { @@ -93,6 +94,20 @@ pinctrl-0 = <&i2c1_pins_a>; status = "okay"; + icn8318: touchscreen@40 { + compatible = "chipone,icn8318"; + reg = <0x40>; + interrupt-parent = <&pio>; + interrupts = <9 IRQ_TYPE_EDGE_FALLING>; /* EINT9 (PG9) */ + pinctrl-names = "default"; + pinctrl-0 = <&ts_wake_pin_p66>; + wake-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */ + touchscreen-size-x = <800>; + touchscreen-size-y = <480>; + touchscreen-inverted-x; + touchscreen-swapped-x-y; + }; + pcf8563: rtc@51 { compatible = "nxp,pcf8563"; reg = <0x51>; @@ -158,6 +173,13 @@ allwinner,pull = ; }; + ts_wake_pin_p66: ts_wake_pin@0 { + allwinner,pins = "PB3"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + usb0_vbus_pin_a: usb0_vbus_pin@0 { allwinner,pins = "PB4"; allwinner,function = "gpio_out"; From ae3bdfe0efe0417b702e6501015375c44226ec23 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 23 Apr 2015 14:26:50 +0200 Subject: [PATCH 0323/3798] ARM: dts: sun7i: Add dts file for the Jesurun Q5 top set box The Jesurun Q5 has a black plastic casing with the approximate dimensions of 100mm x 100mm x 24mm with rounded edges. In terms of hardware it features an Allwinner A10 SoC with 1GB RAM and 8GB of NAND flash. The external connectors are: 2x USB-A female supporting USB2.0, 3.5mm female jack for audio, HDMI female, SPDIF, RJ45 LAN and Power. In addition the device has 1x red LED (hard wired to power) and an programmable green led. On the board there is also an unpopulated IR receiver and the UART. The devices is equipped with an AXP209 PMU. For more details see: http://linux-sunxi.org/Jesurun_Q5 Signed-off-by: Hans de Goede Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts | 194 +++++++++++++++++++++ 2 files changed, 195 insertions(+) create mode 100644 arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index a71d3c77f87d6f..83a4e685b0a559 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -529,6 +529,7 @@ dtb-$(CONFIG_MACH_SUN4I) += \ sun4i-a10-hackberry.dtb \ sun4i-a10-hyundai-a7hd.dtb \ sun4i-a10-inet97fv2.dtb \ + sun4i-a10-jesurun-q5.dtb \ sun4i-a10-marsboard.dtb \ sun4i-a10-mini-xplus.dtb \ sun4i-a10-mk802.dtb \ diff --git a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts new file mode 100644 index 00000000000000..1b0452fea273bf --- /dev/null +++ b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts @@ -0,0 +1,194 @@ +/* + * Copyright 2015 Gábor Nyers + * + * Gábor Nyers + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun4i-a10.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include + +/ { + model = "Jesurun Q5"; + compatible = "jesurun,q5", "allwinner,sun4i-a10"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_q5>; + + green { + label = "q5:green:usr"; + gpios = <&pio 7 20 GPIO_ACTIVE_HIGH>; /* PH20 */ + }; + + }; + + reg_emac_3v3: emac-3v3 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&emac_power_pin_q5>; + regulator-name = "emac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpio = <&pio 7 19 GPIO_ACTIVE_HIGH>; /* PH19 */ + }; +}; + +&ahci { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&emac_pins_a>; + phy = <&phy1>; + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupts = <0>; + + interrupt-controller; + #interrupt-cells = <1>; + }; +}; + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&mdio { + phy-supply = <®_emac_3v3>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pio { + emac_power_pin_q5: emac_power_pin@0 { + allwinner,pins = "PH19"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_q5: led_pins@0 { + allwinner,pins = "PH20"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From 771969ec96ce90413bd749f23409d5266620f1ae Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 23 Mar 2015 16:49:57 +0100 Subject: [PATCH 0324/3798] ARM: ux500: define CPU topology The CPU topology is unspecified for Ux500 but will be needed for things like CoreSight. Let's just add it. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/ste-dbx5x0.dtsi | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi index bfd3f1c734b8d8..bd6bd0926931f5 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi @@ -22,6 +22,32 @@ interrupt-parent = <&intc>; ranges; + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + }; + }; + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0>; + }; + CPU1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <1>; + }; + }; + intc: interrupt-controller@a0411000 { compatible = "arm,cortex-a9-gic"; #interrupt-cells = <3>; From 2186df37831a8bb259bbf2ae07356747a03d0b8d Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 25 Mar 2015 01:22:09 +0800 Subject: [PATCH 0325/3798] ARM: dts: sunxi: Update ahb clocks for sun5i and sun7i The clock driver now supports a muxable ahb clock. Update the dtsi with the proper compatible and add the new parent clocks. This also adds the new pll6/4 output for pll6 on sun7i-a20. The output is not used on sun4/5i. Also use assigned-clocks to reparent ahb to pll6. We want ahb to have a stable, non-changing clock rate. cpu/axi clock rate changes as a result of newly added cpufreq support. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun5i.dtsi | 10 ++++++++-- arch/arm/boot/dts/sun7i-a20.dtsi | 13 ++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index 96b20d646b3fa2..8c04f240f2e94a 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -150,10 +150,16 @@ ahb: ahb@01c20054 { #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-ahb-clk"; + compatible = "allwinner,sun5i-a13-ahb-clk"; reg = <0x01c20054 0x4>; - clocks = <&axi>; + clocks = <&axi>, <&cpu>, <&pll6 1>; clock-output-names = "ahb"; + /* + * Use PLL6 as parent, instead of CPU/AXI + * which has rate changes due to cpufreq + */ + assigned-clocks = <&ahb>; + assigned-clock-parents = <&pll6 1>; }; apb0: apb0@01c20054 { diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index d4ba77202d7afb..4163ade867cb7d 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -224,7 +224,8 @@ compatible = "allwinner,sun4i-a10-pll6-clk"; reg = <0x01c20028 0x4>; clocks = <&osc24M>; - clock-output-names = "pll6_sata", "pll6_other", "pll6"; + clock-output-names = "pll6_sata", "pll6_other", "pll6", + "pll6_div_4"; }; pll8: clk@01c20040 { @@ -253,10 +254,16 @@ ahb: ahb@01c20054 { #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-ahb-clk"; + compatible = "allwinner,sun5i-a13-ahb-clk"; reg = <0x01c20054 0x4>; - clocks = <&axi>; + clocks = <&axi>, <&pll6 3>, <&pll6 1>; clock-output-names = "ahb"; + /* + * Use PLL6 as parent, instead of CPU/AXI + * which has rate changes due to cpufreq + */ + assigned-clocks = <&ahb>; + assigned-clock-parents = <&pll6 3>; }; ahb_gates: clk@01c20060 { From f22fe1c5ab9f061b7e27e1eb31426d106deb1e22 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 26 Mar 2015 05:04:47 +0800 Subject: [PATCH 0326/3798] ARM: dts: sun6i: Set PLL6 as parent to AHB1 clock in AHB1 clock node On sun6i we already have PLL6 as AHB1 clock's parent. However this was previously set in the dma controller node, which takes effect when the dma controller is probed. We want this to take effect as soon as possible, so hrtimer rate calculation is correct, and to be sure the AHB1 clock rate remains as stable as possible. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31.dtsi | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 25a97f08d94b30..60d912eeb7c7d8 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -241,6 +241,14 @@ reg = <0x01c20054 0x4>; clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; clock-output-names = "ahb1"; + + /* + * Clock AHB1 from PLL6, instead of CPU/AXI which + * has rate changes due to cpufreq. Also the DMA + * controller requires AHB1 clocked from PLL6. + */ + assigned-clocks = <&ahb1>; + assigned-clock-parents = <&pll6 0>; }; ahb1_gates: clk@01c20060 { @@ -426,10 +434,6 @@ clocks = <&ahb1_gates 6>; resets = <&ahb1_rst 6>; #dma-cells = <1>; - - /* DMA controller requires AHB1 clocked from PLL6 */ - assigned-clocks = <&ahb1>; - assigned-clock-parents = <&pll6 0>; }; mmc0: mmc@01c0f000 { From f18407800e5d211028858f86f1e78aacbedad298 Mon Sep 17 00:00:00 2001 From: Sonny Rao Date: Tue, 7 Apr 2015 10:52:39 -0700 Subject: [PATCH 0327/3798] ARM: dts: rockchip: Enable Cortex-A12 HW PMU events on rk3288 This adds the dts node for the PMU with the correct PMUIRQ interrupts for each core. Signed-off-by: Sonny Rao Reviewed-by: Doug Anderson Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 165968d51d8fd7..8253abb83f369c 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -44,6 +44,14 @@ spi2 = &spi2; }; + arm-pmu { + compatible = "arm,cortex-a12-pmu"; + interrupts = , + , + , + ; + }; + cpus { #address-cells = <1>; #size-cells = <0>; From e565abe10b851bd1c90f8a39e2e4695f337f3cb0 Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Wed, 11 Mar 2015 15:15:17 -0700 Subject: [PATCH 0328/3798] ARM: dts: rockchip: Specify VMMC and VQMMC on rk3288-evb Specifying these rails should eventually let us do UHS. Signed-off-by: Doug Anderson Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-evb.dtsi | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index 4a457518d86160..41f5f2a02387fc 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -112,6 +112,23 @@ regulator-always-on; regulator-boot-on; }; + + /* + * NOTE: vcc_sd isn't hooked up on v1.0 boards where power comes from + * vcc_io directly. Those boards won't be able to power cycle SD cards + * but it shouldn't hurt to toggle this pin there anyway. + */ + vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio7 11 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_pwr>; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + vin-supply = <&vcc_io>; + }; }; &emmc { @@ -141,6 +158,8 @@ pinctrl-names = "default"; pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; status = "okay"; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; }; &i2c0 { @@ -232,6 +251,10 @@ sdmmc_cmd: sdmmc-cmd { rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_8ma>; }; + + sdmmc_pwr: sdmmc-pwr { + rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>; + }; }; usb { From 71126029211cf67b64ed8b4f03cced508d32efd5 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 6 Apr 2015 02:10:09 +0200 Subject: [PATCH 0329/3798] ARM: dts: rockchip: add act8846 supplies on rk3288-firefly We defined bindings for the supply handling of act8846 regulators now, so describe those on the firefly too. Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-firefly.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-firefly.dtsi b/arch/arm/boot/dts/rk3288-firefly.dtsi index b54dd78580c1c7..a3b1fc43228b72 100644 --- a/arch/arm/boot/dts/rk3288-firefly.dtsi +++ b/arch/arm/boot/dts/rk3288-firefly.dtsi @@ -246,6 +246,14 @@ pinctrl-0 = <&pmic_vsel>, <&pwr_hold>; system-power-controller; + vp1-supply = <&vcc_sys>; + vp2-supply = <&vcc_sys>; + vp3-supply = <&vcc_sys>; + vp4-supply = <&vcc_sys>; + inl1-supply = <&vcc_sys>; + inl2-supply = <&vcc_sys>; + inl3-supply = <&vcc_20>; + regulators { vcc_ddr: REG1 { regulator-name = "vcc_ddr"; From 8c653f9ab6e56921b3704c0b8191f5432de02ad7 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Sun, 5 Apr 2015 11:15:01 +0200 Subject: [PATCH 0330/3798] ARM: dts: rockchip: enable tsadc on rk3288 boards The tsadc is used to read cpu and gpu temperatures. Also enable it on the other rk3288 boards beside the evb using the cru reset settings. Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-firefly.dtsi | 6 ++++++ arch/arm/boot/dts/rk3288-popmetal.dts | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-firefly.dtsi b/arch/arm/boot/dts/rk3288-firefly.dtsi index a3b1fc43228b72..0b42372e437944 100644 --- a/arch/arm/boot/dts/rk3288-firefly.dtsi +++ b/arch/arm/boot/dts/rk3288-firefly.dtsi @@ -465,6 +465,12 @@ status = "okay"; }; +&tsadc { + rockchip,hw-tshut-mode = <0>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_xfer>, <&uart0_cts>, <&uart0_rts>; diff --git a/arch/arm/boot/dts/rk3288-popmetal.dts b/arch/arm/boot/dts/rk3288-popmetal.dts index d081f0e0da36c3..d582811fbd7b0e 100644 --- a/arch/arm/boot/dts/rk3288-popmetal.dts +++ b/arch/arm/boot/dts/rk3288-popmetal.dts @@ -406,6 +406,12 @@ }; }; +&tsadc { + rockchip,hw-tshut-mode = <0>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + &vopb { status = "okay"; }; From 2d5f0764b5264d2954ba6e3deb04f4f5de8e4476 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Mon, 27 Apr 2015 17:58:38 +0800 Subject: [PATCH 0331/3798] workqueue: split apply_workqueue_attrs() into 3 stages Current apply_workqueue_attrs() includes pwqs-allocation and pwqs-installation, so when we batch multiple apply_workqueue_attrs()s as a transaction, we can't ensure the transaction must succeed or fail as a complete unit. To solve this, we split apply_workqueue_attrs() into three stages. The first stage does the preparation: allocation memory, pwqs. The second stage does the attrs-installaion and pwqs-installation. The third stage frees the allocated memory and (old or unused) pwqs. As the result, batching multiple apply_workqueue_attrs()s can succeed or fail as a complete unit: 1) batch do all the first stage for all the workqueues 2) only commit all when all the above succeed. This patch is a preparation for the next patch ("Allow modifying low level unbound workqueue cpumask") which will do a multiple apply_workqueue_attrs(). The patch doesn't have functionality changed except two minor adjustment: 1) free_unbound_pwq() for the error path is removed, we use the heavier version put_pwq_unlocked() instead since the error path is rare. this adjustment simplifies the code. 2) the memory-allocation is also moved into wq_pool_mutex. this is needed to avoid to do the further splitting. tj: minor updates to comments. Suggested-by: Tejun Heo Cc: Christoph Lameter Cc: Kevin Hilman Cc: Lai Jiangshan Cc: Mike Galbraith Cc: Paul E. McKenney Cc: Tejun Heo Cc: Viresh Kumar Cc: Frederic Weisbecker Signed-off-by: Lai Jiangshan Signed-off-by: Tejun Heo --- kernel/workqueue.c | 199 ++++++++++++++++++++++++++------------------- 1 file changed, 115 insertions(+), 84 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 586ad91300b0f3..26ff249240160b 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3425,17 +3425,6 @@ static struct pool_workqueue *alloc_unbound_pwq(struct workqueue_struct *wq, return pwq; } -/* undo alloc_unbound_pwq(), used only in the error path */ -static void free_unbound_pwq(struct pool_workqueue *pwq) -{ - lockdep_assert_held(&wq_pool_mutex); - - if (pwq) { - put_unbound_pool(pwq->pool); - kmem_cache_free(pwq_cache, pwq); - } -} - /** * wq_calc_node_mask - calculate a wq_attrs' cpumask for the specified node * @attrs: the wq_attrs of interest @@ -3498,42 +3487,48 @@ static struct pool_workqueue *numa_pwq_tbl_install(struct workqueue_struct *wq, return old_pwq; } -/** - * apply_workqueue_attrs - apply new workqueue_attrs to an unbound workqueue - * @wq: the target workqueue - * @attrs: the workqueue_attrs to apply, allocated with alloc_workqueue_attrs() - * - * Apply @attrs to an unbound workqueue @wq. Unless disabled, on NUMA - * machines, this function maps a separate pwq to each NUMA node with - * possibles CPUs in @attrs->cpumask so that work items are affine to the - * NUMA node it was issued on. Older pwqs are released as in-flight work - * items finish. Note that a work item which repeatedly requeues itself - * back-to-back will stay on its current pwq. - * - * Performs GFP_KERNEL allocations. - * - * Return: 0 on success and -errno on failure. - */ -int apply_workqueue_attrs(struct workqueue_struct *wq, - const struct workqueue_attrs *attrs) +/* context to store the prepared attrs & pwqs before applying */ +struct apply_wqattrs_ctx { + struct workqueue_struct *wq; /* target workqueue */ + struct workqueue_attrs *attrs; /* attrs to apply */ + struct pool_workqueue *dfl_pwq; + struct pool_workqueue *pwq_tbl[]; +}; + +/* free the resources after success or abort */ +static void apply_wqattrs_cleanup(struct apply_wqattrs_ctx *ctx) +{ + if (ctx) { + int node; + + for_each_node(node) + put_pwq_unlocked(ctx->pwq_tbl[node]); + put_pwq_unlocked(ctx->dfl_pwq); + + free_workqueue_attrs(ctx->attrs); + + kfree(ctx); + } +} + +/* allocate the attrs and pwqs for later installation */ +static struct apply_wqattrs_ctx * +apply_wqattrs_prepare(struct workqueue_struct *wq, + const struct workqueue_attrs *attrs) { + struct apply_wqattrs_ctx *ctx; struct workqueue_attrs *new_attrs, *tmp_attrs; - struct pool_workqueue **pwq_tbl, *dfl_pwq; - int node, ret; + int node; - /* only unbound workqueues can change attributes */ - if (WARN_ON(!(wq->flags & WQ_UNBOUND))) - return -EINVAL; + lockdep_assert_held(&wq_pool_mutex); - /* creating multiple pwqs breaks ordering guarantee */ - if (WARN_ON((wq->flags & __WQ_ORDERED) && !list_empty(&wq->pwqs))) - return -EINVAL; + ctx = kzalloc(sizeof(*ctx) + nr_node_ids * sizeof(ctx->pwq_tbl[0]), + GFP_KERNEL); - pwq_tbl = kzalloc(nr_node_ids * sizeof(pwq_tbl[0]), GFP_KERNEL); new_attrs = alloc_workqueue_attrs(GFP_KERNEL); tmp_attrs = alloc_workqueue_attrs(GFP_KERNEL); - if (!pwq_tbl || !new_attrs || !tmp_attrs) - goto enomem; + if (!ctx || !new_attrs || !tmp_attrs) + goto out_free; /* make a copy of @attrs and sanitize it */ copy_workqueue_attrs(new_attrs, attrs); @@ -3546,76 +3541,112 @@ int apply_workqueue_attrs(struct workqueue_struct *wq, */ copy_workqueue_attrs(tmp_attrs, new_attrs); - /* - * CPUs should stay stable across pwq creations and installations. - * Pin CPUs, determine the target cpumask for each node and create - * pwqs accordingly. - */ - get_online_cpus(); - - mutex_lock(&wq_pool_mutex); - /* * If something goes wrong during CPU up/down, we'll fall back to * the default pwq covering whole @attrs->cpumask. Always create * it even if we don't use it immediately. */ - dfl_pwq = alloc_unbound_pwq(wq, new_attrs); - if (!dfl_pwq) - goto enomem_pwq; + ctx->dfl_pwq = alloc_unbound_pwq(wq, new_attrs); + if (!ctx->dfl_pwq) + goto out_free; for_each_node(node) { if (wq_calc_node_cpumask(attrs, node, -1, tmp_attrs->cpumask)) { - pwq_tbl[node] = alloc_unbound_pwq(wq, tmp_attrs); - if (!pwq_tbl[node]) - goto enomem_pwq; + ctx->pwq_tbl[node] = alloc_unbound_pwq(wq, tmp_attrs); + if (!ctx->pwq_tbl[node]) + goto out_free; } else { - dfl_pwq->refcnt++; - pwq_tbl[node] = dfl_pwq; + ctx->dfl_pwq->refcnt++; + ctx->pwq_tbl[node] = ctx->dfl_pwq; } } - mutex_unlock(&wq_pool_mutex); + ctx->attrs = new_attrs; + ctx->wq = wq; + free_workqueue_attrs(tmp_attrs); + return ctx; + +out_free: + free_workqueue_attrs(tmp_attrs); + free_workqueue_attrs(new_attrs); + apply_wqattrs_cleanup(ctx); + return NULL; +} + +/* set attrs and install prepared pwqs, @ctx points to old pwqs on return */ +static void apply_wqattrs_commit(struct apply_wqattrs_ctx *ctx) +{ + int node; /* all pwqs have been created successfully, let's install'em */ - mutex_lock(&wq->mutex); + mutex_lock(&ctx->wq->mutex); - copy_workqueue_attrs(wq->unbound_attrs, new_attrs); + copy_workqueue_attrs(ctx->wq->unbound_attrs, ctx->attrs); /* save the previous pwq and install the new one */ for_each_node(node) - pwq_tbl[node] = numa_pwq_tbl_install(wq, node, pwq_tbl[node]); + ctx->pwq_tbl[node] = numa_pwq_tbl_install(ctx->wq, node, + ctx->pwq_tbl[node]); /* @dfl_pwq might not have been used, ensure it's linked */ - link_pwq(dfl_pwq); - swap(wq->dfl_pwq, dfl_pwq); + link_pwq(ctx->dfl_pwq); + swap(ctx->wq->dfl_pwq, ctx->dfl_pwq); - mutex_unlock(&wq->mutex); + mutex_unlock(&ctx->wq->mutex); +} - /* put the old pwqs */ - for_each_node(node) - put_pwq_unlocked(pwq_tbl[node]); - put_pwq_unlocked(dfl_pwq); +/** + * apply_workqueue_attrs - apply new workqueue_attrs to an unbound workqueue + * @wq: the target workqueue + * @attrs: the workqueue_attrs to apply, allocated with alloc_workqueue_attrs() + * + * Apply @attrs to an unbound workqueue @wq. Unless disabled, on NUMA + * machines, this function maps a separate pwq to each NUMA node with + * possibles CPUs in @attrs->cpumask so that work items are affine to the + * NUMA node it was issued on. Older pwqs are released as in-flight work + * items finish. Note that a work item which repeatedly requeues itself + * back-to-back will stay on its current pwq. + * + * Performs GFP_KERNEL allocations. + * + * Return: 0 on success and -errno on failure. + */ +int apply_workqueue_attrs(struct workqueue_struct *wq, + const struct workqueue_attrs *attrs) +{ + struct apply_wqattrs_ctx *ctx; + int ret = -ENOMEM; - put_online_cpus(); - ret = 0; - /* fall through */ -out_free: - free_workqueue_attrs(tmp_attrs); - free_workqueue_attrs(new_attrs); - kfree(pwq_tbl); - return ret; + /* only unbound workqueues can change attributes */ + if (WARN_ON(!(wq->flags & WQ_UNBOUND))) + return -EINVAL; -enomem_pwq: - free_unbound_pwq(dfl_pwq); - for_each_node(node) - if (pwq_tbl && pwq_tbl[node] != dfl_pwq) - free_unbound_pwq(pwq_tbl[node]); + /* creating multiple pwqs breaks ordering guarantee */ + if (WARN_ON((wq->flags & __WQ_ORDERED) && !list_empty(&wq->pwqs))) + return -EINVAL; + + /* + * CPUs should stay stable across pwq creations and installations. + * Pin CPUs, determine the target cpumask for each node and create + * pwqs accordingly. + */ + get_online_cpus(); + + mutex_lock(&wq_pool_mutex); + ctx = apply_wqattrs_prepare(wq, attrs); mutex_unlock(&wq_pool_mutex); + + /* the ctx has been prepared successfully, let's commit it */ + if (ctx) { + apply_wqattrs_commit(ctx); + ret = 0; + } + put_online_cpus(); -enomem: - ret = -ENOMEM; - goto out_free; + + apply_wqattrs_cleanup(ctx); + + return ret; } /** From b05a79280b346eb24ddb73b39988398015291075 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Mon, 27 Apr 2015 17:58:39 +0800 Subject: [PATCH 0332/3798] workqueue: Create low-level unbound workqueues cpumask Create a cpumask that limits the affinity of all unbound workqueues. This cpumask is controlled through a file at the root of the workqueue sysfs directory. It works on a lower-level than the per WQ_SYSFS workqueues cpumask files such that the effective cpumask applied for a given unbound workqueue is the intersection of /sys/devices/virtual/workqueue/$WORKQUEUE/cpumask and the new /sys/devices/virtual/workqueue/cpumask file. This patch implements the basic infrastructure and the read interface. wq_unbound_cpumask is initially set to cpu_possible_mask. Cc: Christoph Lameter Cc: Kevin Hilman Cc: Lai Jiangshan Cc: Mike Galbraith Cc: Paul E. McKenney Cc: Tejun Heo Cc: Viresh Kumar Signed-off-by: Frederic Weisbecker Signed-off-by: Lai Jiangshan Signed-off-by: Tejun Heo --- kernel/workqueue.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 26ff249240160b..9be75e2a4da6cb 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -299,6 +299,8 @@ static DEFINE_SPINLOCK(wq_mayday_lock); /* protects wq->maydays list */ static LIST_HEAD(workqueues); /* PR: list of all workqueues */ static bool workqueue_freezing; /* PL: have wqs started freezing? */ +static cpumask_var_t wq_unbound_cpumask; + /* the per-cpu worker pools */ static DEFINE_PER_CPU_SHARED_ALIGNED(struct worker_pool [NR_STD_WORKER_POOLS], cpu_worker_pools); @@ -3532,7 +3534,7 @@ apply_wqattrs_prepare(struct workqueue_struct *wq, /* make a copy of @attrs and sanitize it */ copy_workqueue_attrs(new_attrs, attrs); - cpumask_and(new_attrs->cpumask, new_attrs->cpumask, cpu_possible_mask); + cpumask_and(new_attrs->cpumask, new_attrs->cpumask, wq_unbound_cpumask); /* * We may create multiple pwqs with differing cpumasks. Make a @@ -4945,9 +4947,29 @@ static struct bus_type wq_subsys = { .dev_groups = wq_sysfs_groups, }; +static ssize_t wq_unbound_cpumask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int written; + + written = scnprintf(buf, PAGE_SIZE, "%*pb\n", + cpumask_pr_args(wq_unbound_cpumask)); + + return written; +} + +static struct device_attribute wq_sysfs_cpumask_attr = + __ATTR(cpumask, 0444, wq_unbound_cpumask_show, NULL); + static int __init wq_sysfs_init(void) { - return subsys_virtual_register(&wq_subsys, NULL); + int err; + + err = subsys_virtual_register(&wq_subsys, NULL); + if (err) + return err; + + return device_create_file(wq_subsys.dev_root, &wq_sysfs_cpumask_attr); } core_initcall(wq_sysfs_init); @@ -5095,6 +5117,9 @@ static int __init init_workqueues(void) WARN_ON(__alignof__(struct pool_workqueue) < __alignof__(long long)); + BUG_ON(!alloc_cpumask_var(&wq_unbound_cpumask, GFP_KERNEL)); + cpumask_copy(wq_unbound_cpumask, cpu_possible_mask); + pwq_cache = KMEM_CACHE(pool_workqueue, SLAB_PANIC); cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP); From cabd2ea21636ba7268232b8e2102671f47d2923f Mon Sep 17 00:00:00 2001 From: Yunzhi Li Date: Sun, 26 Apr 2015 17:41:38 +0800 Subject: [PATCH 0333/3798] ARM: dts: rockchip: add properties for dwc2 usb otg controller Add properties for dwc2 usb device controller according to Documentation/devicetree/bindings/usb/dwc2.txt Signed-off-by: Yunzhi Li Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 8253abb83f369c..280aecd35c2709 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -442,6 +442,7 @@ interrupts = ; clocks = <&cru HCLK_USBHOST1>; clock-names = "otg"; + dr_mode = "host"; phys = <&usbphy2>; phy-names = "usb2-phy"; status = "disabled"; @@ -454,6 +455,11 @@ interrupts = ; clocks = <&cru HCLK_OTG0>; clock-names = "otg"; + dr_mode = "otg"; + g-np-tx-fifo-size = <16>; + g-rx-fifo-size = <275>; + g-tx-fifo-size = <256 128 128 64 64 32>; + g-use-dma; phys = <&usbphy0>; phy-names = "usb2-phy"; status = "disabled"; From 87841c887b7b78742d9f8e5da890ed4af21dd978 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 16 Apr 2015 21:07:05 +0800 Subject: [PATCH 0334/3798] usb: gadget: uvc: remove unused including Remove including that don't need it. Signed-off-by: Wei Yongjun Acked-by: Laurent Pinchart Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/uvc.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index ebe409b9e41992..7d3bb6272e063a 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -56,7 +56,6 @@ struct uvc_event #include #include #include -#include #include #include From 2d9c7f3ca54625f4d740af78f84ee232da3ca937 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 14 Apr 2015 04:10:04 +0000 Subject: [PATCH 0335/3798] usb: renesas_usbhs: tidyup usbhs_for_each_dfifo macro Current usbhs_for_each_dfifo macro will read out-of-array's memory after last loop operation. It was not good C language operation, and the binary which was compiled by (at least) gcc 4.8.1 is broken. This patch is based on 925403f425a4a9c503f2fc295652647b1eb10d82 (usb: renesas_usbhs: tidyup original usbhsx_for_each_xxx macro) Signed-off-by: Kuninori Morimoto Tested-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h index 04d3f8abad9e5f..c7d9b86d51bf84 100644 --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h @@ -44,10 +44,11 @@ struct usbhs_fifo_info { struct usbhs_fifo dfifo[USBHS_MAX_NUM_DFIFO]; }; #define usbhsf_get_dnfifo(p, n) (&((p)->fifo_info.dfifo[n])) -#define usbhs_for_each_dfifo(priv, dfifo, i) \ - for ((i) = 0, dfifo = usbhsf_get_dnfifo(priv, (i)); \ - ((i) < USBHS_MAX_NUM_DFIFO); \ - (i)++, dfifo = usbhsf_get_dnfifo(priv, (i))) +#define usbhs_for_each_dfifo(priv, dfifo, i) \ + for ((i) = 0; \ + ((i) < USBHS_MAX_NUM_DFIFO) && \ + ((dfifo) = usbhsf_get_dnfifo(priv, (i))); \ + (i)++) struct usbhs_pkt_handle; struct usbhs_pkt { From d72348fb5ca634583bf3f79996cc4b3ef91d9c3a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 23 Apr 2015 16:06:50 +0200 Subject: [PATCH 0336/3798] usb: musb: fix inefficient copy of unaligned buffers Make sure only to copy any actual data rather than the whole buffer, when releasing the temporary buffer used for unaligned non-isochronous transfers. Signed-off-by: Johan Hovold Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_host.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index c3d5fc9dfb5bd5..e1fb5d885c18ce 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2512,6 +2512,7 @@ static void musb_free_temp_buffer(struct urb *urb) { enum dma_data_direction dir; struct musb_temp_buffer *temp; + size_t length; if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) return; @@ -2522,8 +2523,12 @@ static void musb_free_temp_buffer(struct urb *urb) data); if (dir == DMA_FROM_DEVICE) { - memcpy(temp->old_xfer_buffer, temp->data, - urb->transfer_buffer_length); + if (usb_pipeisoc(urb->pipe)) + length = urb->transfer_buffer_length; + else + length = urb->actual_length; + + memcpy(temp->old_xfer_buffer, temp->data, length); } urb->transfer_buffer = temp->old_xfer_buffer; kfree(temp->kmalloc_ptr); From 205845ef70dd01094415bceafbc86a97eb1899a9 Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Tue, 24 Mar 2015 15:09:25 -0500 Subject: [PATCH 0337/3798] usb: musb: only set test mode once The MUSB test mode register can only be set once, otherwise the result is undefined. This prevents the debugfs testmode entry to set the register more than once which causes test failure. Signed-off-by: Bin Liu Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_debugfs.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index 78a283e9ce40b1..04382ec31d3f07 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -191,9 +191,16 @@ static ssize_t musb_test_mode_write(struct file *file, { struct seq_file *s = file->private_data; struct musb *musb = s->private; - u8 test = 0; + u8 test; char buf[18]; + test = musb_readb(musb->mregs, MUSB_TESTMODE); + if (test) { + dev_err(musb->controller, "Error: test mode is already set. " + "Please do USB Bus Reset to start a new test.\n"); + return count; + } + memset(buf, 0x00, sizeof(buf)); if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) From 4e39acab03de8db6881dfd981407b6d3ff62c62d Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Fri, 27 Mar 2015 16:32:18 +0800 Subject: [PATCH 0338/3798] usb: Documentation: gadget-testing: fix parameter for capture channel mask Fix the UAC2 parameter capture channel mask Signed-off-by: Peter Chen Signed-off-by: Felipe Balbi --- Documentation/usb/gadget-testing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/usb/gadget-testing.txt b/Documentation/usb/gadget-testing.txt index f45b2bf4b41dea..7769eee3b1b5ce 100644 --- a/Documentation/usb/gadget-testing.txt +++ b/Documentation/usb/gadget-testing.txt @@ -629,7 +629,7 @@ Function-specific configfs interface The function name to use when creating the function directory is "uac2". The uac2 function provides these attributes in its function directory: - chmask - capture channel mask + c_chmask - capture channel mask c_srate - capture sampling rate c_ssize - capture sample size (bytes) p_chmask - playback channel mask From 232461ffefa145154831ac5388a80ba26a44141b Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Mon, 20 Apr 2015 10:45:38 +0300 Subject: [PATCH 0339/3798] arm64: dts: qcom: Add SPMI PMIC Arbiter node for MSM8916 Add SPMI PMIC Arbiter configuration nodes for MSM8916. Signed-off-by: Ivan T. Ivanov Signed-off-by: Kumar Gala --- arch/arm64/boot/dts/qcom/msm8916.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index f212b8303d04ff..92c96eb2c74cd2 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -192,5 +192,23 @@ status = "disabled"; }; }; + + spmi_bus: spmi@200f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x200f000 0x001000>, + <0x2400000 0x400000>, + <0x2c00000 0x400000>, + <0x3800000 0x200000>, + <0x200a000 0x002100>; + reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; + interrupt-names = "periph_irq"; + interrupts = ; + qcom,ee = <0>; + qcom,channel = <0>; + #address-cells = <2>; + #size-cells = <0>; + interrupt-controller; + #interrupt-cells = <4>; + }; }; }; From 729ee9c4ab8a107de37330b9d1778d8754351862 Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Mon, 20 Apr 2015 10:45:39 +0300 Subject: [PATCH 0340/3798] arm64: dts: qcom: Add 8x16 chipset SPMI PMIC's nodes PM9816 has 2 SPMI devices per physical package. Add PMIC configuration nodes including sub-function device nodes and include them in boards, which are using 8x16 based chipset. PM9816 sub-function devices include: * GPIO block, with 4 pins * MPP block, with 4 pins * Volatage ADC (VADC), with multiple inputs * Thermal sensor device, which is using on chip VADC channel report PMIC die temperature. * Power key device, which is responsible for clean system reboot or shutdown * RTC device Signed-off-by: Ivan T. Ivanov Signed-off-by: Kumar Gala --- arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi | 1 + arch/arm64/boot/dts/qcom/msm8916-mtp.dtsi | 1 + arch/arm64/boot/dts/qcom/pm8916.dtsi | 99 +++++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/pm8916.dtsi diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi index 703a4f16e711ab..58f0055f72a5e9 100644 --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi @@ -12,6 +12,7 @@ */ #include "msm8916.dtsi" +#include "pm8916.dtsi" / { aliases { diff --git a/arch/arm64/boot/dts/qcom/msm8916-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8916-mtp.dtsi index bea871b0df1367..a1aa0b201e926a 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916-mtp.dtsi @@ -12,6 +12,7 @@ */ #include "msm8916.dtsi" +#include "pm8916.dtsi" / { aliases { diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi new file mode 100644 index 00000000000000..b222ece7e3d25a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi @@ -0,0 +1,99 @@ +#include +#include +#include + +&spmi_bus { + + usid0: pm8916@0 { + compatible = "qcom,spmi-pmic"; + reg = <0x0 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + rtc@6000 { + compatible = "qcom,pm8941-rtc"; + reg = <0x6000 0x6100>; + reg-names = "rtc", "alarm"; + interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>; + }; + + pwrkey@800 { + compatible = "qcom,pm8941-pwrkey"; + reg = <0x800>; + interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + bias-pull-up; + }; + + pm8916_gpios: gpios@c000 { + compatible = "qcom,pm8916-gpio"; + reg = <0xc000 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <0 0xc0 0 IRQ_TYPE_NONE>, + <0 0xc1 0 IRQ_TYPE_NONE>, + <0 0xc2 0 IRQ_TYPE_NONE>, + <0 0xc3 0 IRQ_TYPE_NONE>; + }; + + pm8916_mpps: mpps@a000 { + compatible = "qcom,pm8916-mpp"; + reg = <0xa000 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <0 0xa0 0 IRQ_TYPE_NONE>, + <0 0xa1 0 IRQ_TYPE_NONE>, + <0 0xa2 0 IRQ_TYPE_NONE>, + <0 0xa3 0 IRQ_TYPE_NONE>; + }; + + pm8916_temp: temp-alarm@2400 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400 0x100>; + interrupts = <0 0x24 0 IRQ_TYPE_EDGE_RISING>; + io-channels = <&pm8916_vadc VADC_DIE_TEMP>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + + pm8916_vadc: vadc@3100 { + compatible = "qcom,spmi-vadc"; + reg = <0x3100 0x100>; + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + + usb_in { + reg = ; + qcom,pre-scaling = <1 10>; + }; + vph_pwr { + reg = ; + qcom,pre-scaling = <1 3>; + }; + die_temp { + reg = ; + }; + ref_625mv { + reg = ; + }; + ref_1250v { + reg = ; + }; + ref_gnd { + reg = ; + }; + ref_vdd { + reg = ; + }; + }; + }; + + usid1: pm8916@1 { + compatible = "qcom,spmi-pmic"; + reg = <0x1 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + }; +}; From 366655c95330278f2f6bb9cc9cfddfde42a82440 Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Mon, 20 Apr 2015 10:45:40 +0300 Subject: [PATCH 0341/3798] arm64: dts: qcom: Add MSM8916 restart device node Add the restart node so we can reboot the device. Signed-off-by: Ivan T. Ivanov Signed-off-by: Kumar Gala --- arch/arm64/boot/dts/qcom/msm8916.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 92c96eb2c74cd2..7887588e1c2d7d 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -77,6 +77,11 @@ ranges = <0 0 0 0xffffffff>; compatible = "simple-bus"; + restart@4ab000 { + compatible = "qcom,pshold"; + reg = <0x4ab000 0x4>; + }; + pinctrl@1000000 { compatible = "qcom,msm8916-pinctrl"; reg = <0x1000000 0x300000>; From a190a1ce9a51d3edd52de1b721276d780e0906bb Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Mon, 20 Apr 2015 10:45:41 +0300 Subject: [PATCH 0342/3798] arm64: dts: qcom: Add initial set of PMIC and SoC pins for APQ8016 SBC board Add initial device configuration nodes for APQ8016 and PM8916 GPIO's. Signed-off-by: Ivan T. Ivanov Signed-off-by: Kumar Gala --- .../boot/dts/qcom/apq8016-sbc-pmic-pins.dtsi | 30 +++++++++++++++++++ .../boot/dts/qcom/apq8016-sbc-soc-pins.dtsi | 21 +++++++++++++ arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi | 2 ++ arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 +- 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/boot/dts/qcom/apq8016-sbc-pmic-pins.dtsi create mode 100644 arch/arm64/boot/dts/qcom/apq8016-sbc-soc-pins.dtsi diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc-pmic-pins.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc-pmic-pins.dtsi new file mode 100644 index 00000000000000..535532b9287ff9 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc-pmic-pins.dtsi @@ -0,0 +1,30 @@ +#include + +&pm8916_gpios { + + pinctrl-names = "default"; + pinctrl-0 = <&pm8916_gpios_default>; + + pm8916_gpios_default: default { + usb_hub_reset_pm { + pins = "gpio1"; + function = PMIC_GPIO_FUNC_NORMAL; + output-low; + }; + usb_sw_sel_pm { + pins = "gpio2"; + function = PMIC_GPIO_FUNC_NORMAL; + input-disable; + }; + usr_led_3_ctrl { + pins = "gpio3"; + function = PMIC_GPIO_FUNC_NORMAL; + output-low; + }; + usr_led_4_ctrl { + pins = "gpio4"; + function = PMIC_GPIO_FUNC_NORMAL; + output-low; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc-soc-pins.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc-soc-pins.dtsi new file mode 100644 index 00000000000000..5f7023f90df78c --- /dev/null +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc-soc-pins.dtsi @@ -0,0 +1,21 @@ + +#include + +&msmgpio { + + pinctrl-names = "default"; + pinctrl-0 = <&soc_gpios_default>; + + soc_gpios_default: default { + usr_led_1_ctrl_default: usr_led_1_ctrl_default { + pins = "gpio21"; + function = "gpio"; + output-low; + }; + usr_led_2_ctrl_default: usr_led_2_ctrl_default { + pins = "gpio120"; + function = "gpio"; + output-low; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi index 58f0055f72a5e9..98abece6b23309 100644 --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi @@ -13,6 +13,8 @@ #include "msm8916.dtsi" #include "pm8916.dtsi" +#include "apq8016-sbc-soc-pins.dtsi" +#include "apq8016-sbc-pmic-pins.dtsi" / { aliases { diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 7887588e1c2d7d..0f49ebd0aa8b24 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -82,7 +82,7 @@ reg = <0x4ab000 0x4>; }; - pinctrl@1000000 { + msmgpio: pinctrl@1000000 { compatible = "qcom,msm8916-pinctrl"; reg = <0x1000000 0x300000>; interrupts = ; From dc2f8152535132bcec5ce2d473924ad9251b41e7 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 10 Apr 2015 21:42:44 +0100 Subject: [PATCH 0343/3798] ARM: dts: qcom: apq8064 - add RPM regulators support This patch adds rpm node to apq8064 dt as rpm would be used by other devices for regulator support. Signed-off-by: Srinivas Kandagatla Reviewed-by: Bjorn Andersson Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-apq8064.dtsi | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 6c1511263a55de..19629c9c957c23 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -276,6 +276,30 @@ #reset-cells = <1>; }; + l2cc: clock-controller@2011000 { + compatible = "syscon"; + reg = <0x2011000 0x1000>; + }; + + rpm@108000 { + compatible = "qcom,rpm-apq8064"; + reg = <0x108000 0x1000>; + qcom,ipc = <&l2cc 0x8 2>; + + interrupts = , + , + ; + interrupt-names = "ack", "err", "wakeup"; + + regulators { + compatible = "qcom,rpm-pm8921-regulators"; + + pm8921_hdmi_switch: hdmi-switch { + bias-pull-down; + }; + }; + }; + /* Temporary fixed regulator */ vsdcc_fixed: vsdcc-regulator { compatible = "regulator-fixed"; From ad560450d3107940603fdc73ac86b73fe04894cd Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 10 Apr 2015 21:43:14 +0100 Subject: [PATCH 0344/3798] ARM: dts: qcom: apq8064-ifc6410 - Add basic regulators This patch adds support to basic regulators wiredup on IFC6410 board. All these regulators are tested as part of USB, SATA and HDMI. Signed-off-by: Srinivas Kandagatla Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-apq8064-ifc6410.dts | 67 ++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts index e641001ca2a79c..ca2d7ba4e91a8d 100644 --- a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts +++ b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts @@ -23,6 +23,73 @@ }; }; + rpm@108000 { + regulators { + vin_lvs1_3_6-supply = <&pm8921_s4>; + vin_lvs2-supply = <&pm8921_s1>; + vin_lvs4_5_7-supply = <&pm8921_s4>; + + vdd_l1_l2_l12_l18-supply = <&pm8921_s4>; + vdd_l24-supply = <&pm8921_s1>; + vdd_l25-supply = <&pm8921_s1>; + vdd_l26-supply = <&pm8921_s7>; + vdd_l27-supply = <&pm8921_s7>; + vdd_l28-supply = <&pm8921_s7>; + + + /* Buck SMPS */ + pm8921_s1: s1 { + regulator-always-on; + regulator-min-microvolt = <1225000>; + regulator-max-microvolt = <1225000>; + qcom,switch-mode-frequency = <3200000>; + bias-pull-down; + }; + + pm8921_s3: s3 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + qcom,switch-mode-frequency = <4800000>; + }; + + pm8921_s4: s4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + qcom,switch-mode-frequency = <3200000>; + }; + + pm8921_s7: s7 { + regulator-min-microvolt = <1300000>; + regulator-max-microvolt = <1300000>; + qcom,switch-mode-frequency = <3200000>; + }; + + pm8921_l3: l3 { + regulator-min-microvolt = <3050000>; + regulator-max-microvolt = <3300000>; + bias-pull-down; + }; + + pm8921_l4: l4 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1800000>; + bias-pull-down; + }; + + pm8921_l6: l6 { + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + bias-pull-down; + }; + + pm8921_l23: l23 { + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <1900000>; + bias-pull-down; + }; + }; + }; + gsbi@12440000 { status = "okay"; qcom,mode = ; From 223280b10ef13af2def3a5473a7386c4ba4e204f Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 10 Apr 2015 21:43:30 +0100 Subject: [PATCH 0345/3798] ARM: dts: qcom: apq8064 - Add usb host support. This patch adds device tree nodes to support two usb hosts on APQ8064 SOC. Signed-off-by: Srinivas Kandagatla Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-apq8064-ifc6410.dts | 22 ++++++++++ arch/arm/boot/dts/qcom-apq8064.dtsi | 47 ++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts index ca2d7ba4e91a8d..8fe60fcd6203f7 100644 --- a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts +++ b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts @@ -116,6 +116,28 @@ }; }; + usb3_phy: phy@12520000 { + status = "okay"; + vddcx-supply = <&pm8921_s3>; + v3p3-supply = <&pm8921_l3>; + v1p8-supply = <&pm8921_l23>; + }; + + usb4_phy: phy@12530000 { + status = "okay"; + vddcx-supply = <&pm8921_s3>; + v3p3-supply = <&pm8921_l3>; + v1p8-supply = <&pm8921_l23>; + }; + + usb3: usb@12520000 { + status = "okay"; + }; + + usb4: usb@12530000 { + status = "okay"; + }; + amba { /* eMMC */ sdcc1: sdcc@12400000 { diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 19629c9c957c23..99d8e0708c2a67 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -2,6 +2,7 @@ #include "skeleton.dtsi" #include +#include #include #include #include @@ -300,6 +301,52 @@ }; }; + usb3_phy: phy@12520000 { + compatible = "qcom,usb-otg-ci"; + reg = <0x12520000 0x400>; + interrupts = ; + status = "disabled"; + dr_mode = "host"; + + clocks = <&gcc USB_HS3_XCVR_CLK>, + <&gcc USB_HS3_H_CLK>; + clock-names = "core", "iface"; + + resets = <&gcc USB_HS3_RESET>; + reset-names = "link"; + }; + + usb4_phy: phy@12530000 { + compatible = "qcom,usb-otg-ci"; + reg = <0x12530000 0x400>; + interrupts = ; + status = "disabled"; + dr_mode = "host"; + + clocks = <&gcc USB_HS4_XCVR_CLK>, + <&gcc USB_HS4_H_CLK>; + clock-names = "core", "iface"; + + resets = <&gcc USB_HS4_RESET>; + reset-names = "link"; + }; + + usb3: usb@12520000 { + compatible = "qcom,ehci-host"; + reg = <0x12520000 0x400>; + interrupts = ; + status = "disabled"; + usb-phy = <&usb3_phy>; + }; + + usb4: usb@12530000 { + compatible = "qcom,ehci-host"; + reg = <0x12530000 0x400>; + interrupts = ; + status = "disabled"; + usb-phy = <&usb4_phy>; + }; + /* Temporary fixed regulator */ vsdcc_fixed: vsdcc-regulator { compatible = "regulator-fixed"; From ea986611dca33de16519d3cd84d8e151cfc723cf Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 10 Apr 2015 21:43:42 +0100 Subject: [PATCH 0346/3798] ARM: dts: qcom: apq8064 - Add USB OTG support This patch adds USB OTG support on USB1 of APQ8064 SOC. Tested on IFC6410 with ethernet gadget. Signed-off-by: Srinivas Kandagatla Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-apq8064-ifc6410.dts | 17 ++++++++++++ arch/arm/boot/dts/qcom-apq8064.dtsi | 32 ++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts index 8fe60fcd6203f7..122bf34d752e5e 100644 --- a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts +++ b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts @@ -116,6 +116,14 @@ }; }; + /* OTG */ + usb1_phy: phy@12500000 { + status = "okay"; + vddcx-supply = <&pm8921_s3>; + v3p3-supply = <&pm8921_l3>; + v1p8-supply = <&pm8921_l4>; + }; + usb3_phy: phy@12520000 { status = "okay"; vddcx-supply = <&pm8921_s3>; @@ -130,6 +138,15 @@ v1p8-supply = <&pm8921_l23>; }; + gadget1: gadget@12500000 { + status = "okay"; + }; + + /* OTG */ + usb1: usb@12500000 { + status = "okay"; + }; + usb3: usb@12520000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 99d8e0708c2a67..5aac9a58b02b27 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -301,6 +301,21 @@ }; }; + usb1_phy: phy@12500000 { + compatible = "qcom,usb-otg-ci"; + reg = <0x12500000 0x400>; + interrupts = ; + status = "disabled"; + dr_mode = "host"; + + clocks = <&gcc USB_HS1_XCVR_CLK>, + <&gcc USB_HS1_H_CLK>; + clock-names = "core", "iface"; + + resets = <&gcc USB_HS1_RESET>; + reset-names = "link"; + }; + usb3_phy: phy@12520000 { compatible = "qcom,usb-otg-ci"; reg = <0x12520000 0x400>; @@ -331,6 +346,23 @@ reset-names = "link"; }; + gadget1: gadget@12500000 { + compatible = "qcom,ci-hdrc"; + reg = <0x12500000 0x400>; + status = "disabled"; + dr_mode = "peripheral"; + interrupts = ; + usb-phy = <&usb1_phy>; + }; + + usb1: usb@12500000 { + compatible = "qcom,ehci-host"; + reg = <0x12500000 0x400>; + interrupts = ; + status = "disabled"; + usb-phy = <&usb1_phy>; + }; + usb3: usb@12520000 { compatible = "qcom,ehci-host"; reg = <0x12520000 0x400>; From e629335f6c8d9a6a0784e0a305c3c74d910b6e4d Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 10 Apr 2015 21:43:56 +0100 Subject: [PATCH 0347/3798] ARM: dts: qcom: apq8064 - Add SATA controller support This patch adds AHCI based SATA controller support to APQ8064. Tested on IFC6410 board. Signed-off-by: Srinivas Kandagatla Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-apq8064-ifc6410.dts | 9 ++++++ arch/arm/boot/dts/qcom-apq8064.dtsi | 35 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts index 122bf34d752e5e..3d96cb85e2a2e6 100644 --- a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts +++ b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts @@ -116,6 +116,15 @@ }; }; + sata_phy0: phy@1b400000 { + status = "okay"; + }; + + sata0: sata@29000000 { + status = "okay"; + target-supply = <&pm8921_s4>; + }; + /* OTG */ usb1_phy: phy@12500000 { status = "okay"; diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 5aac9a58b02b27..1f900c755482a7 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -379,6 +379,41 @@ usb-phy = <&usb4_phy>; }; + sata_phy0: phy@1b400000 { + compatible = "qcom,apq8064-sata-phy"; + status = "disabled"; + reg = <0x1b400000 0x200>; + reg-names = "phy_mem"; + clocks = <&gcc SATA_PHY_CFG_CLK>; + clock-names = "cfg"; + #phy-cells = <0>; + }; + + sata0: sata@29000000 { + compatible = "generic-ahci"; + status = "disabled"; + reg = <0x29000000 0x180>; + interrupts = ; + + clocks = <&gcc SFAB_SATA_S_H_CLK>, + <&gcc SATA_H_CLK>, + <&gcc SATA_A_CLK>, + <&gcc SATA_RXOOB_CLK>, + <&gcc SATA_PMALIVE_CLK>; + clock-names = "slave_iface", + "iface", + "bus", + "rxoob", + "core_pmalive"; + + assigned-clocks = <&gcc SATA_RXOOB_CLK>, + <&gcc SATA_PMALIVE_CLK>; + assigned-clock-rates = <100000000>, <100000000>; + + phys = <&sata_phy0>; + phy-names = "sata-phy"; + }; + /* Temporary fixed regulator */ vsdcc_fixed: vsdcc-regulator { compatible = "regulator-fixed"; From 1a621d3568a8f797f9aa082c2f8007fb6fffe016 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 10 Apr 2015 21:44:05 +0100 Subject: [PATCH 0348/3798] ARM: dts: qcom: apq8064-cm-qs600 - Add basic regulators This patch adds basic regulator support for USB and HDMI. Signed-off-by: Srinivas Kandagatla Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts | 61 +++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts b/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts index 5d75666f7f6c95..142885d86d59ef 100644 --- a/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts +++ b/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts @@ -14,6 +14,67 @@ }; }; + rpm@108000 { + regulators { + vin_lvs1_3_6-supply = <&pm8921_s4>; + vin_lvs2-supply = <&pm8921_s1>; + vin_lvs4_5_7-supply = <&pm8921_s4>; + + vdd_l1_l2_l12_l18-supply = <&pm8921_s4>; + vdd_l24-supply = <&pm8921_s1>; + vdd_l25-supply = <&pm8921_s1>; + vdd_l26-supply = <&pm8921_s7>; + vdd_l27-supply = <&pm8921_s7>; + vdd_l28-supply = <&pm8921_s7>; + + + /* Buck SMPS */ + pm8921_s1: s1 { + regulator-always-on; + regulator-min-microvolt = <1225000>; + regulator-max-microvolt = <1225000>; + qcom,switch-mode-frequency = <3200000>; + bias-pull-down; + }; + + pm8921_s3: s3 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + qcom,switch-mode-frequency = <4800000>; + }; + + pm8921_s4: s4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + qcom,switch-mode-frequency = <3200000>; + }; + + pm8921_s7: s7 { + regulator-min-microvolt = <1300000>; + regulator-max-microvolt = <1300000>; + qcom,switch-mode-frequency = <3200000>; + }; + + pm8921_l3: l3 { + regulator-min-microvolt = <3050000>; + regulator-max-microvolt = <3300000>; + bias-pull-down; + }; + + pm8921_l4: l4 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1800000>; + bias-pull-down; + }; + + pm8921_l23: l23 { + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <1900000>; + bias-pull-down; + }; + }; + }; + gsbi@12440000 { status = "okay"; qcom,mode = ; From 84db78b8ac5db9023ad3b1177a61994fecf40824 Mon Sep 17 00:00:00 2001 From: Nicolas Dechesne Date: Fri, 10 Apr 2015 21:44:15 +0100 Subject: [PATCH 0349/3798] ARM: dts: qcom: apq8064 - Add usb host support to CM QS-600 This patch adds device tree nodes to support two usb hosts on Compulab QS600 board. Signed-off-by: Srinivas Kandagatla [Srinivas Kandagatla: fixed up regulators and status properties] Signed-off-by: Nicolas Dechesne Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts b/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts index 142885d86d59ef..4eedfe445e3e69 100644 --- a/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts +++ b/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts @@ -101,6 +101,28 @@ }; }; + usb3_phy: phy@12520000 { + status = "okay"; + vddcx-supply = <&pm8921_s3>; + v3p3-supply = <&pm8921_l3>; + v1p8-supply = <&pm8921_l23>; + }; + + usb4_phy: phy@12530000 { + status = "okay"; + vddcx-supply = <&pm8921_s3>; + v3p3-supply = <&pm8921_l3>; + v1p8-supply = <&pm8921_l23>; + }; + + usb3: usb@12520000 { + status = "okay"; + }; + + usb4: usb@12530000 { + status = "okay"; + }; + amba { /* eMMC */ sdcc1: sdcc@12400000 { From 08372ce9d780cce9cc4380d3639ec28752d44425 Mon Sep 17 00:00:00 2001 From: Nicolas Dechesne Date: Fri, 10 Apr 2015 21:44:23 +0100 Subject: [PATCH 0350/3798] ARM: dts: qcom: apq8064 - Add USB OTG support for CM QS-600 This patch adds USB OTG support on USB1 for Compulab QS-600 Board. Signed-off-by: Srinivas Kandagatla [Srinivas Kandagatla: fixed up regulators and status properties] Signed-off-by: Nicolas Dechesne Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts b/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts index 4eedfe445e3e69..71512b3ca4443c 100644 --- a/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts +++ b/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts @@ -101,6 +101,14 @@ }; }; + /* OTG */ + usb1_phy: phy@12500000 { + status = "okay"; + vddcx-supply = <&pm8921_s3>; + v3p3-supply = <&pm8921_l3>; + v1p8-supply = <&pm8921_l4>; + }; + usb3_phy: phy@12520000 { status = "okay"; vddcx-supply = <&pm8921_s3>; @@ -115,6 +123,15 @@ v1p8-supply = <&pm8921_l23>; }; + gadget1: gadget@12500000 { + status = "ok"; + }; + + /* OTG */ + usb1: usb@12500000 { + status = "ok"; + }; + usb3: usb@12520000 { status = "okay"; }; From d5d4654e9eee81aafae7a4c0aa393d5f1a0882d1 Mon Sep 17 00:00:00 2001 From: Pramod Gurav Date: Fri, 10 Apr 2015 21:44:31 +0100 Subject: [PATCH 0351/3798] ARM: dts: qcom: apq8064-ifc6410 - Add DT alias for serial port Define an alias for serial port present on ifc6410 which is used as console. Signed-off-by: Pramod Gurav Signed-off-by: Srinivas Kandagatla [Srinivas Kandagatla: renamed the serial0 label appropriately] Reviewed-by: Bjorn Andersson Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-apq8064-ifc6410.dts | 4 ++++ arch/arm/boot/dts/qcom-apq8064.dtsi | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts index 3d96cb85e2a2e6..528cb314236e1e 100644 --- a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts +++ b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts @@ -5,6 +5,10 @@ model = "Qualcomm APQ8064/IFC6410"; compatible = "qcom,apq8064-ifc6410", "qcom,apq8064"; + aliases { + serial0 = &gsbi7_serial; + }; + soc { pinctrl@800000 { i2c1_pins: i2c1 { diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 1f900c755482a7..93de48ac0aa566 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -236,10 +236,9 @@ #address-cells = <1>; #size-cells = <1>; ranges; - syscon-tcsr = <&tcsr>; - serial@16640000 { + gsbi7_serial: serial@16640000 { compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; reg = <0x16640000 0x1000>, <0x16600000 0x1000>; From bc0d3076635cc6c7b4c715f676ed1526eed0399d Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 10 Apr 2015 21:44:40 +0100 Subject: [PATCH 0352/3798] ARM: dts: qcom: apq8064 - Move i2c1 pinctrl to apq8064.dtsi I2C1 pinctrl is not really specific to a board, moving to SOC dtsi would avoid redefining this in every board. Signed-off-by: Srinivas Kandagatla Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-apq8064-ifc6410.dts | 7 ------- arch/arm/boot/dts/qcom-apq8064.dtsi | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts index 528cb314236e1e..f97339abbfaa73 100644 --- a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts +++ b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts @@ -11,13 +11,6 @@ soc { pinctrl@800000 { - i2c1_pins: i2c1 { - mux { - pins = "gpio20", "gpio21"; - function = "gsbi1"; - }; - }; - card_detect: card_detect { mux { pins = "gpio26"; diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 93de48ac0aa566..345ea081c76544 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -113,6 +113,13 @@ function = "ps_hold"; }; }; + + i2c1_pins: i2c1 { + mux { + pins = "gpio20", "gpio21"; + function = "gsbi1"; + }; + }; }; intc: interrupt-controller@2000000 { From 3f62b46be1f7f1fc88401e97e0bbe55ca9d3964a Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 10 Apr 2015 21:44:48 +0100 Subject: [PATCH 0353/3798] ARM: dts: qcom: apq8064 - add i2c3 node for panel. This patch adds i2c3 node which is used for panel control on IFC6410. Signed-off-by: Srinivas Kandagatla Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-apq8064-ifc6410.dts | 10 ++++++++ arch/arm/boot/dts/qcom-apq8064.dtsi | 27 ++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts index f97339abbfaa73..a7c939ba88730b 100644 --- a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts +++ b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts @@ -87,6 +87,16 @@ }; }; + gsbi3: gsbi@16200000 { + status = "okay"; + qcom,mode = ; + i2c3: i2c@16280000 { + status = "okay"; + pinctrl-0 = <&i2c3_pins>; + pinctrl-names = "default"; + }; + }; + gsbi@12440000 { status = "okay"; qcom,mode = ; diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 345ea081c76544..df2061ec630d16 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -120,6 +120,13 @@ function = "gsbi1"; }; }; + + i2c3_pins: i2c3 { + mux { + pins = "gpio8", "gpio9"; + function = "gsbi3"; + }; + }; }; intc: interrupt-controller@2000000 { @@ -233,6 +240,26 @@ }; }; + gsbi3: gsbi@16200000 { + status = "disabled"; + compatible = "qcom,gsbi-v1.0.0"; + reg = <0x16200000 0x100>; + clocks = <&gcc GSBI3_H_CLK>; + clock-names = "iface"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + i2c3: i2c@16280000 { + compatible = "qcom,i2c-qup-v1.1.1"; + reg = <0x16280000 0x1000>; + interrupts = ; + clocks = <&gcc GSBI3_QUP_CLK>, + <&gcc GSBI3_H_CLK>; + clock-names = "core", "iface"; + }; + }; + gsbi7: gsbi@16600000 { status = "disabled"; compatible = "qcom,gsbi-v1.0.0"; From dab8134ca0723d7a6fd009a4af6b602f861eb66a Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Mon, 20 Apr 2015 10:45:35 +0300 Subject: [PATCH 0354/3798] ARM: dts: qcom: Add PM8841 functions device nodes Add configuration nodes for multi purpose pins and thermal sensor devices. Thermal sensor will report PMIC die temperature. Signed-off-by: Ivan T. Ivanov Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-pm8841.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm/boot/dts/qcom-pm8841.dtsi b/arch/arm/boot/dts/qcom-pm8841.dtsi index 73813cc118f9e9..8f1a0b16201739 100644 --- a/arch/arm/boot/dts/qcom-pm8841.dtsi +++ b/arch/arm/boot/dts/qcom-pm8841.dtsi @@ -1,3 +1,4 @@ +#include #include &spmi_bus { @@ -7,6 +8,23 @@ reg = <0x4 SPMI_USID>; #address-cells = <1>; #size-cells = <0>; + + pm8841_mpps: mpps@a000 { + compatible = "qcom,pm8841-mpp"; + reg = <0xa000 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <4 0xa0 0 IRQ_TYPE_NONE>, + <4 0xa1 0 IRQ_TYPE_NONE>, + <4 0xa2 0 IRQ_TYPE_NONE>, + <4 0xa3 0 IRQ_TYPE_NONE>; + }; + + temp-alarm@2400 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400 0x100>; + interrupts = <4 0x24 0 IRQ_TYPE_EDGE_RISING>; + }; }; usid5: pm8841@5 { From 635ecad7553b48a80777d8740e7387808d494a92 Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Mon, 20 Apr 2015 10:45:36 +0300 Subject: [PATCH 0355/3798] ARM: dts: qcom: Add PM8941 functions device nodes Add configuration nodes for following devices: * GPIO block, with 36 pins * MPP block, with 8 pins * Current ADC (IADC) * Volatage ADC (VADC), with multiple inputs * Thermal sensor device, which is using on chip VADC channel report PMIC die temperature * Power key device, which is responsible for clean system reboot or shutdown * White LED device * RTC device Signed-off-by: Ivan T. Ivanov Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-pm8941.dtsi | 133 ++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/qcom-pm8941.dtsi b/arch/arm/boot/dts/qcom-pm8941.dtsi index 24c5088acea2a2..aa774e685018a5 100644 --- a/arch/arm/boot/dts/qcom-pm8941.dtsi +++ b/arch/arm/boot/dts/qcom-pm8941.dtsi @@ -1,3 +1,5 @@ +#include +#include #include &spmi_bus { @@ -7,12 +9,141 @@ reg = <0x0 SPMI_USID>; #address-cells = <1>; #size-cells = <0>; + + rtc@6000 { + compatible = "qcom,pm8941-rtc"; + reg = <0x6000 0x100>, + <0x6100 0x100>; + reg-names = "rtc", "alarm"; + interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>; + }; + + pwrkey@800 { + compatible = "qcom,pm8941-pwrkey"; + reg = <0x800 0x100>; + interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + bias-pull-up; + }; + + pm8941_gpios: gpios@c000 { + compatible = "qcom,pm8941-gpio"; + reg = <0xc000 0x2400>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <0 0xc0 0 IRQ_TYPE_NONE>, + <0 0xc1 0 IRQ_TYPE_NONE>, + <0 0xc2 0 IRQ_TYPE_NONE>, + <0 0xc3 0 IRQ_TYPE_NONE>, + <0 0xc4 0 IRQ_TYPE_NONE>, + <0 0xc5 0 IRQ_TYPE_NONE>, + <0 0xc6 0 IRQ_TYPE_NONE>, + <0 0xc7 0 IRQ_TYPE_NONE>, + <0 0xc8 0 IRQ_TYPE_NONE>, + <0 0xc9 0 IRQ_TYPE_NONE>, + <0 0xca 0 IRQ_TYPE_NONE>, + <0 0xcb 0 IRQ_TYPE_NONE>, + <0 0xcc 0 IRQ_TYPE_NONE>, + <0 0xcd 0 IRQ_TYPE_NONE>, + <0 0xce 0 IRQ_TYPE_NONE>, + <0 0xcf 0 IRQ_TYPE_NONE>, + <0 0xd0 0 IRQ_TYPE_NONE>, + <0 0xd1 0 IRQ_TYPE_NONE>, + <0 0xd2 0 IRQ_TYPE_NONE>, + <0 0xd3 0 IRQ_TYPE_NONE>, + <0 0xd4 0 IRQ_TYPE_NONE>, + <0 0xd5 0 IRQ_TYPE_NONE>, + <0 0xd6 0 IRQ_TYPE_NONE>, + <0 0xd7 0 IRQ_TYPE_NONE>, + <0 0xd8 0 IRQ_TYPE_NONE>, + <0 0xd9 0 IRQ_TYPE_NONE>, + <0 0xda 0 IRQ_TYPE_NONE>, + <0 0xdb 0 IRQ_TYPE_NONE>, + <0 0xdc 0 IRQ_TYPE_NONE>, + <0 0xdd 0 IRQ_TYPE_NONE>, + <0 0xde 0 IRQ_TYPE_NONE>, + <0 0xdf 0 IRQ_TYPE_NONE>, + <0 0xe0 0 IRQ_TYPE_NONE>, + <0 0xe1 0 IRQ_TYPE_NONE>, + <0 0xe2 0 IRQ_TYPE_NONE>, + <0 0xe3 0 IRQ_TYPE_NONE>; + }; + + pm8941_mpps: mpps@a000 { + compatible = "qcom,pm8941-mpp"; + reg = <0xa000 0x800>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <0 0xa0 0 IRQ_TYPE_NONE>, + <0 0xa1 0 IRQ_TYPE_NONE>, + <0 0xa2 0 IRQ_TYPE_NONE>, + <0 0xa3 0 IRQ_TYPE_NONE>, + <0 0xa4 0 IRQ_TYPE_NONE>, + <0 0xa5 0 IRQ_TYPE_NONE>, + <0 0xa6 0 IRQ_TYPE_NONE>, + <0 0xa7 0 IRQ_TYPE_NONE>; + }; + + pm8941_temp: temp-alarm@2400 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400 0x100>; + interrupts = <0 0x24 0 IRQ_TYPE_EDGE_RISING>; + io-channels = <&pm8941_vadc VADC_DIE_TEMP>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + + pm8941_vadc: vadc@3100 { + compatible = "qcom,spmi-vadc"; + reg = <0x3100 0x100>; + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + + die_temp { + reg = ; + }; + ref_625mv { + reg = ; + }; + ref_1250v { + reg = ; + }; + ref_gnd { + reg = ; + }; + ref_vdd { + reg = ; + }; + }; + + pm8941_iadc: iadc@3600 { + compatible = "qcom,pm8941-iadc", "qcom,spmi-iadc"; + reg = <0x3600 0x100>, + <0x12f1 0x1>; + interrupts = <0x0 0x36 0x0 IRQ_TYPE_EDGE_RISING>; + qcom,external-resistor-micro-ohms = <10000>; + }; }; usid1: pm8941@1 { - compatible ="qcom,spmi-pmic"; + compatible = "qcom,spmi-pmic"; reg = <0x1 SPMI_USID>; #address-cells = <1>; #size-cells = <0>; + + wled@d800 { + compatible = "qcom,pm8941-wled"; + reg = <0xd800 0x100>; + label = "backlight"; + + qcom,cs-out; + qcom,current-limit = <20>; + qcom,current-boost-limit = <805>; + qcom,switching-freq = <1600>; + qcom,ovp = <29>; + qcom,num-strings = <2>; + }; }; }; From 893475283dc9e2e344ff71912babdf714fc56777 Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Mon, 20 Apr 2015 10:45:37 +0300 Subject: [PATCH 0356/3798] ARM: dts: qcom: Add PMA8084 functions device nodes Add configuration nodes for following devices: * GPIO block, with 22 pins * MPP block, with 8 pins * Volatage ADC (VADC), with multiple inputs * Thermal sensor device, which is using on chip VADC channel report PMIC die temperature. * RTC device Signed-off-by: Ivan T. Ivanov Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-pma8084.dtsi | 92 +++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/arch/arm/boot/dts/qcom-pma8084.dtsi b/arch/arm/boot/dts/qcom-pma8084.dtsi index a5a4fe695a46af..5e240ccc08b705 100644 --- a/arch/arm/boot/dts/qcom-pma8084.dtsi +++ b/arch/arm/boot/dts/qcom-pma8084.dtsi @@ -1,3 +1,5 @@ +#include +#include #include &spmi_bus { @@ -7,6 +9,96 @@ reg = <0x0 SPMI_USID>; #address-cells = <1>; #size-cells = <0>; + + rtc@6000 { + compatible = "qcom,pm8941-rtc"; + reg = <0x6000 0x100>, + <0x6100 0x100>; + reg-names = "rtc", "alarm"; + interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>; + }; + + pma8084_gpios: gpios@c000 { + compatible = "qcom,pma8084-gpio"; + reg = <0xc000 0x1600>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <0 0xc0 0 IRQ_TYPE_NONE>, + <0 0xc1 0 IRQ_TYPE_NONE>, + <0 0xc2 0 IRQ_TYPE_NONE>, + <0 0xc3 0 IRQ_TYPE_NONE>, + <0 0xc4 0 IRQ_TYPE_NONE>, + <0 0xc5 0 IRQ_TYPE_NONE>, + <0 0xc6 0 IRQ_TYPE_NONE>, + <0 0xc7 0 IRQ_TYPE_NONE>, + <0 0xc8 0 IRQ_TYPE_NONE>, + <0 0xc9 0 IRQ_TYPE_NONE>, + <0 0xca 0 IRQ_TYPE_NONE>, + <0 0xcb 0 IRQ_TYPE_NONE>, + <0 0xcc 0 IRQ_TYPE_NONE>, + <0 0xcd 0 IRQ_TYPE_NONE>, + <0 0xce 0 IRQ_TYPE_NONE>, + <0 0xcf 0 IRQ_TYPE_NONE>, + <0 0xd0 0 IRQ_TYPE_NONE>, + <0 0xd1 0 IRQ_TYPE_NONE>, + <0 0xd2 0 IRQ_TYPE_NONE>, + <0 0xd3 0 IRQ_TYPE_NONE>, + <0 0xd4 0 IRQ_TYPE_NONE>, + <0 0xd5 0 IRQ_TYPE_NONE>; + }; + + pma8084_mpps: mpps@a000 { + compatible = "qcom,pma8084-mpp"; + reg = <0xa000 0x800>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <0 0xa0 0 IRQ_TYPE_NONE>, + <0 0xa1 0 IRQ_TYPE_NONE>, + <0 0xa2 0 IRQ_TYPE_NONE>, + <0 0xa3 0 IRQ_TYPE_NONE>, + <0 0xa4 0 IRQ_TYPE_NONE>, + <0 0xa5 0 IRQ_TYPE_NONE>, + <0 0xa6 0 IRQ_TYPE_NONE>, + <0 0xa7 0 IRQ_TYPE_NONE>; + }; + + pma8084_temp: temp-alarm@2400 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400 0x100>; + interrupts = <0 0x24 0 IRQ_TYPE_EDGE_RISING>; + #thermal-sensor-cells = <0>; + io-channels = <&pma8084_vadc VADC_DIE_TEMP>; + io-channel-names = "thermal"; + }; + + pma8084_vadc: vadc@3100 { + compatible = "qcom,spmi-vadc"; + reg = <0x3100 0x100>; + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + io-channel-ranges; + + die_temp { + reg = ; + }; + ref_625mv { + reg = ; + }; + ref_1250v { + reg = ; + }; + ref_buf_625mv { + reg = ; + }; + ref_gnd { + reg = ; + }; + ref_vdd { + reg = ; + }; + }; }; usid1: pma8084@1 { From b73b31577f70a1d03aee21d0127da44862b7b08e Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 10 Feb 2015 17:06:03 -0800 Subject: [PATCH 0357/3798] ARM: dts: qcom: Add msm8660 PMU node Enable perf events on msm8660 devices by adding the pmu node. Signed-off-by: Stephen Boyd Signed-off-by: Kumar Gala --- arch/arm/boot/dts/qcom-msm8660.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/qcom-msm8660.dtsi b/arch/arm/boot/dts/qcom-msm8660.dtsi index 20bbd19b996ecf..e0b2ce2910e0ae 100644 --- a/arch/arm/boot/dts/qcom-msm8660.dtsi +++ b/arch/arm/boot/dts/qcom-msm8660.dtsi @@ -37,6 +37,11 @@ }; }; + cpu-pmu { + compatible = "qcom,scorpion-mp-pmu"; + interrupts = <1 9 0x304>; + }; + soc: soc { #address-cells = <1>; #size-cells = <1>; From 7ce75bb2c05ef6949ab0b93633e052f46855690d Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Thu, 9 Apr 2015 13:20:41 -0600 Subject: [PATCH 0358/3798] ARM: qcom: Add Subsystem Power Manager (SPM) driver SPM is a hardware block that controls the peripheral logic surrounding the application cores (cpu/l$). When the core executes WFI instruction, the SPM takes over the putting the core in low power state as configured. The wake up for the SPM is an interrupt at the GIC, which then completes the rest of low power mode sequence and brings the core out of low power mode. The SPM has a set of control registers that configure the SPMs individually based on the type of the core and the runtime conditions. SPM is a finite state machine block to which a sequence is provided and it interprets the bytes and executes them in sequence. Each low power mode that the core can enter into is provided to the SPM as a sequence. Configure the SPM to set the core (cpu or L2) into its low power mode, the index of the first command in the sequence is set in the SPM_CTL register. When the core executes ARM wfi instruction, it triggers the SPM state machine to start executing from that index. The SPM state machine waits until the interrupt occurs and starts executing the rest of the sequence until it hits the end of the sequence. The end of the sequence jumps the core out of its low power mode. Add support for an idle driver to set up the SPM to place the core in Standby or Standalone power collapse mode when the core is idle. Based on work by: Mahesh Sivasubramanian , Ai Li , Praveen Chidambaram Original tree available at - git://codeaurora.org/quic/la/kernel/msm-3.10.git Cc: Stephen Boyd Cc: Arnd Bergmann Cc: Kevin Hilman Cc: Daniel Lezcano Signed-off-by: Lina Iyer Reviewed-by: Stephen Boyd Tested-by: Kevin Hilman Acked-by: Kumar Gala Acked-by: Kevin Hilman Signed-off-by: Kumar Gala --- drivers/soc/qcom/Kconfig | 7 + drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/spm.c | 385 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 393 insertions(+) create mode 100644 drivers/soc/qcom/spm.c diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 460b2dba109c8d..5eea374c8fa621 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -10,3 +10,10 @@ config QCOM_GSBI functions for connecting the underlying serial UART, SPI, and I2C devices to the output pins. +config QCOM_PM + bool "Qualcomm Power Management" + depends on ARCH_QCOM && !ARM64 + help + QCOM Platform specific power driver to manage cores and L2 low power + modes. It interface with various system drivers to put the cores in + low power modes. diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 438901257ac1e4..931d385386c535 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o +obj-$(CONFIG_QCOM_PM) += spm.o diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c new file mode 100644 index 00000000000000..b562af816c0a5c --- /dev/null +++ b/drivers/soc/qcom/spm.c @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2014,2015, Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define MAX_PMIC_DATA 2 +#define MAX_SEQ_DATA 64 +#define SPM_CTL_INDEX 0x7f +#define SPM_CTL_INDEX_SHIFT 4 +#define SPM_CTL_EN BIT(0) + +enum pm_sleep_mode { + PM_SLEEP_MODE_STBY, + PM_SLEEP_MODE_RET, + PM_SLEEP_MODE_SPC, + PM_SLEEP_MODE_PC, + PM_SLEEP_MODE_NR, +}; + +enum spm_reg { + SPM_REG_CFG, + SPM_REG_SPM_CTL, + SPM_REG_DLY, + SPM_REG_PMIC_DLY, + SPM_REG_PMIC_DATA_0, + SPM_REG_PMIC_DATA_1, + SPM_REG_VCTL, + SPM_REG_SEQ_ENTRY, + SPM_REG_SPM_STS, + SPM_REG_PMIC_STS, + SPM_REG_NR, +}; + +struct spm_reg_data { + const u8 *reg_offset; + u32 spm_cfg; + u32 spm_dly; + u32 pmic_dly; + u32 pmic_data[MAX_PMIC_DATA]; + u8 seq[MAX_SEQ_DATA]; + u8 start_index[PM_SLEEP_MODE_NR]; +}; + +struct spm_driver_data { + void __iomem *reg_base; + const struct spm_reg_data *reg_data; +}; + +static const u8 spm_reg_offset_v2_1[SPM_REG_NR] = { + [SPM_REG_CFG] = 0x08, + [SPM_REG_SPM_CTL] = 0x30, + [SPM_REG_DLY] = 0x34, + [SPM_REG_SEQ_ENTRY] = 0x80, +}; + +/* SPM register data for 8974, 8084 */ +static const struct spm_reg_data spm_reg_8974_8084_cpu = { + .reg_offset = spm_reg_offset_v2_1, + .spm_cfg = 0x1, + .spm_dly = 0x3C102800, + .seq = { 0x03, 0x0B, 0x0F, 0x00, 0x20, 0x80, 0x10, 0xE8, 0x5B, 0x03, + 0x3B, 0xE8, 0x5B, 0x82, 0x10, 0x0B, 0x30, 0x06, 0x26, 0x30, + 0x0F }, + .start_index[PM_SLEEP_MODE_STBY] = 0, + .start_index[PM_SLEEP_MODE_SPC] = 3, +}; + +static const u8 spm_reg_offset_v1_1[SPM_REG_NR] = { + [SPM_REG_CFG] = 0x08, + [SPM_REG_SPM_CTL] = 0x20, + [SPM_REG_PMIC_DLY] = 0x24, + [SPM_REG_PMIC_DATA_0] = 0x28, + [SPM_REG_PMIC_DATA_1] = 0x2C, + [SPM_REG_SEQ_ENTRY] = 0x80, +}; + +/* SPM register data for 8064 */ +static const struct spm_reg_data spm_reg_8064_cpu = { + .reg_offset = spm_reg_offset_v1_1, + .spm_cfg = 0x1F, + .pmic_dly = 0x02020004, + .pmic_data[0] = 0x0084009C, + .pmic_data[1] = 0x00A4001C, + .seq = { 0x03, 0x0F, 0x00, 0x24, 0x54, 0x10, 0x09, 0x03, 0x01, + 0x10, 0x54, 0x30, 0x0C, 0x24, 0x30, 0x0F }, + .start_index[PM_SLEEP_MODE_STBY] = 0, + .start_index[PM_SLEEP_MODE_SPC] = 2, +}; + +static DEFINE_PER_CPU(struct spm_driver_data *, cpu_spm_drv); + +typedef int (*idle_fn)(int); +static DEFINE_PER_CPU(idle_fn*, qcom_idle_ops); + +static inline void spm_register_write(struct spm_driver_data *drv, + enum spm_reg reg, u32 val) +{ + if (drv->reg_data->reg_offset[reg]) + writel_relaxed(val, drv->reg_base + + drv->reg_data->reg_offset[reg]); +} + +/* Ensure a guaranteed write, before return */ +static inline void spm_register_write_sync(struct spm_driver_data *drv, + enum spm_reg reg, u32 val) +{ + u32 ret; + + if (!drv->reg_data->reg_offset[reg]) + return; + + do { + writel_relaxed(val, drv->reg_base + + drv->reg_data->reg_offset[reg]); + ret = readl_relaxed(drv->reg_base + + drv->reg_data->reg_offset[reg]); + if (ret == val) + break; + cpu_relax(); + } while (1); +} + +static inline u32 spm_register_read(struct spm_driver_data *drv, + enum spm_reg reg) +{ + return readl_relaxed(drv->reg_base + drv->reg_data->reg_offset[reg]); +} + +static void spm_set_low_power_mode(struct spm_driver_data *drv, + enum pm_sleep_mode mode) +{ + u32 start_index; + u32 ctl_val; + + start_index = drv->reg_data->start_index[mode]; + + ctl_val = spm_register_read(drv, SPM_REG_SPM_CTL); + ctl_val &= ~(SPM_CTL_INDEX << SPM_CTL_INDEX_SHIFT); + ctl_val |= start_index << SPM_CTL_INDEX_SHIFT; + ctl_val |= SPM_CTL_EN; + spm_register_write_sync(drv, SPM_REG_SPM_CTL, ctl_val); +} + +static int qcom_pm_collapse(unsigned long int unused) +{ + qcom_scm_cpu_power_down(QCOM_SCM_CPU_PWR_DOWN_L2_ON); + + /* + * Returns here only if there was a pending interrupt and we did not + * power down as a result. + */ + return -1; +} + +static int qcom_cpu_spc(int cpu) +{ + int ret; + struct spm_driver_data *drv = per_cpu(cpu_spm_drv, cpu); + + spm_set_low_power_mode(drv, PM_SLEEP_MODE_SPC); + ret = cpu_suspend(0, qcom_pm_collapse); + /* + * ARM common code executes WFI without calling into our driver and + * if the SPM mode is not reset, then we may accidently power down the + * cpu when we intended only to gate the cpu clock. + * Ensure the state is set to standby before returning. + */ + spm_set_low_power_mode(drv, PM_SLEEP_MODE_STBY); + + return ret; +} + +static int qcom_idle_enter(int cpu, unsigned long index) +{ + return per_cpu(qcom_idle_ops, cpu)[index](cpu); +} + +static const struct of_device_id qcom_idle_state_match[] __initconst = { + { .compatible = "qcom,idle-state-spc", .data = qcom_cpu_spc }, + { }, +}; + +static int __init qcom_cpuidle_init(struct device_node *cpu_node, int cpu) +{ + const struct of_device_id *match_id; + struct device_node *state_node; + int i; + int state_count = 1; + idle_fn idle_fns[CPUIDLE_STATE_MAX]; + idle_fn *fns; + cpumask_t mask; + bool use_scm_power_down = false; + + for (i = 0; ; i++) { + state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); + if (!state_node) + break; + + if (!of_device_is_available(state_node)) + continue; + + if (i == CPUIDLE_STATE_MAX) { + pr_warn("%s: cpuidle states reached max possible\n", + __func__); + break; + } + + match_id = of_match_node(qcom_idle_state_match, state_node); + if (!match_id) + return -ENODEV; + + idle_fns[state_count] = match_id->data; + + /* Check if any of the states allow power down */ + if (match_id->data == qcom_cpu_spc) + use_scm_power_down = true; + + state_count++; + } + + if (state_count == 1) + goto check_spm; + + fns = devm_kcalloc(get_cpu_device(cpu), state_count, sizeof(*fns), + GFP_KERNEL); + if (!fns) + return -ENOMEM; + + for (i = 1; i < state_count; i++) + fns[i] = idle_fns[i]; + + if (use_scm_power_down) { + /* We have atleast one power down mode */ + cpumask_clear(&mask); + cpumask_set_cpu(cpu, &mask); + qcom_scm_set_warm_boot_addr(cpu_resume, &mask); + } + + per_cpu(qcom_idle_ops, cpu) = fns; + + /* + * SPM probe for the cpu should have happened by now, if the + * SPM device does not exist, return -ENXIO to indicate that the + * cpu does not support idle states. + */ +check_spm: + return per_cpu(cpu_spm_drv, cpu) ? 0 : -ENXIO; +} + +static struct cpuidle_ops qcom_cpuidle_ops __initdata = { + .suspend = qcom_idle_enter, + .init = qcom_cpuidle_init, +}; + +CPUIDLE_METHOD_OF_DECLARE(qcom_idle_v1, "qcom,kpss-acc-v1", &qcom_cpuidle_ops); +CPUIDLE_METHOD_OF_DECLARE(qcom_idle_v2, "qcom,kpss-acc-v2", &qcom_cpuidle_ops); + +static struct spm_driver_data *spm_get_drv(struct platform_device *pdev, + int *spm_cpu) +{ + struct spm_driver_data *drv = NULL; + struct device_node *cpu_node, *saw_node; + int cpu; + bool found; + + for_each_possible_cpu(cpu) { + cpu_node = of_cpu_device_node_get(cpu); + if (!cpu_node) + continue; + saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0); + found = (saw_node == pdev->dev.of_node); + of_node_put(saw_node); + of_node_put(cpu_node); + if (found) + break; + } + + if (found) { + drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); + if (drv) + *spm_cpu = cpu; + } + + return drv; +} + +static const struct of_device_id spm_match_table[] = { + { .compatible = "qcom,msm8974-saw2-v2.1-cpu", + .data = &spm_reg_8974_8084_cpu }, + { .compatible = "qcom,apq8084-saw2-v2.1-cpu", + .data = &spm_reg_8974_8084_cpu }, + { .compatible = "qcom,apq8064-saw2-v1.1-cpu", + .data = &spm_reg_8064_cpu }, + { }, +}; + +static int spm_dev_probe(struct platform_device *pdev) +{ + struct spm_driver_data *drv; + struct resource *res; + const struct of_device_id *match_id; + void __iomem *addr; + int cpu; + + drv = spm_get_drv(pdev, &cpu); + if (!drv) + return -EINVAL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + drv->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(drv->reg_base)) + return PTR_ERR(drv->reg_base); + + match_id = of_match_node(spm_match_table, pdev->dev.of_node); + if (!match_id) + return -ENODEV; + + drv->reg_data = match_id->data; + + /* Write the SPM sequences first.. */ + addr = drv->reg_base + drv->reg_data->reg_offset[SPM_REG_SEQ_ENTRY]; + __iowrite32_copy(addr, drv->reg_data->seq, + ARRAY_SIZE(drv->reg_data->seq) / 4); + + /* + * ..and then the control registers. + * On some SoC if the control registers are written first and if the + * CPU was held in reset, the reset signal could trigger the SPM state + * machine, before the sequences are completely written. + */ + spm_register_write(drv, SPM_REG_CFG, drv->reg_data->spm_cfg); + spm_register_write(drv, SPM_REG_DLY, drv->reg_data->spm_dly); + spm_register_write(drv, SPM_REG_PMIC_DLY, drv->reg_data->pmic_dly); + spm_register_write(drv, SPM_REG_PMIC_DATA_0, + drv->reg_data->pmic_data[0]); + spm_register_write(drv, SPM_REG_PMIC_DATA_1, + drv->reg_data->pmic_data[1]); + + /* Set up Standby as the default low power mode */ + spm_set_low_power_mode(drv, PM_SLEEP_MODE_STBY); + + per_cpu(cpu_spm_drv, cpu) = drv; + + return 0; +} + +static struct platform_driver spm_driver = { + .probe = spm_dev_probe, + .driver = { + .name = "saw", + .of_match_table = spm_match_table, + }, +}; +module_platform_driver(spm_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("SAW power controller driver"); +MODULE_ALIAS("platform:saw"); From 50663822618670a1e6ea1dd9912790fd7ed3be0b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 27 Apr 2015 15:55:23 +0200 Subject: [PATCH 0359/3798] ARM: shmobile: r8a7740 dtsi: Fix SCIFB naming The single SCIFB on R-Mobile A1 is called "scifb", not "scifb8". Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7740.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi index 83c1c3ca1b8f14..413590d6c31676 100644 --- a/arch/arm/boot/dts/r8a7740.dtsi +++ b/arch/arm/boot/dts/r8a7740.dtsi @@ -275,7 +275,7 @@ status = "disabled"; }; - scifb8: serial@e6c30000 { + scifb: serial@e6c30000 { compatible = "renesas,scifb-r8a7740", "renesas,scifb"; reg = <0xe6c30000 0x100>; interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>; From dfaac7b7e4015ca2e690c7ea4421aec1405de966 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 27 Apr 2015 15:55:24 +0200 Subject: [PATCH 0360/3798] ARM: shmobile: sh73a0 dtsi: Fix SCIFB naming The single SCIFB on SH-Mobile AG5 is called "scifb", not "scifb8". Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/sh73a0.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi index 45b539ce4d3520..cde61b463b6a6d 100644 --- a/arch/arm/boot/dts/sh73a0.dtsi +++ b/arch/arm/boot/dts/sh73a0.dtsi @@ -376,7 +376,7 @@ status = "disabled"; }; - scifb8: serial@e6c30000 { + scifb: serial@e6c30000 { compatible = "renesas,scifb-sh73a0", "renesas,scifb"; reg = <0xe6c30000 0x100>; interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>; From b97c3c1a0b538a61fb1cab057738ccb64ae51e4d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 23 Apr 2015 16:06:52 +0200 Subject: [PATCH 0361/3798] staging: octeon-usb: fix unaligned isochronous transfers Make sure to copy the whole transfer buffer when releasing the temporary buffer used for unaligned isochronous transfers as the data is not necessarily contiguous in that case. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/octeon-hcd.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 9e5476e352b4b3..cdb0981be2e973 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -499,15 +499,21 @@ static int octeon_alloc_temp_buffer(struct urb *urb, gfp_t mem_flags) static void octeon_free_temp_buffer(struct urb *urb) { struct octeon_temp_buffer *temp; + size_t length; if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) return; temp = container_of(urb->transfer_buffer, struct octeon_temp_buffer, data); - if (usb_urb_dir_in(urb)) - memcpy(temp->orig_buffer, urb->transfer_buffer, - urb->actual_length); + if (usb_urb_dir_in(urb)) { + if (usb_pipeisoc(urb->pipe)) + length = urb->transfer_buffer_length; + else + length = urb->actual_length; + + memcpy(temp->orig_buffer, urb->transfer_buffer, length); + } urb->transfer_buffer = temp->orig_buffer; urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; kfree(temp); From 5a294e5469891d0701183049c4a9678887fa7091 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 8 Apr 2015 19:42:24 +0900 Subject: [PATCH 0362/3798] usb: renesas_usbhs: Revise the binding document about the dma-names Since the DT should describe the hardware (not the driver limitation), This patch revises the binding document about the dma-names to change simple numbering as "ch%d" instead of "tx" and "rx". Also this patch fixes the actual code of renesas_usbhs driver to handle the new dma-names. Signed-off-by: Yoshihiro Shimoda Acked-by: Mark Rutland Acked-by: Geert Uytterhoeven Signed-off-by: Felipe Balbi --- .../devicetree/bindings/usb/renesas_usbhs.txt | 6 ++--- drivers/usb/renesas_usbhs/fifo.c | 24 ++++++++++++------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/renesas_usbhs.txt b/Documentation/devicetree/bindings/usb/renesas_usbhs.txt index dc2a18f0b3a10a..ddbe304beb2122 100644 --- a/Documentation/devicetree/bindings/usb/renesas_usbhs.txt +++ b/Documentation/devicetree/bindings/usb/renesas_usbhs.txt @@ -15,10 +15,8 @@ Optional properties: - phys: phandle + phy specifier pair - phy-names: must be "usb" - dmas: Must contain a list of references to DMA specifiers. - - dma-names : Must contain a list of DMA names: - - tx0 ... tx - - rx0 ... rx - - This means DnFIFO in USBHS module. + - dma-names : named "ch%d", where %d is the channel number ranging from zero + to the number of channels (DnFIFOs) minus one. Example: usbhs: usb@e6590000 { diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 8597cf9cfceb77..bc23b4a2c415fa 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -1227,15 +1227,21 @@ static void usbhsf_dma_init_dt(struct device *dev, struct usbhs_fifo *fifo, { char name[16]; - snprintf(name, sizeof(name), "tx%d", channel); - fifo->tx_chan = dma_request_slave_channel_reason(dev, name); - if (IS_ERR(fifo->tx_chan)) - fifo->tx_chan = NULL; - - snprintf(name, sizeof(name), "rx%d", channel); - fifo->rx_chan = dma_request_slave_channel_reason(dev, name); - if (IS_ERR(fifo->rx_chan)) - fifo->rx_chan = NULL; + /* + * To avoid complex handing for DnFIFOs, the driver uses each + * DnFIFO as TX or RX direction (not bi-direction). + * So, the driver uses odd channels for TX, even channels for RX. + */ + snprintf(name, sizeof(name), "ch%d", channel); + if (channel & 1) { + fifo->tx_chan = dma_request_slave_channel_reason(dev, name); + if (IS_ERR(fifo->tx_chan)) + fifo->tx_chan = NULL; + } else { + fifo->rx_chan = dma_request_slave_channel_reason(dev, name); + if (IS_ERR(fifo->rx_chan)) + fifo->rx_chan = NULL; + } } static void usbhsf_dma_init(struct usbhs_priv *priv, struct usbhs_fifo *fifo, From 591fc116f3302da915bb57d4474a61a5e8884cec Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Thu, 9 Apr 2015 11:34:22 +0300 Subject: [PATCH 0363/3798] usb: phy: msm: Use extcon framework for VBUS and ID detection On recent Qualcomm platforms VBUS and ID lines are not routed to USB PHY LINK controller. Use extcon framework to receive connect and disconnect ID and VBUS notification. Signed-off-by: Ivan T. Ivanov Signed-off-by: Felipe Balbi --- .../devicetree/bindings/usb/msm-hsusb.txt | 7 ++ drivers/usb/phy/Kconfig | 1 + drivers/usb/phy/phy-msm-usb.c | 84 +++++++++++++++++++ include/linux/usb/msm_hsusb.h | 17 ++++ 4 files changed, 109 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt index 2826f2af503a2c..f26bcfac3d8fba 100644 --- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt +++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt @@ -69,6 +69,13 @@ Optional properties: (no, min, max) where each value represents either a voltage in microvolts or a value corresponding to voltage corner. +- extcon: phandles to external connector devices. First phandle + should point to external connector, which provide "USB" + cable events, the second should point to external connector + device, which provide "USB-HOST" cable events. If one of + the external connector devices is not required empty <0> + phandle should be specified. + Example HSUSB OTG controller device node: usb@f9a55000 { diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 2175678e674ebf..811f331892d787 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -141,6 +141,7 @@ config USB_MSM_OTG tristate "Qualcomm on-chip USB OTG controller support" depends on (USB || USB_GADGET) && (ARCH_QCOM || COMPILE_TEST) depends on RESET_CONTROLLER + depends on EXTCON select USB_PHY help Enable this to support the USB OTG transceiver on Qualcomm chips. It diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index c9156beeadef66..ad66c67ce9a57c 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -1436,9 +1436,42 @@ static const struct of_device_id msm_otg_dt_match[] = { }; MODULE_DEVICE_TABLE(of, msm_otg_dt_match); +static int msm_otg_vbus_notifier(struct notifier_block *nb, unsigned long event, + void *ptr) +{ + struct msm_usb_cable *vbus = container_of(nb, struct msm_usb_cable, nb); + struct msm_otg *motg = container_of(vbus, struct msm_otg, vbus); + + if (event) + set_bit(B_SESS_VLD, &motg->inputs); + else + clear_bit(B_SESS_VLD, &motg->inputs); + + schedule_work(&motg->sm_work); + + return NOTIFY_DONE; +} + +static int msm_otg_id_notifier(struct notifier_block *nb, unsigned long event, + void *ptr) +{ + struct msm_usb_cable *id = container_of(nb, struct msm_usb_cable, nb); + struct msm_otg *motg = container_of(id, struct msm_otg, id); + + if (event) + clear_bit(ID, &motg->inputs); + else + set_bit(ID, &motg->inputs); + + schedule_work(&motg->sm_work); + + return NOTIFY_DONE; +} + static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) { struct msm_otg_platform_data *pdata; + struct extcon_dev *ext_id, *ext_vbus; const struct of_device_id *id; struct device_node *node = pdev->dev.of_node; struct property *prop; @@ -1487,6 +1520,52 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) motg->vdd_levels[VDD_LEVEL_MAX] = tmp[VDD_LEVEL_MAX]; } + ext_id = ERR_PTR(-ENODEV); + ext_vbus = ERR_PTR(-ENODEV); + if (of_property_read_bool(node, "extcon")) { + + /* Each one of them is not mandatory */ + ext_vbus = extcon_get_edev_by_phandle(&pdev->dev, 0); + if (IS_ERR(ext_vbus) && PTR_ERR(ext_vbus) != -ENODEV) + return PTR_ERR(ext_vbus); + + ext_id = extcon_get_edev_by_phandle(&pdev->dev, 1); + if (IS_ERR(ext_id) && PTR_ERR(ext_id) != -ENODEV) + return PTR_ERR(ext_id); + } + + if (!IS_ERR(ext_vbus)) { + motg->vbus.nb.notifier_call = msm_otg_vbus_notifier; + ret = extcon_register_interest(&motg->vbus.conn, ext_vbus->name, + "USB", &motg->vbus.nb); + if (ret < 0) { + dev_err(&pdev->dev, "register VBUS notifier failed\n"); + return ret; + } + + ret = extcon_get_cable_state(ext_vbus, "USB"); + if (ret) + set_bit(B_SESS_VLD, &motg->inputs); + else + clear_bit(B_SESS_VLD, &motg->inputs); + } + + if (!IS_ERR(ext_id)) { + motg->id.nb.notifier_call = msm_otg_id_notifier; + ret = extcon_register_interest(&motg->id.conn, ext_id->name, + "USB-HOST", &motg->id.nb); + if (ret < 0) { + dev_err(&pdev->dev, "register ID notifier failed\n"); + return ret; + } + + ret = extcon_get_cable_state(ext_id, "USB-HOST"); + if (ret) + clear_bit(ID, &motg->inputs); + else + set_bit(ID, &motg->inputs); + } + prop = of_find_property(node, "qcom,phy-init-sequence", &len); if (!prop || !len) return 0; @@ -1700,6 +1779,11 @@ static int msm_otg_remove(struct platform_device *pdev) if (phy->otg->host || phy->otg->gadget) return -EBUSY; + if (motg->id.conn.edev) + extcon_unregister_interest(&motg->id.conn); + if (motg->vbus.conn.edev) + extcon_unregister_interest(&motg->vbus.conn); + msm_otg_debugfs_cleanup(); cancel_delayed_work_sync(&motg->chg_work); cancel_work_sync(&motg->sm_work); diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index 7dbecf9a46561f..c4d956e50d09c0 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -18,6 +18,7 @@ #ifndef __ASM_ARCH_MSM_HSUSB_H #define __ASM_ARCH_MSM_HSUSB_H +#include #include #include #include @@ -119,6 +120,17 @@ struct msm_otg_platform_data { void (*setup_gpio)(enum usb_otg_state state); }; +/** + * struct msm_usb_cable - structure for exteternal connector cable + * state tracking + * @nb: hold event notification callback + * @conn: used for notification registration + */ +struct msm_usb_cable { + struct notifier_block nb; + struct extcon_specific_cable_nb conn; +}; + /** * struct msm_otg: OTG driver data. Shared by HCD and DCD. * @otg: USB OTG Transceiver structure. @@ -138,6 +150,8 @@ struct msm_otg_platform_data { * @chg_type: The type of charger attached. * @dcd_retires: The retry count used to track Data contact * detection process. + * @vbus: VBUS signal state trakining, using extcon framework + * @id: ID signal state trakining, using extcon framework */ struct msm_otg { struct usb_phy phy; @@ -166,6 +180,9 @@ struct msm_otg { struct reset_control *phy_rst; struct reset_control *link_rst; int vdd_levels[3]; + + struct msm_usb_cable vbus; + struct msm_usb_cable id; }; #endif From 44e42ae3a398b559c768b9b3c324d72b0b0b4479 Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Thu, 9 Apr 2015 11:34:33 +0300 Subject: [PATCH 0364/3798] usb: phy: msm: Manual PHY and LINK controller VBUS change notification VBUS is not routed to USB PHY on recent Qualcomm platforms. USB controller must see VBUS in order to pull-up DP when setting RS bit. Henc configure USB PHY and LINK registers sense VBUS and enable manual pullup on D+ line. Cc: Vamsi Krishna Cc: Mayank Rana Signed-off-by: Ivan T. Ivanov Signed-off-by: Felipe Balbi --- .../devicetree/bindings/usb/msm-hsusb.txt | 4 +++ drivers/usb/phy/phy-msm-usb.c | 26 +++++++++++++++++++ include/linux/usb/msm_hsusb.h | 5 ++++ include/linux/usb/msm_hsusb_hw.h | 9 +++++++ 4 files changed, 44 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt index f26bcfac3d8fba..bd8d9e7530290a 100644 --- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt +++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt @@ -69,6 +69,10 @@ Optional properties: (no, min, max) where each value represents either a voltage in microvolts or a value corresponding to voltage corner. +- qcom,manual-pullup: If present, vbus is not routed to USB controller/phy + and controller driver therefore enables pull-up explicitly + before starting controller using usbcmd run/stop bit. + - extcon: phandles to external connector devices. First phandle should point to external connector, which provide "USB" cable events, the second should point to external connector diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index ad66c67ce9a57c..00c49bb1bd29a8 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -240,8 +240,14 @@ static void ulpi_init(struct msm_otg *motg) static int msm_phy_notify_disconnect(struct usb_phy *phy, enum usb_device_speed speed) { + struct msm_otg *motg = container_of(phy, struct msm_otg, phy); int val; + if (motg->manual_pullup) { + val = ULPI_MISC_A_VBUSVLDEXT | ULPI_MISC_A_VBUSVLDEXTSEL; + usb_phy_io_write(phy, val, ULPI_CLR(ULPI_MISC_A)); + } + /* * Put the transceiver in non-driving mode. Otherwise host * may not detect soft-disconnection. @@ -422,6 +428,24 @@ static int msm_phy_init(struct usb_phy *phy) ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_FALL); } + if (motg->manual_pullup) { + val = ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT; + ulpi_write(phy, val, ULPI_SET(ULPI_MISC_A)); + + val = readl(USB_GENCONFIG_2); + val |= GENCONFIG_2_SESS_VLD_CTRL_EN; + writel(val, USB_GENCONFIG_2); + + val = readl(USB_USBCMD); + val |= USBCMD_SESS_VLD_CTRL; + writel(val, USB_USBCMD); + + val = ulpi_read(phy, ULPI_FUNC_CTRL); + val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; + val |= ULPI_FUNC_CTRL_OPMODE_NORMAL; + ulpi_write(phy, val, ULPI_FUNC_CTRL); + } + if (motg->phy_number) writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2); @@ -1520,6 +1544,8 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) motg->vdd_levels[VDD_LEVEL_MAX] = tmp[VDD_LEVEL_MAX]; } + motg->manual_pullup = of_property_read_bool(node, "qcom,manual-pullup"); + ext_id = ERR_PTR(-ENODEV); ext_vbus = ERR_PTR(-ENODEV); if (of_property_read_bool(node, "extcon")) { diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index c4d956e50d09c0..e55a1504266ec0 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -150,6 +150,9 @@ struct msm_usb_cable { * @chg_type: The type of charger attached. * @dcd_retires: The retry count used to track Data contact * detection process. + * @manual_pullup: true if VBUS is not routed to USB controller/phy + * and controller driver therefore enables pull-up explicitly before + * starting controller using usbcmd run/stop bit. * @vbus: VBUS signal state trakining, using extcon framework * @id: ID signal state trakining, using extcon framework */ @@ -181,6 +184,8 @@ struct msm_otg { struct reset_control *link_rst; int vdd_levels[3]; + bool manual_pullup; + struct msm_usb_cable vbus; struct msm_usb_cable id; }; diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h index a29f6030afb167..e159b39f67a2f4 100644 --- a/include/linux/usb/msm_hsusb_hw.h +++ b/include/linux/usb/msm_hsusb_hw.h @@ -21,6 +21,8 @@ #define USB_AHBBURST (MSM_USB_BASE + 0x0090) #define USB_AHBMODE (MSM_USB_BASE + 0x0098) +#define USB_GENCONFIG_2 (MSM_USB_BASE + 0x00a0) + #define USB_CAPLENGTH (MSM_USB_BASE + 0x0100) /* 8 bit */ #define USB_USBCMD (MSM_USB_BASE + 0x0140) @@ -30,6 +32,9 @@ #define USB_PHY_CTRL (MSM_USB_BASE + 0x0240) #define USB_PHY_CTRL2 (MSM_USB_BASE + 0x0278) +#define GENCONFIG_2_SESS_VLD_CTRL_EN BIT(7) +#define USBCMD_SESS_VLD_CTRL BIT(25) + #define USBCMD_RESET 2 #define USB_USBINTR (MSM_USB_BASE + 0x0148) @@ -50,6 +55,10 @@ #define ULPI_PWR_CLK_MNG_REG 0x88 #define OTG_COMP_DISABLE BIT(0) +#define ULPI_MISC_A 0x96 +#define ULPI_MISC_A_VBUSVLDEXTSEL BIT(1) +#define ULPI_MISC_A_VBUSVLDEXT BIT(0) + #define ASYNC_INTR_CTRL (1 << 29) /* Enable async interrupt */ #define ULPI_STP_CTRL (1 << 30) /* Block communication with PHY */ #define PHY_RETEN (1 << 1) /* PHY retention enable/disable */ From b189a2117223edbe40e0a187ae5c606cbdd6447c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 28 Apr 2015 14:04:07 +0200 Subject: [PATCH 0365/3798] usb: phy: Remove the phy-rcar-gen2-usb driver The phy-rcar-gen2-usb driver, which supports legacy platform data only, is no longer used since commit a483dcbfa21f919c ("ARM: shmobile: lager: Remove legacy board support"). This driver was superseded by the DT-only phy-rcar-gen2 driver, which was introduced in commit 1233f59f745b237d ("phy: Renesas R-Car Gen2 PHY driver"). Signed-off-by: Geert Uytterhoeven Signed-off-by: Felipe Balbi --- drivers/usb/phy/Kconfig | 13 - drivers/usb/phy/Makefile | 1 - drivers/usb/phy/phy-rcar-gen2-usb.c | 246 ------------------ .../linux/platform_data/usb-rcar-gen2-phy.h | 22 -- 4 files changed, 282 deletions(-) delete mode 100644 drivers/usb/phy/phy-rcar-gen2-usb.c delete mode 100644 include/linux/platform_data/usb-rcar-gen2-phy.h diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 811f331892d787..173a5b5d8bc183 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -187,19 +187,6 @@ config USB_RCAR_PHY To compile this driver as a module, choose M here: the module will be called phy-rcar-usb. -config USB_RCAR_GEN2_PHY - tristate "Renesas R-Car Gen2 USB PHY support" - depends on ARCH_R8A7790 || ARCH_R8A7791 || COMPILE_TEST - select USB_PHY - help - Say Y here to add support for the Renesas R-Car Gen2 USB PHY driver. - It is typically used to control internal USB PHY for USBHS, - and to configure shared USB channels 0 and 2. - This driver supports R8A7790 and R8A7791. - - To compile this driver as a module, choose M here: the - module will be called phy-rcar-gen2-usb. - config USB_ULPI bool "Generic ULPI Transceiver Driver" depends on ARM || ARM64 diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 75f2bba58c84c9..e36ab1d46d8b4f 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -23,7 +23,6 @@ obj-$(CONFIG_USB_MSM_OTG) += phy-msm-usb.o obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-usb.o obj-$(CONFIG_USB_RCAR_PHY) += phy-rcar-usb.o -obj-$(CONFIG_USB_RCAR_GEN2_PHY) += phy-rcar-gen2-usb.o obj-$(CONFIG_USB_ULPI) += phy-ulpi.o obj-$(CONFIG_USB_ULPI_VIEWPORT) += phy-ulpi-viewport.o obj-$(CONFIG_KEYSTONE_USB_PHY) += phy-keystone.o diff --git a/drivers/usb/phy/phy-rcar-gen2-usb.c b/drivers/usb/phy/phy-rcar-gen2-usb.c deleted file mode 100644 index f81800b6562a46..00000000000000 --- a/drivers/usb/phy/phy-rcar-gen2-usb.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Renesas R-Car Gen2 USB phy driver - * - * Copyright (C) 2013 Renesas Solutions Corp. - * Copyright (C) 2013 Cogent Embedded, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -struct rcar_gen2_usb_phy_priv { - struct usb_phy phy; - void __iomem *base; - struct clk *clk; - spinlock_t lock; - int usecount; - u32 ugctrl2; -}; - -#define usb_phy_to_priv(p) container_of(p, struct rcar_gen2_usb_phy_priv, phy) - -/* Low Power Status register */ -#define USBHS_LPSTS_REG 0x02 -#define USBHS_LPSTS_SUSPM (1 << 14) - -/* USB General control register */ -#define USBHS_UGCTRL_REG 0x80 -#define USBHS_UGCTRL_CONNECT (1 << 2) -#define USBHS_UGCTRL_PLLRESET (1 << 0) - -/* USB General control register 2 */ -#define USBHS_UGCTRL2_REG 0x84 -#define USBHS_UGCTRL2_USB0_PCI (1 << 4) -#define USBHS_UGCTRL2_USB0_HS (3 << 4) -#define USBHS_UGCTRL2_USB2_PCI (0 << 31) -#define USBHS_UGCTRL2_USB2_SS (1 << 31) - -/* USB General status register */ -#define USBHS_UGSTS_REG 0x88 -#define USBHS_UGSTS_LOCK (1 << 8) - -/* Enable USBHS internal phy */ -static int __rcar_gen2_usbhs_phy_enable(void __iomem *base) -{ - u32 val; - int i; - - /* USBHS PHY power on */ - val = ioread32(base + USBHS_UGCTRL_REG); - val &= ~USBHS_UGCTRL_PLLRESET; - iowrite32(val, base + USBHS_UGCTRL_REG); - - val = ioread16(base + USBHS_LPSTS_REG); - val |= USBHS_LPSTS_SUSPM; - iowrite16(val, base + USBHS_LPSTS_REG); - - for (i = 0; i < 20; i++) { - val = ioread32(base + USBHS_UGSTS_REG); - if ((val & USBHS_UGSTS_LOCK) == USBHS_UGSTS_LOCK) { - val = ioread32(base + USBHS_UGCTRL_REG); - val |= USBHS_UGCTRL_CONNECT; - iowrite32(val, base + USBHS_UGCTRL_REG); - return 0; - } - udelay(1); - } - - /* Timed out waiting for the PLL lock */ - return -ETIMEDOUT; -} - -/* Disable USBHS internal phy */ -static int __rcar_gen2_usbhs_phy_disable(void __iomem *base) -{ - u32 val; - - /* USBHS PHY power off */ - val = ioread32(base + USBHS_UGCTRL_REG); - val &= ~USBHS_UGCTRL_CONNECT; - iowrite32(val, base + USBHS_UGCTRL_REG); - - val = ioread16(base + USBHS_LPSTS_REG); - val &= ~USBHS_LPSTS_SUSPM; - iowrite16(val, base + USBHS_LPSTS_REG); - - val = ioread32(base + USBHS_UGCTRL_REG); - val |= USBHS_UGCTRL_PLLRESET; - iowrite32(val, base + USBHS_UGCTRL_REG); - return 0; -} - -/* Setup USB channels */ -static void __rcar_gen2_usb_phy_init(struct rcar_gen2_usb_phy_priv *priv) -{ - u32 val; - - clk_prepare_enable(priv->clk); - - /* Set USB channels in the USBHS UGCTRL2 register */ - val = ioread32(priv->base + USBHS_UGCTRL2_REG); - val &= ~(USBHS_UGCTRL2_USB0_HS | USBHS_UGCTRL2_USB2_SS); - val |= priv->ugctrl2; - iowrite32(val, priv->base + USBHS_UGCTRL2_REG); -} - -/* Shutdown USB channels */ -static void __rcar_gen2_usb_phy_shutdown(struct rcar_gen2_usb_phy_priv *priv) -{ - __rcar_gen2_usbhs_phy_disable(priv->base); - clk_disable_unprepare(priv->clk); -} - -static int rcar_gen2_usb_phy_set_suspend(struct usb_phy *phy, int suspend) -{ - struct rcar_gen2_usb_phy_priv *priv = usb_phy_to_priv(phy); - unsigned long flags; - int retval; - - spin_lock_irqsave(&priv->lock, flags); - retval = suspend ? __rcar_gen2_usbhs_phy_disable(priv->base) : - __rcar_gen2_usbhs_phy_enable(priv->base); - spin_unlock_irqrestore(&priv->lock, flags); - return retval; -} - -static int rcar_gen2_usb_phy_init(struct usb_phy *phy) -{ - struct rcar_gen2_usb_phy_priv *priv = usb_phy_to_priv(phy); - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - /* - * Enable the clock and setup USB channels - * if it's the first user - */ - if (!priv->usecount++) - __rcar_gen2_usb_phy_init(priv); - spin_unlock_irqrestore(&priv->lock, flags); - return 0; -} - -static void rcar_gen2_usb_phy_shutdown(struct usb_phy *phy) -{ - struct rcar_gen2_usb_phy_priv *priv = usb_phy_to_priv(phy); - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - if (!priv->usecount) { - dev_warn(phy->dev, "Trying to disable phy with 0 usecount\n"); - goto out; - } - - /* Disable everything if it's the last user */ - if (!--priv->usecount) - __rcar_gen2_usb_phy_shutdown(priv); -out: - spin_unlock_irqrestore(&priv->lock, flags); -} - -static int rcar_gen2_usb_phy_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct rcar_gen2_phy_platform_data *pdata; - struct rcar_gen2_usb_phy_priv *priv; - struct resource *res; - void __iomem *base; - struct clk *clk; - int retval; - - pdata = dev_get_platdata(dev); - if (!pdata) { - dev_err(dev, "No platform data\n"); - return -EINVAL; - } - - clk = devm_clk_get(dev, "usbhs"); - if (IS_ERR(clk)) { - dev_err(dev, "Can't get the clock\n"); - return PTR_ERR(clk); - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(dev, res); - if (IS_ERR(base)) - return PTR_ERR(base); - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - spin_lock_init(&priv->lock); - priv->clk = clk; - priv->base = base; - priv->ugctrl2 = pdata->chan0_pci ? - USBHS_UGCTRL2_USB0_PCI : USBHS_UGCTRL2_USB0_HS; - priv->ugctrl2 |= pdata->chan2_pci ? - USBHS_UGCTRL2_USB2_PCI : USBHS_UGCTRL2_USB2_SS; - priv->phy.dev = dev; - priv->phy.label = dev_name(dev); - priv->phy.init = rcar_gen2_usb_phy_init; - priv->phy.shutdown = rcar_gen2_usb_phy_shutdown; - priv->phy.set_suspend = rcar_gen2_usb_phy_set_suspend; - - retval = usb_add_phy_dev(&priv->phy); - if (retval < 0) { - dev_err(dev, "Failed to add USB phy\n"); - return retval; - } - - platform_set_drvdata(pdev, priv); - - return retval; -} - -static int rcar_gen2_usb_phy_remove(struct platform_device *pdev) -{ - struct rcar_gen2_usb_phy_priv *priv = platform_get_drvdata(pdev); - - usb_remove_phy(&priv->phy); - - return 0; -} - -static struct platform_driver rcar_gen2_usb_phy_driver = { - .driver = { - .name = "usb_phy_rcar_gen2", - }, - .probe = rcar_gen2_usb_phy_probe, - .remove = rcar_gen2_usb_phy_remove, -}; - -module_platform_driver(rcar_gen2_usb_phy_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Renesas R-Car Gen2 USB phy"); -MODULE_AUTHOR("Valentine Barshak "); diff --git a/include/linux/platform_data/usb-rcar-gen2-phy.h b/include/linux/platform_data/usb-rcar-gen2-phy.h deleted file mode 100644 index dd3ba46c0d9049..00000000000000 --- a/include/linux/platform_data/usb-rcar-gen2-phy.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2013 Renesas Solutions Corp. - * Copyright (C) 2013 Cogent Embedded, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __USB_RCAR_GEN2_PHY_H -#define __USB_RCAR_GEN2_PHY_H - -#include - -struct rcar_gen2_phy_platform_data { - /* USB channel 0 configuration */ - bool chan0_pci:1; /* true: PCI USB host 0, false: USBHS */ - /* USB channel 2 configuration */ - bool chan2_pci:1; /* true: PCI USB host 2, false: USBSS */ -}; - -#endif From b6a1dfbc7d57409accf213e78db7b059c206be9e Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 11 Mar 2015 16:28:10 -0500 Subject: [PATCH 0366/3798] firmware: qcom: scm: Split out 32-bit specific SCM code Split out the 32-bit SCM implementation into its own file to prep for supporting a 64-bit/ARM64 implementation as well. We create a simple shim to ensure both versions conform to the same interface. Signed-off-by: Kumar Gala --- drivers/firmware/Makefile | 3 +- drivers/firmware/qcom_scm-32.c | 480 +++++++++++++++++++++++++++++++++ drivers/firmware/qcom_scm.c | 442 +----------------------------- drivers/firmware/qcom_scm.h | 38 +++ 4 files changed, 527 insertions(+), 436 deletions(-) create mode 100644 drivers/firmware/qcom_scm-32.c create mode 100644 drivers/firmware/qcom_scm.h diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 3fdd3912709af5..3001f1ae106281 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -12,7 +12,8 @@ obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o obj-$(CONFIG_QCOM_SCM) += qcom_scm.o -CFLAGS_qcom_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) +obj-$(CONFIG_QCOM_SCM) += qcom_scm-32.o +CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ obj-$(CONFIG_EFI) += efi/ diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c new file mode 100644 index 00000000000000..b08b822ebafa87 --- /dev/null +++ b/drivers/firmware/qcom_scm-32.c @@ -0,0 +1,480 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * Copyright (C) 2015 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "qcom_scm.h" + +#define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00 +#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01 +#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08 +#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20 + +#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04 +#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02 +#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10 +#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40 + +struct qcom_scm_entry { + int flag; + void *entry; +}; + +static struct qcom_scm_entry qcom_scm_wb[] = { + { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 }, + { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 }, + { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 }, + { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 }, +}; + +static DEFINE_MUTEX(qcom_scm_lock); + +/** + * struct qcom_scm_command - one SCM command buffer + * @len: total available memory for command and response + * @buf_offset: start of command buffer + * @resp_hdr_offset: start of response buffer + * @id: command to be executed + * @buf: buffer returned from qcom_scm_get_command_buffer() + * + * An SCM command is laid out in memory as follows: + * + * ------------------- <--- struct qcom_scm_command + * | command header | + * ------------------- <--- qcom_scm_get_command_buffer() + * | command buffer | + * ------------------- <--- struct qcom_scm_response and + * | response header | qcom_scm_command_to_response() + * ------------------- <--- qcom_scm_get_response_buffer() + * | response buffer | + * ------------------- + * + * There can be arbitrary padding between the headers and buffers so + * you should always use the appropriate qcom_scm_get_*_buffer() routines + * to access the buffers in a safe manner. + */ +struct qcom_scm_command { + __le32 len; + __le32 buf_offset; + __le32 resp_hdr_offset; + __le32 id; + __le32 buf[0]; +}; + +/** + * struct qcom_scm_response - one SCM response buffer + * @len: total available memory for response + * @buf_offset: start of response data relative to start of qcom_scm_response + * @is_complete: indicates if the command has finished processing + */ +struct qcom_scm_response { + __le32 len; + __le32 buf_offset; + __le32 is_complete; +}; + +/** + * alloc_qcom_scm_command() - Allocate an SCM command + * @cmd_size: size of the command buffer + * @resp_size: size of the response buffer + * + * Allocate an SCM command, including enough room for the command + * and response headers as well as the command and response buffers. + * + * Returns a valid &qcom_scm_command on success or %NULL if the allocation fails. + */ +static struct qcom_scm_command *alloc_qcom_scm_command(size_t cmd_size, size_t resp_size) +{ + struct qcom_scm_command *cmd; + size_t len = sizeof(*cmd) + sizeof(struct qcom_scm_response) + cmd_size + + resp_size; + u32 offset; + + cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL); + if (cmd) { + cmd->len = cpu_to_le32(len); + offset = offsetof(struct qcom_scm_command, buf); + cmd->buf_offset = cpu_to_le32(offset); + cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size); + } + return cmd; +} + +/** + * free_qcom_scm_command() - Free an SCM command + * @cmd: command to free + * + * Free an SCM command. + */ +static inline void free_qcom_scm_command(struct qcom_scm_command *cmd) +{ + kfree(cmd); +} + +/** + * qcom_scm_command_to_response() - Get a pointer to a qcom_scm_response + * @cmd: command + * + * Returns a pointer to a response for a command. + */ +static inline struct qcom_scm_response *qcom_scm_command_to_response( + const struct qcom_scm_command *cmd) +{ + return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset); +} + +/** + * qcom_scm_get_command_buffer() - Get a pointer to a command buffer + * @cmd: command + * + * Returns a pointer to the command buffer of a command. + */ +static inline void *qcom_scm_get_command_buffer(const struct qcom_scm_command *cmd) +{ + return (void *)cmd->buf; +} + +/** + * qcom_scm_get_response_buffer() - Get a pointer to a response buffer + * @rsp: response + * + * Returns a pointer to a response buffer of a response. + */ +static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response *rsp) +{ + return (void *)rsp + le32_to_cpu(rsp->buf_offset); +} + +static int qcom_scm_remap_error(int err) +{ + pr_err("qcom_scm_call failed with error code %d\n", err); + switch (err) { + case QCOM_SCM_ERROR: + return -EIO; + case QCOM_SCM_EINVAL_ADDR: + case QCOM_SCM_EINVAL_ARG: + return -EINVAL; + case QCOM_SCM_EOPNOTSUPP: + return -EOPNOTSUPP; + case QCOM_SCM_ENOMEM: + return -ENOMEM; + } + return -EINVAL; +} + +static u32 smc(u32 cmd_addr) +{ + int context_id; + register u32 r0 asm("r0") = 1; + register u32 r1 asm("r1") = (u32)&context_id; + register u32 r2 asm("r2") = cmd_addr; + do { + asm volatile( + __asmeq("%0", "r0") + __asmeq("%1", "r0") + __asmeq("%2", "r1") + __asmeq("%3", "r2") +#ifdef REQUIRES_SEC + ".arch_extension sec\n" +#endif + "smc #0 @ switch to secure world\n" + : "=r" (r0) + : "r" (r0), "r" (r1), "r" (r2) + : "r3"); + } while (r0 == QCOM_SCM_INTERRUPTED); + + return r0; +} + +static int __qcom_scm_call(const struct qcom_scm_command *cmd) +{ + int ret; + u32 cmd_addr = virt_to_phys(cmd); + + /* + * Flush the command buffer so that the secure world sees + * the correct data. + */ + __cpuc_flush_dcache_area((void *)cmd, cmd->len); + outer_flush_range(cmd_addr, cmd_addr + cmd->len); + + ret = smc(cmd_addr); + if (ret < 0) + ret = qcom_scm_remap_error(ret); + + return ret; +} + +static void qcom_scm_inv_range(unsigned long start, unsigned long end) +{ + u32 cacheline_size, ctr; + + asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr)); + cacheline_size = 4 << ((ctr >> 16) & 0xf); + + start = round_down(start, cacheline_size); + end = round_up(end, cacheline_size); + outer_inv_range(start, end); + while (start < end) { + asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start) + : "memory"); + start += cacheline_size; + } + dsb(); + isb(); +} + +/** + * qcom_scm_call() - Send an SCM command + * @svc_id: service identifier + * @cmd_id: command identifier + * @cmd_buf: command buffer + * @cmd_len: length of the command buffer + * @resp_buf: response buffer + * @resp_len: length of the response buffer + * + * Sends a command to the SCM and waits for the command to finish processing. + * + * A note on cache maintenance: + * Note that any buffers that are expected to be accessed by the secure world + * must be flushed before invoking qcom_scm_call and invalidated in the cache + * immediately after qcom_scm_call returns. Cache maintenance on the command + * and response buffers is taken care of by qcom_scm_call; however, callers are + * responsible for any other cached buffers passed over to the secure world. + */ +static int qcom_scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, + size_t cmd_len, void *resp_buf, size_t resp_len) +{ + int ret; + struct qcom_scm_command *cmd; + struct qcom_scm_response *rsp; + unsigned long start, end; + + cmd = alloc_qcom_scm_command(cmd_len, resp_len); + if (!cmd) + return -ENOMEM; + + cmd->id = cpu_to_le32((svc_id << 10) | cmd_id); + if (cmd_buf) + memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len); + + mutex_lock(&qcom_scm_lock); + ret = __qcom_scm_call(cmd); + mutex_unlock(&qcom_scm_lock); + if (ret) + goto out; + + rsp = qcom_scm_command_to_response(cmd); + start = (unsigned long)rsp; + + do { + qcom_scm_inv_range(start, start + sizeof(*rsp)); + } while (!rsp->is_complete); + + end = (unsigned long)qcom_scm_get_response_buffer(rsp) + resp_len; + qcom_scm_inv_range(start, end); + + if (resp_buf) + memcpy(resp_buf, qcom_scm_get_response_buffer(rsp), resp_len); +out: + free_qcom_scm_command(cmd); + return ret; +} + +#define SCM_CLASS_REGISTER (0x2 << 8) +#define SCM_MASK_IRQS BIT(5) +#define SCM_ATOMIC(svc, cmd, n) (((((svc) << 10)|((cmd) & 0x3ff)) << 12) | \ + SCM_CLASS_REGISTER | \ + SCM_MASK_IRQS | \ + (n & 0xf)) + +/** + * qcom_scm_call_atomic1() - Send an atomic SCM command with one argument + * @svc_id: service identifier + * @cmd_id: command identifier + * @arg1: first argument + * + * This shall only be used with commands that are guaranteed to be + * uninterruptable, atomic and SMP safe. + */ +static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1) +{ + int context_id; + + register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 1); + register u32 r1 asm("r1") = (u32)&context_id; + register u32 r2 asm("r2") = arg1; + + asm volatile( + __asmeq("%0", "r0") + __asmeq("%1", "r0") + __asmeq("%2", "r1") + __asmeq("%3", "r2") +#ifdef REQUIRES_SEC + ".arch_extension sec\n" +#endif + "smc #0 @ switch to secure world\n" + : "=r" (r0) + : "r" (r0), "r" (r1), "r" (r2) + : "r3"); + return r0; +} + +u32 qcom_scm_get_version(void) +{ + int context_id; + static u32 version = -1; + register u32 r0 asm("r0"); + register u32 r1 asm("r1"); + + if (version != -1) + return version; + + mutex_lock(&qcom_scm_lock); + + r0 = 0x1 << 8; + r1 = (u32)&context_id; + do { + asm volatile( + __asmeq("%0", "r0") + __asmeq("%1", "r1") + __asmeq("%2", "r0") + __asmeq("%3", "r1") +#ifdef REQUIRES_SEC + ".arch_extension sec\n" +#endif + "smc #0 @ switch to secure world\n" + : "=r" (r0), "=r" (r1) + : "r" (r0), "r" (r1) + : "r2", "r3"); + } while (r0 == QCOM_SCM_INTERRUPTED); + + version = r1; + mutex_unlock(&qcom_scm_lock); + + return version; +} +EXPORT_SYMBOL(qcom_scm_get_version); + +/* + * Set the cold/warm boot address for one of the CPU cores. + */ +static int qcom_scm_set_boot_addr(u32 addr, int flags) +{ + struct { + __le32 flags; + __le32 addr; + } cmd; + + cmd.addr = cpu_to_le32(addr); + cmd.flags = cpu_to_le32(flags); + return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR, + &cmd, sizeof(cmd), NULL, 0); +} + +/** + * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus + * @entry: Entry point function for the cpus + * @cpus: The cpumask of cpus that will use the entry point + * + * Set the cold boot address of the cpus. Any cpu outside the supported + * range would be removed from the cpu present mask. + */ +int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) +{ + int flags = 0; + int cpu; + int scm_cb_flags[] = { + QCOM_SCM_FLAG_COLDBOOT_CPU0, + QCOM_SCM_FLAG_COLDBOOT_CPU1, + QCOM_SCM_FLAG_COLDBOOT_CPU2, + QCOM_SCM_FLAG_COLDBOOT_CPU3, + }; + + if (!cpus || (cpus && cpumask_empty(cpus))) + return -EINVAL; + + for_each_cpu(cpu, cpus) { + if (cpu < ARRAY_SIZE(scm_cb_flags)) + flags |= scm_cb_flags[cpu]; + else + set_cpu_present(cpu, false); + } + + return qcom_scm_set_boot_addr(virt_to_phys(entry), flags); +} + +/** + * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus + * @entry: Entry point function for the cpus + * @cpus: The cpumask of cpus that will use the entry point + * + * Set the Linux entry point for the SCM to transfer control to when coming + * out of a power down. CPU power down may be executed on cpuidle or hotplug. + */ +int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) +{ + int ret; + int flags = 0; + int cpu; + + /* + * Reassign only if we are switching from hotplug entry point + * to cpuidle entry point or vice versa. + */ + for_each_cpu(cpu, cpus) { + if (entry == qcom_scm_wb[cpu].entry) + continue; + flags |= qcom_scm_wb[cpu].flag; + } + + /* No change in entry function */ + if (!flags) + return 0; + + ret = qcom_scm_set_boot_addr(virt_to_phys(entry), flags); + if (!ret) { + for_each_cpu(cpu, cpus) + qcom_scm_wb[cpu].entry = entry; + } + + return ret; +} + +/** + * qcom_scm_cpu_power_down() - Power down the cpu + * @flags - Flags to flush cache + * + * This is an end point to power down cpu. If there was a pending interrupt, + * the control would return from this function, otherwise, the cpu jumps to the + * warm boot entry point set for this cpu upon reset. + */ +void __qcom_scm_cpu_power_down(u32 flags) +{ + qcom_scm_call_atomic1(QCOM_SCM_SVC_BOOT, QCOM_SCM_CMD_TERMINATE_PC, + flags & QCOM_SCM_FLUSH_FLAG_MASK); +} diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 994b50fd997c5e..99892415299b73 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -16,393 +16,12 @@ * 02110-1301, USA. */ -#include -#include -#include -#include -#include -#include +#include +#include +#include #include -#include -#include - - -#define QCOM_SCM_ENOMEM -5 -#define QCOM_SCM_EOPNOTSUPP -4 -#define QCOM_SCM_EINVAL_ADDR -3 -#define QCOM_SCM_EINVAL_ARG -2 -#define QCOM_SCM_ERROR -1 -#define QCOM_SCM_INTERRUPTED 1 - -#define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00 -#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01 -#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08 -#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20 - -#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04 -#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02 -#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10 -#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40 - -struct qcom_scm_entry { - int flag; - void *entry; -}; - -static struct qcom_scm_entry qcom_scm_wb[] = { - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 }, - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 }, - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 }, - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 }, -}; - -static DEFINE_MUTEX(qcom_scm_lock); - -/** - * struct qcom_scm_command - one SCM command buffer - * @len: total available memory for command and response - * @buf_offset: start of command buffer - * @resp_hdr_offset: start of response buffer - * @id: command to be executed - * @buf: buffer returned from qcom_scm_get_command_buffer() - * - * An SCM command is laid out in memory as follows: - * - * ------------------- <--- struct qcom_scm_command - * | command header | - * ------------------- <--- qcom_scm_get_command_buffer() - * | command buffer | - * ------------------- <--- struct qcom_scm_response and - * | response header | qcom_scm_command_to_response() - * ------------------- <--- qcom_scm_get_response_buffer() - * | response buffer | - * ------------------- - * - * There can be arbitrary padding between the headers and buffers so - * you should always use the appropriate qcom_scm_get_*_buffer() routines - * to access the buffers in a safe manner. - */ -struct qcom_scm_command { - __le32 len; - __le32 buf_offset; - __le32 resp_hdr_offset; - __le32 id; - __le32 buf[0]; -}; - -/** - * struct qcom_scm_response - one SCM response buffer - * @len: total available memory for response - * @buf_offset: start of response data relative to start of qcom_scm_response - * @is_complete: indicates if the command has finished processing - */ -struct qcom_scm_response { - __le32 len; - __le32 buf_offset; - __le32 is_complete; -}; - -/** - * alloc_qcom_scm_command() - Allocate an SCM command - * @cmd_size: size of the command buffer - * @resp_size: size of the response buffer - * - * Allocate an SCM command, including enough room for the command - * and response headers as well as the command and response buffers. - * - * Returns a valid &qcom_scm_command on success or %NULL if the allocation fails. - */ -static struct qcom_scm_command *alloc_qcom_scm_command(size_t cmd_size, size_t resp_size) -{ - struct qcom_scm_command *cmd; - size_t len = sizeof(*cmd) + sizeof(struct qcom_scm_response) + cmd_size + - resp_size; - u32 offset; - - cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL); - if (cmd) { - cmd->len = cpu_to_le32(len); - offset = offsetof(struct qcom_scm_command, buf); - cmd->buf_offset = cpu_to_le32(offset); - cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size); - } - return cmd; -} - -/** - * free_qcom_scm_command() - Free an SCM command - * @cmd: command to free - * - * Free an SCM command. - */ -static inline void free_qcom_scm_command(struct qcom_scm_command *cmd) -{ - kfree(cmd); -} - -/** - * qcom_scm_command_to_response() - Get a pointer to a qcom_scm_response - * @cmd: command - * - * Returns a pointer to a response for a command. - */ -static inline struct qcom_scm_response *qcom_scm_command_to_response( - const struct qcom_scm_command *cmd) -{ - return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset); -} - -/** - * qcom_scm_get_command_buffer() - Get a pointer to a command buffer - * @cmd: command - * - * Returns a pointer to the command buffer of a command. - */ -static inline void *qcom_scm_get_command_buffer(const struct qcom_scm_command *cmd) -{ - return (void *)cmd->buf; -} - -/** - * qcom_scm_get_response_buffer() - Get a pointer to a response buffer - * @rsp: response - * - * Returns a pointer to a response buffer of a response. - */ -static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response *rsp) -{ - return (void *)rsp + le32_to_cpu(rsp->buf_offset); -} - -static int qcom_scm_remap_error(int err) -{ - pr_err("qcom_scm_call failed with error code %d\n", err); - switch (err) { - case QCOM_SCM_ERROR: - return -EIO; - case QCOM_SCM_EINVAL_ADDR: - case QCOM_SCM_EINVAL_ARG: - return -EINVAL; - case QCOM_SCM_EOPNOTSUPP: - return -EOPNOTSUPP; - case QCOM_SCM_ENOMEM: - return -ENOMEM; - } - return -EINVAL; -} - -static u32 smc(u32 cmd_addr) -{ - int context_id; - register u32 r0 asm("r0") = 1; - register u32 r1 asm("r1") = (u32)&context_id; - register u32 r2 asm("r2") = cmd_addr; - do { - asm volatile( - __asmeq("%0", "r0") - __asmeq("%1", "r0") - __asmeq("%2", "r1") - __asmeq("%3", "r2") -#ifdef REQUIRES_SEC - ".arch_extension sec\n" -#endif - "smc #0 @ switch to secure world\n" - : "=r" (r0) - : "r" (r0), "r" (r1), "r" (r2) - : "r3"); - } while (r0 == QCOM_SCM_INTERRUPTED); - - return r0; -} - -static int __qcom_scm_call(const struct qcom_scm_command *cmd) -{ - int ret; - u32 cmd_addr = virt_to_phys(cmd); - - /* - * Flush the command buffer so that the secure world sees - * the correct data. - */ - __cpuc_flush_dcache_area((void *)cmd, cmd->len); - outer_flush_range(cmd_addr, cmd_addr + cmd->len); - - ret = smc(cmd_addr); - if (ret < 0) - ret = qcom_scm_remap_error(ret); - - return ret; -} - -static void qcom_scm_inv_range(unsigned long start, unsigned long end) -{ - u32 cacheline_size, ctr; - - asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr)); - cacheline_size = 4 << ((ctr >> 16) & 0xf); - - start = round_down(start, cacheline_size); - end = round_up(end, cacheline_size); - outer_inv_range(start, end); - while (start < end) { - asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start) - : "memory"); - start += cacheline_size; - } - dsb(); - isb(); -} - -/** - * qcom_scm_call() - Send an SCM command - * @svc_id: service identifier - * @cmd_id: command identifier - * @cmd_buf: command buffer - * @cmd_len: length of the command buffer - * @resp_buf: response buffer - * @resp_len: length of the response buffer - * - * Sends a command to the SCM and waits for the command to finish processing. - * - * A note on cache maintenance: - * Note that any buffers that are expected to be accessed by the secure world - * must be flushed before invoking qcom_scm_call and invalidated in the cache - * immediately after qcom_scm_call returns. Cache maintenance on the command - * and response buffers is taken care of by qcom_scm_call; however, callers are - * responsible for any other cached buffers passed over to the secure world. - */ -static int qcom_scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, - size_t cmd_len, void *resp_buf, size_t resp_len) -{ - int ret; - struct qcom_scm_command *cmd; - struct qcom_scm_response *rsp; - unsigned long start, end; - - cmd = alloc_qcom_scm_command(cmd_len, resp_len); - if (!cmd) - return -ENOMEM; - - cmd->id = cpu_to_le32((svc_id << 10) | cmd_id); - if (cmd_buf) - memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len); - - mutex_lock(&qcom_scm_lock); - ret = __qcom_scm_call(cmd); - mutex_unlock(&qcom_scm_lock); - if (ret) - goto out; - - rsp = qcom_scm_command_to_response(cmd); - start = (unsigned long)rsp; - - do { - qcom_scm_inv_range(start, start + sizeof(*rsp)); - } while (!rsp->is_complete); - - end = (unsigned long)qcom_scm_get_response_buffer(rsp) + resp_len; - qcom_scm_inv_range(start, end); - - if (resp_buf) - memcpy(resp_buf, qcom_scm_get_response_buffer(rsp), resp_len); -out: - free_qcom_scm_command(cmd); - return ret; -} - -#define SCM_CLASS_REGISTER (0x2 << 8) -#define SCM_MASK_IRQS BIT(5) -#define SCM_ATOMIC(svc, cmd, n) (((((svc) << 10)|((cmd) & 0x3ff)) << 12) | \ - SCM_CLASS_REGISTER | \ - SCM_MASK_IRQS | \ - (n & 0xf)) - -/** - * qcom_scm_call_atomic1() - Send an atomic SCM command with one argument - * @svc_id: service identifier - * @cmd_id: command identifier - * @arg1: first argument - * - * This shall only be used with commands that are guaranteed to be - * uninterruptable, atomic and SMP safe. - */ -static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1) -{ - int context_id; - - register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 1); - register u32 r1 asm("r1") = (u32)&context_id; - register u32 r2 asm("r2") = arg1; - - asm volatile( - __asmeq("%0", "r0") - __asmeq("%1", "r0") - __asmeq("%2", "r1") - __asmeq("%3", "r2") -#ifdef REQUIRES_SEC - ".arch_extension sec\n" -#endif - "smc #0 @ switch to secure world\n" - : "=r" (r0) - : "r" (r0), "r" (r1), "r" (r2) - : "r3"); - return r0; -} - -u32 qcom_scm_get_version(void) -{ - int context_id; - static u32 version = -1; - register u32 r0 asm("r0"); - register u32 r1 asm("r1"); - - if (version != -1) - return version; - - mutex_lock(&qcom_scm_lock); - - r0 = 0x1 << 8; - r1 = (u32)&context_id; - do { - asm volatile( - __asmeq("%0", "r0") - __asmeq("%1", "r1") - __asmeq("%2", "r0") - __asmeq("%3", "r1") -#ifdef REQUIRES_SEC - ".arch_extension sec\n" -#endif - "smc #0 @ switch to secure world\n" - : "=r" (r0), "=r" (r1) - : "r" (r0), "r" (r1) - : "r2", "r3"); - } while (r0 == QCOM_SCM_INTERRUPTED); - - version = r1; - mutex_unlock(&qcom_scm_lock); - - return version; -} -EXPORT_SYMBOL(qcom_scm_get_version); - -#define QCOM_SCM_SVC_BOOT 0x1 -#define QCOM_SCM_BOOT_ADDR 0x1 -/* - * Set the cold/warm boot address for one of the CPU cores. - */ -static int qcom_scm_set_boot_addr(u32 addr, int flags) -{ - struct { - __le32 flags; - __le32 addr; - } cmd; - - cmd.addr = cpu_to_le32(addr); - cmd.flags = cpu_to_le32(flags); - return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR, - &cmd, sizeof(cmd), NULL, 0); -} +#include "qcom_scm.h" /** * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus @@ -414,26 +33,7 @@ static int qcom_scm_set_boot_addr(u32 addr, int flags) */ int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) { - int flags = 0; - int cpu; - int scm_cb_flags[] = { - QCOM_SCM_FLAG_COLDBOOT_CPU0, - QCOM_SCM_FLAG_COLDBOOT_CPU1, - QCOM_SCM_FLAG_COLDBOOT_CPU2, - QCOM_SCM_FLAG_COLDBOOT_CPU3, - }; - - if (!cpus || (cpus && cpumask_empty(cpus))) - return -EINVAL; - - for_each_cpu(cpu, cpus) { - if (cpu < ARRAY_SIZE(scm_cb_flags)) - flags |= scm_cb_flags[cpu]; - else - set_cpu_present(cpu, false); - } - - return qcom_scm_set_boot_addr(virt_to_phys(entry), flags); + return __qcom_scm_set_cold_boot_addr(entry, cpus); } EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr); @@ -447,37 +47,10 @@ EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr); */ int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) { - int ret; - int flags = 0; - int cpu; - - /* - * Reassign only if we are switching from hotplug entry point - * to cpuidle entry point or vice versa. - */ - for_each_cpu(cpu, cpus) { - if (entry == qcom_scm_wb[cpu].entry) - continue; - flags |= qcom_scm_wb[cpu].flag; - } - - /* No change in entry function */ - if (!flags) - return 0; - - ret = qcom_scm_set_boot_addr(virt_to_phys(entry), flags); - if (!ret) { - for_each_cpu(cpu, cpus) - qcom_scm_wb[cpu].entry = entry; - } - - return ret; + return __qcom_scm_set_warm_boot_addr(entry, cpus); } EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); -#define QCOM_SCM_CMD_TERMINATE_PC 0x2 -#define QCOM_SCM_FLUSH_FLAG_MASK 0x3 - /** * qcom_scm_cpu_power_down() - Power down the cpu * @flags - Flags to flush cache @@ -488,7 +61,6 @@ EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); */ void qcom_scm_cpu_power_down(u32 flags) { - qcom_scm_call_atomic1(QCOM_SCM_SVC_BOOT, QCOM_SCM_CMD_TERMINATE_PC, - flags & QCOM_SCM_FLUSH_FLAG_MASK); + __qcom_scm_cpu_power_down(flags); } EXPORT_SYMBOL(qcom_scm_cpu_power_down); diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h new file mode 100644 index 00000000000000..1172be917307e8 --- /dev/null +++ b/drivers/firmware/qcom_scm.h @@ -0,0 +1,38 @@ +/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __QCOM_SCM_INT_H +#define __QCOM_SCM_INT_H + +#define QCOM_SCM_SVC_BOOT 0x1 +#define QCOM_SCM_BOOT_ADDR 0x1 +#define QCOM_SCM_BOOT_ADDR_MC 0x11 + +#define QCOM_SCM_FLAG_HLOS 0x01 +#define QCOM_SCM_FLAG_COLDBOOT_MC 0x02 +#define QCOM_SCM_FLAG_WARMBOOT_MC 0x04 +extern int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus); +extern int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); + +#define QCOM_SCM_CMD_TERMINATE_PC 0x2 +#define QCOM_SCM_FLUSH_FLAG_MASK 0x3 +#define QCOM_SCM_CMD_CORE_HOTPLUGGED 0x10 +extern void __qcom_scm_cpu_power_down(u32 flags); + +/* common error codes */ +#define QCOM_SCM_ENOMEM -5 +#define QCOM_SCM_EOPNOTSUPP -4 +#define QCOM_SCM_EINVAL_ADDR -3 +#define QCOM_SCM_EINVAL_ARG -2 +#define QCOM_SCM_ERROR -1 +#define QCOM_SCM_INTERRUPTED 1 + +#endif From 1f048b70b8e4761eb0579c0d668eeb4a3549bfa1 Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Thu, 9 Apr 2015 13:20:42 -0600 Subject: [PATCH 0367/3798] ARM: config: Update qcom_defconfig to enable cpuidle Update qcom_defconfig to allow cpuidle for QCOM cpus. * Enable QCOM_PM * Enable ARM_CPUIDLE Cc: Kumar Gala Signed-off-by: Lina Iyer Signed-off-by: Kumar Gala --- arch/arm/configs/qcom_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/qcom_defconfig b/arch/arm/configs/qcom_defconfig index d2f2babfd47a09..e6a6f282e3de0b 100644 --- a/arch/arm/configs/qcom_defconfig +++ b/arch/arm/configs/qcom_defconfig @@ -30,6 +30,7 @@ CONFIG_CLEANCACHE=y CONFIG_ARM_APPENDED_DTB=y CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y CONFIG_VFP=y CONFIG_NEON=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set @@ -143,6 +144,7 @@ CONFIG_MSM_MMCC_8960=y CONFIG_MSM_MMCC_8974=y CONFIG_MSM_IOMMU=y CONFIG_QCOM_GSBI=y +CONFIG_QCOM_PM=y CONFIG_PHY_QCOM_APQ8064_SATA=y CONFIG_PHY_QCOM_IPQ806X_SATA=y CONFIG_EXT2_FS=y From e3db12b94ed4e70b7f8703a0c7396d6b9028b58a Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Thu, 9 Apr 2015 13:20:43 -0600 Subject: [PATCH 0368/3798] ARM: config: multi_v7: Update to enable cpuidle for QCOM SoCs Update defconfig to allow cpuidle for QCOM cpus. * Enable QCOM_PM * Enable ARM_CPUIDLE Cc: Kumar Gala Signed-off-by: Lina Iyer Signed-off-by: Kumar Gala --- arch/arm/configs/multi_v7_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index ab86655c1f4be2..d11e4050334aa1 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -112,6 +112,7 @@ CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y CONFIG_NEON=y CONFIG_ARM_ZYNQ_CPUIDLE=y CONFIG_NET=y @@ -534,6 +535,7 @@ CONFIG_SERIO_NVEC_PS2=y CONFIG_NVEC_POWER=y CONFIG_NVEC_PAZ00=y CONFIG_QCOM_GSBI=y +CONFIG_QCOM_PM=y CONFIG_COMMON_CLK_QCOM=y CONFIG_COMMON_CLK_MAX77686=y CONFIG_APQ_MMCC_8084=y From 699ab787155d6760b396bfd66c403a6b6a3dfdc0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 27 Apr 2015 16:32:07 +0100 Subject: [PATCH 0369/3798] drm/i915: Silence compiler warning in dvo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/i915/intel_dvo.c: In function ‘intel_dvo_init’: drivers/gpu/drm/i915/intel_dvo.c:531:8: warning: array subscript is above array bounds [-Warray-bounds] gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.7/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.7.2-5' --with-bugurl=file:///usr/share/doc/gcc-4.7/README.Bugs --enable-languages=c,c++,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.7 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.7 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix and gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-linux-gnu/4.8/lto-wrapper Target: i686-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-i386/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-i386 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-i386 --with-arch-directory=i386 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-targets=all --enable-multiarch --disable-werror --with-arch-32=i686 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=i686-linux-gnu --host=i686-linux-gnu --target=i686-linux-gnu Thread model: posix gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) Signed-off-by: Chris Wilson Cc: Ville Syrjälä Reviewed-by: Dave Gordon Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_dvo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 7c9f85285aeaa2..ece5bd754f85f5 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -496,7 +496,7 @@ void intel_dvo_init(struct drm_device *dev) int gpio; bool dvoinit; enum pipe pipe; - uint32_t dpll[2]; + uint32_t dpll[I915_MAX_PIPES]; /* Allow the I2C driver info to specify the GPIO to be used in * special cases, but otherwise default to what's defined From 2c53c272d0d8757e506b16b3c291c5ec193c8ef5 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 22 Jan 2015 11:07:00 +0100 Subject: [PATCH 0370/3798] ARM: sti: Provide DT nodes for SSC[0..4] The Synchronous Serial Controller is used to provide SPI. Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 54 +++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index c06a5468191203..9eba0dc59b4242 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -336,5 +336,59 @@ resets = <&softreset STIH407_MIPHY2_SOFTRESET>; }; }; + + spi@9840000 { + compatible = "st,comms-ssc4-spi"; + reg = <0x9840000 0x110>; + interrupts = ; + clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>; + clock-names = "ssc"; + pinctrl-0 = <&pinctrl_spi0_default>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + spi@9841000 { + compatible = "st,comms-ssc4-spi"; + reg = <0x9841000 0x110>; + interrupts = ; + clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>; + clock-names = "ssc"; + + status = "disabled"; + }; + + spi@9842000 { + compatible = "st,comms-ssc4-spi"; + reg = <0x9842000 0x110>; + interrupts = ; + clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>; + clock-names = "ssc"; + + status = "disabled"; + }; + + spi@9843000 { + compatible = "st,comms-ssc4-spi"; + reg = <0x9843000 0x110>; + interrupts = ; + clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>; + clock-names = "ssc"; + + status = "disabled"; + }; + + spi@9844000 { + compatible = "st,comms-ssc4-spi"; + reg = <0x9844000 0x110>; + interrupts = ; + clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>; + clock-names = "ssc"; + + status = "disabled"; + }; }; }; From b0bb2bae194f17cdc8d455c1d4503bc3bf733897 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 22 Jan 2015 11:07:00 +0100 Subject: [PATCH 0371/3798] ARM: sti: Provide DT nodes for SBC SSC[0..2] The Synchronous Serial Controller is used to provide SPI. These are the ports which are located on the Stand-By Controller (SBC). Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index 9eba0dc59b4242..655f8544a6734b 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -390,5 +390,36 @@ status = "disabled"; }; + + /* SBC SSC */ + spi@9540000 { + compatible = "st,comms-ssc4-spi"; + reg = <0x9540000 0x110>; + interrupts = ; + clocks = <&clk_sysin>; + clock-names = "ssc"; + + status = "disabled"; + }; + + spi@9541000 { + compatible = "st,comms-ssc4-spi"; + reg = <0x9541000 0x110>; + interrupts = ; + clocks = <&clk_sysin>; + clock-names = "ssc"; + + status = "disabled"; + }; + + spi@9542000 { + compatible = "st,comms-ssc4-spi"; + reg = <0x9542000 0x110>; + interrupts = ; + clocks = <&clk_sysin>; + clock-names = "ssc"; + + status = "disabled"; + }; }; }; From f91eea447ac32ddc24eaf1cafeb3830b44b6ceeb Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Wed, 29 Apr 2015 22:08:59 +0200 Subject: [PATCH 0372/3798] usb: dwc2: move debugfs code to a separate file Prepare to add more debug code. Moreover, don't save dentry * for each file in struct dwc2_hsotg as clean up is done with debugfs_remove_recursive(). s3c_hsotg_delete_debug() is removed altogether for the same reason. Acked-by: John Youn Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/Makefile | 4 + drivers/usb/dwc2/core.h | 7 +- drivers/usb/dwc2/debug.h | 27 +++ drivers/usb/dwc2/debugfs.c | 416 ++++++++++++++++++++++++++++++++++++ drivers/usb/dwc2/gadget.c | 405 +---------------------------------- drivers/usb/dwc2/platform.c | 4 + 6 files changed, 456 insertions(+), 407 deletions(-) create mode 100644 drivers/usb/dwc2/debug.h create mode 100644 drivers/usb/dwc2/debugfs.c diff --git a/drivers/usb/dwc2/Makefile b/drivers/usb/dwc2/Makefile index f07b425eaff382..324fbb40aa05be 100644 --- a/drivers/usb/dwc2/Makefile +++ b/drivers/usb/dwc2/Makefile @@ -13,6 +13,10 @@ ifneq ($(filter y,$(CONFIG_USB_DWC2_PERIPHERAL) $(CONFIG_USB_DWC2_DUAL_ROLE)),) dwc2-y += gadget.o endif +ifneq ($(CONFIG_DEBUG_FS),) + dwc2-y += debugfs.o +endif + # NOTE: The previous s3c-hsotg peripheral mode only driver has been moved to # this location and renamed gadget.c. When building for dynamically linked # modules, dwc2.ko will get built for host mode, peripheral mode, and dual-role diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 836c012c770788..3695c6f073a5be 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -615,9 +615,6 @@ struct dwc2_hsotg { enum dwc2_lx_state lx_state; struct dentry *debug_root; - struct dentry *debug_file; - struct dentry *debug_testmode; - struct dentry *debug_fifo; /* DWC OTG HW Release versions */ #define DWC2_CORE_REV_2_71a 0x4f54271a @@ -1005,6 +1002,7 @@ extern void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, bool reset); extern void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg); extern void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2); +extern int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode); #else static inline int s3c_hsotg_remove(struct dwc2_hsotg *dwc2) { return 0; } @@ -1018,6 +1016,9 @@ static inline void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, bool reset) {} static inline void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg) {} static inline void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2) {} +static inline int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, + int testmode) +{ return 0; } #endif #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) diff --git a/drivers/usb/dwc2/debug.h b/drivers/usb/dwc2/debug.h new file mode 100644 index 00000000000000..12dbd1daec8717 --- /dev/null +++ b/drivers/usb/dwc2/debug.h @@ -0,0 +1,27 @@ +/** + * debug.h - Designware USB2 DRD controller debug header + * + * Copyright (C) 2015 Intel Corporation + * Mian Yousaf Kaukab + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "core.h" + +#ifdef CONFIG_DEBUG_FS +extern int dwc2_debugfs_init(struct dwc2_hsotg *); +extern void dwc2_debugfs_exit(struct dwc2_hsotg *); +#else +static inline int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) +{ return 0; } +static inline void dwc2_debugfs_exit(struct dwc2_hsotg *hsotg) +{ } +#endif diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c new file mode 100644 index 00000000000000..e57e554ebfc7b8 --- /dev/null +++ b/drivers/usb/dwc2/debugfs.c @@ -0,0 +1,416 @@ +/** + * debugfs.c - Designware USB2 DRD controller debugfs + * + * Copyright (C) 2015 Intel Corporation + * Mian Yousaf Kaukab + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#include "core.h" +#include "debug.h" + +#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ + IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) +/** + * testmode_write - debugfs: change usb test mode + * @seq: The seq file to write to. + * @v: Unused parameter. + * + * This debugfs entry modify the current usb test mode. + */ +static ssize_t testmode_write(struct file *file, const char __user *ubuf, size_t + count, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct dwc2_hsotg *hsotg = s->private; + unsigned long flags; + u32 testmode = 0; + char buf[32]; + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + if (!strncmp(buf, "test_j", 6)) + testmode = TEST_J; + else if (!strncmp(buf, "test_k", 6)) + testmode = TEST_K; + else if (!strncmp(buf, "test_se0_nak", 12)) + testmode = TEST_SE0_NAK; + else if (!strncmp(buf, "test_packet", 11)) + testmode = TEST_PACKET; + else if (!strncmp(buf, "test_force_enable", 17)) + testmode = TEST_FORCE_EN; + else + testmode = 0; + + spin_lock_irqsave(&hsotg->lock, flags); + s3c_hsotg_set_test_mode(hsotg, testmode); + spin_unlock_irqrestore(&hsotg->lock, flags); + return count; +} + +/** + * testmode_show - debugfs: show usb test mode state + * @seq: The seq file to write to. + * @v: Unused parameter. + * + * This debugfs entry shows which usb test mode is currently enabled. + */ +static int testmode_show(struct seq_file *s, void *unused) +{ + struct dwc2_hsotg *hsotg = s->private; + unsigned long flags; + int dctl; + + spin_lock_irqsave(&hsotg->lock, flags); + dctl = readl(hsotg->regs + DCTL); + dctl &= DCTL_TSTCTL_MASK; + dctl >>= DCTL_TSTCTL_SHIFT; + spin_unlock_irqrestore(&hsotg->lock, flags); + + switch (dctl) { + case 0: + seq_puts(s, "no test\n"); + break; + case TEST_J: + seq_puts(s, "test_j\n"); + break; + case TEST_K: + seq_puts(s, "test_k\n"); + break; + case TEST_SE0_NAK: + seq_puts(s, "test_se0_nak\n"); + break; + case TEST_PACKET: + seq_puts(s, "test_packet\n"); + break; + case TEST_FORCE_EN: + seq_puts(s, "test_force_enable\n"); + break; + default: + seq_printf(s, "UNKNOWN %d\n", dctl); + } + + return 0; +} + +static int testmode_open(struct inode *inode, struct file *file) +{ + return single_open(file, testmode_show, inode->i_private); +} + +static const struct file_operations testmode_fops = { + .owner = THIS_MODULE, + .open = testmode_open, + .write = testmode_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/** + * state_show - debugfs: show overall driver and device state. + * @seq: The seq file to write to. + * @v: Unused parameter. + * + * This debugfs entry shows the overall state of the hardware and + * some general information about each of the endpoints available + * to the system. + */ +static int state_show(struct seq_file *seq, void *v) +{ + struct dwc2_hsotg *hsotg = seq->private; + void __iomem *regs = hsotg->regs; + int idx; + + seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n", + readl(regs + DCFG), + readl(regs + DCTL), + readl(regs + DSTS)); + + seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n", + readl(regs + DIEPMSK), readl(regs + DOEPMSK)); + + seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n", + readl(regs + GINTMSK), + readl(regs + GINTSTS)); + + seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n", + readl(regs + DAINTMSK), + readl(regs + DAINT)); + + seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n", + readl(regs + GNPTXSTS), + readl(regs + GRXSTSR)); + + seq_puts(seq, "\nEndpoint status:\n"); + + for (idx = 0; idx < hsotg->num_of_eps; idx++) { + u32 in, out; + + in = readl(regs + DIEPCTL(idx)); + out = readl(regs + DOEPCTL(idx)); + + seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x", + idx, in, out); + + in = readl(regs + DIEPTSIZ(idx)); + out = readl(regs + DOEPTSIZ(idx)); + + seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x", + in, out); + + seq_puts(seq, "\n"); + } + + return 0; +} + +static int state_open(struct inode *inode, struct file *file) +{ + return single_open(file, state_show, inode->i_private); +} + +static const struct file_operations state_fops = { + .owner = THIS_MODULE, + .open = state_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/** + * fifo_show - debugfs: show the fifo information + * @seq: The seq_file to write data to. + * @v: Unused parameter. + * + * Show the FIFO information for the overall fifo and all the + * periodic transmission FIFOs. + */ +static int fifo_show(struct seq_file *seq, void *v) +{ + struct dwc2_hsotg *hsotg = seq->private; + void __iomem *regs = hsotg->regs; + u32 val; + int idx; + + seq_puts(seq, "Non-periodic FIFOs:\n"); + seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ)); + + val = readl(regs + GNPTXFSIZ); + seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n", + val >> FIFOSIZE_DEPTH_SHIFT, + val & FIFOSIZE_DEPTH_MASK); + + seq_puts(seq, "\nPeriodic TXFIFOs:\n"); + + for (idx = 1; idx < hsotg->num_of_eps; idx++) { + val = readl(regs + DPTXFSIZN(idx)); + + seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx, + val >> FIFOSIZE_DEPTH_SHIFT, + val & FIFOSIZE_STARTADDR_MASK); + } + + return 0; +} + +static int fifo_open(struct inode *inode, struct file *file) +{ + return single_open(file, fifo_show, inode->i_private); +} + +static const struct file_operations fifo_fops = { + .owner = THIS_MODULE, + .open = fifo_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const char *decode_direction(int is_in) +{ + return is_in ? "in" : "out"; +} + +/** + * ep_show - debugfs: show the state of an endpoint. + * @seq: The seq_file to write data to. + * @v: Unused parameter. + * + * This debugfs entry shows the state of the given endpoint (one is + * registered for each available). + */ +static int ep_show(struct seq_file *seq, void *v) +{ + struct s3c_hsotg_ep *ep = seq->private; + struct dwc2_hsotg *hsotg = ep->parent; + struct s3c_hsotg_req *req; + void __iomem *regs = hsotg->regs; + int index = ep->index; + int show_limit = 15; + unsigned long flags; + + seq_printf(seq, "Endpoint index %d, named %s, dir %s:\n", + ep->index, ep->ep.name, decode_direction(ep->dir_in)); + + /* first show the register state */ + + seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n", + readl(regs + DIEPCTL(index)), + readl(regs + DOEPCTL(index))); + + seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n", + readl(regs + DIEPDMA(index)), + readl(regs + DOEPDMA(index))); + + seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n", + readl(regs + DIEPINT(index)), + readl(regs + DOEPINT(index))); + + seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n", + readl(regs + DIEPTSIZ(index)), + readl(regs + DOEPTSIZ(index))); + + seq_puts(seq, "\n"); + seq_printf(seq, "mps %d\n", ep->ep.maxpacket); + seq_printf(seq, "total_data=%ld\n", ep->total_data); + + seq_printf(seq, "request list (%p,%p):\n", + ep->queue.next, ep->queue.prev); + + spin_lock_irqsave(&hsotg->lock, flags); + + list_for_each_entry(req, &ep->queue, queue) { + if (--show_limit < 0) { + seq_puts(seq, "not showing more requests...\n"); + break; + } + + seq_printf(seq, "%c req %p: %d bytes @%p, ", + req == ep->req ? '*' : ' ', + req, req->req.length, req->req.buf); + seq_printf(seq, "%d done, res %d\n", + req->req.actual, req->req.status); + } + + spin_unlock_irqrestore(&hsotg->lock, flags); + + return 0; +} + +static int ep_open(struct inode *inode, struct file *file) +{ + return single_open(file, ep_show, inode->i_private); +} + +static const struct file_operations ep_fops = { + .owner = THIS_MODULE, + .open = ep_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/** + * s3c_hsotg_create_debug - create debugfs directory and files + * @hsotg: The driver state + * + * Create the debugfs files to allow the user to get information + * about the state of the system. The directory name is created + * with the same name as the device itself, in case we end up + * with multiple blocks in future systems. + */ +static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg) +{ + struct dentry *root; + struct dentry *file; + unsigned epidx; + + root = hsotg->debug_root; + + /* create general state file */ + + file = debugfs_create_file("state", S_IRUGO, root, hsotg, &state_fops); + if (IS_ERR(file)) + dev_err(hsotg->dev, "%s: failed to create state\n", __func__); + + file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, hsotg, + &testmode_fops); + if (IS_ERR(file)) + dev_err(hsotg->dev, "%s: failed to create testmode\n", + __func__); + + file = debugfs_create_file("fifo", S_IRUGO, root, hsotg, &fifo_fops); + if (IS_ERR(file)) + dev_err(hsotg->dev, "%s: failed to create fifo\n", __func__); + + /* Create one file for each out endpoint */ + for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) { + struct s3c_hsotg_ep *ep; + + ep = hsotg->eps_out[epidx]; + if (ep) { + file = debugfs_create_file(ep->name, S_IRUGO, + root, ep, &ep_fops); + if (IS_ERR(file)) + dev_err(hsotg->dev, "failed to create %s debug file\n", + ep->name); + } + } + /* Create one file for each in endpoint. EP0 is handled with out eps */ + for (epidx = 1; epidx < hsotg->num_of_eps; epidx++) { + struct s3c_hsotg_ep *ep; + + ep = hsotg->eps_in[epidx]; + if (ep) { + file = debugfs_create_file(ep->name, S_IRUGO, + root, ep, &ep_fops); + if (IS_ERR(file)) + dev_err(hsotg->dev, "failed to create %s debug file\n", + ep->name); + } + } +} +#else +static inline void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg) {} +#endif + +/* s3c_hsotg_delete_debug is removed as cleanup in done in dwc2_debugfs_exit */ + +int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) +{ + int ret; + + hsotg->debug_root = debugfs_create_dir(dev_name(hsotg->dev), NULL); + if (!hsotg->debug_root) { + ret = -ENOMEM; + goto err0; + } + + /* Add gadget debugfs nodes */ + s3c_hsotg_create_debug(hsotg); +err0: + return ret; +} +EXPORT_SYMBOL_GPL(dwc2_debugfs_init); + +void dwc2_debugfs_exit(struct dwc2_hsotg *hsotg) +{ + debugfs_remove_recursive(hsotg->debug_root); + hsotg->debug_root = NULL; +} +EXPORT_SYMBOL_GPL(dwc2_debugfs_exit); diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 6a30887082cd9d..bed56dc27fdcd2 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -35,7 +34,6 @@ #include #include #include -#include #include "core.h" #include "hw.h" @@ -894,7 +892,7 @@ static struct s3c_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg, * @testmode: requested usb test mode * Enable usb Test Mode requested by the Host. */ -static int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode) +int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode) { int dctl = readl(hsotg->regs + DCTL); @@ -3391,404 +3389,6 @@ static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg) #endif } -/** - * testmode_write - debugfs: change usb test mode - * @seq: The seq file to write to. - * @v: Unused parameter. - * - * This debugfs entry modify the current usb test mode. - */ -static ssize_t testmode_write(struct file *file, const char __user *ubuf, size_t - count, loff_t *ppos) -{ - struct seq_file *s = file->private_data; - struct dwc2_hsotg *hsotg = s->private; - unsigned long flags; - u32 testmode = 0; - char buf[32]; - - if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) - return -EFAULT; - - if (!strncmp(buf, "test_j", 6)) - testmode = TEST_J; - else if (!strncmp(buf, "test_k", 6)) - testmode = TEST_K; - else if (!strncmp(buf, "test_se0_nak", 12)) - testmode = TEST_SE0_NAK; - else if (!strncmp(buf, "test_packet", 11)) - testmode = TEST_PACKET; - else if (!strncmp(buf, "test_force_enable", 17)) - testmode = TEST_FORCE_EN; - else - testmode = 0; - - spin_lock_irqsave(&hsotg->lock, flags); - s3c_hsotg_set_test_mode(hsotg, testmode); - spin_unlock_irqrestore(&hsotg->lock, flags); - return count; -} - -/** - * testmode_show - debugfs: show usb test mode state - * @seq: The seq file to write to. - * @v: Unused parameter. - * - * This debugfs entry shows which usb test mode is currently enabled. - */ -static int testmode_show(struct seq_file *s, void *unused) -{ - struct dwc2_hsotg *hsotg = s->private; - unsigned long flags; - int dctl; - - spin_lock_irqsave(&hsotg->lock, flags); - dctl = readl(hsotg->regs + DCTL); - dctl &= DCTL_TSTCTL_MASK; - dctl >>= DCTL_TSTCTL_SHIFT; - spin_unlock_irqrestore(&hsotg->lock, flags); - - switch (dctl) { - case 0: - seq_puts(s, "no test\n"); - break; - case TEST_J: - seq_puts(s, "test_j\n"); - break; - case TEST_K: - seq_puts(s, "test_k\n"); - break; - case TEST_SE0_NAK: - seq_puts(s, "test_se0_nak\n"); - break; - case TEST_PACKET: - seq_puts(s, "test_packet\n"); - break; - case TEST_FORCE_EN: - seq_puts(s, "test_force_enable\n"); - break; - default: - seq_printf(s, "UNKNOWN %d\n", dctl); - } - - return 0; -} - -static int testmode_open(struct inode *inode, struct file *file) -{ - return single_open(file, testmode_show, inode->i_private); -} - -static const struct file_operations testmode_fops = { - .owner = THIS_MODULE, - .open = testmode_open, - .write = testmode_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/** - * state_show - debugfs: show overall driver and device state. - * @seq: The seq file to write to. - * @v: Unused parameter. - * - * This debugfs entry shows the overall state of the hardware and - * some general information about each of the endpoints available - * to the system. - */ -static int state_show(struct seq_file *seq, void *v) -{ - struct dwc2_hsotg *hsotg = seq->private; - void __iomem *regs = hsotg->regs; - int idx; - - seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n", - readl(regs + DCFG), - readl(regs + DCTL), - readl(regs + DSTS)); - - seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n", - readl(regs + DIEPMSK), readl(regs + DOEPMSK)); - - seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n", - readl(regs + GINTMSK), - readl(regs + GINTSTS)); - - seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n", - readl(regs + DAINTMSK), - readl(regs + DAINT)); - - seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n", - readl(regs + GNPTXSTS), - readl(regs + GRXSTSR)); - - seq_puts(seq, "\nEndpoint status:\n"); - - for (idx = 0; idx < hsotg->num_of_eps; idx++) { - u32 in, out; - - in = readl(regs + DIEPCTL(idx)); - out = readl(regs + DOEPCTL(idx)); - - seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x", - idx, in, out); - - in = readl(regs + DIEPTSIZ(idx)); - out = readl(regs + DOEPTSIZ(idx)); - - seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x", - in, out); - - seq_puts(seq, "\n"); - } - - return 0; -} - -static int state_open(struct inode *inode, struct file *file) -{ - return single_open(file, state_show, inode->i_private); -} - -static const struct file_operations state_fops = { - .owner = THIS_MODULE, - .open = state_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/** - * fifo_show - debugfs: show the fifo information - * @seq: The seq_file to write data to. - * @v: Unused parameter. - * - * Show the FIFO information for the overall fifo and all the - * periodic transmission FIFOs. - */ -static int fifo_show(struct seq_file *seq, void *v) -{ - struct dwc2_hsotg *hsotg = seq->private; - void __iomem *regs = hsotg->regs; - u32 val; - int idx; - - seq_puts(seq, "Non-periodic FIFOs:\n"); - seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ)); - - val = readl(regs + GNPTXFSIZ); - seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n", - val >> FIFOSIZE_DEPTH_SHIFT, - val & FIFOSIZE_DEPTH_MASK); - - seq_puts(seq, "\nPeriodic TXFIFOs:\n"); - - for (idx = 1; idx < hsotg->num_of_eps; idx++) { - val = readl(regs + DPTXFSIZN(idx)); - - seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx, - val >> FIFOSIZE_DEPTH_SHIFT, - val & FIFOSIZE_STARTADDR_MASK); - } - - return 0; -} - -static int fifo_open(struct inode *inode, struct file *file) -{ - return single_open(file, fifo_show, inode->i_private); -} - -static const struct file_operations fifo_fops = { - .owner = THIS_MODULE, - .open = fifo_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - - -static const char *decode_direction(int is_in) -{ - return is_in ? "in" : "out"; -} - -/** - * ep_show - debugfs: show the state of an endpoint. - * @seq: The seq_file to write data to. - * @v: Unused parameter. - * - * This debugfs entry shows the state of the given endpoint (one is - * registered for each available). - */ -static int ep_show(struct seq_file *seq, void *v) -{ - struct s3c_hsotg_ep *ep = seq->private; - struct dwc2_hsotg *hsotg = ep->parent; - struct s3c_hsotg_req *req; - void __iomem *regs = hsotg->regs; - int index = ep->index; - int show_limit = 15; - unsigned long flags; - - seq_printf(seq, "Endpoint index %d, named %s, dir %s:\n", - ep->index, ep->ep.name, decode_direction(ep->dir_in)); - - /* first show the register state */ - - seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n", - readl(regs + DIEPCTL(index)), - readl(regs + DOEPCTL(index))); - - seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n", - readl(regs + DIEPDMA(index)), - readl(regs + DOEPDMA(index))); - - seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n", - readl(regs + DIEPINT(index)), - readl(regs + DOEPINT(index))); - - seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n", - readl(regs + DIEPTSIZ(index)), - readl(regs + DOEPTSIZ(index))); - - seq_puts(seq, "\n"); - seq_printf(seq, "mps %d\n", ep->ep.maxpacket); - seq_printf(seq, "total_data=%ld\n", ep->total_data); - - seq_printf(seq, "request list (%p,%p):\n", - ep->queue.next, ep->queue.prev); - - spin_lock_irqsave(&hsotg->lock, flags); - - list_for_each_entry(req, &ep->queue, queue) { - if (--show_limit < 0) { - seq_puts(seq, "not showing more requests...\n"); - break; - } - - seq_printf(seq, "%c req %p: %d bytes @%p, ", - req == ep->req ? '*' : ' ', - req, req->req.length, req->req.buf); - seq_printf(seq, "%d done, res %d\n", - req->req.actual, req->req.status); - } - - spin_unlock_irqrestore(&hsotg->lock, flags); - - return 0; -} - -static int ep_open(struct inode *inode, struct file *file) -{ - return single_open(file, ep_show, inode->i_private); -} - -static const struct file_operations ep_fops = { - .owner = THIS_MODULE, - .open = ep_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/** - * s3c_hsotg_create_debug - create debugfs directory and files - * @hsotg: The driver state - * - * Create the debugfs files to allow the user to get information - * about the state of the system. The directory name is created - * with the same name as the device itself, in case we end up - * with multiple blocks in future systems. - */ -static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg) -{ - struct dentry *root; - unsigned epidx; - - root = debugfs_create_dir(dev_name(hsotg->dev), NULL); - hsotg->debug_root = root; - if (IS_ERR(root)) { - dev_err(hsotg->dev, "cannot create debug root\n"); - return; - } - - /* create general state file */ - - hsotg->debug_file = debugfs_create_file("state", S_IRUGO, root, - hsotg, &state_fops); - - if (IS_ERR(hsotg->debug_file)) - dev_err(hsotg->dev, "%s: failed to create state\n", __func__); - - hsotg->debug_testmode = debugfs_create_file("testmode", - S_IRUGO | S_IWUSR, root, - hsotg, &testmode_fops); - - if (IS_ERR(hsotg->debug_testmode)) - dev_err(hsotg->dev, "%s: failed to create testmode\n", - __func__); - - hsotg->debug_fifo = debugfs_create_file("fifo", S_IRUGO, root, - hsotg, &fifo_fops); - - if (IS_ERR(hsotg->debug_fifo)) - dev_err(hsotg->dev, "%s: failed to create fifo\n", __func__); - - /* Create one file for each out endpoint */ - for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) { - struct s3c_hsotg_ep *ep; - - ep = hsotg->eps_out[epidx]; - if (ep) { - ep->debugfs = debugfs_create_file(ep->name, S_IRUGO, - root, ep, &ep_fops); - - if (IS_ERR(ep->debugfs)) - dev_err(hsotg->dev, "failed to create %s debug file\n", - ep->name); - } - } - /* Create one file for each in endpoint. EP0 is handled with out eps */ - for (epidx = 1; epidx < hsotg->num_of_eps; epidx++) { - struct s3c_hsotg_ep *ep; - - ep = hsotg->eps_in[epidx]; - if (ep) { - ep->debugfs = debugfs_create_file(ep->name, S_IRUGO, - root, ep, &ep_fops); - - if (IS_ERR(ep->debugfs)) - dev_err(hsotg->dev, "failed to create %s debug file\n", - ep->name); - } - } -} - -/** - * s3c_hsotg_delete_debug - cleanup debugfs entries - * @hsotg: The driver state - * - * Cleanup (remove) the debugfs files for use on module exit. - */ -static void s3c_hsotg_delete_debug(struct dwc2_hsotg *hsotg) -{ - unsigned epidx; - - for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) { - if (hsotg->eps_in[epidx]) - debugfs_remove(hsotg->eps_in[epidx]->debugfs); - if (hsotg->eps_out[epidx]) - debugfs_remove(hsotg->eps_out[epidx]->debugfs); - } - - debugfs_remove(hsotg->debug_file); - debugfs_remove(hsotg->debug_testmode); - debugfs_remove(hsotg->debug_fifo); - debugfs_remove(hsotg->debug_root); -} - #ifdef CONFIG_OF static void s3c_hsotg_of_probe(struct dwc2_hsotg *hsotg) { @@ -4028,8 +3628,6 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) if (ret) goto err_supplies; - s3c_hsotg_create_debug(hsotg); - s3c_hsotg_dump(hsotg); return 0; @@ -4050,7 +3648,6 @@ EXPORT_SYMBOL_GPL(dwc2_gadget_init); int s3c_hsotg_remove(struct dwc2_hsotg *hsotg) { usb_del_gadget_udc(&hsotg->gadget); - s3c_hsotg_delete_debug(hsotg); clk_disable_unprepare(hsotg->clk); return 0; diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 185663e0b5f439..4fb058b03eaf0e 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -47,6 +47,7 @@ #include "core.h" #include "hcd.h" +#include "debug.h" static const char dwc2_driver_name[] = "dwc2"; @@ -121,6 +122,7 @@ static int dwc2_driver_remove(struct platform_device *dev) { struct dwc2_hsotg *hsotg = platform_get_drvdata(dev); + dwc2_debugfs_exit(hsotg); if (hsotg->hcd_enabled) dwc2_hcd_remove(hsotg); if (hsotg->gadget_enabled) @@ -256,6 +258,8 @@ static int dwc2_driver_probe(struct platform_device *dev) platform_set_drvdata(dev, hsotg); + dwc2_debugfs_init(hsotg); + return retval; } From 563cf017c443137220428712d29cd5510dae2cb2 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Wed, 29 Apr 2015 22:09:00 +0200 Subject: [PATCH 0373/3798] usb: dwc2: debugfs: add support for complete register dump Dump all registers to take a complete snapshot of dwc2 state. Code is inspired by dwc3/debugfs.c Acked-by: John Youn Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core.h | 1 + drivers/usb/dwc2/debugfs.c | 357 +++++++++++++++++++++++++++++++++++++ 2 files changed, 358 insertions(+) diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 3695c6f073a5be..1fd8d2bc0dc9a4 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -615,6 +615,7 @@ struct dwc2_hsotg { enum dwc2_lx_state lx_state; struct dentry *debug_root; + struct debugfs_regset32 *regset; /* DWC OTG HW Release versions */ #define DWC2_CORE_REV_2_71a 0x4f54271a diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c index e57e554ebfc7b8..af89537872a3e9 100644 --- a/drivers/usb/dwc2/debugfs.c +++ b/drivers/usb/dwc2/debugfs.c @@ -391,9 +391,344 @@ static inline void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg) {} /* s3c_hsotg_delete_debug is removed as cleanup in done in dwc2_debugfs_exit */ +#define dump_register(nm) \ +{ \ + .name = #nm, \ + .offset = nm, \ +} + +static const struct debugfs_reg32 dwc2_regs[] = { + /* + * Accessing registers like this can trigger mode mismatch interrupt. + * However, according to dwc2 databook, the register access, in this + * case, is completed on the processor bus but is ignored by the core + * and does not affect its operation. + */ + dump_register(GOTGCTL), + dump_register(GOTGINT), + dump_register(GAHBCFG), + dump_register(GUSBCFG), + dump_register(GRSTCTL), + dump_register(GINTSTS), + dump_register(GINTMSK), + dump_register(GRXSTSR), + dump_register(GRXSTSP), + dump_register(GRXFSIZ), + dump_register(GNPTXFSIZ), + dump_register(GNPTXSTS), + dump_register(GI2CCTL), + dump_register(GPVNDCTL), + dump_register(GGPIO), + dump_register(GUID), + dump_register(GSNPSID), + dump_register(GHWCFG1), + dump_register(GHWCFG2), + dump_register(GHWCFG3), + dump_register(GHWCFG4), + dump_register(GLPMCFG), + dump_register(GPWRDN), + dump_register(GDFIFOCFG), + dump_register(ADPCTL), + dump_register(HPTXFSIZ), + dump_register(DPTXFSIZN(1)), + dump_register(DPTXFSIZN(2)), + dump_register(DPTXFSIZN(3)), + dump_register(DPTXFSIZN(4)), + dump_register(DPTXFSIZN(5)), + dump_register(DPTXFSIZN(6)), + dump_register(DPTXFSIZN(7)), + dump_register(DPTXFSIZN(8)), + dump_register(DPTXFSIZN(9)), + dump_register(DPTXFSIZN(10)), + dump_register(DPTXFSIZN(11)), + dump_register(DPTXFSIZN(12)), + dump_register(DPTXFSIZN(13)), + dump_register(DPTXFSIZN(14)), + dump_register(DPTXFSIZN(15)), + dump_register(DCFG), + dump_register(DCTL), + dump_register(DSTS), + dump_register(DIEPMSK), + dump_register(DOEPMSK), + dump_register(DAINT), + dump_register(DAINTMSK), + dump_register(DTKNQR1), + dump_register(DTKNQR2), + dump_register(DTKNQR3), + dump_register(DTKNQR4), + dump_register(DVBUSDIS), + dump_register(DVBUSPULSE), + dump_register(DIEPCTL(0)), + dump_register(DIEPCTL(1)), + dump_register(DIEPCTL(2)), + dump_register(DIEPCTL(3)), + dump_register(DIEPCTL(4)), + dump_register(DIEPCTL(5)), + dump_register(DIEPCTL(6)), + dump_register(DIEPCTL(7)), + dump_register(DIEPCTL(8)), + dump_register(DIEPCTL(9)), + dump_register(DIEPCTL(10)), + dump_register(DIEPCTL(11)), + dump_register(DIEPCTL(12)), + dump_register(DIEPCTL(13)), + dump_register(DIEPCTL(14)), + dump_register(DIEPCTL(15)), + dump_register(DOEPCTL(0)), + dump_register(DOEPCTL(1)), + dump_register(DOEPCTL(2)), + dump_register(DOEPCTL(3)), + dump_register(DOEPCTL(4)), + dump_register(DOEPCTL(5)), + dump_register(DOEPCTL(6)), + dump_register(DOEPCTL(7)), + dump_register(DOEPCTL(8)), + dump_register(DOEPCTL(9)), + dump_register(DOEPCTL(10)), + dump_register(DOEPCTL(11)), + dump_register(DOEPCTL(12)), + dump_register(DOEPCTL(13)), + dump_register(DOEPCTL(14)), + dump_register(DOEPCTL(15)), + dump_register(DIEPINT(0)), + dump_register(DIEPINT(1)), + dump_register(DIEPINT(2)), + dump_register(DIEPINT(3)), + dump_register(DIEPINT(4)), + dump_register(DIEPINT(5)), + dump_register(DIEPINT(6)), + dump_register(DIEPINT(7)), + dump_register(DIEPINT(8)), + dump_register(DIEPINT(9)), + dump_register(DIEPINT(10)), + dump_register(DIEPINT(11)), + dump_register(DIEPINT(12)), + dump_register(DIEPINT(13)), + dump_register(DIEPINT(14)), + dump_register(DIEPINT(15)), + dump_register(DOEPINT(0)), + dump_register(DOEPINT(1)), + dump_register(DOEPINT(2)), + dump_register(DOEPINT(3)), + dump_register(DOEPINT(4)), + dump_register(DOEPINT(5)), + dump_register(DOEPINT(6)), + dump_register(DOEPINT(7)), + dump_register(DOEPINT(8)), + dump_register(DOEPINT(9)), + dump_register(DOEPINT(10)), + dump_register(DOEPINT(11)), + dump_register(DOEPINT(12)), + dump_register(DOEPINT(13)), + dump_register(DOEPINT(14)), + dump_register(DOEPINT(15)), + dump_register(DIEPTSIZ(0)), + dump_register(DIEPTSIZ(1)), + dump_register(DIEPTSIZ(2)), + dump_register(DIEPTSIZ(3)), + dump_register(DIEPTSIZ(4)), + dump_register(DIEPTSIZ(5)), + dump_register(DIEPTSIZ(6)), + dump_register(DIEPTSIZ(7)), + dump_register(DIEPTSIZ(8)), + dump_register(DIEPTSIZ(9)), + dump_register(DIEPTSIZ(10)), + dump_register(DIEPTSIZ(11)), + dump_register(DIEPTSIZ(12)), + dump_register(DIEPTSIZ(13)), + dump_register(DIEPTSIZ(14)), + dump_register(DIEPTSIZ(15)), + dump_register(DOEPTSIZ(0)), + dump_register(DOEPTSIZ(1)), + dump_register(DOEPTSIZ(2)), + dump_register(DOEPTSIZ(3)), + dump_register(DOEPTSIZ(4)), + dump_register(DOEPTSIZ(5)), + dump_register(DOEPTSIZ(6)), + dump_register(DOEPTSIZ(7)), + dump_register(DOEPTSIZ(8)), + dump_register(DOEPTSIZ(9)), + dump_register(DOEPTSIZ(10)), + dump_register(DOEPTSIZ(11)), + dump_register(DOEPTSIZ(12)), + dump_register(DOEPTSIZ(13)), + dump_register(DOEPTSIZ(14)), + dump_register(DOEPTSIZ(15)), + dump_register(DIEPDMA(0)), + dump_register(DIEPDMA(1)), + dump_register(DIEPDMA(2)), + dump_register(DIEPDMA(3)), + dump_register(DIEPDMA(4)), + dump_register(DIEPDMA(5)), + dump_register(DIEPDMA(6)), + dump_register(DIEPDMA(7)), + dump_register(DIEPDMA(8)), + dump_register(DIEPDMA(9)), + dump_register(DIEPDMA(10)), + dump_register(DIEPDMA(11)), + dump_register(DIEPDMA(12)), + dump_register(DIEPDMA(13)), + dump_register(DIEPDMA(14)), + dump_register(DIEPDMA(15)), + dump_register(DOEPDMA(0)), + dump_register(DOEPDMA(1)), + dump_register(DOEPDMA(2)), + dump_register(DOEPDMA(3)), + dump_register(DOEPDMA(4)), + dump_register(DOEPDMA(5)), + dump_register(DOEPDMA(6)), + dump_register(DOEPDMA(7)), + dump_register(DOEPDMA(8)), + dump_register(DOEPDMA(9)), + dump_register(DOEPDMA(10)), + dump_register(DOEPDMA(11)), + dump_register(DOEPDMA(12)), + dump_register(DOEPDMA(13)), + dump_register(DOEPDMA(14)), + dump_register(DOEPDMA(15)), + dump_register(DTXFSTS(0)), + dump_register(DTXFSTS(1)), + dump_register(DTXFSTS(2)), + dump_register(DTXFSTS(3)), + dump_register(DTXFSTS(4)), + dump_register(DTXFSTS(5)), + dump_register(DTXFSTS(6)), + dump_register(DTXFSTS(7)), + dump_register(DTXFSTS(8)), + dump_register(DTXFSTS(9)), + dump_register(DTXFSTS(10)), + dump_register(DTXFSTS(11)), + dump_register(DTXFSTS(12)), + dump_register(DTXFSTS(13)), + dump_register(DTXFSTS(14)), + dump_register(DTXFSTS(15)), + dump_register(PCGCTL), + dump_register(HCFG), + dump_register(HFIR), + dump_register(HFNUM), + dump_register(HPTXSTS), + dump_register(HAINT), + dump_register(HAINTMSK), + dump_register(HFLBADDR), + dump_register(HPRT0), + dump_register(HCCHAR(0)), + dump_register(HCCHAR(1)), + dump_register(HCCHAR(2)), + dump_register(HCCHAR(3)), + dump_register(HCCHAR(4)), + dump_register(HCCHAR(5)), + dump_register(HCCHAR(6)), + dump_register(HCCHAR(7)), + dump_register(HCCHAR(8)), + dump_register(HCCHAR(9)), + dump_register(HCCHAR(10)), + dump_register(HCCHAR(11)), + dump_register(HCCHAR(12)), + dump_register(HCCHAR(13)), + dump_register(HCCHAR(14)), + dump_register(HCCHAR(15)), + dump_register(HCSPLT(0)), + dump_register(HCSPLT(1)), + dump_register(HCSPLT(2)), + dump_register(HCSPLT(3)), + dump_register(HCSPLT(4)), + dump_register(HCSPLT(5)), + dump_register(HCSPLT(6)), + dump_register(HCSPLT(7)), + dump_register(HCSPLT(8)), + dump_register(HCSPLT(9)), + dump_register(HCSPLT(10)), + dump_register(HCSPLT(11)), + dump_register(HCSPLT(12)), + dump_register(HCSPLT(13)), + dump_register(HCSPLT(14)), + dump_register(HCSPLT(15)), + dump_register(HCINT(0)), + dump_register(HCINT(1)), + dump_register(HCINT(2)), + dump_register(HCINT(3)), + dump_register(HCINT(4)), + dump_register(HCINT(5)), + dump_register(HCINT(6)), + dump_register(HCINT(7)), + dump_register(HCINT(8)), + dump_register(HCINT(9)), + dump_register(HCINT(10)), + dump_register(HCINT(11)), + dump_register(HCINT(12)), + dump_register(HCINT(13)), + dump_register(HCINT(14)), + dump_register(HCINT(15)), + dump_register(HCINTMSK(0)), + dump_register(HCINTMSK(1)), + dump_register(HCINTMSK(2)), + dump_register(HCINTMSK(3)), + dump_register(HCINTMSK(4)), + dump_register(HCINTMSK(5)), + dump_register(HCINTMSK(6)), + dump_register(HCINTMSK(7)), + dump_register(HCINTMSK(8)), + dump_register(HCINTMSK(9)), + dump_register(HCINTMSK(10)), + dump_register(HCINTMSK(11)), + dump_register(HCINTMSK(12)), + dump_register(HCINTMSK(13)), + dump_register(HCINTMSK(14)), + dump_register(HCINTMSK(15)), + dump_register(HCTSIZ(0)), + dump_register(HCTSIZ(1)), + dump_register(HCTSIZ(2)), + dump_register(HCTSIZ(3)), + dump_register(HCTSIZ(4)), + dump_register(HCTSIZ(5)), + dump_register(HCTSIZ(6)), + dump_register(HCTSIZ(7)), + dump_register(HCTSIZ(8)), + dump_register(HCTSIZ(9)), + dump_register(HCTSIZ(10)), + dump_register(HCTSIZ(11)), + dump_register(HCTSIZ(12)), + dump_register(HCTSIZ(13)), + dump_register(HCTSIZ(14)), + dump_register(HCTSIZ(15)), + dump_register(HCDMA(0)), + dump_register(HCDMA(1)), + dump_register(HCDMA(2)), + dump_register(HCDMA(3)), + dump_register(HCDMA(4)), + dump_register(HCDMA(5)), + dump_register(HCDMA(6)), + dump_register(HCDMA(7)), + dump_register(HCDMA(8)), + dump_register(HCDMA(9)), + dump_register(HCDMA(10)), + dump_register(HCDMA(11)), + dump_register(HCDMA(12)), + dump_register(HCDMA(13)), + dump_register(HCDMA(14)), + dump_register(HCDMA(15)), + dump_register(HCDMAB(0)), + dump_register(HCDMAB(1)), + dump_register(HCDMAB(2)), + dump_register(HCDMAB(3)), + dump_register(HCDMAB(4)), + dump_register(HCDMAB(5)), + dump_register(HCDMAB(6)), + dump_register(HCDMAB(7)), + dump_register(HCDMAB(8)), + dump_register(HCDMAB(9)), + dump_register(HCDMAB(10)), + dump_register(HCDMAB(11)), + dump_register(HCDMAB(12)), + dump_register(HCDMAB(13)), + dump_register(HCDMAB(14)), + dump_register(HCDMAB(15)), +}; + int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) { int ret; + struct dentry *file; hsotg->debug_root = debugfs_create_dir(dev_name(hsotg->dev), NULL); if (!hsotg->debug_root) { @@ -403,6 +738,28 @@ int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) /* Add gadget debugfs nodes */ s3c_hsotg_create_debug(hsotg); + + hsotg->regset = devm_kzalloc(hsotg->dev, sizeof(*hsotg->regset), + GFP_KERNEL); + if (!hsotg->regset) { + ret = -ENOMEM; + goto err1; + } + + hsotg->regset->regs = dwc2_regs; + hsotg->regset->nregs = ARRAY_SIZE(dwc2_regs); + hsotg->regset->base = hsotg->regs; + + file = debugfs_create_regset32("regdump", S_IRUGO, hsotg->debug_root, + hsotg->regset); + if (!file) { + ret = -ENOMEM; + goto err1; + } + + return 0; +err1: + debugfs_remove_recursive(hsotg->debug_root); err0: return ret; } From d17ee77b3044da8b8f550bfdf3be8fdcc9d09858 Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:01 +0200 Subject: [PATCH 0374/3798] usb: dwc2: add controller hibernation support When suspending usb bus, phy driver may disable controller power. In this case, registers need to be saved on suspend and restored on resume. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core.c | 377 ++++++++++++++++++++++++++++++++++++++++ drivers/usb/dwc2/core.h | 84 +++++++++ 2 files changed, 461 insertions(+) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index d5197d492e2179..889dc5fad47c9c 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -56,6 +56,383 @@ #include "core.h" #include "hcd.h" +#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) +/** + * dwc2_backup_host_registers() - Backup controller host registers. + * When suspending usb bus, registers needs to be backuped + * if controller power is disabled once suspended. + * + * @hsotg: Programming view of the DWC_otg controller + */ +static int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) +{ + struct dwc2_hregs_backup *hr; + int i; + + dev_dbg(hsotg->dev, "%s\n", __func__); + + /* Backup Host regs */ + hr = hsotg->hr_backup; + if (!hr) { + hr = devm_kzalloc(hsotg->dev, sizeof(*hr), GFP_KERNEL); + if (!hr) { + dev_err(hsotg->dev, "%s: can't allocate host regs\n", + __func__); + return -ENOMEM; + } + + hsotg->hr_backup = hr; + } + hr->hcfg = readl(hsotg->regs + HCFG); + hr->haintmsk = readl(hsotg->regs + HAINTMSK); + for (i = 0; i < hsotg->core_params->host_channels; ++i) + hr->hcintmsk[i] = readl(hsotg->regs + HCINTMSK(i)); + + hr->hprt0 = readl(hsotg->regs + HPRT0); + hr->hfir = readl(hsotg->regs + HFIR); + + return 0; +} + +/** + * dwc2_restore_host_registers() - Restore controller host registers. + * When resuming usb bus, device registers needs to be restored + * if controller power were disabled. + * + * @hsotg: Programming view of the DWC_otg controller + */ +static int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg) +{ + struct dwc2_hregs_backup *hr; + int i; + + dev_dbg(hsotg->dev, "%s\n", __func__); + + /* Restore host regs */ + hr = hsotg->hr_backup; + if (!hr) { + dev_err(hsotg->dev, "%s: no host registers to restore\n", + __func__); + return -EINVAL; + } + + writel(hr->hcfg, hsotg->regs + HCFG); + writel(hr->haintmsk, hsotg->regs + HAINTMSK); + + for (i = 0; i < hsotg->core_params->host_channels; ++i) + writel(hr->hcintmsk[i], hsotg->regs + HCINTMSK(i)); + + writel(hr->hprt0, hsotg->regs + HPRT0); + writel(hr->hfir, hsotg->regs + HFIR); + + return 0; +} +#else +static inline int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) +{ return 0; } + +static inline int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg) +{ return 0; } +#endif + +#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ + IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) +/** + * dwc2_backup_device_registers() - Backup controller device registers. + * When suspending usb bus, registers needs to be backuped + * if controller power is disabled once suspended. + * + * @hsotg: Programming view of the DWC_otg controller + */ +static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) +{ + struct dwc2_dregs_backup *dr; + int i; + + dev_dbg(hsotg->dev, "%s\n", __func__); + + /* Backup dev regs */ + dr = hsotg->dr_backup; + if (!dr) { + dr = devm_kzalloc(hsotg->dev, sizeof(*dr), GFP_KERNEL); + if (!dr) { + dev_err(hsotg->dev, "%s: can't allocate device regs\n", + __func__); + return -ENOMEM; + } + + hsotg->dr_backup = dr; + } + + dr->dcfg = readl(hsotg->regs + DCFG); + dr->dctl = readl(hsotg->regs + DCTL); + dr->daintmsk = readl(hsotg->regs + DAINTMSK); + dr->diepmsk = readl(hsotg->regs + DIEPMSK); + dr->doepmsk = readl(hsotg->regs + DOEPMSK); + + for (i = 0; i < hsotg->num_of_eps; i++) { + /* Backup IN EPs */ + dr->diepctl[i] = readl(hsotg->regs + DIEPCTL(i)); + + /* Ensure DATA PID is correctly configured */ + if (dr->diepctl[i] & DXEPCTL_DPID) + dr->diepctl[i] |= DXEPCTL_SETD1PID; + else + dr->diepctl[i] |= DXEPCTL_SETD0PID; + + dr->dieptsiz[i] = readl(hsotg->regs + DIEPTSIZ(i)); + dr->diepdma[i] = readl(hsotg->regs + DIEPDMA(i)); + + /* Backup OUT EPs */ + dr->doepctl[i] = readl(hsotg->regs + DOEPCTL(i)); + + /* Ensure DATA PID is correctly configured */ + if (dr->doepctl[i] & DXEPCTL_DPID) + dr->doepctl[i] |= DXEPCTL_SETD1PID; + else + dr->doepctl[i] |= DXEPCTL_SETD0PID; + + dr->doeptsiz[i] = readl(hsotg->regs + DOEPTSIZ(i)); + dr->doepdma[i] = readl(hsotg->regs + DOEPDMA(i)); + } + + return 0; +} + +/** + * dwc2_restore_device_registers() - Restore controller device registers. + * When resuming usb bus, device registers needs to be restored + * if controller power were disabled. + * + * @hsotg: Programming view of the DWC_otg controller + */ +static int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg) +{ + struct dwc2_dregs_backup *dr; + u32 dctl; + int i; + + dev_dbg(hsotg->dev, "%s\n", __func__); + + /* Restore dev regs */ + dr = hsotg->dr_backup; + if (!dr) { + dev_err(hsotg->dev, "%s: no device registers to restore\n", + __func__); + return -EINVAL; + } + + writel(dr->dcfg, hsotg->regs + DCFG); + writel(dr->dctl, hsotg->regs + DCTL); + writel(dr->daintmsk, hsotg->regs + DAINTMSK); + writel(dr->diepmsk, hsotg->regs + DIEPMSK); + writel(dr->doepmsk, hsotg->regs + DOEPMSK); + + for (i = 0; i < hsotg->num_of_eps; i++) { + /* Restore IN EPs */ + writel(dr->diepctl[i], hsotg->regs + DIEPCTL(i)); + writel(dr->dieptsiz[i], hsotg->regs + DIEPTSIZ(i)); + writel(dr->diepdma[i], hsotg->regs + DIEPDMA(i)); + + /* Restore OUT EPs */ + writel(dr->doepctl[i], hsotg->regs + DOEPCTL(i)); + writel(dr->doeptsiz[i], hsotg->regs + DOEPTSIZ(i)); + writel(dr->doepdma[i], hsotg->regs + DOEPDMA(i)); + } + + /* Set the Power-On Programming done bit */ + dctl = readl(hsotg->regs + DCTL); + dctl |= DCTL_PWRONPRGDONE; + writel(dctl, hsotg->regs + DCTL); + + return 0; +} +#else +static inline int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) +{ return 0; } + +static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg) +{ return 0; } +#endif + +/** + * dwc2_backup_global_registers() - Backup global controller registers. + * When suspending usb bus, registers needs to be backuped + * if controller power is disabled once suspended. + * + * @hsotg: Programming view of the DWC_otg controller + */ +static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg) +{ + struct dwc2_gregs_backup *gr; + int i; + + /* Backup global regs */ + gr = hsotg->gr_backup; + if (!gr) { + gr = devm_kzalloc(hsotg->dev, sizeof(*gr), GFP_KERNEL); + if (!gr) { + dev_err(hsotg->dev, "%s: can't allocate global regs\n", + __func__); + return -ENOMEM; + } + + hsotg->gr_backup = gr; + } + + gr->gotgctl = readl(hsotg->regs + GOTGCTL); + gr->gintmsk = readl(hsotg->regs + GINTMSK); + gr->gahbcfg = readl(hsotg->regs + GAHBCFG); + gr->gusbcfg = readl(hsotg->regs + GUSBCFG); + gr->grxfsiz = readl(hsotg->regs + GRXFSIZ); + gr->gnptxfsiz = readl(hsotg->regs + GNPTXFSIZ); + gr->hptxfsiz = readl(hsotg->regs + HPTXFSIZ); + gr->gdfifocfg = readl(hsotg->regs + GDFIFOCFG); + for (i = 0; i < MAX_EPS_CHANNELS; i++) + gr->dtxfsiz[i] = readl(hsotg->regs + DPTXFSIZN(i)); + + return 0; +} + +/** + * dwc2_restore_global_registers() - Restore controller global registers. + * When resuming usb bus, device registers needs to be restored + * if controller power were disabled. + * + * @hsotg: Programming view of the DWC_otg controller + */ +static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg) +{ + struct dwc2_gregs_backup *gr; + int i; + + dev_dbg(hsotg->dev, "%s\n", __func__); + + /* Restore global regs */ + gr = hsotg->gr_backup; + if (!gr) { + dev_err(hsotg->dev, "%s: no global registers to restore\n", + __func__); + return -EINVAL; + } + + writel(0xffffffff, hsotg->regs + GINTSTS); + writel(gr->gotgctl, hsotg->regs + GOTGCTL); + writel(gr->gintmsk, hsotg->regs + GINTMSK); + writel(gr->gusbcfg, hsotg->regs + GUSBCFG); + writel(gr->gahbcfg, hsotg->regs + GAHBCFG); + writel(gr->grxfsiz, hsotg->regs + GRXFSIZ); + writel(gr->gnptxfsiz, hsotg->regs + GNPTXFSIZ); + writel(gr->hptxfsiz, hsotg->regs + HPTXFSIZ); + writel(gr->gdfifocfg, hsotg->regs + GDFIFOCFG); + for (i = 0; i < MAX_EPS_CHANNELS; i++) + writel(gr->dtxfsiz[i], hsotg->regs + DPTXFSIZN(i)); + + return 0; +} + +/** + * dwc2_exit_hibernation() - Exit controller from Partial Power Down. + * + * @hsotg: Programming view of the DWC_otg controller + * @restore: Controller registers need to be restored + */ +int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore) +{ + u32 pcgcctl; + int ret = 0; + + pcgcctl = readl(hsotg->regs + PCGCTL); + pcgcctl &= ~PCGCTL_STOPPCLK; + writel(pcgcctl, hsotg->regs + PCGCTL); + + pcgcctl = readl(hsotg->regs + PCGCTL); + pcgcctl &= ~PCGCTL_PWRCLMP; + writel(pcgcctl, hsotg->regs + PCGCTL); + + pcgcctl = readl(hsotg->regs + PCGCTL); + pcgcctl &= ~PCGCTL_RSTPDWNMODULE; + writel(pcgcctl, hsotg->regs + PCGCTL); + + udelay(100); + if (restore) { + ret = dwc2_restore_global_registers(hsotg); + if (ret) { + dev_err(hsotg->dev, "%s: failed to restore registers\n", + __func__); + return ret; + } + if (dwc2_is_host_mode(hsotg)) { + ret = dwc2_restore_host_registers(hsotg); + if (ret) { + dev_err(hsotg->dev, "%s: failed to restore host registers\n", + __func__); + return ret; + } + } else { + ret = dwc2_restore_device_registers(hsotg); + if (ret) { + dev_err(hsotg->dev, "%s: failed to restore device registers\n", + __func__); + return ret; + } + } + } + + return ret; +} + +/** + * dwc2_enter_hibernation() - Put controller in Partial Power Down. + * + * @hsotg: Programming view of the DWC_otg controller + */ +int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg) +{ + u32 pcgcctl; + int ret = 0; + + /* Backup all registers */ + ret = dwc2_backup_global_registers(hsotg); + if (ret) { + dev_err(hsotg->dev, "%s: failed to backup global registers\n", + __func__); + return ret; + } + + if (dwc2_is_host_mode(hsotg)) { + ret = dwc2_backup_host_registers(hsotg); + if (ret) { + dev_err(hsotg->dev, "%s: failed to backup host registers\n", + __func__); + return ret; + } + } else { + ret = dwc2_backup_device_registers(hsotg); + if (ret) { + dev_err(hsotg->dev, "%s: failed to backup device registers\n", + __func__); + return ret; + } + } + + /* Put the controller in low power state */ + pcgcctl = readl(hsotg->regs + PCGCTL); + + pcgcctl |= PCGCTL_PWRCLMP; + writel(pcgcctl, hsotg->regs + PCGCTL); + ndelay(20); + + pcgcctl |= PCGCTL_RSTPDWNMODULE; + writel(pcgcctl, hsotg->regs + PCGCTL); + ndelay(20); + + pcgcctl |= PCGCTL_STOPPCLK; + writel(pcgcctl, hsotg->regs + PCGCTL); + + return ret; +} + /** * dwc2_enable_common_interrupts() - Initializes the commmon interrupts, * used in both device and host modes diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 1fd8d2bc0dc9a4..b0ee9511dc92ac 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -451,6 +451,82 @@ struct dwc2_hw_params { /* Size of control and EP0 buffers */ #define DWC2_CTRL_BUFF_SIZE 8 +/** + * struct dwc2_gregs_backup - Holds global registers state before entering partial + * power down + * @gotgctl: Backup of GOTGCTL register + * @gintmsk: Backup of GINTMSK register + * @gahbcfg: Backup of GAHBCFG register + * @gusbcfg: Backup of GUSBCFG register + * @grxfsiz: Backup of GRXFSIZ register + * @gnptxfsiz: Backup of GNPTXFSIZ register + * @gi2cctl: Backup of GI2CCTL register + * @hptxfsiz: Backup of HPTXFSIZ register + * @gdfifocfg: Backup of GDFIFOCFG register + * @dtxfsiz: Backup of DTXFSIZ registers for each endpoint + * @gpwrdn: Backup of GPWRDN register + */ +struct dwc2_gregs_backup { + u32 gotgctl; + u32 gintmsk; + u32 gahbcfg; + u32 gusbcfg; + u32 grxfsiz; + u32 gnptxfsiz; + u32 gi2cctl; + u32 hptxfsiz; + u32 pcgcctl; + u32 gdfifocfg; + u32 dtxfsiz[MAX_EPS_CHANNELS]; + u32 gpwrdn; +}; + +/** + * struct dwc2_dregs_backup - Holds device registers state before entering partial + * power down + * @dcfg: Backup of DCFG register + * @dctl: Backup of DCTL register + * @daintmsk: Backup of DAINTMSK register + * @diepmsk: Backup of DIEPMSK register + * @doepmsk: Backup of DOEPMSK register + * @diepctl: Backup of DIEPCTL register + * @dieptsiz: Backup of DIEPTSIZ register + * @diepdma: Backup of DIEPDMA register + * @doepctl: Backup of DOEPCTL register + * @doeptsiz: Backup of DOEPTSIZ register + * @doepdma: Backup of DOEPDMA register + */ +struct dwc2_dregs_backup { + u32 dcfg; + u32 dctl; + u32 daintmsk; + u32 diepmsk; + u32 doepmsk; + u32 diepctl[MAX_EPS_CHANNELS]; + u32 dieptsiz[MAX_EPS_CHANNELS]; + u32 diepdma[MAX_EPS_CHANNELS]; + u32 doepctl[MAX_EPS_CHANNELS]; + u32 doeptsiz[MAX_EPS_CHANNELS]; + u32 doepdma[MAX_EPS_CHANNELS]; +}; + +/** + * struct dwc2_hregs_backup - Holds host registers state before entering partial + * power down + * @hcfg: Backup of HCFG register + * @haintmsk: Backup of HAINTMSK register + * @hcintmsk: Backup of HCINTMSK register + * @hptr0: Backup of HPTR0 register + * @hfir: Backup of HFIR register + */ +struct dwc2_hregs_backup { + u32 hcfg; + u32 haintmsk; + u32 hcintmsk[MAX_EPS_CHANNELS]; + u32 hprt0; + u32 hfir; +}; + /** * struct dwc2_hsotg - Holds the state of the driver, including the non-periodic * and periodic schedules @@ -481,6 +557,9 @@ struct dwc2_hw_params { * interrupt * @wkp_timer: Timer object for handling Wakeup Detected interrupt * @lx_state: Lx state of connected device + * @gregs_backup: Backup of global registers during suspend + * @dregs_backup: Backup of device registers during suspend + * @hregs_backup: Backup of host registers during suspend * * These are for host mode: * @@ -613,6 +692,9 @@ struct dwc2_hsotg { struct work_struct wf_otg; struct timer_list wkp_timer; enum dwc2_lx_state lx_state; + struct dwc2_gregs_backup *gr_backup; + struct dwc2_dregs_backup *dr_backup; + struct dwc2_hregs_backup *hr_backup; struct dentry *debug_root; struct debugfs_regset32 *regset; @@ -749,6 +831,8 @@ enum dwc2_halt_status { * and the DWC_otg controller */ extern void dwc2_core_host_init(struct dwc2_hsotg *hsotg); +extern int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg); +extern int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore); /* * Host core Functions. From f81f46e1f530900323b6e32eba1af7244ca69537 Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:02 +0200 Subject: [PATCH 0375/3798] usb: dwc2: implement hibernation during bus suspend/resume Allow controller to enter in hibernation during usb bus suspend and inform both phy and gadget about the suspended state. While in hibernation, the controller can't detect the resume condition. An external mechanism must call usb_phy_set_suspend on resume. Exit hibernation when controller gets the resume interrupt and inform only gadget driver about it. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core.h | 2 ++ drivers/usb/dwc2/core_intr.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index b0ee9511dc92ac..e6abc28dd6bff6 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -1088,6 +1088,7 @@ extern void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, extern void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg); extern void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2); extern int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode); +#define dwc2_is_device_connected(hsotg) (hsotg->connected) #else static inline int s3c_hsotg_remove(struct dwc2_hsotg *dwc2) { return 0; } @@ -1104,6 +1105,7 @@ static inline void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2) {} static inline int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode) { return 0; } +#define dwc2_is_device_connected(hsotg) (0) #endif #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index 6cf047878dbae1..6ffb5a9c385eaa 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -334,6 +334,7 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg) */ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) { + int ret; dev_dbg(hsotg->dev, "++Resume or Remote Wakeup Detected Interrupt++\n"); dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state); @@ -345,6 +346,11 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) /* Clear Remote Wakeup Signaling */ dctl &= ~DCTL_RMTWKUPSIG; writel(dctl, hsotg->regs + DCTL); + ret = dwc2_exit_hibernation(hsotg, true); + if (ret) + dev_err(hsotg->dev, "exit hibernation failed\n"); + + call_gadget(hsotg, resume); } /* Change to L0 state */ hsotg->lx_state = DWC2_L0; @@ -397,6 +403,7 @@ static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg) static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) { u32 dsts; + int ret; dev_dbg(hsotg->dev, "USB SUSPEND\n"); @@ -411,6 +418,30 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d\n", !!(dsts & DSTS_SUSPSTS), hsotg->hw_params.power_optimized); + if ((dsts & DSTS_SUSPSTS) && hsotg->hw_params.power_optimized) { + /* Ignore suspend request before enumeration */ + if (!dwc2_is_device_connected(hsotg)) { + dev_dbg(hsotg->dev, + "ignore suspend request before enumeration\n"); + goto clear_int; + } + + ret = dwc2_enter_hibernation(hsotg); + if (ret) { + dev_err(hsotg->dev, + "enter hibernation failed\n"); + goto skip_power_saving; + } + + udelay(100); + + /* Ask phy to be suspended */ + if (!IS_ERR_OR_NULL(hsotg->uphy)) + usb_phy_set_suspend(hsotg->uphy, true); +skip_power_saving: + /* Call gadget suspend callback */ + call_gadget(hsotg, suspend); + } } else { if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) { dev_dbg(hsotg->dev, "a_peripheral->a_host\n"); @@ -426,6 +457,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) /* Change to L2 (suspend) state */ hsotg->lx_state = DWC2_L2; +clear_int: /* Clear interrupt */ writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS); } From 3eb42df3ebfbd8d46b831c26ecb90e128ad474a5 Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:03 +0200 Subject: [PATCH 0376/3798] usb: dwc2: controller must update lx_state before releasing lock During suspend, there could a race condition between ep_queue and suspend interrupt if lx_state is updated after releasing spinlock in call_gadget(hsotg, suspend). Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core_intr.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index 6ffb5a9c385eaa..0b7f2b2e580e04 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -439,6 +439,12 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) if (!IS_ERR_OR_NULL(hsotg->uphy)) usb_phy_set_suspend(hsotg->uphy, true); skip_power_saving: + /* + * Change to L2 (suspend) state before releasing + * spinlock + */ + hsotg->lx_state = DWC2_L2; + /* Call gadget suspend callback */ call_gadget(hsotg, suspend); } @@ -446,6 +452,8 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) { dev_dbg(hsotg->dev, "a_peripheral->a_host\n"); + /* Change to L2 (suspend) state */ + hsotg->lx_state = DWC2_L2; /* Clear the a_peripheral flag, back to a_host */ spin_unlock(&hsotg->lock); dwc2_hcd_start(hsotg); @@ -454,9 +462,6 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) } } - /* Change to L2 (suspend) state */ - hsotg->lx_state = DWC2_L2; - clear_int: /* Clear interrupt */ writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS); From a6d249d8373343749f9ae55f5581f3b21e178471 Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:04 +0200 Subject: [PATCH 0377/3798] usb: dwc2: add external_id_pin_ctl core parameter This is required due to an Intel specific hardware issue. Where id- pin setup causes glitches on the interrupt line when CONIDSTSCHG interrupt is enabled. Specify external_id_pin_ctl when an external driver (for example phy) can handle id change, so that CONIDSTSCHG interrupt can be disabled from the controller. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core.c | 22 +++++++++++++++++++++- drivers/usb/dwc2/core.h | 6 ++++++ drivers/usb/dwc2/platform.c | 2 ++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 889dc5fad47c9c..8c3bc84e6e761d 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -454,8 +454,10 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) if (hsotg->core_params->dma_enable <= 0) intmsk |= GINTSTS_RXFLVL; + if (hsotg->core_params->external_id_pin_ctl <= 0) + intmsk |= GINTSTS_CONIDSTSCHNG; - intmsk |= GINTSTS_CONIDSTSCHNG | GINTSTS_WKUPINT | GINTSTS_USBSUSP | + intmsk |= GINTSTS_WKUPINT | GINTSTS_USBSUSP | GINTSTS_SESSREQINT; writel(intmsk, hsotg->regs + GINTMSK); @@ -2979,6 +2981,23 @@ static void dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val) hsotg->core_params->uframe_sched = val; } +static void dwc2_set_param_external_id_pin_ctl(struct dwc2_hsotg *hsotg, + int val) +{ + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { + if (val >= 0) { + dev_err(hsotg->dev, + "'%d' invalid for parameter external_id_pin_ctl\n", + val); + dev_err(hsotg->dev, "external_id_pin_ctl must be 0 or 1\n"); + } + val = 0; + dev_dbg(hsotg->dev, "Setting external_id_pin_ctl to %d\n", val); + } + + hsotg->core_params->external_id_pin_ctl = val; +} + /* * This function is called during module intialization to pass module parameters * for the DWC_otg core. @@ -3023,6 +3042,7 @@ void dwc2_set_parameters(struct dwc2_hsotg *hsotg, dwc2_set_param_ahbcfg(hsotg, params->ahbcfg); dwc2_set_param_otg_ver(hsotg, params->otg_ver); dwc2_set_param_uframe_sched(hsotg, params->uframe_sched); + dwc2_set_param_external_id_pin_ctl(hsotg, params->external_id_pin_ctl); } /** diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index e6abc28dd6bff6..e46304df160f17 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -331,6 +331,11 @@ enum dwc2_ep0_state { * by the driver and are ignored in this * configuration value. * @uframe_sched: True to enable the microframe scheduler + * @external_id_pin_ctl: Specifies whether ID pin is handled externally. + * Disable CONIDSTSCHNG controller interrupt in such + * case. + * 0 - No (default) + * 1 - Yes * * The following parameters may be specified when starting the module. These * parameters define how the DWC_otg controller should be configured. A @@ -368,6 +373,7 @@ struct dwc2_core_params { int reload_ctl; int ahbcfg; int uframe_sched; + int external_id_pin_ctl; }; /** diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 4fb058b03eaf0e..ce39e8a0184408 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -77,6 +77,7 @@ static const struct dwc2_core_params params_bcm2835 = { .reload_ctl = 0, .ahbcfg = 0x10, .uframe_sched = 0, + .external_id_pin_ctl = -1, }; static const struct dwc2_core_params params_rk3066 = { @@ -105,6 +106,7 @@ static const struct dwc2_core_params params_rk3066 = { .reload_ctl = -1, .ahbcfg = 0x7, /* INCR16 */ .uframe_sched = -1, + .external_id_pin_ctl = -1, }; /** From ecb176c63ac49ddcea83b0171ead1372bb78c165 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Wed, 29 Apr 2015 22:09:05 +0200 Subject: [PATCH 0378/3798] usb: dwc2: set parameter values in probe function So the parameters can be used in both host and gadget modes. Also consolidate param functions in the core.h Acked-by: John Youn Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core.c | 19 +++++++++++++++++++ drivers/usb/dwc2/core.h | 13 ++++++++++--- drivers/usb/dwc2/hcd.c | 36 +----------------------------------- drivers/usb/dwc2/hcd.h | 7 +------ drivers/usb/dwc2/platform.c | 17 ++++++++++++++++- 5 files changed, 47 insertions(+), 45 deletions(-) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 8c3bc84e6e761d..6acbe90a78cc7a 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -3044,6 +3044,7 @@ void dwc2_set_parameters(struct dwc2_hsotg *hsotg, dwc2_set_param_uframe_sched(hsotg, params->uframe_sched); dwc2_set_param_external_id_pin_ctl(hsotg, params->external_id_pin_ctl); } +EXPORT_SYMBOL_GPL(dwc2_set_parameters); /** * During device initialization, read various hardware configuration @@ -3210,6 +3211,24 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) return 0; } +EXPORT_SYMBOL_GPL(dwc2_get_hwparams); + +/* + * Sets all parameters to the given value. + * + * Assumes that the dwc2_core_params struct contains only integers. + */ +void dwc2_set_all_params(struct dwc2_core_params *params, int value) +{ + int *p = (int *)params; + size_t size = sizeof(*params) / sizeof(*p); + int i; + + for (i = 0; i < size; i++) + p[i] = value; +} +EXPORT_SYMBOL_GPL(dwc2_set_all_params); + u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg) { diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index e46304df160f17..d7fb1f793207a8 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -1071,6 +1071,15 @@ extern void dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val); extern void dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_parameters(struct dwc2_hsotg *hsotg, + const struct dwc2_core_params *params); + +extern void dwc2_set_all_params(struct dwc2_core_params *params, int value); + +extern int dwc2_get_hwparams(struct dwc2_hsotg *hsotg); + + + /* * Dump core registers and SPRAM */ @@ -1119,14 +1128,12 @@ extern int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg); extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg); extern void dwc2_hcd_start(struct dwc2_hsotg *hsotg); #else -static inline void dwc2_set_all_params(struct dwc2_core_params *params, int value) {} static inline int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg) { return 0; } static inline void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg) {} static inline void dwc2_hcd_start(struct dwc2_hsotg *hsotg) {} static inline void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) {} -static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, - const struct dwc2_core_params *params) +static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) { return 0; } #endif diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index fbbbac2150a53f..8757f62cc6e554 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -2748,8 +2748,6 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) destroy_workqueue(hsotg->wq_otg); } - kfree(hsotg->core_params); - hsotg->core_params = NULL; del_timer(&hsotg->wkp_timer); } @@ -2761,30 +2759,13 @@ static void dwc2_hcd_release(struct dwc2_hsotg *hsotg) dwc2_hcd_free(hsotg); } -/* - * Sets all parameters to the given value. - * - * Assumes that the dwc2_core_params struct contains only integers. - */ -void dwc2_set_all_params(struct dwc2_core_params *params, int value) -{ - int *p = (int *)params; - size_t size = sizeof(*params) / sizeof(*p); - int i; - - for (i = 0; i < size; i++) - p[i] = value; -} -EXPORT_SYMBOL_GPL(dwc2_set_all_params); - /* * Initializes the HCD. This function allocates memory for and initializes the * static parts of the usb_hcd and dwc2_hsotg structures. It also registers the * USB bus with the core and calls the hc_driver->start() function. It returns * a negative error on failure. */ -int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, - const struct dwc2_core_params *params) +int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) { struct usb_hcd *hcd; struct dwc2_host_chan *channel; @@ -2797,12 +2778,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, dev_dbg(hsotg->dev, "DWC OTG HCD INIT\n"); - /* Detect config values from hardware */ - retval = dwc2_get_hwparams(hsotg); - - if (retval) - return retval; - retval = -ENOMEM; hcfg = readl(hsotg->regs + HCFG); @@ -2821,15 +2796,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, hsotg->last_frame_num = HFNUM_MAX_FRNUM; #endif - hsotg->core_params = kzalloc(sizeof(*hsotg->core_params), GFP_KERNEL); - if (!hsotg->core_params) - goto error1; - - dwc2_set_all_params(hsotg->core_params, -1); - - /* Validate parameter values */ - dwc2_set_parameters(hsotg, params); - /* Check if the bus driver or platform code has setup a dma_mask */ if (hsotg->core_params->dma_enable > 0 && hsotg->dev->dma_mask == NULL) { diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h index e69a843d892870..7b5841c4003301 100644 --- a/drivers/usb/dwc2/hcd.h +++ b/drivers/usb/dwc2/hcd.h @@ -451,13 +451,8 @@ static inline u8 dwc2_hcd_is_pipe_out(struct dwc2_hcd_pipe_info *pipe) return !dwc2_hcd_is_pipe_in(pipe); } -extern int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, - const struct dwc2_core_params *params); +extern int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq); extern void dwc2_hcd_remove(struct dwc2_hsotg *hsotg); -extern void dwc2_set_parameters(struct dwc2_hsotg *hsotg, - const struct dwc2_core_params *params); -extern void dwc2_set_all_params(struct dwc2_core_params *params, int value); -extern int dwc2_get_hwparams(struct dwc2_hsotg *hsotg); /* Transaction Execution Functions */ extern enum dwc2_transaction_type dwc2_hcd_select_transactions( diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index ce39e8a0184408..2562c901995570 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -241,6 +241,21 @@ static int dwc2_driver_probe(struct platform_device *dev) spin_lock_init(&hsotg->lock); mutex_init(&hsotg->init_mutex); + /* Detect config values from hardware */ + retval = dwc2_get_hwparams(hsotg); + if (retval) + return retval; + + hsotg->core_params = devm_kzalloc(&dev->dev, + sizeof(*hsotg->core_params), GFP_KERNEL); + if (!hsotg->core_params) + return -ENOMEM; + + dwc2_set_all_params(hsotg->core_params, -1); + + /* Validate parameter values */ + dwc2_set_parameters(hsotg, params); + if (hsotg->dr_mode != USB_DR_MODE_HOST) { retval = dwc2_gadget_init(hsotg, irq); if (retval) @@ -249,7 +264,7 @@ static int dwc2_driver_probe(struct platform_device *dev) } if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) { - retval = dwc2_hcd_init(hsotg, irq, params); + retval = dwc2_hcd_init(hsotg, irq); if (retval) { if (hsotg->gadget_enabled) s3c_hsotg_remove(hsotg); From 4876886fb95f93c8b09381ffbdac969d1a1fee0d Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:06 +0200 Subject: [PATCH 0379/3798] usb: dwc2: gadget: use reset detect interrupt ResetDet interrupt is used to detect a reset of the bus while the controller is suspended. This may happens for example when using Command Verifier. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index bed56dc27fdcd2..f867e954764fbc 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -2308,8 +2308,9 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, writel(GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT | GINTSTS_GOUTNAKEFF | GINTSTS_GINNAKEFF | GINTSTS_CONIDSTSCHNG | GINTSTS_USBRST | - GINTSTS_ENUMDONE | GINTSTS_OTGINT | - GINTSTS_USBSUSP | GINTSTS_WKUPINT, + GINTSTS_RESETDET | GINTSTS_ENUMDONE | + GINTSTS_OTGINT | GINTSTS_USBSUSP | + GINTSTS_WKUPINT, hsotg->regs + GINTMSK); if (using_dma(hsotg)) @@ -2475,7 +2476,19 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) } } - if (gintsts & GINTSTS_USBRST) { + if (gintsts & GINTSTS_RESETDET) { + dev_dbg(hsotg->dev, "%s: USBRstDet\n", __func__); + + writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS); + + /* This event must be used only if controller is suspended */ + if (hsotg->lx_state == DWC2_L2) { + dwc2_exit_hibernation(hsotg, true); + hsotg->lx_state = DWC2_L0; + } + } + + if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) { u32 usb_status = readl(hsotg->regs + GOTGCTL); From 9e779778ad7e503434aa76bfc96f98d7d7b2d139 Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:07 +0200 Subject: [PATCH 0380/3798] usb: dwc2: gadget: ignore pm suspend/resume in L2 Nothing to be done in pm suspend/resume when controller is in L2. Don't disconnect or reset. State is already saved when putting controller in hibernation and will be restored on USB bus resume. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index f867e954764fbc..a360f49d3fd027 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -3672,6 +3672,9 @@ int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg) unsigned long flags; int ret = 0; + if (hsotg->lx_state != DWC2_L0) + return ret; + mutex_lock(&hsotg->init_mutex); if (hsotg->driver) { @@ -3712,6 +3715,9 @@ int s3c_hsotg_resume(struct dwc2_hsotg *hsotg) unsigned long flags; int ret = 0; + if (hsotg->lx_state == DWC2_L2) + return ret; + mutex_lock(&hsotg->init_mutex); if (hsotg->driver) { From 7ababa926c66c5c5a862489b475ff5d96a7dd03a Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:08 +0200 Subject: [PATCH 0381/3798] usb: dwc2: gadget: prevent new request submission during suspend If usb controller is in partial power down, any write to registers may cause unpredictable behavior. Thus, prevent any new request submission once controller is in partial power down. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index a360f49d3fd027..732761f9466b9e 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -790,6 +790,13 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, ep->name, req, req->length, req->buf, req->no_interrupt, req->zero, req->short_not_ok); + /* Prevent new request submission when controller is suspended */ + if (hs->lx_state == DWC2_L2) { + dev_dbg(hs->dev, "%s: don't submit request while suspended\n", + __func__); + return -EAGAIN; + } + /* initialise status of the request */ INIT_LIST_HEAD(&hs_req->queue); req->actual = 0; From 18b2b37c59e1bcd5a61716731ec5549fb5bb0203 Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:09 +0200 Subject: [PATCH 0382/3798] usb: dwc2: gadget: powerup controller if needed During vbus session, usb controller needs to exit hibernation if it was previously in suspend state. Since controller will be resetted and configured, there is no need to restore registers. Moreover, set lx_state to L0 on B session. vbus_session callback may not be used by all platforms. Thus, controller software state needs to be set to L0 if the controller detects a valid B session. Otherwise, lx_state will remain L2 and prevent any request submission. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 732761f9466b9e..56a08ac3849ab4 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -2515,6 +2515,7 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET); + hsotg->lx_state = DWC2_L0; s3c_hsotg_core_init_disconnected(hsotg, true); } } @@ -3205,6 +3206,14 @@ static int s3c_hsotg_vbus_session(struct usb_gadget *gadget, int is_active) spin_lock_irqsave(&hsotg->lock, flags); if (is_active) { + /* + * If controller is hibernated, it must exit from hibernation + * before being initialized + */ + if (hsotg->lx_state == DWC2_L2) { + dwc2_exit_hibernation(hsotg, false); + hsotg->lx_state = DWC2_L0; + } /* Kill any ep0 requests as controller will be reinitialized */ kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET); s3c_hsotg_core_init_disconnected(hsotg, false); From 097ee6627cc8c400d77fc9a42fd787fe0fb04d76 Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:10 +0200 Subject: [PATCH 0383/3798] usb: dwc2: gadget: enable otg flag in dual role configuration Inform that device is otg-capable in case of otg configuration. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 56a08ac3849ab4..eb906bd85aab38 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -3525,6 +3525,8 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) hsotg->gadget.max_speed = USB_SPEED_HIGH; hsotg->gadget.ops = &s3c_hsotg_gadget_ops; hsotg->gadget.name = dev_name(dev); + if (hsotg->dr_mode == USB_DR_MODE_OTG) + hsotg->gadget.is_otg = 1; /* reset the system */ From 31bebf4a7f0372b7b1ddc1921c61cfc67aa1e597 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Wed, 29 Apr 2015 22:09:11 +0200 Subject: [PATCH 0384/3798] usb: dwc2: gadget: remove s3c_hsotg_ep_disable_force Force argument is not used anymore. Clean up leftovers from https://lkml.org/lkml/2014/12/9/283 Acked-by: John Youn Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index eb906bd85aab38..2b736156fbf084 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -2764,7 +2764,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, * s3c_hsotg_ep_disable - disable given endpoint * @ep: The endpoint to disable. */ -static int s3c_hsotg_ep_disable_force(struct usb_ep *ep, bool force) +static int s3c_hsotg_ep_disable(struct usb_ep *ep) { struct s3c_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hsotg = hs_ep->parent; @@ -2807,10 +2807,6 @@ static int s3c_hsotg_ep_disable_force(struct usb_ep *ep, bool force) return 0; } -static int s3c_hsotg_ep_disable(struct usb_ep *ep) -{ - return s3c_hsotg_ep_disable_force(ep, false); -} /** * on_list - check request is on the given endpoint * @ep: The endpoint to check. From 9df4ceac8b359b6c261c10132fd3a49558bebd16 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Wed, 29 Apr 2015 22:09:12 +0200 Subject: [PATCH 0385/3798] usb: dwc2: host: register handle to the phy If phy driver is present register hcd handle to it. Acked-by: John Youn Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/hcd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 8757f62cc6e554..1875f7ad849793 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -2913,6 +2913,9 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) /* Don't support SG list at this point */ hcd->self.sg_tablesize = 0; + if (!IS_ERR_OR_NULL(hsotg->uphy)) + otg_set_host(hsotg->uphy->otg, &hcd->self); + /* * Finish generic HCD initialization and start the HCD. This function * allocates the DMA buffer pool, registers the USB bus, requests the @@ -2966,6 +2969,9 @@ void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) return; } + if (!IS_ERR_OR_NULL(hsotg->uphy)) + otg_set_host(hsotg->uphy->otg, NULL); + usb_remove_hcd(hcd); hsotg->priv = NULL; dwc2_hcd_release(hsotg); From 99a657983a1e03fd3b8495199bb0a4870c1abda4 Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:13 +0200 Subject: [PATCH 0386/3798] usb: dwc2: host: add bus_suspend/bus_resume callback Update controller state to indicate suspend entry. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/hcd.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 1875f7ad849793..780f298ec02d3f 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -2313,6 +2313,22 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd) usleep_range(1000, 3000); } +static int _dwc2_hcd_suspend(struct usb_hcd *hcd) +{ + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); + + hsotg->lx_state = DWC2_L2; + return 0; +} + +static int _dwc2_hcd_resume(struct usb_hcd *hcd) +{ + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); + + hsotg->lx_state = DWC2_L0; + return 0; +} + /* Returns the current frame number */ static int _dwc2_hcd_get_frame_number(struct usb_hcd *hcd) { @@ -2683,6 +2699,9 @@ static struct hc_driver dwc2_hc_driver = { .hub_status_data = _dwc2_hcd_hub_status_data, .hub_control = _dwc2_hcd_hub_control, .clear_tt_buffer_complete = _dwc2_hcd_clear_tt_buffer_complete, + + .bus_suspend = _dwc2_hcd_suspend, + .bus_resume = _dwc2_hcd_resume, }; /* From a7714c1cb11dc3bb97a76d2bb0560415d155b1d5 Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:14 +0200 Subject: [PATCH 0387/3798] usb: dwc2: host: resume root hub on port connect Once hub is runtime suspended, dwc2 must resume it on port connect event. Else, roothub will stay in suspended state and will not resume transfers. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/hcd_intr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index 551ba878b003c9..6927bba8624584 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -350,6 +350,9 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg) dev_vdbg(hsotg->dev, "--Port Interrupt HPRT0=0x%08x Port Connect Detected--\n", hprt0); + if (hsotg->lx_state != DWC2_L0) + usb_hcd_resume_root_hub(hsotg->priv); + hsotg->flags.b.port_connect_status_change = 1; hsotg->flags.b.port_connect_status = 1; hprt0_modify |= HPRT0_CONNDET; From 33ad261aa62be02f0cedeb4d5735cc726de84a3f Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:15 +0200 Subject: [PATCH 0388/3798] usb: dwc2: host: spinlock urb_enqueue During urb_enqueue, if the urb can't be queued to the endpoint, the urb is freed without any spinlock protection. This leads to memory corruption when concurrent urb_dequeue try to free same urb->hcpriv. Thus, ensure the whole urb_enqueue in spinlocked. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/hcd.c | 15 ++++++--------- drivers/usb/dwc2/hcd_queue.c | 8 +------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 780f298ec02d3f..d72557cfc05280 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -357,12 +357,12 @@ void dwc2_hcd_stop(struct dwc2_hsotg *hsotg) writel(0, hsotg->regs + HPRT0); } +/* Caller must hold driver lock */ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, struct dwc2_hcd_urb *urb, void **ep_handle, gfp_t mem_flags) { struct dwc2_qtd *qtd; - unsigned long flags; u32 intr_mask; int retval; int dev_speed; @@ -413,11 +413,9 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, */ return 0; - spin_lock_irqsave(&hsotg->lock, flags); tr_type = dwc2_hcd_select_transactions(hsotg); if (tr_type != DWC2_TRANSACTION_NONE) dwc2_hcd_queue_transactions(hsotg, tr_type); - spin_unlock_irqrestore(&hsotg->lock, flags); } return 0; @@ -2484,7 +2482,7 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, "%s: unaligned transfer with no transfer_buffer", __func__); retval = -EINVAL; - goto fail1; + goto fail0; } } @@ -2512,7 +2510,6 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, spin_lock_irqsave(&hsotg->lock, flags); retval = usb_hcd_link_urb_to_ep(hcd, urb); - spin_unlock_irqrestore(&hsotg->lock, flags); if (retval) goto fail1; @@ -2521,22 +2518,22 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, goto fail2; if (alloc_bandwidth) { - spin_lock_irqsave(&hsotg->lock, flags); dwc2_allocate_bus_bandwidth(hcd, dwc2_hcd_get_ep_bandwidth(hsotg, ep), urb); - spin_unlock_irqrestore(&hsotg->lock, flags); } + spin_unlock_irqrestore(&hsotg->lock, flags); + return 0; fail2: - spin_lock_irqsave(&hsotg->lock, flags); dwc2_urb->priv = NULL; usb_hcd_unlink_urb_from_ep(hcd, urb); - spin_unlock_irqrestore(&hsotg->lock, flags); fail1: + spin_unlock_irqrestore(&hsotg->lock, flags); urb->hcpriv = NULL; +fail0: kfree(dwc2_urb); return retval; diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index bb97838bc6c04c..63207dc3cb2292 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c @@ -761,6 +761,7 @@ void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb) /** * dwc2_hcd_qtd_add() - Adds a QTD to the QTD-list of a QH + * Caller must hold driver lock. * * @hsotg: The DWC HCD structure * @qtd: The QTD to add @@ -777,7 +778,6 @@ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, struct dwc2_qh **qh, gfp_t mem_flags) { struct dwc2_hcd_urb *urb = qtd->urb; - unsigned long flags; int allocated = 0; int retval; @@ -792,15 +792,12 @@ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, allocated = 1; } - spin_lock_irqsave(&hsotg->lock, flags); - retval = dwc2_hcd_qh_add(hsotg, *qh); if (retval) goto fail; qtd->qh = *qh; list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list); - spin_unlock_irqrestore(&hsotg->lock, flags); return 0; @@ -817,10 +814,7 @@ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, qtd_list_entry) dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh_tmp); - spin_unlock_irqrestore(&hsotg->lock, flags); dwc2_hcd_qh_free(hsotg, qh_tmp); - } else { - spin_unlock_irqrestore(&hsotg->lock, flags); } return retval; From db62b9a804b465f5050438eb06151c99c625ec9a Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:16 +0200 Subject: [PATCH 0389/3798] usb: dwc2: host: don't use dma_alloc_coherent with irqs disabled Align buffer must be allocated using kmalloc since irqs are disabled. Coherency is handled through dma_map_single which can be used with irqs disabled. Reviewed-by: Julius Werner Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/hcd.c | 13 +++++++-- drivers/usb/dwc2/hcd_intr.c | 53 ++++++++++++++++++++++++++---------- drivers/usb/dwc2/hcd_queue.c | 10 ++++--- 3 files changed, 54 insertions(+), 22 deletions(-) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index d72557cfc05280..745230d0d8b310 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -719,9 +719,7 @@ static int dwc2_hc_setup_align_buf(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, /* 3072 = 3 max-size Isoc packets */ buf_size = 3072; - qh->dw_align_buf = dma_alloc_coherent(hsotg->dev, buf_size, - &qh->dw_align_buf_dma, - GFP_ATOMIC); + qh->dw_align_buf = kmalloc(buf_size, GFP_ATOMIC | GFP_DMA); if (!qh->dw_align_buf) return -ENOMEM; qh->dw_align_buf_size = buf_size; @@ -746,6 +744,15 @@ static int dwc2_hc_setup_align_buf(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, } } + qh->dw_align_buf_dma = dma_map_single(hsotg->dev, + qh->dw_align_buf, qh->dw_align_buf_size, + chan->ep_is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE); + if (dma_mapping_error(hsotg->dev, qh->dw_align_buf_dma)) { + dev_err(hsotg->dev, "can't map align_buf\n"); + chan->align_buf = (dma_addr_t)NULL; + return -EINVAL; + } + chan->align_buf = qh->dw_align_buf_dma; return 0; } diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index 6927bba8624584..6ea8eb6899f4d0 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -466,10 +466,15 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg, } /* Non DWORD-aligned buffer case handling */ - if (chan->align_buf && xfer_length && chan->ep_is_in) { + if (chan->align_buf && xfer_length) { dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); - memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf, - xfer_length); + dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma, + chan->qh->dw_align_buf_size, + chan->ep_is_in ? + DMA_FROM_DEVICE : DMA_TO_DEVICE); + if (chan->ep_is_in) + memcpy(urb->buf + urb->actual_length, + chan->qh->dw_align_buf, xfer_length); } dev_vdbg(hsotg->dev, "urb->actual_length=%d xfer_length=%d\n", @@ -555,13 +560,18 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( chan, chnum, qtd, halt_status, NULL); /* Non DWORD-aligned buffer case handling */ - if (chan->align_buf && frame_desc->actual_length && - chan->ep_is_in) { + if (chan->align_buf && frame_desc->actual_length) { dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); - memcpy(urb->buf + frame_desc->offset + - qtd->isoc_split_offset, chan->qh->dw_align_buf, - frame_desc->actual_length); + dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma, + chan->qh->dw_align_buf_size, + chan->ep_is_in ? + DMA_FROM_DEVICE : DMA_TO_DEVICE); + if (chan->ep_is_in) + memcpy(urb->buf + frame_desc->offset + + qtd->isoc_split_offset, + chan->qh->dw_align_buf, + frame_desc->actual_length); } break; case DWC2_HC_XFER_FRAME_OVERRUN: @@ -584,13 +594,18 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( chan, chnum, qtd, halt_status, NULL); /* Non DWORD-aligned buffer case handling */ - if (chan->align_buf && frame_desc->actual_length && - chan->ep_is_in) { + if (chan->align_buf && frame_desc->actual_length) { dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); - memcpy(urb->buf + frame_desc->offset + - qtd->isoc_split_offset, chan->qh->dw_align_buf, - frame_desc->actual_length); + dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma, + chan->qh->dw_align_buf_size, + chan->ep_is_in ? + DMA_FROM_DEVICE : DMA_TO_DEVICE); + if (chan->ep_is_in) + memcpy(urb->buf + frame_desc->offset + + qtd->isoc_split_offset, + chan->qh->dw_align_buf, + frame_desc->actual_length); } /* Skip whole frame */ @@ -926,6 +941,8 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, if (chan->align_buf) { dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); + dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma, + chan->qh->dw_align_buf_size, DMA_FROM_DEVICE); memcpy(qtd->urb->buf + frame_desc->offset + qtd->isoc_split_offset, chan->qh->dw_align_buf, len); } @@ -1155,8 +1172,14 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg, /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && xfer_length && chan->ep_is_in) { dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); - memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf, - xfer_length); + dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma, + chan->qh->dw_align_buf_size, + chan->ep_is_in ? + DMA_FROM_DEVICE : DMA_TO_DEVICE); + if (chan->ep_is_in) + memcpy(urb->buf + urb->actual_length, + chan->qh->dw_align_buf, + xfer_length); } urb->actual_length += xfer_length; diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index 63207dc3cb2292..9b5c36256627b0 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c @@ -229,11 +229,13 @@ static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, */ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { - if (hsotg->core_params->dma_desc_enable > 0) + if (hsotg->core_params->dma_desc_enable > 0) { dwc2_hcd_qh_free_ddma(hsotg, qh); - else if (qh->dw_align_buf) - dma_free_coherent(hsotg->dev, qh->dw_align_buf_size, - qh->dw_align_buf, qh->dw_align_buf_dma); + } else { + /* kfree(NULL) is safe */ + kfree(qh->dw_align_buf); + qh->dw_align_buf_dma = (dma_addr_t)0; + } kfree(qh); } From 96d480e65ea0e4e950f75029b8a1ff4c1269f8b0 Mon Sep 17 00:00:00 2001 From: Jingwu Lin Date: Wed, 29 Apr 2015 22:09:17 +0200 Subject: [PATCH 0390/3798] usb: dwc2: host: implement test mode Add support for SetPortFeature(PORT_TEST) for root port. Acked-by: John Youn Signed-off-by: Jingwu Lin Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/hcd.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 745230d0d8b310..4773d2770363ce 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -1779,6 +1779,15 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, /* Not supported */ break; + case USB_PORT_FEAT_TEST: + hprt0 = dwc2_read_hprt0(hsotg); + dev_dbg(hsotg->dev, + "SetPortFeature - USB_PORT_FEAT_TEST\n"); + hprt0 &= ~HPRT0_TSTCTL_MASK; + hprt0 |= (windex >> 8) << HPRT0_TSTCTL_SHIFT; + writel(hprt0, hsotg->regs + HPRT0); + break; + default: retval = -EINVAL; dev_err(hsotg->dev, From 2d1165a4b95e25aed83fed737d53ab0c87b831e6 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Wed, 29 Apr 2015 22:09:18 +0200 Subject: [PATCH 0391/3798] usb: dwc2: remove dwc2_platform.ko As dwc2 pci module is now exporting dwc2 platform device, include platform.o in dwc2-y and remove USB_DWC2_PLATFORM configuration option. Driver will be built as two modules, dwc2.ko and dwc2_pci.ko. dwc2.ko is the new platform driver. Remove all EXPORT_SYMBOL_GPL as they are not needed any more. Acked-by: John Youn Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/Kconfig | 8 -------- drivers/usb/dwc2/Makefile | 5 +---- drivers/usb/dwc2/core.c | 3 --- drivers/usb/dwc2/core_intr.c | 1 - drivers/usb/dwc2/debugfs.c | 2 -- drivers/usb/dwc2/gadget.c | 5 ----- drivers/usb/dwc2/hcd.c | 2 -- 7 files changed, 1 insertion(+), 25 deletions(-) diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig index 1bcb36ae6505af..fd95ba6ec317fd 100644 --- a/drivers/usb/dwc2/Kconfig +++ b/drivers/usb/dwc2/Kconfig @@ -50,18 +50,10 @@ config USB_DWC2_DUAL_ROLE option requires USB_GADGET to be enabled. endchoice -config USB_DWC2_PLATFORM - tristate "DWC2 Platform" - default USB_DWC2_HOST || USB_DWC2_PERIPHERAL - help - The Designware USB2.0 platform interface module for - controllers directly connected to the CPU. - config USB_DWC2_PCI tristate "DWC2 PCI" depends on PCI default n - select USB_DWC2_PLATFORM select NOP_USB_XCEIV help The Designware USB2.0 PCI interface module for controllers diff --git a/drivers/usb/dwc2/Makefile b/drivers/usb/dwc2/Makefile index 324fbb40aa05be..50fdaace1e735f 100644 --- a/drivers/usb/dwc2/Makefile +++ b/drivers/usb/dwc2/Makefile @@ -2,7 +2,7 @@ ccflags-$(CONFIG_USB_DWC2_DEBUG) += -DDEBUG ccflags-$(CONFIG_USB_DWC2_VERBOSE) += -DVERBOSE_DEBUG obj-$(CONFIG_USB_DWC2) += dwc2.o -dwc2-y := core.o core_intr.o +dwc2-y := core.o core_intr.o platform.o ifneq ($(filter y,$(CONFIG_USB_DWC2_HOST) $(CONFIG_USB_DWC2_DUAL_ROLE)),) dwc2-y += hcd.o hcd_intr.o @@ -25,6 +25,3 @@ endif obj-$(CONFIG_USB_DWC2_PCI) += dwc2_pci.o dwc2_pci-y := pci.o - -obj-$(CONFIG_USB_DWC2_PLATFORM) += dwc2_platform.o -dwc2_platform-y := platform.o diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 6acbe90a78cc7a..7f461e3bc7a174 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -3044,7 +3044,6 @@ void dwc2_set_parameters(struct dwc2_hsotg *hsotg, dwc2_set_param_uframe_sched(hsotg, params->uframe_sched); dwc2_set_param_external_id_pin_ctl(hsotg, params->external_id_pin_ctl); } -EXPORT_SYMBOL_GPL(dwc2_set_parameters); /** * During device initialization, read various hardware configuration @@ -3211,7 +3210,6 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) return 0; } -EXPORT_SYMBOL_GPL(dwc2_get_hwparams); /* * Sets all parameters to the given value. @@ -3227,7 +3225,6 @@ void dwc2_set_all_params(struct dwc2_core_params *params, int value) for (i = 0; i < size; i++) p[i] = value; } -EXPORT_SYMBOL_GPL(dwc2_set_all_params); u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg) diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index 0b7f2b2e580e04..9e510bb612bdc8 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -559,4 +559,3 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev) spin_unlock(&hsotg->lock); return retval; } -EXPORT_SYMBOL_GPL(dwc2_handle_common_intr); diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c index af89537872a3e9..ef2ee3d9a25d2e 100644 --- a/drivers/usb/dwc2/debugfs.c +++ b/drivers/usb/dwc2/debugfs.c @@ -763,11 +763,9 @@ int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) err0: return ret; } -EXPORT_SYMBOL_GPL(dwc2_debugfs_init); void dwc2_debugfs_exit(struct dwc2_hsotg *hsotg) { debugfs_remove_recursive(hsotg->debug_root); hsotg->debug_root = NULL; } -EXPORT_SYMBOL_GPL(dwc2_debugfs_exit); diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 2b736156fbf084..4d47b7c092387f 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -2190,7 +2190,6 @@ void s3c_hsotg_disconnect(struct dwc2_hsotg *hsotg) call_gadget(hsotg, disconnect); } -EXPORT_SYMBOL_GPL(s3c_hsotg_disconnect); /** * s3c_hsotg_irq_fifoempty - TX FIFO empty interrupt handler @@ -3666,7 +3665,6 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) return ret; } -EXPORT_SYMBOL_GPL(dwc2_gadget_init); /** * s3c_hsotg_remove - remove function for hsotg driver @@ -3679,7 +3677,6 @@ int s3c_hsotg_remove(struct dwc2_hsotg *hsotg) return 0; } -EXPORT_SYMBOL_GPL(s3c_hsotg_remove); int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg) { @@ -3722,7 +3719,6 @@ int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg) return ret; } -EXPORT_SYMBOL_GPL(s3c_hsotg_suspend); int s3c_hsotg_resume(struct dwc2_hsotg *hsotg) { @@ -3754,4 +3750,3 @@ int s3c_hsotg_resume(struct dwc2_hsotg *hsotg) return ret; } -EXPORT_SYMBOL_GPL(s3c_hsotg_resume); diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 4773d2770363ce..d9b8cc36de529b 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -2980,7 +2980,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) dev_err(hsotg->dev, "%s() FAILED, returning %d\n", __func__, retval); return retval; } -EXPORT_SYMBOL_GPL(dwc2_hcd_init); /* * Removes the HCD. @@ -3014,4 +3013,3 @@ void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) kfree(hsotg->frame_num_array); #endif } -EXPORT_SYMBOL_GPL(dwc2_hcd_remove); From 285046aa11ad85a4de24891f5458d45f50d1bcc5 Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:19 +0200 Subject: [PATCH 0392/3798] usb: dwc2: add hibernation core parameter dwc2 may not be able to exit from hibernation if the hardware does not provide a way to detect resume signalling in this state. Thus, add the possibility to disable hibernation feature. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core.c | 24 ++++++++++++++++++++++++ drivers/usb/dwc2/core.h | 7 +++++++ drivers/usb/dwc2/core_intr.c | 7 ++++--- drivers/usb/dwc2/platform.c | 2 ++ 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 7f461e3bc7a174..e5b546f1152ef0 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -342,6 +342,9 @@ int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore) u32 pcgcctl; int ret = 0; + if (!hsotg->core_params->hibernation) + return -ENOTSUPP; + pcgcctl = readl(hsotg->regs + PCGCTL); pcgcctl &= ~PCGCTL_STOPPCLK; writel(pcgcctl, hsotg->regs + PCGCTL); @@ -392,6 +395,9 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg) u32 pcgcctl; int ret = 0; + if (!hsotg->core_params->hibernation) + return -ENOTSUPP; + /* Backup all registers */ ret = dwc2_backup_global_registers(hsotg); if (ret) { @@ -2998,6 +3004,23 @@ static void dwc2_set_param_external_id_pin_ctl(struct dwc2_hsotg *hsotg, hsotg->core_params->external_id_pin_ctl = val; } +static void dwc2_set_param_hibernation(struct dwc2_hsotg *hsotg, + int val) +{ + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { + if (val >= 0) { + dev_err(hsotg->dev, + "'%d' invalid for parameter hibernation\n", + val); + dev_err(hsotg->dev, "hibernation must be 0 or 1\n"); + } + val = 0; + dev_dbg(hsotg->dev, "Setting hibernation to %d\n", val); + } + + hsotg->core_params->hibernation = val; +} + /* * This function is called during module intialization to pass module parameters * for the DWC_otg core. @@ -3043,6 +3066,7 @@ void dwc2_set_parameters(struct dwc2_hsotg *hsotg, dwc2_set_param_otg_ver(hsotg, params->otg_ver); dwc2_set_param_uframe_sched(hsotg, params->uframe_sched); dwc2_set_param_external_id_pin_ctl(hsotg, params->external_id_pin_ctl); + dwc2_set_param_hibernation(hsotg, params->hibernation); } /** diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index d7fb1f793207a8..53b8de03f1028c 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -336,6 +336,12 @@ enum dwc2_ep0_state { * case. * 0 - No (default) * 1 - Yes + * @hibernation: Specifies whether the controller support hibernation. + * If hibernation is enabled, the controller will enter + * hibernation in both peripheral and host mode when + * needed. + * 0 - No (default) + * 1 - Yes * * The following parameters may be specified when starting the module. These * parameters define how the DWC_otg controller should be configured. A @@ -374,6 +380,7 @@ struct dwc2_core_params { int ahbcfg; int uframe_sched; int external_id_pin_ctl; + int hibernation; }; /** diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index 9e510bb612bdc8..927be1e8b3dc93 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -347,7 +347,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) dctl &= ~DCTL_RMTWKUPSIG; writel(dctl, hsotg->regs + DCTL); ret = dwc2_exit_hibernation(hsotg, true); - if (ret) + if (ret && (ret != -ENOTSUPP)) dev_err(hsotg->dev, "exit hibernation failed\n"); call_gadget(hsotg, resume); @@ -428,8 +428,9 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) ret = dwc2_enter_hibernation(hsotg); if (ret) { - dev_err(hsotg->dev, - "enter hibernation failed\n"); + if (ret != -ENOTSUPP) + dev_err(hsotg->dev, + "enter hibernation failed\n"); goto skip_power_saving; } diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 2562c901995570..90935304185a01 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -78,6 +78,7 @@ static const struct dwc2_core_params params_bcm2835 = { .ahbcfg = 0x10, .uframe_sched = 0, .external_id_pin_ctl = -1, + .hibernation = -1, }; static const struct dwc2_core_params params_rk3066 = { @@ -107,6 +108,7 @@ static const struct dwc2_core_params params_rk3066 = { .ahbcfg = 0x7, /* INCR16 */ .uframe_sched = -1, .external_id_pin_ctl = -1, + .hibernation = -1, }; /** From e499123ed780df64a35e6cc0a8c892b282fa71a4 Mon Sep 17 00:00:00 2001 From: Gregory Herrero Date: Wed, 29 Apr 2015 22:09:20 +0200 Subject: [PATCH 0393/3798] usb: dwc2: host: ensure qtb exists before dereferencing it dwc2_hc_nak_intr could be called with a NULL qtd. Ensure qtd exists before dereferencing it to avoid kernel panic. This happens when using usb to ethernet adapter. Acked-by: John Youn Signed-off-by: Gregory Herrero Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/hcd_intr.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index 6ea8eb6899f4d0..4cc95df4262d27 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -1208,6 +1208,16 @@ static void dwc2_hc_nak_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { + if (!qtd) { + dev_dbg(hsotg->dev, "%s: qtd is NULL\n", __func__); + return; + } + + if (!qtd->urb) { + dev_dbg(hsotg->dev, "%s: qtd->urb is NULL\n", __func__); + return; + } + if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "--Host Channel %d Interrupt: NAK Received--\n", chnum); From 94a3e0c4559d22acf05495dc1c4f82d26d5f07d1 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Tue, 28 Apr 2015 20:01:06 +0200 Subject: [PATCH 0394/3798] ARM: sun7i: dt: Add new MK808C device The MK808C is an A20 based android stick, with 1G RAM, 8G NAND flash, a RTL8723au wifi + bt combo chip, a USB host ports using USB-A receptacles, a mini USB-B receptacle for USB OTG, mini HDMI and a TRS connector for AV. This patch adds basic support for the device, more information can be found here (http://linux-sunxi.org/MK808C). Signed-off-by: Marcus Cooper Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/sun7i-a20-mk808c.dts | 148 +++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 arch/arm/boot/dts/sun7i-a20-mk808c.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 83a4e685b0a559..31e1f416b86989 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -560,6 +560,7 @@ dtb-$(CONFIG_MACH_SUN7I) += \ sun7i-a20-hummingbird.dtb \ sun7i-a20-i12-tvbox.dtb \ sun7i-a20-m3.dtb \ + sun7i-a20-mk808c.dtb \ sun7i-a20-olinuxino-lime.dtb \ sun7i-a20-olinuxino-lime2.dtb \ sun7i-a20-olinuxino-micro.dtb \ diff --git a/arch/arm/boot/dts/sun7i-a20-mk808c.dts b/arch/arm/boot/dts/sun7i-a20-mk808c.dts new file mode 100644 index 00000000000000..4f432f8ade77aa --- /dev/null +++ b/arch/arm/boot/dts/sun7i-a20-mk808c.dts @@ -0,0 +1,148 @@ +/* + * Copyright 2015 Marcus Cooper + * + * Marcus Cooper + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun7i-a20.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include + +/ { + model = "mk808c"; + compatible = "allwinner,mk808c", "allwinner,sun7i-a20"; + + aliases { + serial0 = &uart0; + serial1 = &uart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + #interrupt-cells = <1>; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v0>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; From eeea3e67a4b2ab1df4e6e42e86d365fd14e070af Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Apr 2015 14:29:39 +0300 Subject: [PATCH 0395/3798] drm/i915/hdmi: fix vlv infoframe port check Due to missing shifting, the vlv infoframe port check only works for port A. Fix it. Broken since introduction in commit 535afa2e9e3c1867460d6981d879b04d8b2b9ab3 Author: Jesse Barnes Date: Wed Apr 15 16:52:29 2015 -0700 drm/i915/vlv: check port in infoframe_enabled v2 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90059 Tested-by: xubin Tested-by: Ye Tian Reviewed-by: Jesse Barnes Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_hdmi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 56d1d13c075a21..3b9c1176be5b53 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -327,9 +327,8 @@ static bool vlv_infoframe_enabled(struct drm_encoder *encoder) struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); - u32 port = intel_dig_port->port; - if (port == (val & VIDEO_DIP_PORT_MASK)) + if (VIDEO_DIP_PORT(intel_dig_port->port) == (val & VIDEO_DIP_PORT_MASK)) return val & VIDEO_DIP_ENABLE; return false; From d8b183479cd007f7ac5297c7bc4108985b026e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Thu, 30 Apr 2015 09:33:32 +0200 Subject: [PATCH 0396/3798] ARM: at91/dt: kizbox: rename to at91-kizbox MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename to match AT91 naming convention. Signed-off-by: Gaël PORTAY Acked-by: Boris Brezillon Acked-by: Alexandre Belloni Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/Makefile | 2 +- arch/arm/boot/dts/{kizbox.dts => at91-kizbox.dts} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename arch/arm/boot/dts/{kizbox.dts => at91-kizbox.dts} (97%) diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 86217db2937ab3..640c913924cca1 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -20,9 +20,9 @@ dtb-$(CONFIG_SOC_SAM_V4_V5) += \ tny_a9263.dtb \ usb_a9263.dtb \ at91-foxg20.dtb \ + at91-kizbox.dtb \ at91sam9g20ek.dtb \ at91sam9g20ek_2mmc.dtb \ - kizbox.dtb \ tny_a9g20.dtb \ usb_a9g20.dtb \ usb_a9g20_lpw.dtb \ diff --git a/arch/arm/boot/dts/kizbox.dts b/arch/arm/boot/dts/at91-kizbox.dts similarity index 97% rename from arch/arm/boot/dts/kizbox.dts rename to arch/arm/boot/dts/at91-kizbox.dts index e83e4f9310b873..e07afaefcf76a8 100644 --- a/arch/arm/boot/dts/kizbox.dts +++ b/arch/arm/boot/dts/at91-kizbox.dts @@ -1,5 +1,5 @@ /* - * kizbox.dts - Device Tree file for Overkiz Kizbox board + * at91-kizbox.dts - Device Tree file for Overkiz Kizbox board * * Copyright (C) 2012 Boris BREZILLON * From 49668b014db289b034463a810cc936a79a59f1c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Thu, 30 Apr 2015 09:33:33 +0200 Subject: [PATCH 0397/3798] ARM: at91/dt: at91-kizbox: sanitize file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consists in: * sorting nodes by address as possible or alphabetically, * adding myself as new maintainer and * update license. Signed-off-by: Gaël PORTAY Acked-by: Boris Brezillon Acked-by: Alexandre Belloni Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/at91-kizbox.dts | 65 +++++++++++++++---------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/arch/arm/boot/dts/at91-kizbox.dts b/arch/arm/boot/dts/at91-kizbox.dts index e07afaefcf76a8..00c86c1d0a01c2 100644 --- a/arch/arm/boot/dts/at91-kizbox.dts +++ b/arch/arm/boot/dts/at91-kizbox.dts @@ -1,16 +1,16 @@ /* * at91-kizbox.dts - Device Tree file for Overkiz Kizbox board * - * Copyright (C) 2012 Boris BREZILLON + * Copyright (C) 2012-2014 Boris BREZILLON + * 2014-2015 Gaël PORTAY * - * Licensed under GPLv2. + * Licensed under GPLv2 or later. */ /dts-v1/; #include "at91sam9g20.dtsi" / { - - model = "Overkiz kizbox"; + model = "Overkiz Kizbox"; compatible = "overkiz,kizbox", "atmel,at91sam9g20", "atmel,at91sam9"; chosen { @@ -38,10 +38,6 @@ ahb { apb { - dbgu: serial@fffff200 { - status = "okay"; - }; - usart0: serial@fffb0000 { status = "okay"; }; @@ -57,6 +53,10 @@ status = "okay"; }; + dbgu: serial@fffff200 { + status = "okay"; + }; + watchdog@fffffd40 { timeout-sec = <15>; atmel,max-heartbeat-sec = <16>; @@ -65,6 +65,11 @@ }; }; + usb0: ohci@00500000 { + num-ports = <1>; + status = "okay"; + }; + nand0: nand@40000000 { nand-bus-width = <8>; nand-ecc-mode = "soft"; @@ -79,24 +84,36 @@ label = "ubi"; reg = <0xc0000 0x7f40000>; }; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + reset { + label = "reset"; + gpios = <&pioB 30 GPIO_ACTIVE_LOW>; + linux,code = <0x100>; + gpio-key,wakeup; }; - usb0: ohci@00500000 { - num-ports = <1>; - status = "okay"; + mode { + label = "mode"; + gpios = <&pioB 31 GPIO_ACTIVE_LOW>; + linux,code = <0x101>; + gpio-key,wakeup; }; }; i2c@0 { status = "okay"; - pcf8563@51 { - /* nxp pcf8563 rtc */ + rtc: pcf8563@51 { compatible = "nxp,pcf8563"; reg = <0x51>; }; - }; leds { @@ -127,24 +144,4 @@ linux,default-trigger = "none"; }; }; - - gpio_keys { - compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; - - reset { - label = "reset"; - gpios = <&pioB 30 GPIO_ACTIVE_LOW>; - linux,code = <0x100>; - gpio-key,wakeup; - }; - - mode { - label = "mode"; - gpios = <&pioB 31 GPIO_ACTIVE_LOW>; - linux,code = <0x101>; - gpio-key,wakeup; - }; - }; }; From e9942d1f99934fe6c5651e758baf311589fbc72d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Thu, 30 Apr 2015 09:33:34 +0200 Subject: [PATCH 0398/3798] ARM: at91/dt: at91-kizbox: user proper serial uart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit USART3 is the only serial UART accessible. Signed-off-by: Gaël PORTAY Acked-by: Boris Brezillon Acked-by: Alexandre Belloni Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/at91-kizbox.dts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/at91-kizbox.dts b/arch/arm/boot/dts/at91-kizbox.dts index 00c86c1d0a01c2..72d5de807826b9 100644 --- a/arch/arm/boot/dts/at91-kizbox.dts +++ b/arch/arm/boot/dts/at91-kizbox.dts @@ -38,14 +38,6 @@ ahb { apb { - usart0: serial@fffb0000 { - status = "okay"; - }; - - usart1: serial@fffb4000 { - status = "okay"; - }; - macb0: ethernet@fffc4000 { phy-mode = "mii"; pinctrl-0 = <&pinctrl_macb_rmii @@ -53,6 +45,10 @@ status = "okay"; }; + usart3: serial@fffd0000 { + status = "okay"; + }; + dbgu: serial@fffff200 { status = "okay"; }; From d1b063aba81320cabdb093739b54dd4b3c92d159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Thu, 30 Apr 2015 09:33:35 +0200 Subject: [PATCH 0399/3798] ARM: at91/dt: at91-kizbox: gpio-keys related changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This: * fixes active level of GPIO (active high) and * renames buttons: - reset (PB_RST), and - mode to user (PB_USER). Signed-off-by: Gaël PORTAY Acked-by: Boris Brezillon Acked-by: Alexandre Belloni Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/at91-kizbox.dts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/at91-kizbox.dts b/arch/arm/boot/dts/at91-kizbox.dts index 72d5de807826b9..73e4559862d39b 100644 --- a/arch/arm/boot/dts/at91-kizbox.dts +++ b/arch/arm/boot/dts/at91-kizbox.dts @@ -89,15 +89,15 @@ #size-cells = <0>; reset { - label = "reset"; - gpios = <&pioB 30 GPIO_ACTIVE_LOW>; + label = "PB_RST"; + gpios = <&pioB 30 GPIO_ACTIVE_HIGH>; linux,code = <0x100>; gpio-key,wakeup; }; - mode { - label = "mode"; - gpios = <&pioB 31 GPIO_ACTIVE_LOW>; + user { + label = "PB_USER"; + gpios = <&pioB 31 GPIO_ACTIVE_HIGH>; linux,code = <0x101>; gpio-key,wakeup; }; From 4a225bed2b6e45b146d508ceb55f1d7c813050c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Thu, 30 Apr 2015 09:33:36 +0200 Subject: [PATCH 0400/3798] ARM: at91/dt: at91-kizbox: leds related changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This: * moves to pwm-leds using tcb-pwm driver and * renames leds to pwm::. Signed-off-by: Gaël PORTAY Acked-by: Boris Brezillon Acked-by: Alexandre Belloni Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/at91-kizbox.dts | 53 ++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/arch/arm/boot/dts/at91-kizbox.dts b/arch/arm/boot/dts/at91-kizbox.dts index 73e4559862d39b..b19f568824df29 100644 --- a/arch/arm/boot/dts/at91-kizbox.dts +++ b/arch/arm/boot/dts/at91-kizbox.dts @@ -8,6 +8,7 @@ */ /dts-v1/; #include "at91sam9g20.dtsi" +#include / { model = "Overkiz Kizbox"; @@ -112,32 +113,46 @@ }; }; - leds { - compatible = "gpio-leds"; + pwm_leds { + compatible = "pwm-leds"; - led1g { - label = "led1:green"; - gpios = <&pioB 0 GPIO_ACTIVE_LOW>; - linux,default-trigger = "none"; + network_green { + label = "pwm:green:network"; + pwms = <&tcb_pwm 2 10000000 PWM_POLARITY_INVERTED>; + max-brightness = <255>; + linux,default-trigger = "default-on"; }; - led1r { - label = "led1:red"; - gpios = <&pioB 1 GPIO_ACTIVE_LOW>; - linux,default-trigger = "none"; + network_red { + label = "pwm:red:network"; + pwms = <&tcb_pwm 3 10000000 PWM_POLARITY_INVERTED>; + max-brightness = <255>; + linux,default-trigger = "default-on"; }; - led2g { - label = "led2:green"; - gpios = <&pioB 2 GPIO_ACTIVE_LOW>; - linux,default-trigger = "none"; - default-state = "on"; + user_green { + label = "pwm:green:user"; + pwms = <&tcb_pwm 0 10000000 PWM_POLARITY_INVERTED>; + max-brightness = <255>; + linux,default-trigger = "default-on"; }; - led2r { - label = "led2:red"; - gpios = <&pioB 3 GPIO_ACTIVE_LOW>; - linux,default-trigger = "none"; + user_red { + label = "pwm:red:user"; + pwms = <&tcb_pwm 1 10000000 PWM_POLARITY_INVERTED>; + max-brightness = <255>; + linux,default-trigger = "default-on"; }; }; + + tcb_pwm: pwm { + compatible = "atmel,tcb-pwm"; + #pwm-cells = <3>; + tc-block = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_tcb1_tioa0 + &pinctrl_tcb1_tioa1 + &pinctrl_tcb1_tioa2 + &pinctrl_tcb1_tiob0>; + }; }; From ea6858497c4332500669118faa9b79729c5f68a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Thu, 30 Apr 2015 09:33:37 +0200 Subject: [PATCH 0401/3798] ARM: at91/dt: at91-kizbox: re-size nand partitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-size NAND partitions since the bootstrap is able to read volumes from an UBI image. Signed-off-by: Gaël PORTAY Acked-by: Boris Brezillon Acked-by: Alexandre Belloni Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/at91-kizbox.dts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/at91-kizbox.dts b/arch/arm/boot/dts/at91-kizbox.dts index b19f568824df29..e7391047f08e2c 100644 --- a/arch/arm/boot/dts/at91-kizbox.dts +++ b/arch/arm/boot/dts/at91-kizbox.dts @@ -72,14 +72,14 @@ nand-ecc-mode = "soft"; status = "okay"; - bootloaderkernel@0 { - label = "bootloader-kernel"; - reg = <0x0 0xc0000>; + bootstrap@0 { + label = "bootstrap"; + reg = <0x0 0x20000>; }; - ubi@c0000 { + ubi@20000 { label = "ubi"; - reg = <0xc0000 0x7f40000>; + reg = <0x20000 0x7fe0000>; }; }; }; From 81104f6082d5a684d644932068ee3bbb969daf23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Thu, 30 Apr 2015 09:33:38 +0200 Subject: [PATCH 0402/3798] ARM: at91/dt: at91-kizbox: update chosen node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify the bootargs since the platform is booting from an initramfs and set the kernel stdout path to DBGU. Signed-off-by: Gaël PORTAY Acked-by: Boris Brezillon Acked-by: Alexandre Belloni Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/at91-kizbox.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/at91-kizbox.dts b/arch/arm/boot/dts/at91-kizbox.dts index e7391047f08e2c..b567b5ff908fa8 100644 --- a/arch/arm/boot/dts/at91-kizbox.dts +++ b/arch/arm/boot/dts/at91-kizbox.dts @@ -15,7 +15,8 @@ compatible = "overkiz,kizbox", "atmel,at91sam9g20", "atmel,at91sam9"; chosen { - bootargs = "panic=5 ubi.mtd=1 rootfstype=ubifs root=ubi0:root"; + bootargs = "ubi.mtd=ubi"; + linux,stdout-path = &dbgu; }; memory { From 052f62f78955106a14961f0d3d34c256e896303a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Apr 2015 15:30:07 +0300 Subject: [PATCH 0403/3798] drm/i915/hdmi: check port in ibx_infoframe_enabled Add port check for ibx similar to vlv in commit 535afa2e9e3c1867460d6981d879b04d8b2b9ab3 Author: Jesse Barnes Date: Wed Apr 15 16:52:29 2015 -0700 drm/i915/vlv: check port in infoframe_enabled v2 Reviewed-by: Jesse Barnes Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_hdmi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 3b9c1176be5b53..f8d0d81da47de6 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -223,10 +223,14 @@ static bool ibx_infoframe_enabled(struct drm_encoder *encoder) struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); + struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); - return val & VIDEO_DIP_ENABLE; + if (VIDEO_DIP_PORT(intel_dig_port->port) == (val & VIDEO_DIP_PORT_MASK)) + return val & VIDEO_DIP_ENABLE; + + return false; } static void cpt_write_infoframe(struct drm_encoder *encoder, From 9286ac4829ba66efa1c258411dfe51736cb3cfc0 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Fri, 10 Apr 2015 11:40:00 +0200 Subject: [PATCH 0404/3798] ARM: STi: DT: STiH407: Add dt nodes for sdhci and emmc. The nodes have been split to allow as much commonality as possible. The stih407 has a silicon bug with eMMC UHS modes (with top regs) and as such doesn't have any of the uhs dt properties. Signed-off-by: Peter Griffin Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 30 +++++++++++++++++++++++++++ arch/arm/boot/dts/stih410-b2120.dts | 10 +++++++++ arch/arm/boot/dts/stihxxx-b2120.dtsi | 8 +++++++ 3 files changed, 48 insertions(+) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index 655f8544a6734b..11d5c70b8d80b6 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -421,5 +421,35 @@ status = "disabled"; }; + + mmc0: sdhci@09060000 { + compatible = "st,sdhci-stih407", "st,sdhci"; + status = "disabled"; + reg = <0x09060000 0x7ff>, <0x9061008 0x20>; + reg-names = "mmc", "top-mmc-delay"; + interrupts = ; + interrupt-names = "mmcirq"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mmc0>; + clock-names = "mmc"; + clocks = <&clk_s_c0_flexgen CLK_MMC_0>; + bus-width = <8>; + non-removable; + }; + + mmc1: sdhci@09080000 { + compatible = "st,sdhci-stih407", "st,sdhci"; + status = "disabled"; + reg = <0x09080000 0x7ff>; + reg-names = "mmc"; + interrupts = ; + interrupt-names = "mmcirq"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sd1>; + clock-names = "mmc"; + clocks = <&clk_s_c0_flexgen CLK_MMC_1>; + resets = <&softreset STIH407_MMC1_SOFTRESET>; + bus-width = <4>; + }; }; }; diff --git a/arch/arm/boot/dts/stih410-b2120.dts b/arch/arm/boot/dts/stih410-b2120.dts index 2f61a9960dee60..16f02c5e33a468 100644 --- a/arch/arm/boot/dts/stih410-b2120.dts +++ b/arch/arm/boot/dts/stih410-b2120.dts @@ -26,4 +26,14 @@ aliases { ttyAS0 = &sbc_serial0; }; + + soc { + + mmc0: sdhci@09060000 { + max-frequency = <200000000>; + sd-uhs-sdr50; + sd-uhs-sdr104; + sd-uhs-ddr50; + }; + }; }; diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi b/arch/arm/boot/dts/stihxxx-b2120.dtsi index c1d859092be7f0..64fa0b5a0f2444 100644 --- a/arch/arm/boot/dts/stihxxx-b2120.dtsi +++ b/arch/arm/boot/dts/stihxxx-b2120.dtsi @@ -47,6 +47,14 @@ status = "okay"; }; + mmc0: sdhci@09060000 { + status = "okay"; + }; + + mmc1: sdhci@09080000 { + status = "okay"; + }; + /* SSC11 to HDMI */ hdmiddc: i2c@9541000 { status = "okay"; From ba7f2728dd6f266a8b46def8eb7ede07a2ed2b00 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Fri, 10 Apr 2015 11:40:00 +0200 Subject: [PATCH 0405/3798] ARM: STi: DT: STiH418: Add dt nodes for sdhci and emmc. Add dt nodes to enable sdhci / eMMC for stih418-b2199 board. Signed-off-by: Peter Griffin Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih418-b2199.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/stih418-b2199.dts b/arch/arm/boot/dts/stih418-b2199.dts index 926235c08e4d05..a2fdada5b4e57f 100644 --- a/arch/arm/boot/dts/stih418-b2199.dts +++ b/arch/arm/boot/dts/stih418-b2199.dts @@ -74,5 +74,17 @@ st,i2c-min-scl-pulse-width-us = <0>; st,i2c-min-sda-pulse-width-us = <5>; }; + + mmc1: sdhci@09080000 { + status = "okay"; + }; + + mmc0: sdhci@09060000 { + status = "okay"; + max-frequency = <200000000>; + sd-uhs-sdr50; + sd-uhs-sdr104; + sd-uhs-ddr50; + }; }; }; From d9ca7e929d0825984873c2dd3e0bd9fda82e44be Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 29 Apr 2015 16:21:59 +0200 Subject: [PATCH 0406/3798] Staging: iop.c: move assignment out of if () block We should not be doing assignments within an if () block so fix up the code to not do this. change was created using Coccinelle. CC: Supriya Karanth CC: Somya Anand CC: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i2o/iop.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/staging/i2o/iop.c b/drivers/staging/i2o/iop.c index 23bdbe4aa48021..142aab8c77387f 100644 --- a/drivers/staging/i2o/iop.c +++ b/drivers/staging/i2o/iop.c @@ -300,7 +300,8 @@ static int i2o_iop_quiesce(struct i2o_controller *c) ADAPTER_TID); /* Long timeout needed for quiesce if lots of devices */ - if ((rc = i2o_msg_post_wait(c, msg, 240))) + rc = i2o_msg_post_wait(c, msg, 240); + if (rc) osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc); else osm_debug("%s: Quiesced.\n", c->name); @@ -340,7 +341,8 @@ static int i2o_iop_enable(struct i2o_controller *c) ADAPTER_TID); /* How long of a timeout do we need? */ - if ((rc = i2o_msg_post_wait(c, msg, 240))) + rc = i2o_msg_post_wait(c, msg, 240); + if (rc) osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc); else osm_debug("%s: Enabled.\n", c->name); @@ -406,7 +408,8 @@ static int i2o_iop_clear(struct i2o_controller *c) cpu_to_le32(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | ADAPTER_TID); - if ((rc = i2o_msg_post_wait(c, msg, 30))) + rc = i2o_msg_post_wait(c, msg, 30); + if (rc) osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc); else osm_debug("%s: Cleared.\n", c->name); From a1e6ad667550a9be173d0a0cfbba236d9252f837 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 17 Apr 2015 19:31:21 +0300 Subject: [PATCH 0407/3798] drm/i915: factor out ddi_get_encoder_port In the next patch we'll need to get at both the encoder's intel_digital_port object - which maybe NULL for a CRT - and it's port, so factor out this functionality. No functional change. Signed-off-by: Imre Deak Reviewed-by: Damien Lespiau Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_ddi.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 455d44b49c66b6..903d395b27cc85 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -210,29 +210,39 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = { { 154, 0x9A, 1, 128, true }, /* 9: 1200 0 */ }; -enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) +static void ddi_get_encoder_port(struct intel_encoder *intel_encoder, + struct intel_digital_port **dig_port, + enum port *port) { struct drm_encoder *encoder = &intel_encoder->base; int type = intel_encoder->type; if (type == INTEL_OUTPUT_DP_MST) { - struct intel_digital_port *intel_dig_port = enc_to_mst(encoder)->primary; - return intel_dig_port->port; + *dig_port = enc_to_mst(encoder)->primary; + *port = (*dig_port)->port; } else if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_UNKNOWN) { - struct intel_digital_port *intel_dig_port = - enc_to_dig_port(encoder); - return intel_dig_port->port; - + *dig_port = enc_to_dig_port(encoder); + *port = (*dig_port)->port; } else if (type == INTEL_OUTPUT_ANALOG) { - return PORT_E; - + *dig_port = NULL; + *port = PORT_E; } else { DRM_ERROR("Invalid DDI encoder type %d\n", type); BUG(); } } +enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) +{ + struct intel_digital_port *dig_port; + enum port port; + + ddi_get_encoder_port(intel_encoder, &dig_port, &port); + + return port; +} + static bool intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) { From faa0cdbec1c258896bff8bb59051bbada4fd6f09 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 17 Apr 2015 19:31:22 +0300 Subject: [PATCH 0408/3798] drm/i915: fix intel_prepare_ddi At the moment intel_prepare_ddi buffer will iterate through both MST and CRT encoders, which is incorrect. Neither of these encoder types have an embedding intel_digital_port object, so for these encoder types we will use random data when dereferencing the corresponding intel_digital_port->port field. Introduced in commit b403745c84592b26a0713e6944c2b109f6df5c82 Author: Damien Lespiau Date: Mon Aug 4 22:01:33 2014 +0100 drm/i915: Iterate through the initialized DDIs to prepare their buffers v2: - fix getting at the port for MST encoders too - make sure that intel_prepare_ddi_buffers() gets called for port E too (Paulo) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90067 Signed-off-by: Imre Deak Reviewed-by: Damien Lespiau Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.h | 5 ----- drivers/gpu/drm/i915/intel_ddi.c | 28 ++++++++++++++++++---------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6c030639f8d9e0..e08cd85eb51905 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -251,11 +251,6 @@ enum hpd_pin { &dev->mode_config.connector_list, \ base.head) -#define for_each_digital_port(dev, digital_port) \ - list_for_each_entry(digital_port, \ - &dev->mode_config.encoder_list, \ - base.base.head) - #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \ list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \ if ((intel_encoder)->base.crtc == (__crtc)) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 903d395b27cc85..9c1e74a3a27728 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -256,12 +256,11 @@ intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) * in either FDI or DP modes only, as HDMI connections will work with both * of those */ -static void intel_prepare_ddi_buffers(struct drm_device *dev, - struct intel_digital_port *intel_dig_port) +static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, + bool supports_hdmi) { struct drm_i915_private *dev_priv = dev->dev_private; u32 reg; - int port = intel_dig_port->port; int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_default_entry, size; int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; @@ -272,7 +271,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, const struct ddi_buf_trans *ddi_translations; if (IS_BROXTON(dev)) { - if (!intel_dig_port_supports_hdmi(intel_dig_port)) + if (!supports_hdmi) return; /* Vswing programming for HDMI */ @@ -360,7 +359,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, reg += 4; } - if (!intel_dig_port_supports_hdmi(intel_dig_port)) + if (!supports_hdmi) return; /* Choose a good default if VBT is badly populated */ @@ -380,18 +379,27 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, */ void intel_prepare_ddi(struct drm_device *dev) { - struct intel_digital_port *intel_dig_port; + struct intel_encoder *intel_encoder; bool visited[I915_MAX_PORTS] = { 0, }; if (!HAS_DDI(dev)) return; - for_each_digital_port(dev, intel_dig_port) { - if (visited[intel_dig_port->port]) + for_each_intel_encoder(dev, intel_encoder) { + struct intel_digital_port *intel_dig_port; + enum port port; + bool supports_hdmi; + + ddi_get_encoder_port(intel_encoder, &intel_dig_port, &port); + + if (visited[port]) continue; - intel_prepare_ddi_buffers(dev, intel_dig_port); - visited[intel_dig_port->port] = true; + supports_hdmi = intel_dig_port && + intel_dig_port_supports_hdmi(intel_dig_port); + + intel_prepare_ddi_buffers(dev, port, supports_hdmi); + visited[port] = true; } } From 245054a1fe33c06ad233e0d58a27ec7b64db9284 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 14 Apr 2015 17:35:22 +0200 Subject: [PATCH 0409/3798] drm/i915: Enable cmd parser to do secure batch promotion for aliasing ppgtt With the binding regression from the original full ppgtt patches fixed we can throw the switch. Yay! Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90190 Signed-off-by: Daniel Vetter Reviewed-by: Mika Kuoppala [Jani: tweaked commit title per Chris' suggestion] Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index cfdc8c6073aa87..d2e21c549756ac 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1558,12 +1558,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, * dispatch_execbuffer implementations. We specifically * don't want that set when the command parser is * enabled. - * - * FIXME: with aliasing ppgtt, buffers that should only - * be in ggtt still end up in the aliasing ppgtt. remove - * this check when that is fixed. */ - if (USES_FULL_PPGTT(dev)) + if (USES_PPGTT(dev)) dispatch_flags |= I915_DISPATCH_SECURE; exec_start = 0; From 75d04a3773ecee617847de963ae4195d6aa74c28 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 28 Apr 2015 17:56:17 +0300 Subject: [PATCH 0410/3798] drm/i915/gtt: Allocate va range only if vma is not bound When we have bound vma into an address space, the layout of page table structures is immutable. So we can be absolutely certain that if vma is already bound, there is no need to (re)allocate a virtual address range for it. v2: - add sanity checks and remove superfluous GLOBAL_BIND set - we might do update for an unbound vma (Chris) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90224 Testcase: igt/gem_exec_big #bdw Reported-by: Chris Wilson Cc: Chris Wilson Cc: Michel Thierry Cc: Daniel Vetter Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gem_gtt.c | 39 ++++++++++++++++------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 6fae6bdde156f1..9d3852c521c753 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1928,8 +1928,6 @@ static int ggtt_bind_vma(struct i915_vma *vma, vma->vm->insert_entries(vma->vm, pages, vma->node.start, cache_level, pte_flags); - - vma->bound |= GLOBAL_BIND; } if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) { @@ -2804,21 +2802,13 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma) int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags) { - int ret = 0; - u32 bind_flags = 0; - - if (vma->vm->allocate_va_range) { - trace_i915_va_alloc(vma->vm, vma->node.start, - vma->node.size, - VM_TO_TRACE_NAME(vma->vm)); + int ret; + u32 bind_flags; - ret = vma->vm->allocate_va_range(vma->vm, - vma->node.start, - vma->node.size); - if (ret) - return ret; - } + if (WARN_ON(flags == 0)) + return -EINVAL; + bind_flags = 0; if (flags & PIN_GLOBAL) bind_flags |= GLOBAL_BIND; if (flags & PIN_USER) @@ -2829,8 +2819,23 @@ int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, else bind_flags &= ~vma->bound; - if (bind_flags) - ret = vma->vm->bind_vma(vma, cache_level, bind_flags); + if (bind_flags == 0) + return 0; + + if (vma->bound == 0 && vma->vm->allocate_va_range) { + trace_i915_va_alloc(vma->vm, + vma->node.start, + vma->node.size, + VM_TO_TRACE_NAME(vma->vm)); + + ret = vma->vm->allocate_va_range(vma->vm, + vma->node.start, + vma->node.size); + if (ret) + return ret; + } + + ret = vma->vm->bind_vma(vma, cache_level, bind_flags); if (ret) return ret; From 1b344b9669930ec36b86b639ee71bb6bf3ba425a Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 9 Apr 2015 16:47:00 +0200 Subject: [PATCH 0411/3798] ARM: multi_v7_defconfig: Enable support for ST's LPC Watchdog Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index ab86655c1f4be2..8a566fd8f7b9ee 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -334,6 +334,7 @@ CONFIG_WATCHDOG=y CONFIG_XILINX_WATCHDOG=y CONFIG_ARM_SP805_WATCHDOG=y CONFIG_ORION_WATCHDOG=y +CONFIG_ST_LPC_WATCHDOG=y CONFIG_SUNXI_WATCHDOG=y CONFIG_MESON_WATCHDOG=y CONFIG_MFD_AS3711=y From cb6a7a9e00fda1d51880ac0e93ad54a87034e822 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 9 Apr 2015 16:47:00 +0200 Subject: [PATCH 0412/3798] ARM: multi_v7_defconfig: Enable support for ST's LPC RTC Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 8a566fd8f7b9ee..a841847f9c6e7c 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -500,6 +500,7 @@ CONFIG_RTC_DRV_MAX8907=y CONFIG_RTC_DRV_MAX77686=y CONFIG_RTC_DRV_RS5C372=m CONFIG_RTC_DRV_PALMAS=y +CONFIG_RTC_DRV_ST_LPC=y CONFIG_RTC_DRV_TWL4030=y CONFIG_RTC_DRV_TPS6586X=y CONFIG_RTC_DRV_TPS65910=y From 042f7df15a4fff8eec42873f755aea848dcdedd1 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Thu, 30 Apr 2015 17:16:12 +0800 Subject: [PATCH 0413/3798] workqueue: Allow modifying low level unbound workqueue cpumask Allow to modify the low-level unbound workqueues cpumask through sysfs. This is performed by traversing the entire workqueue list and calling apply_wqattrs_prepare() on the unbound workqueues with the new low level mask. Only after all the preparation are done, we commit them all together. Ordered workqueues are ignored from the low level unbound workqueue cpumask, it will be handled in near future. All the (default & per-node) pwqs are mandatorily controlled by the low level cpumask. If the user configured cpumask doesn't overlap with the low level cpumask, the low level cpumask will be used for the wq instead. The comment of wq_calc_node_cpumask() is updated and explicitly requires that its first argument should be the attrs of the default pwq. The default wq_unbound_cpumask is cpu_possible_mask. The workqueue subsystem doesn't know its best default value, let the system manager or the other subsystem set it when needed. Changed from V8: merge the calculating code for the attrs of the default pwq together. minor change the code&comments for saving the user configured attrs. remove unnecessary list_del(). minor update the comment of wq_calc_node_cpumask(). update the comment of workqueue_set_unbound_cpumask(); Cc: Christoph Lameter Cc: Kevin Hilman Cc: Lai Jiangshan Cc: Mike Galbraith Cc: Paul E. McKenney Cc: Tejun Heo Cc: Viresh Kumar Cc: Frederic Weisbecker Original-patch-by: Frederic Weisbecker Signed-off-by: Lai Jiangshan Signed-off-by: Tejun Heo --- include/linux/workqueue.h | 1 + kernel/workqueue.c | 127 +++++++++++++++++++++++++++++++++++--- 2 files changed, 119 insertions(+), 9 deletions(-) diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index deee212af8e093..4618dd672d1b34 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -424,6 +424,7 @@ struct workqueue_attrs *alloc_workqueue_attrs(gfp_t gfp_mask); void free_workqueue_attrs(struct workqueue_attrs *attrs); int apply_workqueue_attrs(struct workqueue_struct *wq, const struct workqueue_attrs *attrs); +int workqueue_set_unbound_cpumask(cpumask_var_t cpumask); extern bool queue_work_on(int cpu, struct workqueue_struct *wq, struct work_struct *work); diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 9be75e2a4da6cb..a3915abc19833c 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -299,7 +299,7 @@ static DEFINE_SPINLOCK(wq_mayday_lock); /* protects wq->maydays list */ static LIST_HEAD(workqueues); /* PR: list of all workqueues */ static bool workqueue_freezing; /* PL: have wqs started freezing? */ -static cpumask_var_t wq_unbound_cpumask; +static cpumask_var_t wq_unbound_cpumask; /* PL: low level cpumask for all unbound wqs */ /* the per-cpu worker pools */ static DEFINE_PER_CPU_SHARED_ALIGNED(struct worker_pool [NR_STD_WORKER_POOLS], @@ -3429,7 +3429,7 @@ static struct pool_workqueue *alloc_unbound_pwq(struct workqueue_struct *wq, /** * wq_calc_node_mask - calculate a wq_attrs' cpumask for the specified node - * @attrs: the wq_attrs of interest + * @attrs: the wq_attrs of the default pwq of the target workqueue * @node: the target NUMA node * @cpu_going_down: if >= 0, the CPU to consider as offline * @cpumask: outarg, the resulting cpumask @@ -3493,6 +3493,7 @@ static struct pool_workqueue *numa_pwq_tbl_install(struct workqueue_struct *wq, struct apply_wqattrs_ctx { struct workqueue_struct *wq; /* target workqueue */ struct workqueue_attrs *attrs; /* attrs to apply */ + struct list_head list; /* queued for batching commit */ struct pool_workqueue *dfl_pwq; struct pool_workqueue *pwq_tbl[]; }; @@ -3532,9 +3533,15 @@ apply_wqattrs_prepare(struct workqueue_struct *wq, if (!ctx || !new_attrs || !tmp_attrs) goto out_free; - /* make a copy of @attrs and sanitize it */ + /* + * Calculate the attrs of the default pwq. + * If the user configured cpumask doesn't overlap with the + * wq_unbound_cpumask, we fallback to the wq_unbound_cpumask. + */ copy_workqueue_attrs(new_attrs, attrs); cpumask_and(new_attrs->cpumask, new_attrs->cpumask, wq_unbound_cpumask); + if (unlikely(cpumask_empty(new_attrs->cpumask))) + cpumask_copy(new_attrs->cpumask, wq_unbound_cpumask); /* * We may create multiple pwqs with differing cpumasks. Make a @@ -3553,7 +3560,7 @@ apply_wqattrs_prepare(struct workqueue_struct *wq, goto out_free; for_each_node(node) { - if (wq_calc_node_cpumask(attrs, node, -1, tmp_attrs->cpumask)) { + if (wq_calc_node_cpumask(new_attrs, node, -1, tmp_attrs->cpumask)) { ctx->pwq_tbl[node] = alloc_unbound_pwq(wq, tmp_attrs); if (!ctx->pwq_tbl[node]) goto out_free; @@ -3563,7 +3570,11 @@ apply_wqattrs_prepare(struct workqueue_struct *wq, } } + /* save the user configured attrs and sanitize it. */ + copy_workqueue_attrs(new_attrs, attrs); + cpumask_and(new_attrs->cpumask, new_attrs->cpumask, cpu_possible_mask); ctx->attrs = new_attrs; + ctx->wq = wq; free_workqueue_attrs(tmp_attrs); return ctx; @@ -3704,11 +3715,11 @@ static void wq_update_unbound_numa(struct workqueue_struct *wq, int cpu, /* * Let's determine what needs to be done. If the target cpumask is - * different from wq's, we need to compare it to @pwq's and create - * a new one if they don't match. If the target cpumask equals - * wq's, the default pwq should be used. + * different from the default pwq's, we need to compare it to @pwq's + * and create a new one if they don't match. If the target cpumask + * equals the default pwq's, the default pwq should be used. */ - if (wq_calc_node_cpumask(wq->unbound_attrs, node, cpu_off, cpumask)) { + if (wq_calc_node_cpumask(wq->dfl_pwq->pool->attrs, node, cpu_off, cpumask)) { if (cpumask_equal(cpumask, pwq->pool->attrs->cpumask)) goto out_unlock; } else { @@ -4731,6 +4742,84 @@ void thaw_workqueues(void) } #endif /* CONFIG_FREEZER */ +static int workqueue_apply_unbound_cpumask(void) +{ + LIST_HEAD(ctxs); + int ret = 0; + struct workqueue_struct *wq; + struct apply_wqattrs_ctx *ctx, *n; + + lockdep_assert_held(&wq_pool_mutex); + + list_for_each_entry(wq, &workqueues, list) { + if (!(wq->flags & WQ_UNBOUND)) + continue; + /* creating multiple pwqs breaks ordering guarantee */ + if (wq->flags & __WQ_ORDERED) + continue; + + ctx = apply_wqattrs_prepare(wq, wq->unbound_attrs); + if (!ctx) { + ret = -ENOMEM; + break; + } + + list_add_tail(&ctx->list, &ctxs); + } + + list_for_each_entry_safe(ctx, n, &ctxs, list) { + if (!ret) + apply_wqattrs_commit(ctx); + apply_wqattrs_cleanup(ctx); + } + + return ret; +} + +/** + * workqueue_set_unbound_cpumask - Set the low-level unbound cpumask + * @cpumask: the cpumask to set + * + * The low-level workqueues cpumask is a global cpumask that limits + * the affinity of all unbound workqueues. This function check the @cpumask + * and apply it to all unbound workqueues and updates all pwqs of them. + * + * Retun: 0 - Success + * -EINVAL - Invalid @cpumask + * -ENOMEM - Failed to allocate memory for attrs or pwqs. + */ +int workqueue_set_unbound_cpumask(cpumask_var_t cpumask) +{ + int ret = -EINVAL; + cpumask_var_t saved_cpumask; + + if (!zalloc_cpumask_var(&saved_cpumask, GFP_KERNEL)) + return -ENOMEM; + + get_online_cpus(); + cpumask_and(cpumask, cpumask, cpu_possible_mask); + if (!cpumask_empty(cpumask)) { + mutex_lock(&wq_pool_mutex); + + /* save the old wq_unbound_cpumask. */ + cpumask_copy(saved_cpumask, wq_unbound_cpumask); + + /* update wq_unbound_cpumask at first and apply it to wqs. */ + cpumask_copy(wq_unbound_cpumask, cpumask); + ret = workqueue_apply_unbound_cpumask(); + + /* restore the wq_unbound_cpumask when failed. */ + if (ret < 0) + cpumask_copy(wq_unbound_cpumask, saved_cpumask); + + mutex_unlock(&wq_pool_mutex); + } + put_online_cpus(); + + free_cpumask_var(saved_cpumask); + return ret; +} + #ifdef CONFIG_SYSFS /* * Workqueues with WQ_SYSFS flag set is visible to userland via @@ -4952,14 +5041,34 @@ static ssize_t wq_unbound_cpumask_show(struct device *dev, { int written; + mutex_lock(&wq_pool_mutex); written = scnprintf(buf, PAGE_SIZE, "%*pb\n", cpumask_pr_args(wq_unbound_cpumask)); + mutex_unlock(&wq_pool_mutex); return written; } +static ssize_t wq_unbound_cpumask_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + cpumask_var_t cpumask; + int ret; + + if (!zalloc_cpumask_var(&cpumask, GFP_KERNEL)) + return -ENOMEM; + + ret = cpumask_parse(buf, cpumask); + if (!ret) + ret = workqueue_set_unbound_cpumask(cpumask); + + free_cpumask_var(cpumask); + return ret ? ret : count; +} + static struct device_attribute wq_sysfs_cpumask_attr = - __ATTR(cpumask, 0444, wq_unbound_cpumask_show, NULL); + __ATTR(cpumask, 0644, wq_unbound_cpumask_show, + wq_unbound_cpumask_store); static int __init wq_sysfs_init(void) { From 358764f306242bf2b3d71693b04b05e0b75718ae Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 9 Apr 2015 16:47:00 +0200 Subject: [PATCH 0414/3798] ARM: STi: DT: STiH407: Add Device Tree node for the LPC On current ST platforms the LPC controls a number of functions. This patch enables support for the LPC Watchdog and LPC RTC devices on LPC1 and LPC2 respectively. Signed-off-by: David Paris Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index 11d5c70b8d80b6..cdee4a7799b451 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -7,6 +7,7 @@ * publishhed by the Free Software Foundation. */ #include "stih407-pinctrl.dtsi" +#include #include / { #address-cells = <1>; @@ -451,5 +452,24 @@ resets = <&softreset STIH407_MMC1_SOFTRESET>; bus-width = <4>; }; + + /* Watchdog and Real-Time Clock */ + lpc@8787000 { + compatible = "st,stih407-lpc"; + reg = <0x8787000 0x1000>; + interrupts = ; + clocks = <&clk_s_d3_flexgen CLK_LPC_0>; + timeout-sec = <120>; + st,syscfg = <&syscfg_core>; + st,lpc-mode = ; + }; + + lpc@8788000 { + compatible = "st,stih407-lpc"; + reg = <0x8788000 0x1000>; + interrupts = ; + clocks = <&clk_s_d3_flexgen CLK_LPC_1>; + st,lpc-mode = ; + }; }; }; From d90accb913a7a72172ec6b82f8b8766d9c9bf8bf Mon Sep 17 00:00:00 2001 From: Karim BEN BELGACEM Date: Wed, 18 Mar 2015 18:21:00 +0100 Subject: [PATCH 0415/3798] ARM: STi: DT: STiH407: Fix retime pin mask for PIO5 and PIO35 This will avoid programming the retime registers when not implemented - PIO5 : no retime registers assigned to pins 6 and 7 - PIO35 : pin 7 is reserved so no retime register assigned to it Signed-off-by: Karim BEN BELGACEM Acked-by: Maxime Coquelin Signed-off-by: Lee Jones Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-pinctrl.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/stih407-pinctrl.dtsi b/arch/arm/boot/dts/stih407-pinctrl.dtsi index 402844cb31524d..0a754f2752121e 100644 --- a/arch/arm/boot/dts/stih407-pinctrl.dtsi +++ b/arch/arm/boot/dts/stih407-pinctrl.dtsi @@ -104,6 +104,7 @@ #interrupt-cells = <2>; reg = <0x5000 0x100>; st,bank-name = "PIO5"; + st,retime-pin-mask = <0x3f>; }; rc { @@ -519,6 +520,7 @@ #interrupt-cells = <2>; reg = <0x5000 0x100>; st,bank-name = "PIO35"; + st,retime-pin-mask = <0x7f>; }; i2c4 { From b3d37f92a79a329c392712da5e71fdd6c0258c3a Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Tue, 31 Mar 2015 09:35:00 +0200 Subject: [PATCH 0416/3798] ARM: DT: STi: STiH407: Add sata DT nodes. Now that the miphy28lp is upstream, we can add the sata dt nodes for stih407 family silicon. This has been tested on b2120 board J4 (sata0 channel). These nodes are disabled by default as a special mini pci-e to sata daughter board is required which isn't shipped with the board. Signed-off-by: Peter Griffin Acked-by: Lee Jones Acked-by: Maxime Coquelin Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 45 +++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index cdee4a7799b451..85159b823867ee 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -8,6 +8,7 @@ */ #include "stih407-pinctrl.dtsi" #include +#include #include / { #address-cells = <1>; @@ -471,5 +472,49 @@ clocks = <&clk_s_d3_flexgen CLK_LPC_1>; st,lpc-mode = ; }; + + sata0: sata@9b20000 { + compatible = "st,ahci"; + reg = <0x9b20000 0x1000>; + + interrupts = ; + interrupt-names = "hostc"; + + phys = <&phy_port0 PHY_TYPE_SATA>; + phy-names = "ahci_phy"; + + resets = <&powerdown STIH407_SATA0_POWERDOWN>, + <&softreset STIH407_SATA0_SOFTRESET>, + <&softreset STIH407_SATA0_PWR_SOFTRESET>; + reset-names = "pwr-dwn", "sw-rst", "pwr-rst"; + + clock-names = "ahci_clk"; + clocks = <&clk_s_c0_flexgen CLK_ICN_REG>; + + status = "disabled"; + }; + + sata1: sata@9b28000 { + compatible = "st,ahci"; + reg = <0x9b28000 0x1000>; + + interrupts = ; + interrupt-names = "hostc"; + + phys = <&phy_port1 PHY_TYPE_SATA>; + phy-names = "ahci_phy"; + + resets = <&powerdown STIH407_SATA1_POWERDOWN>, + <&softreset STIH407_SATA1_SOFTRESET>, + <&softreset STIH407_SATA1_PWR_SOFTRESET>; + reset-names = "pwr-dwn", + "sw-rst", + "pwr-rst"; + + clock-names = "ahci_clk"; + clocks = <&clk_s_c0_flexgen CLK_ICN_REG>; + + status = "disabled"; + }; }; }; From 3ede1b6be0718eb22531c573afc87f275147fbbe Mon Sep 17 00:00:00 2001 From: "Gujulan Elango, Hari Prasath (H.)" Date: Thu, 23 Apr 2015 13:43:01 +0000 Subject: [PATCH 0417/3798] staging: i2o: Remove unwanted semicolon This patch removes unwanted semicolon around close braces of code blocks Signed-off-by: Hari Prasath Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i2o/iop.c | 44 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/staging/i2o/iop.c b/drivers/staging/i2o/iop.c index 142aab8c77387f..c88df551bbb028 100644 --- a/drivers/staging/i2o/iop.c +++ b/drivers/staging/i2o/iop.c @@ -75,7 +75,7 @@ struct i2o_message *i2o_msg_get_wait(struct i2o_controller *c, int wait) } return msg; -}; +} #if BITS_PER_LONG == 64 /** @@ -123,7 +123,7 @@ u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr) osm_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context); return entry->context; -}; +} /** * i2o_cntxt_list_remove - Remove a pointer from the context list @@ -159,7 +159,7 @@ u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr) context, ptr); return context; -}; +} /** * i2o_cntxt_list_get - Get a pointer from the context list and remove it @@ -192,7 +192,7 @@ void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) ptr); return ptr; -}; +} /** * i2o_cntxt_list_get_ptr - Get a context id from the context list @@ -224,7 +224,7 @@ u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr) ptr, context); return context; -}; +} #endif /** @@ -245,7 +245,7 @@ struct i2o_controller *i2o_find_iop(int unit) } return NULL; -}; +} /** * i2o_iop_find_device - Find a I2O device on an I2O controller @@ -266,7 +266,7 @@ struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid) return dev; return NULL; -}; +} /** * i2o_quiesce_controller - quiesce controller @@ -309,7 +309,7 @@ static int i2o_iop_quiesce(struct i2o_controller *c) i2o_status_get(c); // Entered READY state return rc; -}; +} /** * i2o_iop_enable - move controller from ready to OPERATIONAL @@ -350,7 +350,7 @@ static int i2o_iop_enable(struct i2o_controller *c) i2o_status_get(c); // entered OPERATIONAL state return rc; -}; +} /** * i2o_iop_quiesce_all - Quiesce all I2O controllers on the system @@ -365,7 +365,7 @@ static inline void i2o_iop_quiesce_all(void) if (!c->no_quiesce) i2o_iop_quiesce(c); } -}; +} /** * i2o_iop_enable_all - Enables all controllers on the system @@ -378,7 +378,7 @@ static inline void i2o_iop_enable_all(void) list_for_each_entry_safe(c, tmp, &i2o_controllers, list) i2o_iop_enable(c); -}; +} /** * i2o_clear_controller - Bring I2O controller into HOLD state @@ -584,7 +584,7 @@ static int i2o_iop_reset(struct i2o_controller *c) i2o_iop_enable_all(); return rc; -}; +} /** * i2o_iop_activate - Bring controller up to HOLD @@ -653,7 +653,7 @@ static int i2o_iop_activate(struct i2o_controller *c) } return i2o_hrt_get(c); -}; +} static void i2o_res_alloc(struct i2o_controller *c, unsigned long flags) { @@ -782,7 +782,7 @@ static int i2o_iop_online(struct i2o_controller *c) return rc; return 0; -}; +} /** * i2o_iop_remove - Remove the I2O controller from the I2O core @@ -894,7 +894,7 @@ static int i2o_systab_build(void) systab->num_entries = count; return 0; -}; +} /** * i2o_parse_hrt - Parse the hardware resource table. @@ -908,7 +908,7 @@ static int i2o_parse_hrt(struct i2o_controller *c) { i2o_dump_hrt(c); return 0; -}; +} /** * i2o_status_get - Get the status block from the I2O controller @@ -1032,7 +1032,7 @@ static void i2o_iop_release(struct device *dev) struct i2o_controller *c = to_i2o_controller(dev); i2o_iop_free(c); -}; +} /** * i2o_iop_alloc - Allocate and initialize a i2o_controller struct @@ -1065,7 +1065,7 @@ struct i2o_controller *i2o_iop_alloc(void) I2O_MSG_INPOOL_MIN)) { kfree(c); return ERR_PTR(-ENOMEM); - }; + } INIT_LIST_HEAD(&c->devices); spin_lock_init(&c->lock); @@ -1084,7 +1084,7 @@ struct i2o_controller *i2o_iop_alloc(void) #endif return c; -}; +} /** * i2o_iop_add - Initialize the I2O controller and add him to the I2O core @@ -1148,7 +1148,7 @@ int i2o_iop_add(struct i2o_controller *c) i2o_iop_reset(c); return rc; -}; +} /** * i2o_event_register - Turn on/off event notification for a I2O device @@ -1184,7 +1184,7 @@ int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv, i2o_msg_post(c, msg); return 0; -}; +} /** * i2o_iop_init - I2O main initialization function @@ -1234,7 +1234,7 @@ static void __exit i2o_iop_exit(void) i2o_pci_exit(); i2o_exec_exit(); i2o_driver_exit(); -}; +} module_init(i2o_iop_init); module_exit(i2o_iop_exit); From 41d98f584f03660324f078fd812342a1e75edd6d Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Thu, 30 Apr 2015 21:03:04 +0800 Subject: [PATCH 0418/3798] i2o: fix simple_return.cocci warnings drivers/staging/i2o/iop.c:777:1-3: WARNING: end returns can be simpified Simplify a trivial if-return sequence. Possibly combine with a preceding function call. Generated by: scripts/coccinelle/misc/simple_return.cocci CC: Alan Cox Signed-off-by: Fengguang Wu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/i2o/iop.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/i2o/iop.c b/drivers/staging/i2o/iop.c index c88df551bbb028..3c237909758623 100644 --- a/drivers/staging/i2o/iop.c +++ b/drivers/staging/i2o/iop.c @@ -777,11 +777,7 @@ static int i2o_iop_online(struct i2o_controller *c) /* In READY state */ osm_debug("%s: Attempting to enable...\n", c->name); - rc = i2o_iop_enable(c); - if (rc) - return rc; - - return 0; + return i2o_iop_enable(c); } /** From 3746e6f93bbf28a25d2d69350ab6bfba02e14654 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Wed, 8 Apr 2015 17:24:02 -0600 Subject: [PATCH 0419/3798] staging: lustre: llite: remove obsolete conditional code Remove conditional flock/aops code that was only for out-of-tree vendor kernels but is not relevant for in-kernel code. Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/llite/llite_internal.h | 4 ---- .../staging/lustre/lustre/llite/llite_lib.c | 8 -------- drivers/staging/lustre/lustre/llite/rw26.c | 20 ------------------- 3 files changed, 32 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 5f918e3c4683dd..1253b3cf50a80d 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -727,11 +727,7 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, struct ll_readahead_state *ras, struct address_space *mapping, struct cl_page_list *queue, int flags); -#ifndef MS_HAS_NEW_AOPS extern const struct address_space_operations ll_aops; -#else -extern const struct address_space_operations_ext ll_aops; -#endif /* llite/file.c */ extern struct file_operations ll_file_operations; diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index a27af7882170f4..f3980b3fb45b81 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -227,14 +227,6 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (sbi->ll_flags & LL_SBI_USER_XATTR) data->ocd_connect_flags |= OBD_CONNECT_XATTR; -#ifdef HAVE_MS_FLOCK_LOCK - /* force vfs to use lustre handler for flock() calls - bug 10743 */ - sb->s_flags |= MS_FLOCK_LOCK; -#endif -#ifdef MS_HAS_NEW_AOPS - sb->s_flags |= MS_HAS_NEW_AOPS; -#endif - if (sbi->ll_flags & LL_SBI_FLOCK) sbi->ll_fop = &ll_file_operations_flock; else if (sbi->ll_flags & LL_SBI_LOCALFLOCK) diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index c6c824356464c7..7c643130499f86 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -517,7 +517,6 @@ static int ll_migratepage(struct address_space *mapping, } #endif -#ifndef MS_HAS_NEW_AOPS const struct address_space_operations ll_aops = { .readpage = ll_readpage, .direct_IO = ll_direct_IO_26, @@ -532,22 +531,3 @@ const struct address_space_operations ll_aops = { .migratepage = ll_migratepage, #endif }; -#else -const struct address_space_operations_ext ll_aops = { - .orig_aops.readpage = ll_readpage, -/* .orig_aops.readpages = ll_readpages, */ - .orig_aops.direct_IO = ll_direct_IO_26, - .orig_aops.writepage = ll_writepage, - .orig_aops.writepages = ll_writepages, - .orig_aops.set_page_dirty = ll_set_page_dirty, - .orig_aops.prepare_write = ll_prepare_write, - .orig_aops.commit_write = ll_commit_write, - .orig_aops.invalidatepage = ll_invalidatepage, - .orig_aops.releasepage = ll_releasepage, -#ifdef CONFIG_MIGRATION - .orig_aops.migratepage = ll_migratepage, -#endif - .write_begin = ll_write_begin, - .write_end = ll_write_end -}; -#endif From 97903a26fcfc84b93a9cdb09d649c1b748383c24 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 12 Apr 2015 22:55:02 +0200 Subject: [PATCH 0420/3798] staging: lustre: llite: drop uses of OBD free functions Replace OBD_FREE and OBD_FREE_PTR by kfree. The semantic patch that makes these changes is as follows: (http://coccinelle.lip6.fr/) // @@ expression ptr, size; @@ - OBD_FREE(ptr, size); + kfree(ptr); @@ expression ptr; @@ - OBD_FREE_PTR(ptr); + kfree(ptr); // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dcache.c | 6 ++-- drivers/staging/lustre/lustre/llite/dir.c | 34 +++++++++--------- drivers/staging/lustre/lustre/llite/file.c | 36 +++++++++---------- .../staging/lustre/lustre/llite/llite_close.c | 6 ++-- .../staging/lustre/lustre/llite/llite_lib.c | 31 ++++++++-------- .../staging/lustre/lustre/llite/llite_nfs.c | 2 +- .../lustre/lustre/llite/llite_rmtacl.c | 4 +-- drivers/staging/lustre/lustre/llite/lloop.c | 8 ++--- drivers/staging/lustre/lustre/llite/namei.c | 2 +- .../staging/lustre/lustre/llite/statahead.c | 20 +++++------ .../staging/lustre/lustre/llite/xattr_cache.c | 6 ++-- 11 files changed, 77 insertions(+), 78 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 5af01351306d3d..7b008a64707d7a 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -52,7 +52,7 @@ static void free_dentry_data(struct rcu_head *head) struct ll_dentry_data *lld; lld = container_of(head, struct ll_dentry_data, lld_rcu_head); - OBD_FREE_PTR(lld); + kfree(lld); } /* should NOT be called with the dcache lock, see fs/dcache.c */ @@ -67,7 +67,7 @@ static void ll_release(struct dentry *de) if (lld->lld_it) { ll_intent_release(lld->lld_it); - OBD_FREE(lld->lld_it, sizeof(*lld->lld_it)); + kfree(lld->lld_it); } de->d_fsdata = NULL; @@ -194,7 +194,7 @@ int ll_d_init(struct dentry *de) de->d_fsdata = lld; __d_lustre_invalidate(de); } else { - OBD_FREE_PTR(lld); + kfree(lld); } spin_unlock(&de->d_lock); } else { diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index a5bc694dcb64aa..0f5d57cb149ad8 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -239,7 +239,7 @@ static int ll_dir_filler(void *_hash, struct page *page0) ll_pagevec_lru_add_file(&lru_pvec); if (page_pool != &page0) - OBD_FREE(page_pool, sizeof(struct page *) * max_pages); + kfree(page_pool); return rc; } @@ -650,7 +650,7 @@ static int ll_send_mgc_param(struct obd_export *mgc, char *string) sizeof(struct mgs_send_param), msp, NULL); if (rc) CERROR("Failed to set parameter: %d\n", rc); - OBD_FREE_PTR(msp); + kfree(msp); return rc; } @@ -787,7 +787,7 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump, end: if (param != NULL) - OBD_FREE(param, MGS_PARAM_MAXLEN); + kfree(param); } return rc; } @@ -1072,7 +1072,7 @@ static int copy_and_ioctl(int cmd, struct obd_export *exp, rc = obd_iocontrol(cmd, exp, size, copy, NULL); out: - OBD_FREE(copy, size); + kfree(copy); return rc; } @@ -1163,7 +1163,7 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl) oqctl->qc_cmd = Q_QUOTAOFF; obd_quotactl(sbi->ll_md_exp, oqctl); } - OBD_FREE_PTR(oqctl); + kfree(oqctl); return rc; } /* If QIF_SPACE is not set, client should collect the @@ -1206,11 +1206,11 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl) oqctl->qc_dqblk.dqb_valid &= ~QIF_SPACE; } - OBD_FREE_PTR(oqctl_tmp); + kfree(oqctl_tmp); } out: QCTL_COPY(qctl, oqctl); - OBD_FREE_PTR(oqctl); + kfree(oqctl); } return rc; @@ -1437,7 +1437,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } free_lmv: if (tmp) - OBD_FREE(tmp, lum_size); + kfree(tmp); return rc; } case LL_IOC_REMOVE_ENTRY: { @@ -1657,7 +1657,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (rc < 0) CDEBUG(D_INFO, "obd_quotacheck failed: rc %d\n", rc); - OBD_FREE_PTR(oqctl); + kfree(oqctl); return error ?: rc; } case OBD_IOC_POLL_QUOTACHECK: { @@ -1691,7 +1691,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) goto out_poll; } out_poll: - OBD_FREE_PTR(check); + kfree(check); return rc; } case LL_IOC_QUOTACTL: { @@ -1712,7 +1712,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) rc = -EFAULT; out_quotactl: - OBD_FREE_PTR(qctl); + kfree(qctl); return rc; } case OBD_IOC_GETDTNAME: @@ -1781,13 +1781,13 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) /* We don't know the true size yet; copy the fixed-size part */ if (copy_from_user(hur, (void *)arg, sizeof(*hur))) { - OBD_FREE_PTR(hur); + kfree(hur); return -EFAULT; } /* Compute the whole struct size */ totalsize = hur_len(hur); - OBD_FREE_PTR(hur); + kfree(hur); if (totalsize < 0) return -E2BIG; @@ -1865,7 +1865,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (!copy) return -ENOMEM; if (copy_from_user(copy, (char *)arg, sizeof(*copy))) { - OBD_FREE_PTR(copy); + kfree(copy); return -EFAULT; } @@ -1873,7 +1873,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (copy_to_user((char *)arg, copy, sizeof(*copy))) rc = -EFAULT; - OBD_FREE_PTR(copy); + kfree(copy); return rc; } case LL_IOC_HSM_COPY_END: { @@ -1884,7 +1884,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (!copy) return -ENOMEM; if (copy_from_user(copy, (char *)arg, sizeof(*copy))) { - OBD_FREE_PTR(copy); + kfree(copy); return -EFAULT; } @@ -1892,7 +1892,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (copy_to_user((char *)arg, copy, sizeof(*copy))) rc = -EFAULT; - OBD_FREE_PTR(copy); + kfree(copy); return rc; } default: diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 4b44c634fcc3de..6e50b3554e336b 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -213,7 +213,7 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp, md_clear_open_replay_data(md_exp, och); /* Free @och if it is not waiting for DONE_WRITING. */ och->och_fh.cookie = DEAD_HANDLE_MAGIC; - OBD_FREE_PTR(och); + kfree(och); } if (req) /* This is close request */ ptlrpc_req_finished(req); @@ -693,7 +693,7 @@ int ll_file_open(struct inode *inode, struct file *file) out_och_free: if (rc) { if (och_p && *och_p) { - OBD_FREE(*och_p, sizeof(struct obd_client_handle)); + kfree(*och_p); *och_p = NULL; /* OBD_FREE writes some magic there */ (*och_usecount)--; } @@ -875,7 +875,7 @@ ll_lease_open(struct inode *inode, struct file *file, fmode_t fmode, out_release_it: ll_intent_release(&it); out: - OBD_FREE_PTR(och); + kfree(och); return ERR_PTR(rc); } @@ -1779,7 +1779,7 @@ int ll_fid2path(struct inode *inode, void __user *arg) rc = -EFAULT; gf_free: - OBD_FREE(gfout, outsize); + kfree(gfout); return rc; } @@ -1883,7 +1883,7 @@ int ll_data_version(struct inode *inode, __u64 *data_version, *data_version = obdo->o_data_version; } - OBD_FREE_PTR(obdo); + kfree(obdo); out: ccc_inode_lsm_put(inode, lsm); return rc; @@ -2110,7 +2110,7 @@ static int ll_swap_layouts(struct file *file1, struct file *file2, free: if (llss != NULL) - OBD_FREE_PTR(llss); + kfree(llss); return rc; } @@ -2195,10 +2195,10 @@ static int ll_hsm_import(struct inode *inode, struct file *file, out: if (hss != NULL) - OBD_FREE_PTR(hss); + kfree(hss); if (attr != NULL) - OBD_FREE_PTR(attr); + kfree(attr); return rc; } @@ -2350,7 +2350,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, LUSTRE_OPC_ANY, hus); if (IS_ERR(op_data)) { - OBD_FREE_PTR(hus); + kfree(hus); return PTR_ERR(op_data); } @@ -2361,7 +2361,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) rc = -EFAULT; ll_finish_md_op_data(op_data); - OBD_FREE_PTR(hus); + kfree(hus); return rc; } case LL_IOC_HSM_STATE_SET: { @@ -2373,13 +2373,13 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -ENOMEM; if (copy_from_user(hss, (char *)arg, sizeof(*hss))) { - OBD_FREE_PTR(hss); + kfree(hss); return -EFAULT; } rc = ll_hsm_state_set(inode, hss); - OBD_FREE_PTR(hss); + kfree(hss); return rc; } case LL_IOC_HSM_ACTION: { @@ -2394,7 +2394,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, LUSTRE_OPC_ANY, hca); if (IS_ERR(op_data)) { - OBD_FREE_PTR(hca); + kfree(hca); return PTR_ERR(op_data); } @@ -2405,7 +2405,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) rc = -EFAULT; ll_finish_md_op_data(op_data); - OBD_FREE_PTR(hca); + kfree(hca); return rc; } case LL_IOC_SET_LEASE: { @@ -2500,13 +2500,13 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -ENOMEM; if (copy_from_user(hui, (void *)arg, sizeof(*hui))) { - OBD_FREE_PTR(hui); + kfree(hui); return -EFAULT; } rc = ll_hsm_import(inode, file, hui); - OBD_FREE_PTR(hui); + kfree(hui); return rc; } default: { @@ -3251,7 +3251,7 @@ void ll_iocontrol_unregister(void *magic) list_del(&tmp->iocd_list); up_write(&llioc.ioc_sem); - OBD_FREE(tmp, size); + kfree(tmp); return; } } @@ -3619,6 +3619,6 @@ int ll_layout_restore(struct inode *inode) hur->hur_request.hr_itemcount = 1; rc = obd_iocontrol(LL_IOC_HSM_REQUEST, cl_i2sbi(inode)->ll_md_exp, len, hur, NULL); - OBD_FREE(hur, len); + kfree(hur); return rc; } diff --git a/drivers/staging/lustre/lustre/llite/llite_close.c b/drivers/staging/lustre/lustre/llite/llite_close.c index a94ba02ccf02ea..7bdae723fedde6 100644 --- a/drivers/staging/lustre/lustre/llite/llite_close.c +++ b/drivers/staging/lustre/lustre/llite/llite_close.c @@ -305,7 +305,7 @@ static void ll_done_writing(struct inode *inode) ll_finish_md_op_data(op_data); if (och) { md_clear_open_replay_data(ll_i2sbi(inode)->ll_md_exp, och); - OBD_FREE_PTR(och); + kfree(och); } } @@ -374,7 +374,7 @@ int ll_close_thread_start(struct ll_close_queue **lcq_ret) task = kthread_run(ll_close_thread, lcq, "ll_close"); if (IS_ERR(task)) { - OBD_FREE(lcq, sizeof(*lcq)); + kfree(lcq); return PTR_ERR(task); } @@ -389,5 +389,5 @@ void ll_close_thread_shutdown(struct ll_close_queue *lcq) atomic_inc(&lcq->lcq_stop); wake_up(&lcq->lcq_waitq); wait_for_completion(&lcq->lcq_comp); - OBD_FREE(lcq, sizeof(*lcq)); + kfree(lcq); } diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index f3980b3fb45b81..f44abb6614047a 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -145,7 +145,7 @@ static void ll_free_sbi(struct super_block *sb) spin_lock(&ll_sb_lock); list_del(&sbi->ll_list); spin_unlock(&ll_sb_lock); - OBD_FREE(sbi, sizeof(*sbi)); + kfree(sbi); } } @@ -177,7 +177,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, osfs = kzalloc(sizeof(*osfs), GFP_NOFS); if (!osfs) { - OBD_FREE_PTR(data); + kfree(data); return -ENOMEM; } @@ -288,7 +288,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, valid ^ CLIENT_CONNECT_MDT_REQD, ","); LCONSOLE_ERROR_MSG(0x170, "Server %s does not support feature(s) needed for correct operation of this client (%s). Please upgrade server or downgrade client.\n", sbi->ll_md_exp->exp_obd->obd_name, buf); - OBD_FREE(buf, PAGE_CACHE_SIZE); + kfree(buf); err = -EPROTO; goto out_md_fid; } @@ -493,7 +493,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, err = md_getattr(sbi->ll_md_exp, op_data, &request); if (oc) capa_put(oc); - OBD_FREE_PTR(op_data); + kfree(op_data); if (err) { CERROR("%s: md_getattr failed for root: rc = %d\n", sbi->ll_md_exp->exp_obd->obd_name, err); @@ -575,9 +575,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, } if (data != NULL) - OBD_FREE_PTR(data); + kfree(data); if (osfs != NULL) - OBD_FREE_PTR(osfs); + kfree(osfs); return err; out_root: @@ -596,9 +596,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sbi->ll_md_exp = NULL; out: if (data != NULL) - OBD_FREE_PTR(data); + kfree(data); if (osfs != NULL) - OBD_FREE_PTR(osfs); + kfree(osfs); lprocfs_unregister_mountpoint(sbi); return err; } @@ -924,7 +924,7 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) lsi->lsi_llsbi = sbi = ll_init_sbi(); if (!sbi) { module_put(THIS_MODULE); - OBD_FREE_PTR(cfg); + kfree(cfg); return -ENOMEM; } @@ -986,15 +986,15 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) out_free: if (md) - OBD_FREE(md, strlen(lprof->lp_md) + instlen + 2); + kfree(md); if (dt) - OBD_FREE(dt, strlen(lprof->lp_dt) + instlen + 2); + kfree(dt); if (err) ll_put_super(sb); else if (sbi->ll_flags & LL_SBI_VERBOSE) LCONSOLE_WARN("Mounted %s\n", profilenm); - OBD_FREE_PTR(cfg); + kfree(cfg); return err; } /* ll_fill_super */ @@ -1118,8 +1118,7 @@ void ll_clear_inode(struct inode *inode) ll_md_real_close(inode, FMODE_READ); if (S_ISLNK(inode->i_mode) && lli->lli_symlink_name) { - OBD_FREE(lli->lli_symlink_name, - strlen(lli->lli_symlink_name) + 1); + kfree(lli->lli_symlink_name); lli->lli_symlink_name = NULL; } @@ -1949,7 +1948,7 @@ void ll_umount_begin(struct super_block *sb) obd_iocontrol(IOC_OSC_SET_ACTIVE, sbi->ll_dt_exp, sizeof(*ioc_data), ioc_data, NULL); - OBD_FREE_PTR(ioc_data); + kfree(ioc_data); } /* Really, we'd like to wait until there are no requests outstanding, @@ -2228,7 +2227,7 @@ void ll_finish_md_op_data(struct md_op_data *op_data) { capa_put(op_data->op_capa1); capa_put(op_data->op_capa2); - OBD_FREE_PTR(op_data); + kfree(op_data); } int ll_show_options(struct seq_file *seq, struct dentry *dentry) diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index db43b81386f7ae..8d1c253d4669b3 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -116,7 +116,7 @@ struct inode *search_inode_for_lustre(struct super_block *sb, /* mds_fid2dentry ignores f_type */ rc = md_getattr(sbi->ll_md_exp, op_data, &req); - OBD_FREE_PTR(op_data); + kfree(op_data); if (rc) { CERROR("can't get object attrs, fid "DFID", rc %d\n", PFID(fid), rc); diff --git a/drivers/staging/lustre/lustre/llite/llite_rmtacl.c b/drivers/staging/lustre/lustre/llite/llite_rmtacl.c index f4da156f387492..c8a450b5cb180b 100644 --- a/drivers/staging/lustre/lustre/llite/llite_rmtacl.c +++ b/drivers/staging/lustre/lustre/llite/llite_rmtacl.c @@ -94,7 +94,7 @@ static void rce_free(struct rmtacl_ctl_entry *rce) if (!list_empty(&rce->rce_list)) list_del(&rce->rce_list); - OBD_FREE_PTR(rce); + kfree(rce); } static struct rmtacl_ctl_entry *__rct_search(struct rmtacl_ctl_table *rct, @@ -205,7 +205,7 @@ void ee_free(struct eacl_entry *ee) if (ee->ee_acl) lustre_ext_acl_xattr_free(ee->ee_acl); - OBD_FREE_PTR(ee); + kfree(ee); } static struct eacl_entry *__et_search_del(struct eacl_table *et, pid_t key, diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c index 413a8408e3f5b9..cc00fd10fbcf77 100644 --- a/drivers/staging/lustre/lustre/llite/lloop.c +++ b/drivers/staging/lustre/lustre/llite/lloop.c @@ -840,9 +840,9 @@ static int __init lloop_init(void) out_mem3: while (i--) put_disk(disks[i]); - OBD_FREE(disks, max_loop * sizeof(*disks)); + kfree(disks); out_mem2: - OBD_FREE(loop_dev, max_loop * sizeof(*loop_dev)); + kfree(loop_dev); out_mem1: unregister_blkdev(lloop_major, "lloop"); ll_iocontrol_unregister(ll_iocontrol_magic); @@ -863,8 +863,8 @@ static void lloop_exit(void) unregister_blkdev(lloop_major, "lloop"); - OBD_FREE(disks, max_loop * sizeof(*disks)); - OBD_FREE(loop_dev, max_loop * sizeof(*loop_dev)); + kfree(disks); + kfree(loop_dev); } module_init(lloop_init); diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 5a25dcd10126c1..72ce6e72845fdd 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -665,7 +665,7 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry, out_release: ll_intent_release(it); - OBD_FREE(it, sizeof(*it)); + kfree(it); return rc; } diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 7f8071242f2344..fdf953f691fa2f 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -312,7 +312,7 @@ static void ll_sa_entry_cleanup(struct ll_statahead_info *sai, entry->se_minfo = NULL; ll_intent_release(&minfo->mi_it); iput(minfo->mi_dir); - OBD_FREE_PTR(minfo); + kfree(minfo); } if (req) { @@ -336,7 +336,7 @@ static void ll_sa_entry_put(struct ll_statahead_info *sai, ll_sa_entry_cleanup(sai, entry); iput(entry->se_inode); - OBD_FREE(entry, entry->se_size); + kfree(entry); atomic_dec(&sai->sai_cache_count); } } @@ -544,7 +544,7 @@ static void ll_sai_put(struct ll_statahead_info *sai) LASSERT(agl_list_empty(sai)); iput(inode); - OBD_FREE_PTR(sai); + kfree(sai); } } @@ -772,7 +772,7 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, if (rc != 0) { ll_intent_release(it); iput(dir); - OBD_FREE_PTR(minfo); + kfree(minfo); } if (sai != NULL) ll_sai_put(sai); @@ -786,8 +786,8 @@ static void sa_args_fini(struct md_enqueue_info *minfo, iput(minfo->mi_dir); capa_put(minfo->mi_data.op_capa1); capa_put(minfo->mi_data.op_capa2); - OBD_FREE_PTR(minfo); - OBD_FREE_PTR(einfo); + kfree(minfo); + kfree(einfo); } /** @@ -816,15 +816,15 @@ static int sa_args_init(struct inode *dir, struct inode *child, minfo = kzalloc(sizeof(*minfo), GFP_NOFS); if (!minfo) { - OBD_FREE_PTR(einfo); + kfree(einfo); return -ENOMEM; } op_data = ll_prep_md_op_data(&minfo->mi_data, dir, child, qstr->name, qstr->len, 0, LUSTRE_OPC_ANY, NULL); if (IS_ERR(op_data)) { - OBD_FREE_PTR(einfo); - OBD_FREE_PTR(minfo); + kfree(einfo); + kfree(minfo); return PTR_ERR(op_data); } @@ -1720,7 +1720,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, out: if (sai != NULL) - OBD_FREE_PTR(sai); + kfree(sai); spin_lock(&lli->lli_sa_lock); lli->lli_opendir_key = NULL; lli->lli_opendir_pid = 0; diff --git a/drivers/staging/lustre/lustre/llite/xattr_cache.c b/drivers/staging/lustre/lustre/llite/xattr_cache.c index 69ea92adf4f1ff..6956dec53fcc5d 100644 --- a/drivers/staging/lustre/lustre/llite/xattr_cache.c +++ b/drivers/staging/lustre/lustre/llite/xattr_cache.c @@ -144,7 +144,7 @@ static int ll_xattr_cache_add(struct list_head *cache, return 0; err_value: - OBD_FREE(xattr->xe_name, xattr->xe_namelen); + kfree(xattr->xe_name); err_name: OBD_SLAB_FREE_PTR(xattr, xattr_kmem); @@ -170,8 +170,8 @@ static int ll_xattr_cache_del(struct list_head *cache, if (ll_xattr_cache_find(cache, xattr_name, &xattr) == 0) { list_del(&xattr->xe_list); - OBD_FREE(xattr->xe_name, xattr->xe_namelen); - OBD_FREE(xattr->xe_value, xattr->xe_vallen); + kfree(xattr->xe_name); + kfree(xattr->xe_value); OBD_SLAB_FREE_PTR(xattr, xattr_kmem); return 0; From 840c94d574a8bb5fb03cad0b5aa1bd0e2984b01a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 12 Apr 2015 23:34:20 +0200 Subject: [PATCH 0421/3798] staging: lustre: drop uses of some OBD alloc and free functions Replace OBD_ALLOC, OBD_ALLOC_WAIT, OBD_ALLOC_PTR, and OBD_ALLOC_PTR_WAIT by kzalloc or calloc, as appropriate. Replace OBD_FREE and OBD_FREE_PTR by kfree. A simplified version of the semantic patch that makes these changes in the OBD_ALLOC/FREE case is as follows: (http://coccinelle.lip6.fr/) // @@ expression ptr,e1,e2; @@ - OBD_ALLOC(ptr,sizeof e1 * e2) + ptr = kcalloc(e2, sizeof e1, GFP_NOFS) @@ expression ptr,size; @@ - OBD_ALLOC(ptr,size) + ptr = kzalloc(size, GFP_NOFS) @@ expression ptr, size; @@ - OBD_FREE(ptr, size); + kfree(ptr); // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_dev.c | 18 +++++----- drivers/staging/lustre/lustre/lov/lov_io.c | 5 +-- drivers/staging/lustre/lustre/lov/lov_obd.c | 21 ++++++------ drivers/staging/lustre/lustre/lov/lov_pool.c | 18 +++++----- .../staging/lustre/lustre/lov/lov_request.c | 34 +++++++++---------- .../staging/lustre/lustre/lov/lovsub_dev.c | 4 +-- 6 files changed, 50 insertions(+), 50 deletions(-) diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c index 711b837ddba23a..63db87af7fe205 100644 --- a/drivers/staging/lustre/lustre/lov/lov_dev.c +++ b/drivers/staging/lustre/lustre/lov/lov_dev.c @@ -285,10 +285,10 @@ static void lov_emerg_free(struct lov_device_emerg **emrg, int nr) LASSERT(em->emrg_page_list.pl_nr == 0); if (em->emrg_env != NULL) cl_env_put(em->emrg_env, &em->emrg_refcheck); - OBD_FREE_PTR(em); + kfree(em); } } - OBD_FREE(emrg, nr * sizeof(emrg[0])); + kfree(emrg); } static struct lu_device *lov_device_free(const struct lu_env *env, @@ -299,10 +299,10 @@ static struct lu_device *lov_device_free(const struct lu_env *env, cl_device_fini(lu2cl_dev(d)); if (ld->ld_target != NULL) - OBD_FREE(ld->ld_target, nr * sizeof(ld->ld_target[0])); + kfree(ld->ld_target); if (ld->ld_emrg != NULL) lov_emerg_free(ld->ld_emrg, nr); - OBD_FREE_PTR(ld); + kfree(ld); return NULL; } @@ -323,13 +323,13 @@ static struct lov_device_emerg **lov_emerg_alloc(int nr) int i; int result; - OBD_ALLOC(emerg, nr * sizeof(emerg[0])); + emerg = kcalloc(nr, sizeof(emerg[0]), GFP_NOFS); if (emerg == NULL) return ERR_PTR(-ENOMEM); for (result = i = 0; i < nr && result == 0; i++) { struct lov_device_emerg *em; - OBD_ALLOC_PTR(em); + em = kzalloc(sizeof(*em), GFP_NOFS); if (em != NULL) { emerg[i] = em; cl_page_list_init(&em->emrg_page_list); @@ -369,12 +369,12 @@ static int lov_expand_targets(const struct lu_env *env, struct lov_device *dev) if (IS_ERR(emerg)) return PTR_ERR(emerg); - OBD_ALLOC(newd, tgt_size * sz); + newd = kcalloc(tgt_size, sz, GFP_NOFS); if (newd != NULL) { mutex_lock(&dev->ld_mutex); if (sub_size > 0) { memcpy(newd, dev->ld_target, sub_size * sz); - OBD_FREE(dev->ld_target, sub_size * sz); + kfree(dev->ld_target); } dev->ld_target = newd; dev->ld_target_nr = tgt_size; @@ -478,7 +478,7 @@ static struct lu_device *lov_device_alloc(const struct lu_env *env, struct obd_device *obd; int rc; - OBD_ALLOC_PTR(ld); + ld = kzalloc(sizeof(*ld), GFP_NOFS); if (ld == NULL) return ERR_PTR(-ENOMEM); diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index cf96e0d01e22d5..a043df0c519f76 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -70,7 +70,7 @@ static void lov_io_sub_fini(const struct lu_env *env, struct lov_io *lio, if (sub->sub_stripe == lio->lis_single_subio_index) lio->lis_single_subio_index = -1; else if (!sub->sub_borrowed) - OBD_FREE_PTR(sub->sub_io); + kfree(sub->sub_io); sub->sub_io = NULL; } if (sub->sub_env != NULL && !IS_ERR(sub->sub_env)) { @@ -179,7 +179,8 @@ static int lov_io_sub_init(const struct lu_env *env, struct lov_io *lio, sub->sub_io = &lio->lis_single_subio; lio->lis_single_subio_index = stripe; } else { - OBD_ALLOC_PTR(sub->sub_io); + sub->sub_io = kzalloc(sizeof(*sub->sub_io), + GFP_NOFS); if (sub->sub_io == NULL) result = -ENOMEM; } diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 02781576637edd..7e125380970872 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -554,7 +554,7 @@ static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp, newsize = max_t(__u32, lov->lov_tgt_size, 2); while (newsize < index + 1) newsize <<= 1; - OBD_ALLOC(newtgts, sizeof(*newtgts) * newsize); + newtgts = kcalloc(newsize, sizeof(*newtgts), GFP_NOFS); if (newtgts == NULL) { mutex_unlock(&lov->lov_lock); return -ENOMEM; @@ -571,13 +571,13 @@ static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp, lov->lov_tgt_size = newsize; smp_rmb(); if (old) - OBD_FREE(old, sizeof(*old) * oldsize); + kfree(old); CDEBUG(D_CONFIG, "tgts: %p size: %d\n", lov->lov_tgts, lov->lov_tgt_size); } - OBD_ALLOC_PTR(tgt); + tgt = kzalloc(sizeof(*tgt), GFP_NOFS); if (!tgt) { mutex_unlock(&lov->lov_lock); return -ENOMEM; @@ -586,7 +586,7 @@ static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp, rc = lov_ost_pool_add(&lov->lov_packed, index, lov->lov_tgt_size); if (rc) { mutex_unlock(&lov->lov_lock); - OBD_FREE_PTR(tgt); + kfree(tgt); return rc; } @@ -712,7 +712,7 @@ static void __lov_del_obd(struct obd_device *obd, struct lov_tgt_desc *tgt) if (tgt->ltd_exp) lov_disconnect_obd(obd, tgt); - OBD_FREE_PTR(tgt); + kfree(tgt); /* Manual cleanup - no cleanup logs to clean up the osc's. We must do it ourselves. And we can't do it from lov_cleanup, @@ -903,8 +903,7 @@ static int lov_cleanup(struct obd_device *obd) lov_del_target(obd, i, NULL, 0); } obd_putref(obd); - OBD_FREE(lov->lov_tgts, sizeof(*lov->lov_tgts) * - lov->lov_tgt_size); + kfree(lov->lov_tgts); lov->lov_tgt_size = 0; } return 0; @@ -994,7 +993,7 @@ static int lov_recreate(struct obd_export *exp, struct obdo *src_oa, LASSERT(src_oa->o_valid & OBD_MD_FLFLAGS && src_oa->o_flags & OBD_FL_RECREATE_OBJS); - OBD_ALLOC(obj_mdp, sizeof(*obj_mdp)); + obj_mdp = kzalloc(sizeof(*obj_mdp), GFP_NOFS); if (obj_mdp == NULL) return -ENOMEM; @@ -1032,7 +1031,7 @@ static int lov_recreate(struct obd_export *exp, struct obdo *src_oa, rc = obd_create(NULL, lov->lov_tgts[ost_idx]->ltd_exp, src_oa, &obj_mdp, oti); out: - OBD_FREE(obj_mdp, sizeof(*obj_mdp)); + kfree(obj_mdp); return rc; } @@ -1532,7 +1531,7 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, return -EAGAIN; LASSERT(tgt && tgt->ltd_exp); - OBD_ALLOC_PTR(oqctl); + oqctl = kzalloc(sizeof(*oqctl), GFP_NOFS); if (!oqctl) return -ENOMEM; @@ -1543,7 +1542,7 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, qctl->qc_valid = QC_OSTIDX; qctl->obd_uuid = tgt->ltd_uuid; } - OBD_FREE_PTR(oqctl); + kfree(oqctl); break; } default: { diff --git a/drivers/staging/lustre/lustre/lov/lov_pool.c b/drivers/staging/lustre/lustre/lov/lov_pool.c index d96163de773f75..75301fa066a0bb 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pool.c +++ b/drivers/staging/lustre/lustre/lov/lov_pool.c @@ -67,7 +67,7 @@ void lov_pool_putref(struct pool_desc *pool) LASSERT(pool->pool_proc_entry == NULL); lov_ost_pool_free(&(pool->pool_rr.lqr_pool)); lov_ost_pool_free(&(pool->pool_obds)); - OBD_FREE_PTR(pool); + kfree(pool); } } @@ -210,7 +210,7 @@ static void *pool_proc_start(struct seq_file *s, loff_t *pos) return NULL; } - OBD_ALLOC_PTR(iter); + iter = kzalloc(sizeof(*iter), GFP_NOFS); if (!iter) return ERR_PTR(-ENOMEM); iter->magic = POOL_IT_MAGIC; @@ -246,7 +246,7 @@ static void pool_proc_stop(struct seq_file *s, void *v) * will work */ s->private = iter->pool; lov_pool_putref(iter->pool); - OBD_FREE_PTR(iter); + kfree(iter); } return; } @@ -327,7 +327,7 @@ int lov_ost_pool_init(struct ost_pool *op, unsigned int count) op->op_count = 0; init_rwsem(&op->op_rw_sem); op->op_size = count; - OBD_ALLOC(op->op_array, op->op_size * sizeof(op->op_array[0])); + op->op_array = kcalloc(op->op_size, sizeof(op->op_array[0]), GFP_NOFS); if (op->op_array == NULL) { op->op_size = 0; return -ENOMEM; @@ -347,13 +347,13 @@ int lov_ost_pool_extend(struct ost_pool *op, unsigned int min_count) return 0; new_size = max(min_count, 2 * op->op_size); - OBD_ALLOC(new, new_size * sizeof(op->op_array[0])); + new = kcalloc(new_size, sizeof(op->op_array[0]), GFP_NOFS); if (new == NULL) return -ENOMEM; /* copy old array to new one */ memcpy(new, op->op_array, op->op_size * sizeof(op->op_array[0])); - OBD_FREE(op->op_array, op->op_size * sizeof(op->op_array[0])); + kfree(op->op_array); op->op_array = new; op->op_size = new_size; return 0; @@ -411,7 +411,7 @@ int lov_ost_pool_free(struct ost_pool *op) down_write(&op->op_rw_sem); - OBD_FREE(op->op_array, op->op_size * sizeof(op->op_array[0])); + kfree(op->op_array); op->op_array = NULL; op->op_count = 0; op->op_size = 0; @@ -432,7 +432,7 @@ int lov_pool_new(struct obd_device *obd, char *poolname) if (strlen(poolname) > LOV_MAXPOOLNAME) return -ENAMETOOLONG; - OBD_ALLOC_PTR(new_pool); + new_pool = kzalloc(sizeof(*new_pool), GFP_NOFS); if (new_pool == NULL) return -ENOMEM; @@ -498,7 +498,7 @@ int lov_pool_new(struct obd_device *obd, char *poolname) lov_ost_pool_free(&new_pool->pool_rr.lqr_pool); out_free_pool_obds: lov_ost_pool_free(&new_pool->pool_obds); - OBD_FREE_PTR(new_pool); + kfree(new_pool); return rc; } diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 933e2d1f8127e1..0a8cdbe1a537dc 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -71,9 +71,8 @@ void lov_finish_set(struct lov_request_set *set) if (req->rq_oi.oi_md) OBD_FREE_LARGE(req->rq_oi.oi_md, req->rq_buflen); if (req->rq_oi.oi_osfs) - OBD_FREE(req->rq_oi.oi_osfs, - sizeof(*req->rq_oi.oi_osfs)); - OBD_FREE(req, sizeof(*req)); + kfree(req->rq_oi.oi_osfs); + kfree(req); } if (set->set_pga) { @@ -83,7 +82,7 @@ void lov_finish_set(struct lov_request_set *set) if (set->set_lockh) lov_llh_put(set->set_lockh); - OBD_FREE(set, sizeof(*set)); + kfree(set); } int lov_set_finished(struct lov_request_set *set, int idempotent) @@ -286,7 +285,7 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_obd *lov = &exp->exp_obd->u.lov; int rc = 0, i; - OBD_ALLOC(set, sizeof(*set)); + set = kzalloc(sizeof(*set), GFP_NOFS); if (set == NULL) return -ENOMEM; lov_init_set(set); @@ -312,7 +311,7 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo, continue; } - OBD_ALLOC(req, sizeof(*req)); + req = kzalloc(sizeof(*req), GFP_NOFS); if (req == NULL) { rc = -ENOMEM; goto out_set; @@ -323,7 +322,7 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo, OBDO_ALLOC(req->rq_oi.oi_oa); if (req->rq_oi.oi_oa == NULL) { - OBD_FREE(req, sizeof(*req)); + kfree(req); rc = -ENOMEM; goto out_set; } @@ -369,7 +368,7 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_obd *lov = &exp->exp_obd->u.lov; int rc = 0, i; - OBD_ALLOC(set, sizeof(*set)); + set = kzalloc(sizeof(*set), GFP_NOFS); if (set == NULL) return -ENOMEM; lov_init_set(set); @@ -395,7 +394,7 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo, continue; } - OBD_ALLOC(req, sizeof(*req)); + req = kzalloc(sizeof(*req), GFP_NOFS); if (req == NULL) { rc = -ENOMEM; goto out_set; @@ -406,7 +405,7 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo, OBDO_ALLOC(req->rq_oi.oi_oa); if (req->rq_oi.oi_oa == NULL) { - OBD_FREE(req, sizeof(*req)); + kfree(req); rc = -ENOMEM; goto out_set; } @@ -488,7 +487,7 @@ int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_obd *lov = &exp->exp_obd->u.lov; int rc = 0, i; - OBD_ALLOC(set, sizeof(*set)); + set = kzalloc(sizeof(*set), GFP_NOFS); if (set == NULL) return -ENOMEM; lov_init_set(set); @@ -511,7 +510,7 @@ int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo, continue; } - OBD_ALLOC(req, sizeof(*req)); + req = kzalloc(sizeof(*req), GFP_NOFS); if (req == NULL) { rc = -ENOMEM; goto out_set; @@ -521,7 +520,7 @@ int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo, OBDO_ALLOC(req->rq_oi.oi_oa); if (req->rq_oi.oi_oa == NULL) { - OBD_FREE(req, sizeof(*req)); + kfree(req); rc = -ENOMEM; goto out_set; } @@ -716,7 +715,7 @@ int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo, struct lov_obd *lov = &obd->u.lov; int rc = 0, i; - OBD_ALLOC(set, sizeof(*set)); + set = kzalloc(sizeof(*set), GFP_NOFS); if (set == NULL) return -ENOMEM; lov_init_set(set); @@ -742,15 +741,16 @@ int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo, continue; } - OBD_ALLOC(req, sizeof(*req)); + req = kzalloc(sizeof(*req), GFP_NOFS); if (req == NULL) { rc = -ENOMEM; goto out_set; } - OBD_ALLOC(req->rq_oi.oi_osfs, sizeof(*req->rq_oi.oi_osfs)); + req->rq_oi.oi_osfs = kzalloc(sizeof(*req->rq_oi.oi_osfs), + GFP_NOFS); if (req->rq_oi.oi_osfs == NULL) { - OBD_FREE(req, sizeof(*req)); + kfree(req); rc = -ENOMEM; goto out_set; } diff --git a/drivers/staging/lustre/lustre/lov/lovsub_dev.c b/drivers/staging/lustre/lustre/lov/lovsub_dev.c index 42336f13a76f6f..90d9ec386a1a7c 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_dev.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_dev.c @@ -136,7 +136,7 @@ static struct lu_device *lovsub_device_free(const struct lu_env *env, lu_site_print(env, d->ld_site, &msgdata, lu_cdebug_printer); } cl_device_fini(lu2cl_dev(d)); - OBD_FREE_PTR(lsd); + kfree(lsd); return next; } @@ -172,7 +172,7 @@ static struct lu_device *lovsub_device_alloc(const struct lu_env *env, struct lu_device *d; struct lovsub_device *lsd; - OBD_ALLOC_PTR(lsd); + lsd = kzalloc(sizeof(*lsd), GFP_NOFS); if (lsd != NULL) { int result; From 3b2f5202c52a842a6528a72e85b46435c1d59116 Mon Sep 17 00:00:00 2001 From: Dzmitry Sledneu Date: Sat, 18 Apr 2015 15:20:43 +0200 Subject: [PATCH 0422/3798] staging: lustre: Make struct mdc_kuc_fops static This patch fixes the following Sparse warning: "symbol 'mdc_kuc_fops' was not declared. Should it be static?". Signed-off-by: Dzmitry Sledneu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/mdc/lproc_mdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c index acfe08e459c0c5..b41e50ea6ed8de 100644 --- a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c +++ b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c @@ -147,7 +147,7 @@ static ssize_t mdc_kuc_write(struct file *file, return count; } -struct file_operations mdc_kuc_fops = { +static struct file_operations mdc_kuc_fops = { .open = mdc_kuc_open, .write = mdc_kuc_write, .release = single_release, From 9c4e936abfadf5fc64481f06f7ba351b007af1ff Mon Sep 17 00:00:00 2001 From: Andreas Theodosiou Date: Sun, 5 Apr 2015 02:09:30 +0300 Subject: [PATCH 0423/3798] staging : unisys: Fix brace coding style issue This is a patch to visorchannel/visorchannel_funcs.c that fixes a couple of brace warnings found by checkpatch.pl. Signed-off-by: Andreas Theodosiou Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchannel/visorchannel_funcs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c index 7a9a7242f75d92..9ae5f752bbf5ea 100644 --- a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c +++ b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c @@ -405,9 +405,8 @@ signalremove_inner(struct visorchannel *channel, u32 queue, void *msg) return FALSE; /* no signals to remove */ sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots; - if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg)) { + if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg)) return FALSE; - } sig_hdr.num_received++; /* For each data field in SIGNAL_QUEUE_HEADER that was modified, @@ -470,9 +469,8 @@ signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) mb(); /* required for channel synch */ if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head)) return FALSE; - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent)) { + if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent)) return FALSE; - } return TRUE; } From 1ba00980f6b9151066e8ed19e4eb37e769b3ef70 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Mon, 6 Apr 2015 10:27:40 -0400 Subject: [PATCH 0424/3798] staging: unisys: fix kdump support The s-Par drivers used to be out-of-tree, so they needed a parameter to let them know we were going into a dump. This patch removes that code and uses the built-in kernel function instead. Reviewed-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/globals.h | 1 - drivers/staging/unisys/visorchipset/visorchipset_main.c | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/staging/unisys/visorchipset/globals.h b/drivers/staging/unisys/visorchipset/globals.h index f76e498a36b5f0..36b21ec3b120cd 100644 --- a/drivers/staging/unisys/visorchipset/globals.h +++ b/drivers/staging/unisys/visorchipset/globals.h @@ -36,7 +36,6 @@ extern int visorchipset_serverregwait; extern int visorchipset_clientregwait; extern int visorchipset_testteardown; extern int visorchipset_disable_controlvm; -extern int visorchipset_crash_kernel; extern int visorchipset_holdchipsetready; #endif diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index f2663d2c753003..899bf684cf0067 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -30,6 +30,7 @@ #include #include #include +#include #define CURRENT_FILE_PC VISOR_CHIPSET_PC_visorchipset_main_c #define TEST_VNIC_PHYSITF "eth0" /* physical network itf for @@ -2207,7 +2208,7 @@ visorchipset_init(void) } if (!visorchipset_disable_controlvm) { /* if booting in a crash kernel */ - if (visorchipset_crash_kernel) + if (is_kdump_kernel()) INIT_DELAYED_WORK(&periodic_controlvm_work, setup_crash_devices_work_queue); else @@ -2315,10 +2316,6 @@ module_param_named(disable_controlvm, visorchipset_disable_controlvm, int, MODULE_PARM_DESC(visorchipset_disable_controlvm, "1 to disable polling of controlVm channel"); int visorchipset_disable_controlvm = 0; /* default is off */ -module_param_named(crash_kernel, visorchipset_crash_kernel, int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_crash_kernel, - "1 means we are running in crash kernel"); -int visorchipset_crash_kernel = 0; /* default is running in non-crash kernel */ module_param_named(holdchipsetready, visorchipset_holdchipsetready, int, S_IRUGO); MODULE_PARM_DESC(visorchipset_holdchipsetready, From 0a22650b920fa9062e75ea51941a6249a0d16be7 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:38 -0400 Subject: [PATCH 0425/3798] staging: unisys: visorchipset: Remove unused NONULLSTR() Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset_main.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 899bf684cf0067..6144a945629f50 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -52,14 +52,6 @@ static ulong poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; static ulong most_recent_message_jiffies; /* when we got our last * controlvm message */ -static inline char * -NONULLSTR(char *s) -{ - if (s) - return s; - return ""; -} - static int serverregistered; static int clientregistered; From c1f834eb104d67a57ac745a36ace5e084328bda6 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:39 -0400 Subject: [PATCH 0426/3798] staging: unisys: visorchipset: Avoid struct typedef abuse Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- .../unisys/visorchipset/visorchipset_main.c | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 6144a945629f50..9e142a9199823c 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -92,17 +92,19 @@ static LIST_HEAD(dev_info_list); static struct visorchannel *controlvm_channel; /* Manages the request payload in the controlvm channel */ -static struct controlvm_payload_info { +struct visor_controlvm_payload_info { u8 __iomem *ptr; /* pointer to base address of payload pool */ u64 offset; /* offset from beginning of controlvm * channel to beginning of payload * pool */ u32 bytes; /* number of bytes in payload pool */ -} controlvm_payload_info; +}; + +static struct visor_controlvm_payload_info controlvm_payload_info; /* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE / * CONTROLVM_DUMP_GETTEXTDUMP / CONTROLVM_DUMP_COMPLETE conversation. */ -static struct livedump_info { +struct visor_livedump_info { struct controlvm_message_header dumpcapture_header; struct controlvm_message_header gettextdump_header; struct controlvm_message_header dumpcomplete_header; @@ -111,7 +113,9 @@ static struct livedump_info { ulong length; atomic_t buffers_in_use; ulong destination; -} livedump_info; +}; + +static struct visor_livedump_info livedump_info; /* The following globals are used to handle the scenario where we are unable to * offload the payload from a controlvm message due to memory requirements. In @@ -1263,7 +1267,7 @@ my_device_destroy(struct controlvm_message *inmsg) */ static int initialize_controlvm_payload_info(HOSTADDRESS phys_addr, u64 offset, u32 bytes, - struct controlvm_payload_info *info) + struct visor_controlvm_payload_info *info) { u8 __iomem *payload = NULL; int rc = CONTROLVM_RESP_SUCCESS; @@ -1272,7 +1276,7 @@ initialize_controlvm_payload_info(HOSTADDRESS phys_addr, u64 offset, u32 bytes, rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; goto cleanup; } - memset(info, 0, sizeof(struct controlvm_payload_info)); + memset(info, 0, sizeof(struct visor_controlvm_payload_info)); if ((offset == 0) || (bytes == 0)) { rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; goto cleanup; @@ -1298,13 +1302,13 @@ initialize_controlvm_payload_info(HOSTADDRESS phys_addr, u64 offset, u32 bytes, } static void -destroy_controlvm_payload_info(struct controlvm_payload_info *info) +destroy_controlvm_payload_info(struct visor_controlvm_payload_info *info) { if (info->ptr) { iounmap(info->ptr); info->ptr = NULL; } - memset(info, 0, sizeof(struct controlvm_payload_info)); + memset(info, 0, sizeof(struct visor_controlvm_payload_info)); } static void From f4c11551e7109f0d3a4708a149903e4c75e962d2 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:40 -0400 Subject: [PATCH 0427/3798] staging: unisys: visorchipset: Get rid of ugly BOOL/TRUE/FALSE usage Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/parser.c | 24 ++--- drivers/staging/unisys/visorchipset/parser.h | 8 +- .../unisys/visorchipset/visorchipset.h | 10 +- .../unisys/visorchipset/visorchipset_main.c | 98 +++++++++---------- 4 files changed, 70 insertions(+), 70 deletions(-) diff --git a/drivers/staging/unisys/visorchipset/parser.c b/drivers/staging/unisys/visorchipset/parser.c index d8a2d6f5a75d7a..b30e4c158b410b 100644 --- a/drivers/staging/unisys/visorchipset/parser.c +++ b/drivers/staging/unisys/visorchipset/parser.c @@ -36,13 +36,13 @@ struct parser_context { ulong param_bytes; u8 *curr; ulong bytes_remaining; - BOOL byte_stream; + bool byte_stream; char data[0]; }; static struct parser_context * -parser_init_guts(u64 addr, u32 bytes, BOOL local, - BOOL standard_payload_header, BOOL *retry) +parser_init_guts(u64 addr, u32 bytes, bool local, + bool standard_payload_header, bool *retry) { int allocbytes = sizeof(struct parser_context) + bytes; struct parser_context *rc = NULL; @@ -51,7 +51,7 @@ parser_init_guts(u64 addr, u32 bytes, BOOL local, struct spar_controlvm_parameters_header *phdr = NULL; if (retry) - *retry = FALSE; + *retry = false; if (!standard_payload_header) /* alloc and 0 extra byte to ensure payload is * '\0'-terminated @@ -60,14 +60,14 @@ parser_init_guts(u64 addr, u32 bytes, BOOL local, if ((controlvm_payload_bytes_buffered + bytes) > MAX_CONTROLVM_PAYLOAD_BYTES) { if (retry) - *retry = TRUE; + *retry = true; rc = NULL; goto cleanup; } ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY); if (!ctx) { if (retry) - *retry = TRUE; + *retry = true; rc = NULL; goto cleanup; } @@ -76,7 +76,7 @@ parser_init_guts(u64 addr, u32 bytes, BOOL local, ctx->param_bytes = bytes; ctx->curr = NULL; ctx->bytes_remaining = 0; - ctx->byte_stream = FALSE; + ctx->byte_stream = false; if (local) { void *p; @@ -98,7 +98,7 @@ parser_init_guts(u64 addr, u32 bytes, BOOL local, } } if (!standard_payload_header) { - ctx->byte_stream = TRUE; + ctx->byte_stream = true; rc = ctx; goto cleanup; } @@ -135,9 +135,9 @@ parser_init_guts(u64 addr, u32 bytes, BOOL local, } struct parser_context * -parser_init(u64 addr, u32 bytes, BOOL local, BOOL *retry) +parser_init(u64 addr, u32 bytes, bool local, bool *retry) { - return parser_init_guts(addr, bytes, local, TRUE, retry); + return parser_init_guts(addr, bytes, local, true, retry); } /* Call this instead of parser_init() if the payload area consists of just @@ -146,9 +146,9 @@ parser_init(u64 addr, u32 bytes, BOOL local, BOOL *retry) * parser_byteStream_get() to obtain the data. */ struct parser_context * -parser_init_byte_stream(u64 addr, u32 bytes, BOOL local, BOOL *retry) +parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) { - return parser_init_guts(addr, bytes, local, FALSE, retry); + return parser_init_guts(addr, bytes, local, false, retry); } /* Obtain '\0'-terminated copy of string in payload area. diff --git a/drivers/staging/unisys/visorchipset/parser.h b/drivers/staging/unisys/visorchipset/parser.h index 2b903f1beff2e3..d3b0b33348b300 100644 --- a/drivers/staging/unisys/visorchipset/parser.h +++ b/drivers/staging/unisys/visorchipset/parser.h @@ -30,10 +30,10 @@ typedef enum { PARSERSTRING_NAME, } PARSER_WHICH_STRING; -struct parser_context *parser_init(u64 addr, u32 bytes, BOOL isLocal, - BOOL *tryAgain); -struct parser_context *parser_init_byte_stream(u64 addr, u32 bytes, BOOL local, - BOOL *retry); +struct parser_context *parser_init(u64 addr, u32 bytes, bool isLocal, + bool *tryAgain); +struct parser_context *parser_init_byte_stream(u64 addr, u32 bytes, bool local, + bool *retry); void parser_param_start(struct parser_context *ctx, PARSER_WHICH_STRING which_string); void *parser_param_get(struct parser_context *ctx, char *nam, int namesize); diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index bd46df9ef45a36..4c1a74f6a5b845 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -217,19 +217,19 @@ typedef void (*SPARREPORTEVENT_COMPLETE_FUNC) (struct controlvm_message *msg, void visorchipset_device_pause_response(ulong bus_no, ulong dev_no, int response); -BOOL visorchipset_get_bus_info(ulong bus_no, +bool visorchipset_get_bus_info(ulong bus_no, struct visorchipset_bus_info *bus_info); -BOOL visorchipset_get_device_info(ulong bus_no, ulong dev_no, +bool visorchipset_get_device_info(ulong bus_no, ulong dev_no, struct visorchipset_device_info *dev_info); -BOOL visorchipset_set_bus_context(ulong bus_no, void *context); -BOOL visorchipset_set_device_context(ulong bus_no, ulong dev_no, void *context); +bool visorchipset_set_bus_context(ulong bus_no, void *context); +bool visorchipset_set_device_context(ulong bus_no, ulong dev_no, void *context); int visorchipset_chipset_ready(void); int visorchipset_chipset_selftest(void); int visorchipset_chipset_notready(void); void visorchipset_save_message(struct controlvm_message *msg, enum crash_obj_type type); void *visorchipset_cache_alloc(struct kmem_cache *pool, - BOOL ok_to_block, char *fn, int ln); + bool ok_to_block, char *fn, int ln); void visorchipset_cache_free(struct kmem_cache *pool, void *p, char *fn, int ln); diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 9e142a9199823c..8e7885452a724c 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -108,7 +108,7 @@ struct visor_livedump_info { struct controlvm_message_header dumpcapture_header; struct controlvm_message_header gettextdump_header; struct controlvm_message_header dumpcomplete_header; - BOOL gettextdump_outstanding; + bool gettextdump_outstanding; u32 crc32; ulong length; atomic_t buffers_in_use; @@ -123,7 +123,7 @@ static struct visor_livedump_info livedump_info; * process it again the next time controlvm_periodic_work() runs. */ static struct controlvm_message controlvm_pending_msg; -static BOOL controlvm_pending_msg_valid = FALSE; +static bool controlvm_pending_msg_valid = false; /* Pool of struct putfile_buffer_entry, for keeping track of pending (incoming) * TRANSMIT_FILE PutFile payloads. @@ -776,7 +776,7 @@ static void bus_responder(enum controlvm_id cmd_id, ulong bus_no, int response) { struct visorchipset_bus_info *p = NULL; - BOOL need_clear = FALSE; + bool need_clear = false; p = findbus(&bus_info_list, bus_no); if (!p) @@ -791,7 +791,7 @@ bus_responder(enum controlvm_id cmd_id, ulong bus_no, int response) if (cmd_id == CONTROLVM_BUS_CREATE) p->state.created = 1; if (cmd_id == CONTROLVM_BUS_DESTROY) - need_clear = TRUE; + need_clear = true; } if (p->pending_msg_hdr.id == CONTROLVM_INVALID) @@ -840,7 +840,7 @@ device_responder(enum controlvm_id cmd_id, ulong bus_no, ulong dev_no, int response) { struct visorchipset_device_info *p = NULL; - BOOL need_clear = FALSE; + bool need_clear = false; p = finddevice(&dev_info_list, bus_no, dev_no); if (!p) @@ -849,7 +849,7 @@ device_responder(enum controlvm_id cmd_id, ulong bus_no, ulong dev_no, if (cmd_id == CONTROLVM_DEVICE_CREATE) p->state.created = 1; if (cmd_id == CONTROLVM_DEVICE_DESTROY) - need_clear = TRUE; + need_clear = true; } if (p->pending_msg_hdr.id == CONTROLVM_INVALID) @@ -867,9 +867,9 @@ device_responder(enum controlvm_id cmd_id, ulong bus_no, ulong dev_no, static void bus_epilog(u32 bus_no, u32 cmd, struct controlvm_message_header *msg_hdr, - int response, BOOL need_response) + int response, bool need_response) { - BOOL notified = FALSE; + bool notified = false; struct visorchipset_bus_info *bus_info = findbus(&bus_info_list, bus_no); @@ -900,23 +900,23 @@ bus_epilog(u32 bus_no, * devices */ if (busdev_server_notifiers.bus_create) { (*busdev_server_notifiers.bus_create) (bus_no); - notified = TRUE; + notified = true; } if ((!bus_info->flags.server) /*client */ && busdev_client_notifiers.bus_create) { (*busdev_client_notifiers.bus_create) (bus_no); - notified = TRUE; + notified = true; } break; case CONTROLVM_BUS_DESTROY: if (busdev_server_notifiers.bus_destroy) { (*busdev_server_notifiers.bus_destroy) (bus_no); - notified = TRUE; + notified = true; } if ((!bus_info->flags.server) /*client */ && busdev_client_notifiers.bus_destroy) { (*busdev_client_notifiers.bus_destroy) (bus_no); - notified = TRUE; + notified = true; } break; } @@ -935,10 +935,10 @@ bus_epilog(u32 bus_no, static void device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, struct controlvm_message_header *msg_hdr, int response, - BOOL need_response, BOOL for_visorbus) + bool need_response, bool for_visorbus) { struct visorchipset_busdev_notifiers *notifiers = NULL; - BOOL notified = FALSE; + bool notified = false; struct visorchipset_device_info *dev_info = finddevice(&dev_info_list, bus_no, dev_no); @@ -967,7 +967,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, case CONTROLVM_DEVICE_CREATE: if (notifiers->device_create) { (*notifiers->device_create) (bus_no, dev_no); - notified = TRUE; + notified = true; } break; case CONTROLVM_DEVICE_CHANGESTATE: @@ -978,7 +978,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, if (notifiers->device_resume) { (*notifiers->device_resume) (bus_no, dev_no); - notified = TRUE; + notified = true; } } /* ServerNotReady / ServerLost / SegmentStateStandby */ @@ -991,7 +991,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, if (notifiers->device_pause) { (*notifiers->device_pause) (bus_no, dev_no); - notified = TRUE; + notified = true; } } else if (state.alive == segment_state_paused.alive && state.operating == @@ -1013,7 +1013,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, case CONTROLVM_DEVICE_DESTROY: if (notifiers->device_destroy) { (*notifiers->device_destroy) (bus_no, dev_no); - notified = TRUE; + notified = true; } break; } @@ -1262,7 +1262,7 @@ my_device_destroy(struct controlvm_message *inmsg) /* When provided with the physical address of the controlvm channel * (phys_addr), the offset to the payload area we need to manage * (offset), and the size of this payload area (bytes), fills in the - * controlvm_payload_info struct. Returns TRUE for success or FALSE + * controlvm_payload_info struct. Returns true for success or false * for failure. */ static int @@ -1416,17 +1416,17 @@ chipset_notready(struct controlvm_message_header *msg_hdr) /* This is your "one-stop" shop for grabbing the next message from the * CONTROLVM_QUEUE_EVENT queue in the controlvm channel. */ -static BOOL +static bool read_controlvm_event(struct controlvm_message *msg) { if (visorchannel_signalremove(controlvm_channel, CONTROLVM_QUEUE_EVENT, msg)) { /* got a message */ if (msg->hdr.flags.test_message == 1) - return FALSE; - return TRUE; + return false; + return true; } - return FALSE; + return false; } /* @@ -1637,16 +1637,16 @@ parahotplug_process_message(struct controlvm_message *inmsg) /* Process a controlvm message. * Return result: - * FALSE - this function will return FALSE only in the case where the + * false - this function will return FALSE only in the case where the * controlvm message was NOT processed, but processing must be * retried before reading the next controlvm message; a * scenario where this can occur is when we need to throttle * the allocation of memory in which to copy out controlvm * payload data - * TRUE - processing of the controlvm message completed, + * true - processing of the controlvm message completed, * either successfully or with an error. */ -static BOOL +static bool handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr) { struct controlvm_message_packet *cmd = &inmsg.cmd; @@ -1659,7 +1659,7 @@ handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr) /* create parsing context if necessary */ local_addr = (inmsg.hdr.flags.test_message == 1); if (channel_addr == 0) - return TRUE; + return true; parm_addr = channel_addr + inmsg.hdr.payload_vm_offset; parm_bytes = inmsg.hdr.payload_bytes; @@ -1668,13 +1668,13 @@ handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr) * makes a difference in how we compute the virtual address. */ if (parm_addr != 0 && parm_bytes != 0) { - BOOL retry = FALSE; + bool retry = false; parser_ctx = parser_init_byte_stream(parm_addr, parm_bytes, local_addr, &retry); if (!parser_ctx && retry) - return FALSE; + return false; } if (!local_addr) { @@ -1741,7 +1741,7 @@ handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr) parser_done(parser_ctx); parser_ctx = NULL; } - return TRUE; + return true; } static HOSTADDRESS controlvm_get_channel_address(void) @@ -1759,8 +1759,8 @@ static void controlvm_periodic_work(struct work_struct *work) { struct controlvm_message inmsg; - BOOL got_command = FALSE; - BOOL handle_command_failed = FALSE; + bool got_command = false; + bool handle_command_failed = false; static u64 poll_count; /* make sure visorbus server is registered for controlvm callbacks */ @@ -1802,14 +1802,14 @@ controlvm_periodic_work(struct work_struct *work) * rather than reading a new one */ inmsg = controlvm_pending_msg; - controlvm_pending_msg_valid = FALSE; + controlvm_pending_msg_valid = false; got_command = true; } else { got_command = read_controlvm_event(&inmsg); } } - handle_command_failed = FALSE; + handle_command_failed = false; while (got_command && (!handle_command_failed)) { most_recent_message_jiffies = jiffies; if (handle_command(inmsg, @@ -1823,9 +1823,9 @@ controlvm_periodic_work(struct work_struct *work) * controlvm msg so we will attempt to * reprocess it on our next loop */ - handle_command_failed = TRUE; + handle_command_failed = true; controlvm_pending_msg = inmsg; - controlvm_pending_msg_valid = TRUE; + controlvm_pending_msg_valid = true; } } @@ -1996,60 +1996,60 @@ device_resume_response(ulong bus_no, ulong dev_no, int response) segment_state_running); } -BOOL +bool visorchipset_get_bus_info(ulong bus_no, struct visorchipset_bus_info *bus_info) { void *p = findbus(&bus_info_list, bus_no); if (!p) - return FALSE; + return false; memcpy(bus_info, p, sizeof(struct visorchipset_bus_info)); - return TRUE; + return true; } EXPORT_SYMBOL_GPL(visorchipset_get_bus_info); -BOOL +bool visorchipset_set_bus_context(ulong bus_no, void *context) { struct visorchipset_bus_info *p = findbus(&bus_info_list, bus_no); if (!p) - return FALSE; + return false; p->bus_driver_context = context; - return TRUE; + return true; } EXPORT_SYMBOL_GPL(visorchipset_set_bus_context); -BOOL +bool visorchipset_get_device_info(ulong bus_no, ulong dev_no, struct visorchipset_device_info *dev_info) { void *p = finddevice(&dev_info_list, bus_no, dev_no); if (!p) - return FALSE; + return false; memcpy(dev_info, p, sizeof(struct visorchipset_device_info)); - return TRUE; + return true; } EXPORT_SYMBOL_GPL(visorchipset_get_device_info); -BOOL +bool visorchipset_set_device_context(ulong bus_no, ulong dev_no, void *context) { struct visorchipset_device_info *p = finddevice(&dev_info_list, bus_no, dev_no); if (!p) - return FALSE; + return false; p->bus_driver_context = context; - return TRUE; + return true; } EXPORT_SYMBOL_GPL(visorchipset_set_device_context); /* Generic wrapper function for allocating memory from a kmem_cache pool. */ void * -visorchipset_cache_alloc(struct kmem_cache *pool, BOOL ok_to_block, +visorchipset_cache_alloc(struct kmem_cache *pool, bool ok_to_block, char *fn, int ln) { gfp_t gfp; From 52063eca7fd04cb4e8a5b8f0d4f99c5e8816d59e Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:41 -0400 Subject: [PATCH 0428/3798] staging: unisys: visorchipset: Do not use confuse size of long with size of u32 struct visorcipset_device_info defines bus_no and dev_no as u32, while the deprecated ulong type is 64 bits. Hence avoid promoting the values to 64 bit just to truncate them again later. Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- .../unisys/visorchipset/visorchipset.h | 35 +++++----- .../unisys/visorchipset/visorchipset_main.c | 67 +++++++++---------- 2 files changed, 50 insertions(+), 52 deletions(-) diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 4c1a74f6a5b845..3a8aa5614b4b29 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -162,12 +162,12 @@ findbus(struct list_head *list, u32 bus_no) * visorchipset.) */ struct visorchipset_busdev_notifiers { - void (*bus_create)(ulong bus_no); - void (*bus_destroy)(ulong bus_no); - void (*device_create)(ulong bus_no, ulong dev_no); - void (*device_destroy)(ulong bus_no, ulong dev_no); - void (*device_pause)(ulong bus_no, ulong dev_no); - void (*device_resume)(ulong bus_no, ulong dev_no); + void (*bus_create)(u32 bus_no); + void (*bus_destroy)(u32 bus_no); + void (*device_create)(u32 bus_no, u32 dev_no); + void (*device_destroy)(u32 bus_no, u32 dev_no); + void (*device_pause)(u32 bus_no, u32 dev_no); + void (*device_resume)(u32 bus_no, u32 dev_no); int (*get_channel_info)(uuid_le type_uuid, ulong *min_size, ulong *max_size); }; @@ -179,12 +179,12 @@ struct visorchipset_busdev_notifiers { * -1 = it failed */ struct visorchipset_busdev_responders { - void (*bus_create)(ulong bus_no, int response); - void (*bus_destroy)(ulong bus_no, int response); - void (*device_create)(ulong bus_no, ulong dev_no, int response); - void (*device_destroy)(ulong bus_no, ulong dev_no, int response); - void (*device_pause)(ulong bus_no, ulong dev_no, int response); - void (*device_resume)(ulong bus_no, ulong dev_no, int response); + void (*bus_create)(u32 bus_no, int response); + void (*bus_destroy)(u32 bus_no, int response); + void (*device_create)(u32 bus_no, u32 dev_no, int response); + void (*device_destroy)(u32 bus_no, u32 dev_no, int response); + void (*device_pause)(u32 bus_no, u32 dev_no, int response); + void (*device_resume)(u32 bus_no, u32 dev_no, int response); }; /** Register functions (in the bus driver) to get called by visorchipset @@ -214,15 +214,14 @@ visorchipset_register_busdev_server( typedef void (*SPARREPORTEVENT_COMPLETE_FUNC) (struct controlvm_message *msg, int status); -void visorchipset_device_pause_response(ulong bus_no, ulong dev_no, - int response); +void visorchipset_device_pause_response(u32 bus_no, u32 dev_no, int response); -bool visorchipset_get_bus_info(ulong bus_no, +bool visorchipset_get_bus_info(u32 bus_no, struct visorchipset_bus_info *bus_info); -bool visorchipset_get_device_info(ulong bus_no, ulong dev_no, +bool visorchipset_get_device_info(u32 bus_no, u32 dev_no, struct visorchipset_device_info *dev_info); -bool visorchipset_set_bus_context(ulong bus_no, void *context); -bool visorchipset_set_device_context(ulong bus_no, ulong dev_no, void *context); +bool visorchipset_set_bus_context(u32 bus_no, void *context); +bool visorchipset_set_device_context(u32 bus_no, u32 dev_no, void *context); int visorchipset_chipset_ready(void); int visorchipset_chipset_selftest(void); int visorchipset_chipset_notready(void); diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 8e7885452a724c..90e41cb6459796 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -49,8 +49,8 @@ * message, we switch back to fast polling mode. */ #define MIN_IDLE_SECONDS 10 -static ulong poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; -static ulong most_recent_message_jiffies; /* when we got our last +static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; +static unsigned long most_recent_message_jiffies; /* when we got our last * controlvm message */ static int serverregistered; static int clientregistered; @@ -68,8 +68,8 @@ static struct controlvm_message_header g_del_dump_msg_hdr; static const uuid_le spar_diag_pool_channel_protocol_uuid = SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID; /* 0xffffff is an invalid Bus/Device number */ -static ulong g_diagpool_bus_no = 0xffffff; -static ulong g_diagpool_dev_no = 0xffffff; +static u32 g_diagpool_bus_no = 0xffffff; +static u32 g_diagpool_dev_no = 0xffffff; static struct controlvm_message_packet g_devicechangestate_packet; /* Only VNIC and VHBA channels are sent to visorclientbus (aka @@ -110,9 +110,9 @@ struct visor_livedump_info { struct controlvm_message_header dumpcomplete_header; bool gettextdump_outstanding; u32 crc32; - ulong length; + unsigned long length; atomic_t buffers_in_use; - ulong destination; + unsigned long destination; }; static struct visor_livedump_info livedump_info; @@ -219,11 +219,11 @@ static void parahotplug_process_list(void); static struct visorchipset_busdev_notifiers busdev_server_notifiers; static struct visorchipset_busdev_notifiers busdev_client_notifiers; -static void bus_create_response(ulong bus_no, int response); -static void bus_destroy_response(ulong bus_no, int response); -static void device_create_response(ulong bus_no, ulong dev_no, int response); -static void device_destroy_response(ulong bus_no, ulong dev_no, int response); -static void device_resume_response(ulong bus_no, ulong dev_no, int response); +static void bus_create_response(u32 bus_no, int response); +static void bus_destroy_response(u32 bus_no, int response); +static void device_create_response(u32 bus_no, u32 dev_no, int response); +static void device_destroy_response(u32 bus_no, u32 dev_no, int response); +static void device_resume_response(u32 bus_no, u32 dev_no, int response); static struct visorchipset_busdev_responders busdev_responders = { .bus_create = bus_create_response, @@ -773,7 +773,7 @@ visorchipset_save_message(struct controlvm_message *msg, EXPORT_SYMBOL_GPL(visorchipset_save_message); static void -bus_responder(enum controlvm_id cmd_id, ulong bus_no, int response) +bus_responder(enum controlvm_id cmd_id, u32 bus_no, int response) { struct visorchipset_bus_info *p = NULL; bool need_clear = false; @@ -808,7 +808,7 @@ bus_responder(enum controlvm_id cmd_id, ulong bus_no, int response) static void device_changestate_responder(enum controlvm_id cmd_id, - ulong bus_no, ulong dev_no, int response, + u32 bus_no, u32 dev_no, int response, struct spar_segment_state response_state) { struct visorchipset_device_info *p = NULL; @@ -836,8 +836,7 @@ device_changestate_responder(enum controlvm_id cmd_id, } static void -device_responder(enum controlvm_id cmd_id, ulong bus_no, ulong dev_no, - int response) +device_responder(enum controlvm_id cmd_id, u32 bus_no, u32 dev_no, int response) { struct visorchipset_device_info *p = NULL; bool need_clear = false; @@ -1033,7 +1032,7 @@ static void bus_create(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - ulong bus_no = cmd->create_bus.bus_no; + u32 bus_no = cmd->create_bus.bus_no; int rc = CONTROLVM_RESP_SUCCESS; struct visorchipset_bus_info *bus_info = NULL; @@ -1083,7 +1082,7 @@ static void bus_destroy(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - ulong bus_no = cmd->destroy_bus.bus_no; + u32 bus_no = cmd->destroy_bus.bus_no; struct visorchipset_bus_info *bus_info; int rc = CONTROLVM_RESP_SUCCESS; @@ -1102,7 +1101,7 @@ bus_configure(struct controlvm_message *inmsg, struct parser_context *parser_ctx) { struct controlvm_message_packet *cmd = &inmsg->cmd; - ulong bus_no = cmd->configure_bus.bus_no; + u32 bus_no = cmd->configure_bus.bus_no; struct visorchipset_bus_info *bus_info = NULL; int rc = CONTROLVM_RESP_SUCCESS; char s[99]; @@ -1142,8 +1141,8 @@ static void my_device_create(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - ulong bus_no = cmd->create_device.bus_no; - ulong dev_no = cmd->create_device.dev_no; + u32 bus_no = cmd->create_device.bus_no; + u32 dev_no = cmd->create_device.dev_no; struct visorchipset_device_info *dev_info = NULL; struct visorchipset_bus_info *bus_info = NULL; int rc = CONTROLVM_RESP_SUCCESS; @@ -1212,8 +1211,8 @@ static void my_device_changestate(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - ulong bus_no = cmd->device_change_state.bus_no; - ulong dev_no = cmd->device_change_state.dev_no; + u32 bus_no = cmd->device_change_state.bus_no; + u32 dev_no = cmd->device_change_state.dev_no; struct spar_segment_state state = cmd->device_change_state.state; struct visorchipset_device_info *dev_info = NULL; int rc = CONTROLVM_RESP_SUCCESS; @@ -1240,8 +1239,8 @@ static void my_device_destroy(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - ulong bus_no = cmd->destroy_device.bus_no; - ulong dev_no = cmd->destroy_device.dev_no; + u32 bus_no = cmd->destroy_device.bus_no; + u32 dev_no = cmd->destroy_device.dev_no; struct visorchipset_device_info *dev_info = NULL; int rc = CONTROLVM_RESP_SUCCESS; @@ -1956,31 +1955,31 @@ setup_crash_devices_work_queue(struct work_struct *work) } static void -bus_create_response(ulong bus_no, int response) +bus_create_response(u32 bus_no, int response) { bus_responder(CONTROLVM_BUS_CREATE, bus_no, response); } static void -bus_destroy_response(ulong bus_no, int response) +bus_destroy_response(u32 bus_no, int response) { bus_responder(CONTROLVM_BUS_DESTROY, bus_no, response); } static void -device_create_response(ulong bus_no, ulong dev_no, int response) +device_create_response(u32 bus_no, u32 dev_no, int response) { device_responder(CONTROLVM_DEVICE_CREATE, bus_no, dev_no, response); } static void -device_destroy_response(ulong bus_no, ulong dev_no, int response) +device_destroy_response(u32 bus_no, u32 dev_no, int response) { device_responder(CONTROLVM_DEVICE_DESTROY, bus_no, dev_no, response); } void -visorchipset_device_pause_response(ulong bus_no, ulong dev_no, int response) +visorchipset_device_pause_response(u32 bus_no, u32 dev_no, int response) { device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, bus_no, dev_no, response, @@ -1989,7 +1988,7 @@ visorchipset_device_pause_response(ulong bus_no, ulong dev_no, int response) EXPORT_SYMBOL_GPL(visorchipset_device_pause_response); static void -device_resume_response(ulong bus_no, ulong dev_no, int response) +device_resume_response(u32 bus_no, u32 dev_no, int response) { device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, bus_no, dev_no, response, @@ -1997,7 +1996,7 @@ device_resume_response(ulong bus_no, ulong dev_no, int response) } bool -visorchipset_get_bus_info(ulong bus_no, struct visorchipset_bus_info *bus_info) +visorchipset_get_bus_info(u32 bus_no, struct visorchipset_bus_info *bus_info) { void *p = findbus(&bus_info_list, bus_no); @@ -2009,7 +2008,7 @@ visorchipset_get_bus_info(ulong bus_no, struct visorchipset_bus_info *bus_info) EXPORT_SYMBOL_GPL(visorchipset_get_bus_info); bool -visorchipset_set_bus_context(ulong bus_no, void *context) +visorchipset_set_bus_context(u32 bus_no, void *context) { struct visorchipset_bus_info *p = findbus(&bus_info_list, bus_no); @@ -2021,7 +2020,7 @@ visorchipset_set_bus_context(ulong bus_no, void *context) EXPORT_SYMBOL_GPL(visorchipset_set_bus_context); bool -visorchipset_get_device_info(ulong bus_no, ulong dev_no, +visorchipset_get_device_info(u32 bus_no, u32 dev_no, struct visorchipset_device_info *dev_info) { void *p = finddevice(&dev_info_list, bus_no, dev_no); @@ -2034,7 +2033,7 @@ visorchipset_get_device_info(ulong bus_no, ulong dev_no, EXPORT_SYMBOL_GPL(visorchipset_get_device_info); bool -visorchipset_set_device_context(ulong bus_no, ulong dev_no, void *context) +visorchipset_set_device_context(u32 bus_no, u32 dev_no, void *context) { struct visorchipset_device_info *p = finddevice(&dev_info_list, bus_no, dev_no); From a6e7fe5c042c171d912783a8bf0918b7f68aefe4 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:42 -0400 Subject: [PATCH 0429/3798] staging: unisys: visorchipset: Use correct type for dev_no visorchipset_bus_info.dev_no is only assigned the value of controlvm_message_packet.create_bus.dev_count, which is a u32. No point promoting it to a u64. Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 3a8aa5614b4b29..3848de2533710c 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -141,8 +141,7 @@ struct visorchipset_bus_info { struct controlvm_message_header pending_msg_hdr;/* CONTROLVM MsgHdr */ /** For private use by the bus driver */ void *bus_driver_context; - u64 dev_no; - + u32 dev_no; }; static inline struct visorchipset_bus_info * From ac48c05c678e9917b9f3e9b6e1792675a6a1d672 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:43 -0400 Subject: [PATCH 0430/3798] staging: unisys: visorchipset: Remove unused get_channel_info notifier Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 3848de2533710c..87b63f0dc36a48 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -167,8 +167,6 @@ struct visorchipset_busdev_notifiers { void (*device_destroy)(u32 bus_no, u32 dev_no); void (*device_pause)(u32 bus_no, u32 dev_no); void (*device_resume)(u32 bus_no, u32 dev_no); - int (*get_channel_info)(uuid_le type_uuid, ulong *min_size, - ulong *max_size); }; /* These functions live inside visorchipset, and will be called to indicate From 1d4c1afac4c46723475ec8e10ff7eed3c439393c Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:44 -0400 Subject: [PATCH 0431/3798] staging: unisys: visorchipset: Get rid of ulong usage Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/file.c | 6 +++--- drivers/staging/unisys/visorchipset/parser.c | 16 ++++++++-------- drivers/staging/unisys/visorchipset/parser.h | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index 203de0b5f6071f..6fc56896e42707 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -60,8 +60,8 @@ visorchipset_release(struct inode *inode, struct file *file) static int visorchipset_mmap(struct file *file, struct vm_area_struct *vma) { - ulong physaddr = 0; - ulong offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long physaddr = 0; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; GUEST_PHYSICAL_ADDRESS addr = 0; /* sv_enable_dfp(); */ @@ -81,7 +81,7 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma) if (addr == 0) { return -ENXIO; } - physaddr = (ulong)addr; + physaddr = (unsigned long)addr; if (remap_pfn_range(vma, vma->vm_start, physaddr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, diff --git a/drivers/staging/unisys/visorchipset/parser.c b/drivers/staging/unisys/visorchipset/parser.c index b30e4c158b410b..6ca6da8772a896 100644 --- a/drivers/staging/unisys/visorchipset/parser.c +++ b/drivers/staging/unisys/visorchipset/parser.c @@ -29,13 +29,13 @@ * incoming payloads. This serves as a throttling mechanism. */ #define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128) -static ulong controlvm_payload_bytes_buffered; +static unsigned long controlvm_payload_bytes_buffered; struct parser_context { - ulong allocbytes; - ulong param_bytes; + unsigned long allocbytes; + unsigned long param_bytes; u8 *curr; - ulong bytes_remaining; + unsigned long bytes_remaining; bool byte_stream; char data[0]; }; @@ -84,7 +84,7 @@ parser_init_guts(u64 addr, u32 bytes, bool local, rc = NULL; goto cleanup; } - p = __va((ulong) (addr)); + p = __va((unsigned long) (addr)); memcpy(ctx->data, p, bytes); } else { rgn = visor_memregion_create(addr, bytes); @@ -165,7 +165,7 @@ parser_simpleString_get(struct parser_context *ctx) /* Obtain a copy of the buffer in the payload area. */ -void *parser_byte_stream_get(struct parser_context *ctx, ulong *nbytes) +void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes) { if (!ctx->byte_stream) return NULL; @@ -265,7 +265,7 @@ void * parser_param_get(struct parser_context *ctx, char *nam, int namesize) { u8 *pscan, *pnam = nam; - ulong nscan; + unsigned long nscan; int value_length = -1, orig_value_length = -1; void *value = NULL; int i; @@ -400,7 +400,7 @@ void * parser_string_get(struct parser_context *ctx) { u8 *pscan; - ulong nscan; + unsigned long nscan; int value_length = -1; void *value = NULL; int i; diff --git a/drivers/staging/unisys/visorchipset/parser.h b/drivers/staging/unisys/visorchipset/parser.h index d3b0b33348b300..73be279bb401a2 100644 --- a/drivers/staging/unisys/visorchipset/parser.h +++ b/drivers/staging/unisys/visorchipset/parser.h @@ -40,7 +40,7 @@ void *parser_param_get(struct parser_context *ctx, char *nam, int namesize); void *parser_string_get(struct parser_context *ctx); uuid_le parser_id_get(struct parser_context *ctx); char *parser_simpleString_get(struct parser_context *ctx); -void *parser_byte_stream_get(struct parser_context *ctx, ulong *nbytes); +void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes); void parser_done(struct parser_context *ctx); #endif From 3d3fb181309c68850762123f6f87f660a7606dfb Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Mon, 13 Apr 2015 21:16:49 -0400 Subject: [PATCH 0432/3798] staging: unisys: remove virthba driver for rewrite The virthba driver is being rewritten and will be renamed to visorhba, so delete the old driver from the source tree. Signed-off-by: Benjamin Romer Reviewed-by: Don Zickus Reviewed-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/Kconfig | 1 - drivers/staging/unisys/Makefile | 1 - drivers/staging/unisys/virthba/Kconfig | 13 - drivers/staging/unisys/virthba/Makefile | 12 - drivers/staging/unisys/virthba/virthba.c | 1572 ---------------------- drivers/staging/unisys/virthba/virthba.h | 27 - 6 files changed, 1626 deletions(-) delete mode 100644 drivers/staging/unisys/virthba/Kconfig delete mode 100644 drivers/staging/unisys/virthba/Makefile delete mode 100644 drivers/staging/unisys/virthba/virthba.c delete mode 100644 drivers/staging/unisys/virthba/virthba.h diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig index 19fcb34655093a..906cd589048d8a 100644 --- a/drivers/staging/unisys/Kconfig +++ b/drivers/staging/unisys/Kconfig @@ -14,6 +14,5 @@ source "drivers/staging/unisys/visorchannel/Kconfig" source "drivers/staging/unisys/visorchipset/Kconfig" source "drivers/staging/unisys/uislib/Kconfig" source "drivers/staging/unisys/virtpci/Kconfig" -source "drivers/staging/unisys/virthba/Kconfig" endif # UNISYSSPAR diff --git a/drivers/staging/unisys/Makefile b/drivers/staging/unisys/Makefile index 68b9925e7d5eb3..3283a013d0c687 100644 --- a/drivers/staging/unisys/Makefile +++ b/drivers/staging/unisys/Makefile @@ -6,4 +6,3 @@ obj-$(CONFIG_UNISYS_VISORCHANNEL) += visorchannel/ obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset/ obj-$(CONFIG_UNISYS_UISLIB) += uislib/ obj-$(CONFIG_UNISYS_VIRTPCI) += virtpci/ -obj-$(CONFIG_UNISYS_VIRTHBA) += virthba/ diff --git a/drivers/staging/unisys/virthba/Kconfig b/drivers/staging/unisys/virthba/Kconfig deleted file mode 100644 index dfadfc49114aba..00000000000000 --- a/drivers/staging/unisys/virthba/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -# -# Unisys virthba configuration -# - -config UNISYS_VIRTHBA - tristate "Unisys virthba driver" - depends on SCSI - select UNISYS_VISORCHIPSET - select UNISYS_UISLIB - select UNISYS_VIRTPCI - ---help--- - If you say Y here, you will enable the Unisys virthba driver. - diff --git a/drivers/staging/unisys/virthba/Makefile b/drivers/staging/unisys/virthba/Makefile deleted file mode 100644 index a4e40373918327..00000000000000 --- a/drivers/staging/unisys/virthba/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for Unisys virthba -# - -obj-$(CONFIG_UNISYS_VIRTHBA) += virthba.o - -ccflags-y += -Idrivers/staging/unisys/include -ccflags-y += -Idrivers/staging/unisys/uislib -ccflags-y += -Idrivers/staging/unisys/visorchipset -ccflags-y += -Idrivers/staging/unisys/virtpci -ccflags-y += -Idrivers/staging/unisys/common-spar/include -ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c deleted file mode 100644 index d9001cca0f7357..00000000000000 --- a/drivers/staging/unisys/virthba/virthba.c +++ /dev/null @@ -1,1572 +0,0 @@ -/* virthba.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#define EXPORT_SYMTAB - -/* if you want to turn on some debugging of write device data or read - * device data, define these two undefs. You will probably want to - * customize the code which is here since it was written assuming - * reading and writing a specific data file df.64M.txt which is a - * 64Megabyte file created by Art Nilson using a scritp I wrote called - * cr_test_data.pl. The data file consists of 256 byte lines of text - * which start with an 8 digit sequence number, a colon, and then - * letters after that */ - -#include -#ifdef CONFIG_MODVERSIONS -#include -#endif - -#include "diagnostics/appos_subsystems.h" -#include "uisutils.h" -#include "uisqueue.h" -#include "uisthread.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "virthba.h" -#include "virtpci.h" -#include "visorchipset.h" -#include "version.h" -#include "guestlinuxdebug.h" -/* this is shorter than using __FILE__ (full path name) in - * debug/info/error messages - */ -#define CURRENT_FILE_PC VIRT_HBA_PC_virthba_c -#define __MYFILE__ "virthba.c" - -/* NOTE: L1_CACHE_BYTES >=128 */ -#define DEVICE_ATTRIBUTE struct device_attribute - - /* MAX_BUF = 6 lines x 10 MAXVHBA x 80 characters - * = 4800 bytes ~ 2^13 = 8192 bytes - */ -#define MAX_BUF 8192 - -/*****************************************************/ -/* Forward declarations */ -/*****************************************************/ -static int virthba_probe(struct virtpci_dev *dev, - const struct pci_device_id *id); -static void virthba_remove(struct virtpci_dev *dev); -static int virthba_abort_handler(struct scsi_cmnd *scsicmd); -static int virthba_bus_reset_handler(struct scsi_cmnd *scsicmd); -static int virthba_device_reset_handler(struct scsi_cmnd *scsicmd); -static int virthba_host_reset_handler(struct scsi_cmnd *scsicmd); -static const char *virthba_get_info(struct Scsi_Host *shp); -static int virthba_ioctl(struct scsi_device *dev, int cmd, void __user *arg); -static int virthba_queue_command_lck(struct scsi_cmnd *scsicmd, - void (*virthba_cmnd_done) - (struct scsi_cmnd *)); - -static const struct x86_cpu_id unisys_spar_ids[] = { - { X86_VENDOR_INTEL, 6, 62, X86_FEATURE_ANY }, - {} -}; - -/* Autoload */ -MODULE_DEVICE_TABLE(x86cpu, unisys_spar_ids); - -#ifdef DEF_SCSI_QCMD -static DEF_SCSI_QCMD(virthba_queue_command) -#else -#define virthba_queue_command virthba_queue_command_lck -#endif - -static int virthba_slave_alloc(struct scsi_device *scsidev); -static int virthba_slave_configure(struct scsi_device *scsidev); -static void virthba_slave_destroy(struct scsi_device *scsidev); -static int process_incoming_rsps(void *); -static int virthba_serverup(struct virtpci_dev *virtpcidev); -static int virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state); -static void do_disk_add_remove(struct work_struct *work); -static void virthba_serverdown_complete(struct work_struct *work); -static ssize_t info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset); -static ssize_t enable_ints_write(struct file *file, - const char __user *buffer, size_t count, - loff_t *ppos); - -/*****************************************************/ -/* Globals */ -/*****************************************************/ - -static int rsltq_wait_usecs = 4000; /* Default 4ms */ -static unsigned int max_buff_len; - -/* Module options */ -static char *virthba_options = "NONE"; - -static const struct pci_device_id virthba_id_table[] = { - {PCI_DEVICE(PCI_VENDOR_ID_UNISYS, PCI_DEVICE_ID_VIRTHBA)}, - {0}, -}; - -/* export virthba_id_table */ -MODULE_DEVICE_TABLE(pci, virthba_id_table); - -static struct workqueue_struct *virthba_serverdown_workqueue; - -static struct virtpci_driver virthba_driver = { - .name = "uisvirthba", - .version = VERSION, - .vertag = NULL, - .id_table = virthba_id_table, - .probe = virthba_probe, - .remove = virthba_remove, - .resume = virthba_serverup, - .suspend = virthba_serverdown -}; - -/* The Send and Recive Buffers of the IO Queue may both be full */ -#define MAX_PENDING_REQUESTS (MIN_NUMSIGNALS*2) -#define INTERRUPT_VECTOR_MASK 0x3F - -struct scsipending { - char cmdtype; /* Type of pointer that is being stored */ - void *sent; /* The Data being tracked */ - /* struct scsi_cmnd *type for virthba_queue_command */ - /* struct uiscmdrsp *type for management commands */ -}; - -#define VIRTHBA_ERROR_COUNT 30 -#define IOS_ERROR_THRESHOLD 1000 -struct virtdisk_info { - u32 valid; - u32 channel, id, lun; /* Disk Path */ - atomic_t ios_threshold; - atomic_t error_count; - struct virtdisk_info *next; -}; - -/* Each Scsi_Host has a host_data area that contains this struct. */ -struct virthba_info { - struct Scsi_Host *scsihost; - struct virtpci_dev *virtpcidev; - struct list_head dev_info_list; - struct chaninfo chinfo; - struct irq_info intr; /* use recvInterrupt info to receive - interrupts when IOs complete */ - int interrupt_vector; - struct scsipending pending[MAX_PENDING_REQUESTS]; /* Tracks the requests - that have been */ - /* forwarded to the IOVM and haven't returned yet */ - unsigned int nextinsert; /* Start search for next pending - free slot here */ - spinlock_t privlock; - bool serverdown; - bool serverchangingstate; - unsigned long long acquire_failed_cnt; - unsigned long long interrupts_rcvd; - unsigned long long interrupts_notme; - unsigned long long interrupts_disabled; - struct work_struct serverdown_completion; - u64 __iomem *flags_addr; - atomic_t interrupt_rcvd; - wait_queue_head_t rsp_queue; - struct virtdisk_info head; -}; - -/* Work Data for dar_work_queue */ -struct diskaddremove { - u8 add; /* 0-remove, 1-add */ - struct Scsi_Host *shost; /* Scsi Host for this virthba instance */ - u32 channel, id, lun; /* Disk Path */ - struct diskaddremove *next; -}; - -#define virtpci_dev_to_virthba_virthba_get_info(d) \ - container_of(d, struct virthba_info, virtpcidev) - -static DEVICE_ATTRIBUTE *virthba_shost_attrs[]; -static struct scsi_host_template virthba_driver_template = { - .name = "Unisys Virtual HBA", - .info = virthba_get_info, - .ioctl = virthba_ioctl, - .queuecommand = virthba_queue_command, - .eh_abort_handler = virthba_abort_handler, - .eh_device_reset_handler = virthba_device_reset_handler, - .eh_bus_reset_handler = virthba_bus_reset_handler, - .eh_host_reset_handler = virthba_host_reset_handler, - .shost_attrs = virthba_shost_attrs, - -#define VIRTHBA_MAX_CMNDS 128 - .can_queue = VIRTHBA_MAX_CMNDS, - .sg_tablesize = 64, /* largest number of address/length pairs */ - .this_id = -1, - .slave_alloc = virthba_slave_alloc, - .slave_configure = virthba_slave_configure, - .slave_destroy = virthba_slave_destroy, - .use_clustering = ENABLE_CLUSTERING, -}; - -struct virthba_devices_open { - struct virthba_info *virthbainfo; -}; - -static const struct file_operations debugfs_info_fops = { - .read = info_debugfs_read, -}; - -static const struct file_operations debugfs_enable_ints_fops = { - .write = enable_ints_write, -}; - -/*****************************************************/ -/* Structs */ -/*****************************************************/ - -#define VIRTHBASOPENMAX 1 -/* array of open devices maintained by open() and close(); */ -static struct virthba_devices_open virthbas_open[VIRTHBASOPENMAX]; -static struct dentry *virthba_debugfs_dir; - -/*****************************************************/ -/* Local Functions */ -/*****************************************************/ -static int -add_scsipending_entry(struct virthba_info *vhbainfo, char cmdtype, void *new) -{ - unsigned long flags; - int insert_location; - - spin_lock_irqsave(&vhbainfo->privlock, flags); - insert_location = vhbainfo->nextinsert; - while (vhbainfo->pending[insert_location].sent) { - insert_location = (insert_location + 1) % MAX_PENDING_REQUESTS; - if (insert_location == (int)vhbainfo->nextinsert) { - spin_unlock_irqrestore(&vhbainfo->privlock, flags); - return -1; - } - } - - vhbainfo->pending[insert_location].cmdtype = cmdtype; - vhbainfo->pending[insert_location].sent = new; - vhbainfo->nextinsert = (insert_location + 1) % MAX_PENDING_REQUESTS; - spin_unlock_irqrestore(&vhbainfo->privlock, flags); - - return insert_location; -} - -static unsigned int -add_scsipending_entry_with_wait(struct virthba_info *vhbainfo, char cmdtype, - void *new) -{ - int insert_location = add_scsipending_entry(vhbainfo, cmdtype, new); - - while (insert_location == -1) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(10)); - insert_location = add_scsipending_entry(vhbainfo, cmdtype, new); - } - - return (unsigned int)insert_location; -} - -static void * -del_scsipending_entry(struct virthba_info *vhbainfo, uintptr_t del) -{ - unsigned long flags; - void *sent = NULL; - - if (del < MAX_PENDING_REQUESTS) { - spin_lock_irqsave(&vhbainfo->privlock, flags); - sent = vhbainfo->pending[del].sent; - - vhbainfo->pending[del].cmdtype = 0; - vhbainfo->pending[del].sent = NULL; - spin_unlock_irqrestore(&vhbainfo->privlock, flags); - } - - return sent; -} - -/* dar_work_queue (Disk Add/Remove) */ -static struct work_struct dar_work_queue; -static struct diskaddremove *dar_work_queue_head; -static spinlock_t dar_work_queue_lock; -static unsigned short dar_work_queue_sched; -#define QUEUE_DISKADDREMOVE(dar) { \ - spin_lock_irqsave(&dar_work_queue_lock, flags); \ - if (!dar_work_queue_head) { \ - dar_work_queue_head = dar; \ - dar->next = NULL; \ - } \ - else { \ - dar->next = dar_work_queue_head; \ - dar_work_queue_head = dar; \ - } \ - if (!dar_work_queue_sched) { \ - schedule_work(&dar_work_queue); \ - dar_work_queue_sched = 1; \ - } \ - spin_unlock_irqrestore(&dar_work_queue_lock, flags); \ -} - -static inline void -send_disk_add_remove(struct diskaddremove *dar) -{ - struct scsi_device *sdev; - int error; - - sdev = scsi_device_lookup(dar->shost, dar->channel, dar->id, dar->lun); - if (sdev) { - if (!(dar->add)) - scsi_remove_device(sdev); - } else if (dar->add) { - error = - scsi_add_device(dar->shost, dar->channel, dar->id, - dar->lun); - } - kfree(dar); -} - -/*****************************************************/ -/* dar_work_queue Handler Thread */ -/*****************************************************/ -static void -do_disk_add_remove(struct work_struct *work) -{ - struct diskaddremove *dar; - struct diskaddremove *tmphead; - int i = 0; - unsigned long flags; - - spin_lock_irqsave(&dar_work_queue_lock, flags); - tmphead = dar_work_queue_head; - dar_work_queue_head = NULL; - dar_work_queue_sched = 0; - spin_unlock_irqrestore(&dar_work_queue_lock, flags); - while (tmphead) { - dar = tmphead; - tmphead = dar->next; - send_disk_add_remove(dar); - i++; - } -} - -/*****************************************************/ -/* Routine to add entry to dar_work_queue */ -/*****************************************************/ -static void -process_disk_notify(struct Scsi_Host *shost, struct uiscmdrsp *cmdrsp) -{ - struct diskaddremove *dar; - unsigned long flags; - - dar = kzalloc(sizeof(*dar), GFP_ATOMIC); - if (dar) { - dar->add = cmdrsp->disknotify.add; - dar->shost = shost; - dar->channel = cmdrsp->disknotify.channel; - dar->id = cmdrsp->disknotify.id; - dar->lun = cmdrsp->disknotify.lun; - QUEUE_DISKADDREMOVE(dar); - } -} - -/*****************************************************/ -/* Probe Remove Functions */ -/*****************************************************/ -static irqreturn_t -virthba_isr(int irq, void *dev_id) -{ - struct virthba_info *virthbainfo = (struct virthba_info *)dev_id; - struct channel_header __iomem *channel_header; - struct signal_queue_header __iomem *pqhdr; - u64 mask; - unsigned long long rc1; - - if (!virthbainfo) - return IRQ_NONE; - virthbainfo->interrupts_rcvd++; - channel_header = virthbainfo->chinfo.queueinfo->chan; - if (((readq(&channel_header->features) - & ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS) != 0) && - ((readq(&channel_header->features) & - ULTRA_IO_DRIVER_DISABLES_INTS) != - 0)) { - virthbainfo->interrupts_disabled++; - mask = ~ULTRA_CHANNEL_ENABLE_INTS; - rc1 = uisqueue_interlocked_and(virthbainfo->flags_addr, mask); - } - if (spar_signalqueue_empty(channel_header, IOCHAN_FROM_IOPART)) { - virthbainfo->interrupts_notme++; - return IRQ_NONE; - } - pqhdr = (struct signal_queue_header __iomem *) - ((char __iomem *)channel_header + - readq(&channel_header->ch_space_offset)) + IOCHAN_FROM_IOPART; - writeq(readq(&pqhdr->num_irq_received) + 1, - &pqhdr->num_irq_received); - atomic_set(&virthbainfo->interrupt_rcvd, 1); - wake_up_interruptible(&virthbainfo->rsp_queue); - return IRQ_HANDLED; -} - -static int -virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) -{ - int error; - struct Scsi_Host *scsihost; - struct virthba_info *virthbainfo; - int rsp; - int i; - irq_handler_t handler = virthba_isr; - struct channel_header __iomem *channel_header; - struct signal_queue_header __iomem *pqhdr; - u64 mask; - - POSTCODE_LINUX_2(VHBA_PROBE_ENTRY_PC, POSTCODE_SEVERITY_INFO); - /* call scsi_host_alloc to register a scsi host adapter - * instance - this virthba that has just been created is an - * instance of a scsi host adapter. This scsi_host_alloc - * function allocates a new Scsi_Host struct & performs basic - * initialization. The host is not published to the scsi - * midlayer until scsi_add_host is called. - */ - - /* arg 2 passed in length of extra space we want allocated - * with scsi_host struct for our own use scsi_host_alloc - * assign host_no - */ - scsihost = scsi_host_alloc(&virthba_driver_template, - sizeof(struct virthba_info)); - if (!scsihost) - return -ENODEV; - - scsihost->this_id = UIS_MAGIC_VHBA; - /* linux treats max-channel differently than max-id & max-lun. - * In the latter cases, those two values result in 0 to max-1 - * (inclusive) being scanned. But in the case of channels, the - * scan is 0 to max (inclusive); so we will subtract one from - * the max-channel value. - */ - scsihost->max_channel = (unsigned)virtpcidev->scsi.max.max_channel; - scsihost->max_id = (unsigned)virtpcidev->scsi.max.max_id; - scsihost->max_lun = (unsigned)virtpcidev->scsi.max.max_lun; - scsihost->cmd_per_lun = (unsigned)virtpcidev->scsi.max.cmd_per_lun; - scsihost->max_sectors = - (unsigned short)(virtpcidev->scsi.max.max_io_size >> 9); - scsihost->sg_tablesize = - (unsigned short)(virtpcidev->scsi.max.max_io_size / PAGE_SIZE); - if (scsihost->sg_tablesize > MAX_PHYS_INFO) - scsihost->sg_tablesize = MAX_PHYS_INFO; - - /* this creates "host%d" in sysfs. If 2nd argument is NULL, - * then this generic /sys/devices/platform/host? device is - * created and /sys/scsi_host/host? -> - * /sys/devices/platform/host? If 2nd argument is not NULL, - * then this generic /sys/devices//host? is created and - * host? points to that device instead. - */ - error = scsi_add_host(scsihost, &virtpcidev->generic_dev); - if (error) { - POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR); - /* decr refcount on scsihost which was incremented by - * scsi_add_host so the scsi_host gets deleted - */ - scsi_host_put(scsihost); - return -ENODEV; - } - - virthbainfo = (struct virthba_info *)scsihost->hostdata; - memset(virthbainfo, 0, sizeof(struct virthba_info)); - for (i = 0; i < VIRTHBASOPENMAX; i++) { - if (!virthbas_open[i].virthbainfo) { - virthbas_open[i].virthbainfo = virthbainfo; - break; - } - } - virthbainfo->interrupt_vector = -1; - virthbainfo->chinfo.queueinfo = &virtpcidev->queueinfo; - virthbainfo->virtpcidev = virtpcidev; - spin_lock_init(&virthbainfo->chinfo.insertlock); - - init_waitqueue_head(&virthbainfo->rsp_queue); - spin_lock_init(&virthbainfo->privlock); - memset(&virthbainfo->pending, 0, sizeof(virthbainfo->pending)); - virthbainfo->serverdown = false; - virthbainfo->serverchangingstate = false; - - virthbainfo->intr = virtpcidev->intr; - /* save of host within virthba_info */ - virthbainfo->scsihost = scsihost; - - /* save of host within virtpci_dev */ - virtpcidev->scsi.scsihost = scsihost; - - /* Setup workqueue for serverdown messages */ - INIT_WORK(&virthbainfo->serverdown_completion, - virthba_serverdown_complete); - - writeq(readq(&virthbainfo->chinfo.queueinfo->chan->features) | - ULTRA_IO_CHANNEL_IS_POLLING, - &virthbainfo->chinfo.queueinfo->chan->features); - /* start thread that will receive scsicmnd responses */ - - channel_header = virthbainfo->chinfo.queueinfo->chan; - pqhdr = (struct signal_queue_header __iomem *) - ((char __iomem *)channel_header + - readq(&channel_header->ch_space_offset)) + IOCHAN_FROM_IOPART; - virthbainfo->flags_addr = &pqhdr->features; - - if (!uisthread_start(&virthbainfo->chinfo.threadinfo, - process_incoming_rsps, - virthbainfo, "vhba_incoming")) { - /* decr refcount on scsihost which was incremented by - * scsi_add_host so the scsi_host gets deleted - */ - POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR); - scsi_host_put(scsihost); - return -ENODEV; - } - virthbainfo->interrupt_vector = - virthbainfo->intr.recv_irq_handle & INTERRUPT_VECTOR_MASK; - rsp = request_irq(virthbainfo->interrupt_vector, handler, IRQF_SHARED, - scsihost->hostt->name, virthbainfo); - if (rsp != 0) { - virthbainfo->interrupt_vector = -1; - POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR); - } else { - u64 __iomem *features_addr = - &virthbainfo->chinfo.queueinfo->chan->features; - mask = ~(ULTRA_IO_CHANNEL_IS_POLLING | - ULTRA_IO_DRIVER_DISABLES_INTS); - uisqueue_interlocked_and(features_addr, mask); - mask = ULTRA_IO_DRIVER_ENABLES_INTS; - uisqueue_interlocked_or(features_addr, mask); - rsltq_wait_usecs = 4000000; - } - - scsi_scan_host(scsihost); - - POSTCODE_LINUX_2(VHBA_PROBE_EXIT_PC, POSTCODE_SEVERITY_INFO); - return 0; -} - -static void -virthba_remove(struct virtpci_dev *virtpcidev) -{ - struct virthba_info *virthbainfo; - struct Scsi_Host *scsihost = - (struct Scsi_Host *)virtpcidev->scsi.scsihost; - - virthbainfo = (struct virthba_info *)scsihost->hostdata; - if (virthbainfo->interrupt_vector != -1) - free_irq(virthbainfo->interrupt_vector, virthbainfo); - - scsi_remove_host(scsihost); - - uisthread_stop(&virthbainfo->chinfo.threadinfo); - - /* decr refcount on scsihost which was incremented by - * scsi_add_host so the scsi_host gets deleted - */ - scsi_host_put(scsihost); -} - -static int -forward_vdiskmgmt_command(enum vdisk_mgmt_types vdiskcmdtype, - struct Scsi_Host *scsihost, - struct uisscsi_dest *vdest) -{ - struct uiscmdrsp *cmdrsp; - struct virthba_info *virthbainfo = - (struct virthba_info *)scsihost->hostdata; - int notifyresult = 0xffff; - wait_queue_head_t notifyevent; - - if (virthbainfo->serverdown || virthbainfo->serverchangingstate) - return FAILED; - - cmdrsp = kzalloc(SIZEOF_CMDRSP, GFP_ATOMIC); - if (!cmdrsp) - return FAILED; /* reject */ - - init_waitqueue_head(¬ifyevent); - - /* issue VDISK_MGMT_CMD - * set type to command - as opposed to task mgmt - */ - cmdrsp->cmdtype = CMD_VDISKMGMT_TYPE; - /* specify the event that has to be triggered when this cmd is - * complete - */ - cmdrsp->vdiskmgmt.notify = (void *)¬ifyevent; - cmdrsp->vdiskmgmt.notifyresult = (void *)¬ifyresult; - - /* save destination */ - cmdrsp->vdiskmgmt.vdisktype = vdiskcmdtype; - cmdrsp->vdiskmgmt.vdest.channel = vdest->channel; - cmdrsp->vdiskmgmt.vdest.id = vdest->id; - cmdrsp->vdiskmgmt.vdest.lun = vdest->lun; - cmdrsp->vdiskmgmt.scsicmd = - (void *)(uintptr_t) - add_scsipending_entry_with_wait(virthbainfo, CMD_VDISKMGMT_TYPE, - (void *)cmdrsp); - - uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo, - cmdrsp, IOCHAN_TO_IOPART, - &virthbainfo->chinfo.insertlock, - DONT_ISSUE_INTERRUPT, (u64)NULL, - OK_TO_WAIT, "vhba"); - wait_event(notifyevent, notifyresult != 0xffff); - kfree(cmdrsp); - return SUCCESS; -} - -/*****************************************************/ -/* Scsi Host support functions */ -/*****************************************************/ - -static int -forward_taskmgmt_command(enum task_mgmt_types tasktype, - struct scsi_device *scsidev) -{ - struct uiscmdrsp *cmdrsp; - struct virthba_info *virthbainfo = - (struct virthba_info *)scsidev->host->hostdata; - int notifyresult = 0xffff; - wait_queue_head_t notifyevent; - - if (virthbainfo->serverdown || virthbainfo->serverchangingstate) - return FAILED; - - cmdrsp = kzalloc(SIZEOF_CMDRSP, GFP_ATOMIC); - if (!cmdrsp) - return FAILED; /* reject */ - - init_waitqueue_head(¬ifyevent); - - /* issue TASK_MGMT_ABORT_TASK */ - /* set type to command - as opposed to task mgmt */ - cmdrsp->cmdtype = CMD_SCSITASKMGMT_TYPE; - /* specify the event that has to be triggered when this */ - /* cmd is complete */ - cmdrsp->scsitaskmgmt.notify = (void *)¬ifyevent; - cmdrsp->scsitaskmgmt.notifyresult = (void *)¬ifyresult; - - /* save destination */ - cmdrsp->scsitaskmgmt.tasktype = tasktype; - cmdrsp->scsitaskmgmt.vdest.channel = scsidev->channel; - cmdrsp->scsitaskmgmt.vdest.id = scsidev->id; - cmdrsp->scsitaskmgmt.vdest.lun = scsidev->lun; - cmdrsp->scsitaskmgmt.scsicmd = - (void *)(uintptr_t) - add_scsipending_entry_with_wait(virthbainfo, - CMD_SCSITASKMGMT_TYPE, - (void *)cmdrsp); - - uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo, - cmdrsp, IOCHAN_TO_IOPART, - &virthbainfo->chinfo.insertlock, - DONT_ISSUE_INTERRUPT, (u64)NULL, - OK_TO_WAIT, "vhba"); - wait_event(notifyevent, notifyresult != 0xffff); - kfree(cmdrsp); - return SUCCESS; -} - -/* The abort handler returns SUCCESS if it has succeeded to make LLDD - * and all related hardware forget about the scmd. - */ -static int -virthba_abort_handler(struct scsi_cmnd *scsicmd) -{ - /* issue TASK_MGMT_ABORT_TASK */ - struct scsi_device *scsidev; - struct virtdisk_info *vdisk; - - scsidev = scsicmd->device; - for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; - vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel == vdisk->channel) && - (scsidev->id == vdisk->id) && - (scsidev->lun == vdisk->lun)) { - if (atomic_read(&vdisk->error_count) < - VIRTHBA_ERROR_COUNT) { - atomic_inc(&vdisk->error_count); - POSTCODE_LINUX_2(VHBA_COMMAND_HANDLER_PC, - POSTCODE_SEVERITY_INFO); - } else - atomic_set(&vdisk->ios_threshold, - IOS_ERROR_THRESHOLD); - } - } - return forward_taskmgmt_command(TASK_MGMT_ABORT_TASK, scsicmd->device); -} - -static int -virthba_bus_reset_handler(struct scsi_cmnd *scsicmd) -{ - /* issue TASK_MGMT_TARGET_RESET for each target on the bus */ - struct scsi_device *scsidev; - struct virtdisk_info *vdisk; - - scsidev = scsicmd->device; - for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; - vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel == vdisk->channel) && - (scsidev->id == vdisk->id) && - (scsidev->lun == vdisk->lun)) { - if (atomic_read(&vdisk->error_count) < - VIRTHBA_ERROR_COUNT) { - atomic_inc(&vdisk->error_count); - POSTCODE_LINUX_2(VHBA_COMMAND_HANDLER_PC, - POSTCODE_SEVERITY_INFO); - } else - atomic_set(&vdisk->ios_threshold, - IOS_ERROR_THRESHOLD); - } - } - return forward_taskmgmt_command(TASK_MGMT_BUS_RESET, scsicmd->device); -} - -static int -virthba_device_reset_handler(struct scsi_cmnd *scsicmd) -{ - /* issue TASK_MGMT_LUN_RESET */ - struct scsi_device *scsidev; - struct virtdisk_info *vdisk; - - scsidev = scsicmd->device; - for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; - vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel == vdisk->channel) && - (scsidev->id == vdisk->id) && - (scsidev->lun == vdisk->lun)) { - if (atomic_read(&vdisk->error_count) < - VIRTHBA_ERROR_COUNT) { - atomic_inc(&vdisk->error_count); - POSTCODE_LINUX_2(VHBA_COMMAND_HANDLER_PC, - POSTCODE_SEVERITY_INFO); - } else - atomic_set(&vdisk->ios_threshold, - IOS_ERROR_THRESHOLD); - } - } - return forward_taskmgmt_command(TASK_MGMT_LUN_RESET, scsicmd->device); -} - -static int -virthba_host_reset_handler(struct scsi_cmnd *scsicmd) -{ - /* issue TASK_MGMT_TARGET_RESET for each target on each bus for host */ - return SUCCESS; -} - -static char virthba_get_info_str[256]; - -static const char * -virthba_get_info(struct Scsi_Host *shp) -{ - /* Return version string */ - sprintf(virthba_get_info_str, "virthba, version %s\n", VIRTHBA_VERSION); - return virthba_get_info_str; -} - -static int -virthba_ioctl(struct scsi_device *dev, int cmd, void __user *arg) -{ - return -EINVAL; -} - -/* This returns SCSI_MLQUEUE_DEVICE_BUSY if the signal queue to IOpart - * is full. - */ -static int -virthba_queue_command_lck(struct scsi_cmnd *scsicmd, - void (*virthba_cmnd_done)(struct scsi_cmnd *)) -{ - struct scsi_device *scsidev = scsicmd->device; - int insert_location; - unsigned char op; - unsigned char *cdb = scsicmd->cmnd; - struct Scsi_Host *scsihost = scsidev->host; - struct uiscmdrsp *cmdrsp; - unsigned int i; - struct virthba_info *virthbainfo = - (struct virthba_info *)scsihost->hostdata; - struct scatterlist *sg = NULL; - struct scatterlist *sgl = NULL; - int sg_failed = 0; - - if (virthbainfo->serverdown || virthbainfo->serverchangingstate) - return SCSI_MLQUEUE_DEVICE_BUSY; - cmdrsp = kzalloc(SIZEOF_CMDRSP, GFP_ATOMIC); - if (!cmdrsp) - return 1; /* reject the command */ - - /* now saving everything we need from scsi_cmd into cmdrsp - * before we queue cmdrsp set type to command - as opposed to - * task mgmt - */ - cmdrsp->cmdtype = CMD_SCSI_TYPE; - /* save the pending insertion location. Deletion from pending - * will return the scsicmd pointer for completion - */ - insert_location = - add_scsipending_entry(virthbainfo, CMD_SCSI_TYPE, (void *)scsicmd); - if (insert_location != -1) { - cmdrsp->scsi.scsicmd = (void *)(uintptr_t)insert_location; - } else { - kfree(cmdrsp); - return SCSI_MLQUEUE_DEVICE_BUSY; - } - /* save done function that we have call when cmd is complete */ - scsicmd->scsi_done = virthba_cmnd_done; - /* save destination */ - cmdrsp->scsi.vdest.channel = scsidev->channel; - cmdrsp->scsi.vdest.id = scsidev->id; - cmdrsp->scsi.vdest.lun = scsidev->lun; - /* save datadir */ - cmdrsp->scsi.data_dir = scsicmd->sc_data_direction; - memcpy(cmdrsp->scsi.cmnd, cdb, MAX_CMND_SIZE); - - cmdrsp->scsi.bufflen = scsi_bufflen(scsicmd); - - /* keep track of the max buffer length so far. */ - if (cmdrsp->scsi.bufflen > max_buff_len) - max_buff_len = cmdrsp->scsi.bufflen; - - if (scsi_sg_count(scsicmd) > MAX_PHYS_INFO) { - del_scsipending_entry(virthbainfo, (uintptr_t)insert_location); - kfree(cmdrsp); - return 1; /* reject the command */ - } - - /* This is what we USED to do when we assumed we were running */ - /* uissd & virthba on the same Linux system. */ - /* cmdrsp->scsi.buffer = scsicmd->request_buffer; */ - /* The following code does NOT make that assumption. */ - /* convert buffer to phys information */ - if (scsi_sg_count(scsicmd) == 0) { - if (scsi_bufflen(scsicmd) > 0) { - BUG_ON(scsi_sg_count(scsicmd) == 0); - } - } else { - /* buffer is scatterlist - copy it out */ - sgl = scsi_sglist(scsicmd); - - for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) { - cmdrsp->scsi.gpi_list[i].address = sg_phys(sg); - cmdrsp->scsi.gpi_list[i].length = sg->length; - } - - if (sg_failed) { - /* BUG(); ***** For now, let it fail in uissd - * if it is a problem, as it might just - * work - */ - } - - cmdrsp->scsi.guest_phys_entries = scsi_sg_count(scsicmd); - } - - op = cdb[0]; - i = uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo, - cmdrsp, IOCHAN_TO_IOPART, - &virthbainfo->chinfo. - insertlock, - DONT_ISSUE_INTERRUPT, - (u64)NULL, DONT_WAIT, "vhba"); - if (i == 0) { - /* queue must be full - and we said don't wait - return busy */ - kfree(cmdrsp); - del_scsipending_entry(virthbainfo, (uintptr_t)insert_location); - return SCSI_MLQUEUE_DEVICE_BUSY; - } - - /* we're done with cmdrsp space - data from it has been copied - * into channel - free it now. - */ - kfree(cmdrsp); - return 0; /* non-zero implies host/device is busy */ -} - -static int -virthba_slave_alloc(struct scsi_device *scsidev) -{ - /* this called by the midlayer before scan for new devices - - * LLD can alloc any struct & do init if needed. - */ - struct virtdisk_info *vdisk; - struct virtdisk_info *tmpvdisk; - struct virthba_info *virthbainfo; - struct Scsi_Host *scsihost = (struct Scsi_Host *)scsidev->host; - - virthbainfo = (struct virthba_info *)scsihost->hostdata; - if (!virthbainfo) - return 0; /* even though we errored, treat as success */ - - for (vdisk = &virthbainfo->head; vdisk->next; vdisk = vdisk->next) { - if (vdisk->next->valid && - (vdisk->next->channel == scsidev->channel) && - (vdisk->next->id == scsidev->id) && - (vdisk->next->lun == scsidev->lun)) - return 0; - } - tmpvdisk = kzalloc(sizeof(*tmpvdisk), GFP_ATOMIC); - if (!tmpvdisk) - return 0; - - tmpvdisk->channel = scsidev->channel; - tmpvdisk->id = scsidev->id; - tmpvdisk->lun = scsidev->lun; - tmpvdisk->valid = 1; - vdisk->next = tmpvdisk; - return 0; /* success */ -} - -static int -virthba_slave_configure(struct scsi_device *scsidev) -{ - return 0; /* success */ -} - -static void -virthba_slave_destroy(struct scsi_device *scsidev) -{ - /* midlevel calls this after device has been quiesced and - * before it is to be deleted. - */ - struct virtdisk_info *vdisk, *delvdisk; - struct virthba_info *virthbainfo; - struct Scsi_Host *scsihost = (struct Scsi_Host *)scsidev->host; - - virthbainfo = (struct virthba_info *)scsihost->hostdata; - for (vdisk = &virthbainfo->head; vdisk->next; vdisk = vdisk->next) { - if (vdisk->next->valid && - (vdisk->next->channel == scsidev->channel) && - (vdisk->next->id == scsidev->id) && - (vdisk->next->lun == scsidev->lun)) { - delvdisk = vdisk->next; - vdisk->next = vdisk->next->next; - kfree(delvdisk); - return; - } - } -} - -/*****************************************************/ -/* Scsi Cmnd support thread */ -/*****************************************************/ - -static void -do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) -{ - struct virtdisk_info *vdisk; - struct scsi_device *scsidev; - struct sense_data *sd; - - scsidev = scsicmd->device; - memcpy(scsicmd->sense_buffer, cmdrsp->scsi.sensebuf, MAX_SENSE_SIZE); - sd = (struct sense_data *)scsicmd->sense_buffer; - - /* Do not log errors for disk-not-present inquiries */ - if ((cmdrsp->scsi.cmnd[0] == INQUIRY) && - (host_byte(cmdrsp->scsi.linuxstat) == DID_NO_CONNECT) && - (cmdrsp->scsi.addlstat == ADDL_SEL_TIMEOUT)) - return; - - /* Okay see what our error_count is here.... */ - for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; - vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel != vdisk->channel) || - (scsidev->id != vdisk->id) || - (scsidev->lun != vdisk->lun)) - continue; - - if (atomic_read(&vdisk->error_count) < VIRTHBA_ERROR_COUNT) { - atomic_inc(&vdisk->error_count); - atomic_set(&vdisk->ios_threshold, IOS_ERROR_THRESHOLD); - } - } -} - -static void -do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) -{ - struct scsi_device *scsidev; - unsigned char buf[36]; - struct scatterlist *sg; - unsigned int i; - char *thispage; - char *thispage_orig; - int bufind = 0; - struct virtdisk_info *vdisk; - - scsidev = scsicmd->device; - if ((cmdrsp->scsi.cmnd[0] == INQUIRY) && - (cmdrsp->scsi.bufflen >= MIN_INQUIRY_RESULT_LEN)) { - if (cmdrsp->scsi.no_disk_result == 0) - return; - - /* Linux scsi code is weird; it wants - * a device at Lun 0 to issue report - * luns, but we don't want a disk - * there so we'll present a processor - * there. */ - SET_NO_DISK_INQUIRY_RESULT(buf, cmdrsp->scsi.bufflen, - scsidev->lun, - DEV_DISK_CAPABLE_NOT_PRESENT, - DEV_NOT_CAPABLE); - - if (scsi_sg_count(scsicmd) == 0) { - if (scsi_bufflen(scsicmd) > 0) { - BUG_ON(scsi_sg_count(scsicmd) == - 0); - } - memcpy(scsi_sglist(scsicmd), buf, - cmdrsp->scsi.bufflen); - return; - } - - sg = scsi_sglist(scsicmd); - for (i = 0; i < scsi_sg_count(scsicmd); i++) { - thispage_orig = kmap_atomic(sg_page(sg + i)); - thispage = (void *)((unsigned long)thispage_orig | - sg[i].offset); - memcpy(thispage, buf + bufind, sg[i].length); - kunmap_atomic(thispage_orig); - bufind += sg[i].length; - } - } else { - vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; - for ( ; vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel != vdisk->channel) || - (scsidev->id != vdisk->id) || - (scsidev->lun != vdisk->lun)) - continue; - - if (atomic_read(&vdisk->ios_threshold) > 0) { - atomic_dec(&vdisk->ios_threshold); - if (atomic_read(&vdisk->ios_threshold) == 0) { - atomic_set(&vdisk->error_count, 0); - } - } - } - } -} - -static void -complete_scsi_command(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) -{ - /* take what we need out of cmdrsp and complete the scsicmd */ - scsicmd->result = cmdrsp->scsi.linuxstat; - if (cmdrsp->scsi.linuxstat) - do_scsi_linuxstat(cmdrsp, scsicmd); - else - do_scsi_nolinuxstat(cmdrsp, scsicmd); - - if (scsicmd->scsi_done) - scsicmd->scsi_done(scsicmd); -} - -static inline void -complete_vdiskmgmt_command(struct uiscmdrsp *cmdrsp) -{ - /* copy the result of the taskmgmt and */ - /* wake up the error handler that is waiting for this */ - *(int *)cmdrsp->vdiskmgmt.notifyresult = cmdrsp->vdiskmgmt.result; - wake_up_all((wait_queue_head_t *)cmdrsp->vdiskmgmt.notify); -} - -static inline void -complete_taskmgmt_command(struct uiscmdrsp *cmdrsp) -{ - /* copy the result of the taskmgmt and */ - /* wake up the error handler that is waiting for this */ - *(int *)cmdrsp->scsitaskmgmt.notifyresult = - cmdrsp->scsitaskmgmt.result; - wake_up_all((wait_queue_head_t *)cmdrsp->scsitaskmgmt.notify); -} - -static void -drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc, - struct uiscmdrsp *cmdrsp) -{ - unsigned long flags; - int qrslt = 0; - struct scsi_cmnd *scsicmd; - struct Scsi_Host *shost = virthbainfo->scsihost; - - while (1) { - spin_lock_irqsave(&virthbainfo->chinfo.insertlock, flags); - if (!spar_channel_client_acquire_os(dc->queueinfo->chan, - "vhba")) { - spin_unlock_irqrestore(&virthbainfo->chinfo.insertlock, - flags); - virthbainfo->acquire_failed_cnt++; - break; - } - qrslt = uisqueue_get_cmdrsp(dc->queueinfo, cmdrsp, - IOCHAN_FROM_IOPART); - spar_channel_client_release_os(dc->queueinfo->chan, "vhba"); - spin_unlock_irqrestore(&virthbainfo->chinfo.insertlock, flags); - if (qrslt == 0) - break; - if (cmdrsp->cmdtype == CMD_SCSI_TYPE) { - /* scsicmd location is returned by the - * deletion - */ - scsicmd = del_scsipending_entry(virthbainfo, - (uintptr_t) - cmdrsp->scsi.scsicmd); - if (!scsicmd) - break; - /* complete the orig cmd */ - complete_scsi_command(cmdrsp, scsicmd); - } else if (cmdrsp->cmdtype == CMD_SCSITASKMGMT_TYPE) { - if (!del_scsipending_entry(virthbainfo, - (uintptr_t)cmdrsp->scsitaskmgmt.scsicmd)) - break; - complete_taskmgmt_command(cmdrsp); - } else if (cmdrsp->cmdtype == CMD_NOTIFYGUEST_TYPE) { - /* The vHba pointer has no meaning in - * a Client/Guest Partition. Let's be - * safe and set it to NULL now. Do - * not use it here! */ - cmdrsp->disknotify.v_hba = NULL; - process_disk_notify(shost, cmdrsp); - } else if (cmdrsp->cmdtype == CMD_VDISKMGMT_TYPE) { - if (!del_scsipending_entry(virthbainfo, - (uintptr_t) - cmdrsp->vdiskmgmt.scsicmd)) - break; - complete_vdiskmgmt_command(cmdrsp); - } - /* cmdrsp is now available for reuse */ - } -} - -/* main function for the thread that waits for scsi commands to arrive - * in a specified queue - */ -static int -process_incoming_rsps(void *v) -{ - struct virthba_info *virthbainfo = v; - struct chaninfo *dc = &virthbainfo->chinfo; - struct uiscmdrsp *cmdrsp = NULL; - const int SZ = sizeof(struct uiscmdrsp); - u64 mask; - unsigned long long rc1; - - UIS_DAEMONIZE("vhba_incoming"); - /* alloc once and reuse */ - cmdrsp = kmalloc(SZ, GFP_ATOMIC); - if (!cmdrsp) { - complete_and_exit(&dc->threadinfo.has_stopped, 0); - return 0; - } - mask = ULTRA_CHANNEL_ENABLE_INTS; - while (1) { - if (kthread_should_stop()) - break; - wait_event_interruptible_timeout(virthbainfo->rsp_queue, - (atomic_read(&virthbainfo->interrupt_rcvd) == 1), - usecs_to_jiffies(rsltq_wait_usecs)); - atomic_set(&virthbainfo->interrupt_rcvd, 0); - /* drain queue */ - drain_queue(virthbainfo, dc, cmdrsp); - rc1 = uisqueue_interlocked_or(virthbainfo->flags_addr, mask); - } - - kfree(cmdrsp); - - complete_and_exit(&dc->threadinfo.has_stopped, 0); -} - -/*****************************************************/ -/* Debugfs filesystem functions */ -/*****************************************************/ - -static ssize_t info_debugfs_read(struct file *file, - char __user *buf, size_t len, loff_t *offset) -{ - ssize_t bytes_read = 0; - int str_pos = 0; - u64 phys_flags_addr; - int i; - struct virthba_info *virthbainfo; - char *vbuf; - - if (len > MAX_BUF) - len = MAX_BUF; - vbuf = kzalloc(len, GFP_KERNEL); - if (!vbuf) - return -ENOMEM; - - for (i = 0; i < VIRTHBASOPENMAX; i++) { - if (!virthbas_open[i].virthbainfo) - continue; - - virthbainfo = virthbas_open[i].virthbainfo; - - str_pos += scnprintf(vbuf + str_pos, - len - str_pos, "max_buff_len:%u\n", - max_buff_len); - - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - "\nvirthba result queue poll wait:%d usecs.\n", - rsltq_wait_usecs); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - "\ninterrupts_rcvd = %llu, interrupts_disabled = %llu\n", - virthbainfo->interrupts_rcvd, - virthbainfo->interrupts_disabled); - str_pos += scnprintf(vbuf + str_pos, - len - str_pos, "\ninterrupts_notme = %llu,\n", - virthbainfo->interrupts_notme); - phys_flags_addr = virt_to_phys((__force void *) - virthbainfo->flags_addr); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - "flags_addr = %p, phys_flags_addr=0x%016llx, FeatureFlags=%llu\n", - virthbainfo->flags_addr, phys_flags_addr, - (__le64)readq(virthbainfo->flags_addr)); - str_pos += scnprintf(vbuf + str_pos, - len - str_pos, "acquire_failed_cnt:%llu\n", - virthbainfo->acquire_failed_cnt); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, "\n"); - } - - bytes_read = simple_read_from_buffer(buf, len, offset, vbuf, str_pos); - kfree(vbuf); - return bytes_read; -} - -static ssize_t enable_ints_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) -{ - char buf[4]; - int i, new_value; - struct virthba_info *virthbainfo; - - u64 __iomem *features_addr; - u64 mask; - - if (count >= ARRAY_SIZE(buf)) - return -EINVAL; - - buf[count] = '\0'; - if (copy_from_user(buf, buffer, count)) - return -EFAULT; - - i = kstrtoint(buf, 10, &new_value); - - if (i != 0) - return -EFAULT; - - /* set all counts to new_value usually 0 */ - for (i = 0; i < VIRTHBASOPENMAX; i++) { - if (virthbas_open[i].virthbainfo) { - virthbainfo = virthbas_open[i].virthbainfo; - features_addr = - &virthbainfo->chinfo.queueinfo->chan->features; - if (new_value == 1) { - mask = ~(ULTRA_IO_CHANNEL_IS_POLLING | - ULTRA_IO_DRIVER_DISABLES_INTS); - uisqueue_interlocked_and(features_addr, mask); - mask = ULTRA_IO_DRIVER_ENABLES_INTS; - uisqueue_interlocked_or(features_addr, mask); - rsltq_wait_usecs = 4000000; - } else { - mask = ~(ULTRA_IO_DRIVER_ENABLES_INTS | - ULTRA_IO_DRIVER_DISABLES_INTS); - uisqueue_interlocked_and(features_addr, mask); - mask = ULTRA_IO_CHANNEL_IS_POLLING; - uisqueue_interlocked_or(features_addr, mask); - rsltq_wait_usecs = 4000; - } - } - } - return count; -} - -/* As per VirtpciFunc returns 1 for success and 0 for failure */ -static int -virthba_serverup(struct virtpci_dev *virtpcidev) -{ - struct virthba_info *virthbainfo = - (struct virthba_info *)((struct Scsi_Host *)virtpcidev->scsi. - scsihost)->hostdata; - - if (!virthbainfo->serverdown) - return 1; - - if (virthbainfo->serverchangingstate) - return 0; - - virthbainfo->serverchangingstate = true; - /* Must transition channel to ATTACHED state BEFORE we - * can start using the device again - */ - SPAR_CHANNEL_CLIENT_TRANSITION(virthbainfo->chinfo.queueinfo->chan, - dev_name(&virtpcidev->generic_dev), - CHANNELCLI_ATTACHED, NULL); - - /* Start Processing the IOVM Response Queue Again */ - if (!uisthread_start(&virthbainfo->chinfo.threadinfo, - process_incoming_rsps, - virthbainfo, "vhba_incoming")) { - return 0; - } - virthbainfo->serverdown = false; - virthbainfo->serverchangingstate = false; - - return 1; -} - -static void -virthba_serverdown_complete(struct work_struct *work) -{ - struct virthba_info *virthbainfo; - struct virtpci_dev *virtpcidev; - int i; - struct scsipending *pendingdel = NULL; - struct scsi_cmnd *scsicmd = NULL; - struct uiscmdrsp *cmdrsp; - unsigned long flags; - - virthbainfo = container_of(work, struct virthba_info, - serverdown_completion); - - /* Stop Using the IOVM Response Queue (queue should be drained - * by the end) - */ - uisthread_stop(&virthbainfo->chinfo.threadinfo); - - /* Fail Commands that weren't completed */ - spin_lock_irqsave(&virthbainfo->privlock, flags); - for (i = 0; i < MAX_PENDING_REQUESTS; i++) { - pendingdel = &virthbainfo->pending[i]; - switch (pendingdel->cmdtype) { - case CMD_SCSI_TYPE: - scsicmd = (struct scsi_cmnd *)pendingdel->sent; - scsicmd->result = DID_RESET << 16; - if (scsicmd->scsi_done) - scsicmd->scsi_done(scsicmd); - break; - case CMD_SCSITASKMGMT_TYPE: - cmdrsp = (struct uiscmdrsp *)pendingdel->sent; - wake_up_all((wait_queue_head_t *) - cmdrsp->scsitaskmgmt.notify); - *(int *)cmdrsp->scsitaskmgmt.notifyresult = - TASK_MGMT_FAILED; - break; - case CMD_VDISKMGMT_TYPE: - cmdrsp = (struct uiscmdrsp *)pendingdel->sent; - *(int *)cmdrsp->vdiskmgmt.notifyresult = - VDISK_MGMT_FAILED; - wake_up_all((wait_queue_head_t *) - cmdrsp->vdiskmgmt.notify); - break; - default: - break; - } - pendingdel->cmdtype = 0; - pendingdel->sent = NULL; - } - spin_unlock_irqrestore(&virthbainfo->privlock, flags); - - virtpcidev = virthbainfo->virtpcidev; - - virthbainfo->serverdown = true; - virthbainfo->serverchangingstate = false; - /* Return the ServerDown response to Command */ - visorchipset_device_pause_response(virtpcidev->bus_no, - virtpcidev->device_no, 0); -} - -/* As per VirtpciFunc returns 1 for success and 0 for failure */ -static int -virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state) -{ - int stat = 1; - - struct virthba_info *virthbainfo = - (struct virthba_info *)((struct Scsi_Host *)virtpcidev->scsi. - scsihost)->hostdata; - - if (!virthbainfo->serverdown && !virthbainfo->serverchangingstate) { - virthbainfo->serverchangingstate = true; - queue_work(virthba_serverdown_workqueue, - &virthbainfo->serverdown_completion); - } else if (virthbainfo->serverchangingstate) { - stat = 0; - } - - return stat; -} - -/*****************************************************/ -/* Module Init & Exit functions */ -/*****************************************************/ - -static int __init -virthba_parse_line(char *str) -{ - return 1; -} - -static void __init -virthba_parse_options(char *line) -{ - char *next = line; - - POSTCODE_LINUX_2(VHBA_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO); - if (!line || !*line) - return; - while ((line = next)) { - next = strchr(line, ' '); - if (next) - *next++ = 0; - virthba_parse_line(line); - } - - POSTCODE_LINUX_2(VHBA_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO); -} - -static int __init -virthba_mod_init(void) -{ - int error; - int i; - - if (!unisys_spar_platform) - return -ENODEV; - - POSTCODE_LINUX_2(VHBA_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO); - virthba_parse_options(virthba_options); - - error = virtpci_register_driver(&virthba_driver); - if (error < 0) { - POSTCODE_LINUX_3(VHBA_CREATE_FAILURE_PC, error, - POSTCODE_SEVERITY_ERR); - } else { - /* create the debugfs directories and entries */ - virthba_debugfs_dir = debugfs_create_dir("virthba", NULL); - debugfs_create_file("info", S_IRUSR, virthba_debugfs_dir, - NULL, &debugfs_info_fops); - debugfs_create_u32("rqwait_usecs", S_IRUSR | S_IWUSR, - virthba_debugfs_dir, &rsltq_wait_usecs); - debugfs_create_file("enable_ints", S_IWUSR, - virthba_debugfs_dir, NULL, - &debugfs_enable_ints_fops); - /* Initialize dar_work_queue */ - INIT_WORK(&dar_work_queue, do_disk_add_remove); - spin_lock_init(&dar_work_queue_lock); - - /* clear out array */ - for (i = 0; i < VIRTHBASOPENMAX; i++) - virthbas_open[i].virthbainfo = NULL; - /* Initialize the serverdown workqueue */ - virthba_serverdown_workqueue = - create_singlethread_workqueue("virthba_serverdown"); - if (!virthba_serverdown_workqueue) { - POSTCODE_LINUX_2(VHBA_CREATE_FAILURE_PC, - POSTCODE_SEVERITY_ERR); - error = -1; - } - } - - POSTCODE_LINUX_2(VHBA_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO); - return error; -} - -static ssize_t -virthba_acquire_lun(struct device *cdev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct uisscsi_dest vdest; - struct Scsi_Host *shost = class_to_shost(cdev); - int i; - - i = sscanf(buf, "%d-%d-%d", &vdest.channel, &vdest.id, &vdest.lun); - if (i != 3) - return i; - - return forward_vdiskmgmt_command(VDISK_MGMT_ACQUIRE, shost, &vdest); -} - -static ssize_t -virthba_release_lun(struct device *cdev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct uisscsi_dest vdest; - struct Scsi_Host *shost = class_to_shost(cdev); - int i; - - i = sscanf(buf, "%d-%d-%d", &vdest.channel, &vdest.id, &vdest.lun); - if (i != 3) - return i; - - return forward_vdiskmgmt_command(VDISK_MGMT_RELEASE, shost, &vdest); -} - -#define CLASS_DEVICE_ATTR(_name, _mode, _show, _store) \ - struct device_attribute class_device_attr_##_name = \ - __ATTR(_name, _mode, _show, _store) - -static CLASS_DEVICE_ATTR(acquire_lun, S_IWUSR, NULL, virthba_acquire_lun); -static CLASS_DEVICE_ATTR(release_lun, S_IWUSR, NULL, virthba_release_lun); - -static DEVICE_ATTRIBUTE *virthba_shost_attrs[] = { - &class_device_attr_acquire_lun, - &class_device_attr_release_lun, - NULL -}; - -static void __exit -virthba_mod_exit(void) -{ - virtpci_unregister_driver(&virthba_driver); - /* unregister is going to call virthba_remove */ - /* destroy serverdown completion workqueue */ - if (virthba_serverdown_workqueue) { - destroy_workqueue(virthba_serverdown_workqueue); - virthba_serverdown_workqueue = NULL; - } - - debugfs_remove_recursive(virthba_debugfs_dir); -} - -/* specify function to be run at module insertion time */ -module_init(virthba_mod_init); - -/* specify function to be run when module is removed */ -module_exit(virthba_mod_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Usha Srinivasan"); -MODULE_ALIAS("uisvirthba"); - /* this is extracted during depmod and kept in modules.dep */ -/* module parameter */ -module_param(virthba_options, charp, S_IRUGO); diff --git a/drivers/staging/unisys/virthba/virthba.h b/drivers/staging/unisys/virthba/virthba.h deleted file mode 100644 index 59901668d4f458..00000000000000 --- a/drivers/staging/unisys/virthba/virthba.h +++ /dev/null @@ -1,27 +0,0 @@ -/* virthba.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* - * Unisys Virtual HBA driver header - */ - -#ifndef __VIRTHBA_H__ -#define __VIRTHBA_H__ - -#define VIRTHBA_VERSION "01.00" - -#endif /* __VIRTHBA_H__ */ From 280b5a4366dd4b813cad180e39b04e773ca0ebe0 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Mon, 13 Apr 2015 21:16:50 -0400 Subject: [PATCH 0433/3798] staging: unisys: remove virtpci driver from staging tree The virtpci driver is being rewritten, so remove the driver from the staging tree. Signed-off-by: Benjamin Romer Reviewed-by: Don Zickus Reviewed-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/Kconfig | 1 - drivers/staging/unisys/Makefile | 1 - drivers/staging/unisys/virtpci/Kconfig | 10 - drivers/staging/unisys/virtpci/Makefile | 10 - drivers/staging/unisys/virtpci/virtpci.c | 1394 ---------------------- drivers/staging/unisys/virtpci/virtpci.h | 103 -- 6 files changed, 1519 deletions(-) delete mode 100644 drivers/staging/unisys/virtpci/Kconfig delete mode 100644 drivers/staging/unisys/virtpci/Makefile delete mode 100644 drivers/staging/unisys/virtpci/virtpci.c delete mode 100644 drivers/staging/unisys/virtpci/virtpci.h diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig index 906cd589048d8a..1de86d147b39d1 100644 --- a/drivers/staging/unisys/Kconfig +++ b/drivers/staging/unisys/Kconfig @@ -13,6 +13,5 @@ source "drivers/staging/unisys/visorutil/Kconfig" source "drivers/staging/unisys/visorchannel/Kconfig" source "drivers/staging/unisys/visorchipset/Kconfig" source "drivers/staging/unisys/uislib/Kconfig" -source "drivers/staging/unisys/virtpci/Kconfig" endif # UNISYSSPAR diff --git a/drivers/staging/unisys/Makefile b/drivers/staging/unisys/Makefile index 3283a013d0c687..899b0cbdb5ddc9 100644 --- a/drivers/staging/unisys/Makefile +++ b/drivers/staging/unisys/Makefile @@ -5,4 +5,3 @@ obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil/ obj-$(CONFIG_UNISYS_VISORCHANNEL) += visorchannel/ obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset/ obj-$(CONFIG_UNISYS_UISLIB) += uislib/ -obj-$(CONFIG_UNISYS_VIRTPCI) += virtpci/ diff --git a/drivers/staging/unisys/virtpci/Kconfig b/drivers/staging/unisys/virtpci/Kconfig deleted file mode 100644 index 6d19482ce11bad..00000000000000 --- a/drivers/staging/unisys/virtpci/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -# -# Unisys virtpci configuration -# - -config UNISYS_VIRTPCI - tristate "Unisys virtpci driver" - select UNISYS_UISLIB - ---help--- - If you say Y here, you will enable the Unisys virtpci driver. - diff --git a/drivers/staging/unisys/virtpci/Makefile b/drivers/staging/unisys/virtpci/Makefile deleted file mode 100644 index a26c696219a50c..00000000000000 --- a/drivers/staging/unisys/virtpci/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for Unisys virtpci -# - -obj-$(CONFIG_UNISYS_VIRTPCI) += virtpci.o - -ccflags-y += -Idrivers/staging/unisys/include -ccflags-y += -Idrivers/staging/unisys/uislib -ccflags-y += -Idrivers/staging/unisys/common-spar/include -ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels diff --git a/drivers/staging/unisys/virtpci/virtpci.c b/drivers/staging/unisys/virtpci/virtpci.c deleted file mode 100644 index d5ad01783c0721..00000000000000 --- a/drivers/staging/unisys/virtpci/virtpci.c +++ /dev/null @@ -1,1394 +0,0 @@ -/* virtpci.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#define EXPORT_SYMTAB - -#include -#ifdef CONFIG_MODVERSIONS -#include -#endif -#include "diagnostics/appos_subsystems.h" -#include "uisutils.h" -#include "vbuschannel.h" -#include "vbushelper.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" -#include "guestlinuxdebug.h" -#include "timskmod.h" - -struct driver_private { - struct kobject kobj; - struct klist klist_devices; - struct klist_node knode_bus; - struct module_kobject *mkobj; - struct device_driver *driver; -}; - -#define to_driver(obj) container_of(obj, struct driver_private, kobj) - -/* bus_id went away in 2.6.30 - the size was 20 bytes, so we'll define - * it ourselves, and a macro to make getting the field a bit simpler. - */ -#ifndef BUS_ID_SIZE -#define BUS_ID_SIZE 20 -#endif - -#define BUS_ID(x) dev_name(x) - -/* MAX_BUF = 4 busses x ( 32 devices/bus + 1 busline) x 80 characters - * = 10,560 bytes ~ 2^14 = 16,384 bytes - */ -#define MAX_BUF 16384 - -#include "virtpci.h" - -/* this is shorter than using __FILE__ (full path name) in - * debug/info/error messages - */ -#define CURRENT_FILE_PC VIRT_PCI_PC_virtpci_c -#define __MYFILE__ "virtpci.c" - -#define VIRTPCI_VERSION "01.00" - -/*****************************************************/ -/* Forward declarations */ -/*****************************************************/ - -static int delete_vbus_device(struct device *vbus, void *data); -static int match_busid(struct device *dev, void *data); -static void virtpci_bus_release(struct device *dev); -static void virtpci_device_release(struct device *dev); -static int virtpci_device_add(struct device *parentbus, int devtype, - struct add_virt_guestpart *addparams, - struct scsi_adap_info *scsi, - struct net_adap_info *net); -static int virtpci_device_del(struct device *parentbus, int devtype, - struct vhba_wwnn *wwnn, unsigned char macaddr[]); -static int virtpci_device_serverdown(struct device *parentbus, int devtype, - struct vhba_wwnn *wwnn, - unsigned char macaddr[]); -static int virtpci_device_serverup(struct device *parentbus, int devtype, - struct vhba_wwnn *wwnn, - unsigned char macaddr[]); -static ssize_t virtpci_driver_attr_show(struct kobject *kobj, - struct attribute *attr, char *buf); -static ssize_t virtpci_driver_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, size_t count); -static int virtpci_bus_match(struct device *dev, struct device_driver *drv); -static int virtpci_uevent(struct device *dev, struct kobj_uevent_env *env); -static int virtpci_device_probe(struct device *dev); -static int virtpci_device_remove(struct device *dev); - -static ssize_t info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset); - -static const struct file_operations debugfs_info_fops = { - .read = info_debugfs_read, -}; - -/*****************************************************/ -/* Globals */ -/*****************************************************/ - -/* methods in bus_type struct allow the bus code to serve as an - * intermediary between the device core and individual device core and - * individual drivers - */ -static struct bus_type virtpci_bus_type = { - .name = "uisvirtpci", - .match = virtpci_bus_match, - .uevent = virtpci_uevent, -}; - -static struct device virtpci_rootbus_device = { - .init_name = "vbusroot", /* root bus */ - .release = virtpci_bus_release -}; - -/* filled in with info about parent chipset driver when we register with it */ -static struct ultra_vbus_deviceinfo chipset_driver_info; - -static const struct sysfs_ops virtpci_driver_sysfs_ops = { - .show = virtpci_driver_attr_show, - .store = virtpci_driver_attr_store, -}; - -static struct kobj_type virtpci_driver_kobj_type = { - .sysfs_ops = &virtpci_driver_sysfs_ops, -}; - -static struct virtpci_dev *vpcidev_list_head; -static DEFINE_RWLOCK(vpcidev_list_lock); - -/* filled in with info about this driver, wrt it servicing client busses */ -static struct ultra_vbus_deviceinfo bus_driver_info; - -/*****************************************************/ -/* debugfs entries */ -/*****************************************************/ -/* dentry is used to create the debugfs entry directory - * for virtpci - */ -static struct dentry *virtpci_debugfs_dir; - -struct virtpci_busdev { - struct device virtpci_bus_device; -}; - -/*****************************************************/ -/* Local functions */ -/*****************************************************/ - -static inline -int WAIT_FOR_IO_CHANNEL(struct spar_io_channel_protocol __iomem *chanptr) -{ - int count = 120; - - while (count > 0) { - if (SPAR_CHANNEL_SERVER_READY(&chanptr->channel_header)) - return 1; - UIS_THREAD_WAIT_SEC(1); - count--; - } - return 0; -} - -/* Write the contents of to the ULTRA_VBUS_CHANNEL_PROTOCOL.ChpInfo. */ -static int write_vbus_chp_info(struct spar_vbus_channel_protocol *chan, - struct ultra_vbus_deviceinfo *info) -{ - int off; - - if (!chan) - return -1; - - off = sizeof(struct channel_header) + chan->hdr_info.chp_info_offset; - if (chan->hdr_info.chp_info_offset == 0) { - return -1; - } - memcpy(((u8 *)(chan)) + off, info, sizeof(*info)); - return 0; -} - -/* Write the contents of to the ULTRA_VBUS_CHANNEL_PROTOCOL.BusInfo. */ -static int write_vbus_bus_info(struct spar_vbus_channel_protocol *chan, - struct ultra_vbus_deviceinfo *info) -{ - int off; - - if (!chan) - return -1; - - off = sizeof(struct channel_header) + chan->hdr_info.bus_info_offset; - if (chan->hdr_info.bus_info_offset == 0) - return -1; - memcpy(((u8 *)(chan)) + off, info, sizeof(*info)); - return 0; -} - -/* Write the contents of to the - * ULTRA_VBUS_CHANNEL_PROTOCOL.DevInfo[]. - */ -static int -write_vbus_dev_info(struct spar_vbus_channel_protocol *chan, - struct ultra_vbus_deviceinfo *info, int devix) -{ - int off; - - if (!chan) - return -1; - - off = - (sizeof(struct channel_header) + - chan->hdr_info.dev_info_offset) + - (chan->hdr_info.device_info_struct_bytes * devix); - if (chan->hdr_info.dev_info_offset == 0) - return -1; - - memcpy(((u8 *)(chan)) + off, info, sizeof(*info)); - return 0; -} - -/* adds a vbus - * returns 0 failure, 1 success, - */ -static int add_vbus(struct add_vbus_guestpart *addparams) -{ - int ret; - struct device *vbus; - - vbus = kzalloc(sizeof(*vbus), GFP_ATOMIC); - - POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO); - if (!vbus) - return 0; - - dev_set_name(vbus, "vbus%d", addparams->bus_no); - vbus->release = virtpci_bus_release; - vbus->parent = &virtpci_rootbus_device; /* root bus is parent */ - vbus->bus = &virtpci_bus_type; /* bus type */ - vbus->platform_data = (__force void *)addparams->chanptr; - - /* register a virt bus device - - * this bus shows up under /sys/devices with .name value - * "virtpci%d" any devices added to this bus then show up under - * /sys/devices/virtpci0 - */ - ret = device_register(vbus); - if (ret) { - POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR); - return 0; - } - write_vbus_chp_info(vbus->platform_data /* chanptr */, - &chipset_driver_info); - write_vbus_bus_info(vbus->platform_data /* chanptr */, - &bus_driver_info); - POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO); - return 1; -} - -/* for CHANSOCK wwwnn/max are AUTO-GENERATED; for normal channels, - * wwnn/max are in the channel header. - */ -#define GET_SCSIADAPINFO_FROM_CHANPTR(chanptr) { \ - memcpy_fromio(&scsi.wwnn, \ - &((struct spar_io_channel_protocol __iomem *) \ - chanptr)->vhba.wwnn, \ - sizeof(struct vhba_wwnn)); \ - memcpy_fromio(&scsi.max, \ - &((struct spar_io_channel_protocol __iomem *) \ - chanptr)->vhba.max, \ - sizeof(struct vhba_config_max)); \ - } - -/* adds a vhba - * returns 0 failure, 1 success, - */ -static int add_vhba(struct add_virt_guestpart *addparams) -{ - int i; - struct scsi_adap_info scsi; - struct device *vbus; - unsigned char busid[BUS_ID_SIZE]; - - POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO); - if (!WAIT_FOR_IO_CHANNEL - ((struct spar_io_channel_protocol __iomem *)addparams->chanptr)) { - POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR); - return 0; - } - - GET_SCSIADAPINFO_FROM_CHANPTR(addparams->chanptr); - - /* find bus device with the busid that matches match_busid */ - sprintf(busid, "vbus%d", addparams->bus_no); - vbus = bus_find_device(&virtpci_bus_type, NULL, - (void *)busid, match_busid); - if (!vbus) - return 0; - - i = virtpci_device_add(vbus, VIRTHBA_TYPE, addparams, &scsi, NULL); - if (i) { - POSTCODE_LINUX_3(VPCI_CREATE_EXIT_PC, i, - POSTCODE_SEVERITY_INFO); - } - return i; -} - -/* for CHANSOCK macaddr is AUTO-GENERATED; for normal channels, - * macaddr is in the channel header. - */ -#define GET_NETADAPINFO_FROM_CHANPTR(chanptr) { \ - memcpy_fromio(net.mac_addr, \ - ((struct spar_io_channel_protocol __iomem *) \ - chanptr)->vnic.macaddr, \ - MAX_MACADDR_LEN); \ - net.num_rcv_bufs = \ - readl(&((struct spar_io_channel_protocol __iomem *)\ - chanptr)->vnic.num_rcv_bufs); \ - net.mtu = readl(&((struct spar_io_channel_protocol __iomem *) \ - chanptr)->vnic.mtu); \ - memcpy_fromio(&net.zone_uuid, \ - &((struct spar_io_channel_protocol __iomem *)\ - chanptr)->vnic.zone_uuid, \ - sizeof(uuid_le)); \ -} - -/* adds a vnic - * returns 0 failure, 1 success, - */ -static int -add_vnic(struct add_virt_guestpart *addparams) -{ - int i; - struct net_adap_info net; - struct device *vbus; - unsigned char busid[BUS_ID_SIZE]; - - POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO); - if (!WAIT_FOR_IO_CHANNEL - ((struct spar_io_channel_protocol __iomem *)addparams->chanptr)) { - POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR); - return 0; - } - - GET_NETADAPINFO_FROM_CHANPTR(addparams->chanptr); - - /* find bus device with the busid that matches match_busid */ - sprintf(busid, "vbus%d", addparams->bus_no); - vbus = bus_find_device(&virtpci_bus_type, NULL, - (void *)busid, match_busid); - if (!vbus) - return 0; - - i = virtpci_device_add(vbus, VIRTNIC_TYPE, addparams, NULL, &net); - if (i) { - POSTCODE_LINUX_3(VPCI_CREATE_EXIT_PC, i, - POSTCODE_SEVERITY_INFO); - return 1; - } - return 0; -} - -/* delete vbus - * returns 0 failure, 1 success, - */ -static int -delete_vbus(struct del_vbus_guestpart *delparams) -{ - struct device *vbus; - unsigned char busid[BUS_ID_SIZE]; - - /* find bus device with the busid that matches match_busid */ - sprintf(busid, "vbus%d", delparams->bus_no); - vbus = bus_find_device(&virtpci_bus_type, NULL, - (void *)busid, match_busid); - if (!vbus) - return 0; - - /* ensure that bus has no devices? -- TBD */ - return 1; -} - -static int -delete_vbus_device(struct device *vbus, void *data) -{ - struct device *dev = &virtpci_rootbus_device; - - if ((data) && match_busid(vbus, (void *)BUS_ID(dev))) { - /* skip it - don't delete root bus */ - return 0; /* pretend no error */ - } - device_unregister(vbus); - kfree(vbus); - return 0; /* no error */ -} - -/* pause vhba -* returns 0 failure, 1 success, -*/ -static int pause_vhba(struct pause_virt_guestpart *pauseparams) -{ - int i; - struct scsi_adap_info scsi; - - GET_SCSIADAPINFO_FROM_CHANPTR(pauseparams->chanptr); - - i = virtpci_device_serverdown(NULL /*no parent bus */, VIRTHBA_TYPE, - &scsi.wwnn, NULL); - return i; -} - -/* pause vnic - * returns 0 failure, 1 success, - */ -static int pause_vnic(struct pause_virt_guestpart *pauseparams) -{ - int i; - struct net_adap_info net; - - GET_NETADAPINFO_FROM_CHANPTR(pauseparams->chanptr); - - i = virtpci_device_serverdown(NULL /*no parent bus */, VIRTNIC_TYPE, - NULL, net.mac_addr); - return i; -} - -/* resume vhba - * returns 0 failure, 1 success, - */ -static int resume_vhba(struct resume_virt_guestpart *resumeparams) -{ - int i; - struct scsi_adap_info scsi; - - GET_SCSIADAPINFO_FROM_CHANPTR(resumeparams->chanptr); - - i = virtpci_device_serverup(NULL /*no parent bus */, VIRTHBA_TYPE, - &scsi.wwnn, NULL); - return i; -} - -/* resume vnic -* returns 0 failure, 1 success, -*/ -static int -resume_vnic(struct resume_virt_guestpart *resumeparams) -{ - int i; - struct net_adap_info net; - - GET_NETADAPINFO_FROM_CHANPTR(resumeparams->chanptr); - - i = virtpci_device_serverup(NULL /*no parent bus */, VIRTNIC_TYPE, - NULL, net.mac_addr); - return i; -} - -/* delete vhba -* returns 0 failure, 1 success, -*/ -static int delete_vhba(struct del_virt_guestpart *delparams) -{ - int i; - struct scsi_adap_info scsi; - - GET_SCSIADAPINFO_FROM_CHANPTR(delparams->chanptr); - - i = virtpci_device_del(NULL /*no parent bus */, VIRTHBA_TYPE, - &scsi.wwnn, NULL); - if (i) { - return 1; - } - return 0; -} - -/* deletes a vnic - * returns 0 failure, 1 success, - */ -static int delete_vnic(struct del_virt_guestpart *delparams) -{ - int i; - struct net_adap_info net; - - GET_NETADAPINFO_FROM_CHANPTR(delparams->chanptr); - - i = virtpci_device_del(NULL /*no parent bus */, VIRTNIC_TYPE, NULL, - net.mac_addr); - return i; -} - -#define DELETE_ONE_VPCIDEV(vpcidev) { \ - device_unregister(&vpcidev->generic_dev); \ - kfree(vpcidev); \ -} - -/* deletes all vhbas and vnics - * returns 0 failure, 1 success, - */ -static void delete_all(void) -{ - int count = 0; - unsigned long flags; - struct virtpci_dev *tmpvpcidev, *nextvpcidev; - - /* delete the entire vhba/vnic list in one shot */ - write_lock_irqsave(&vpcidev_list_lock, flags); - tmpvpcidev = vpcidev_list_head; - vpcidev_list_head = NULL; - write_unlock_irqrestore(&vpcidev_list_lock, flags); - - /* delete one vhba/vnic at a time */ - while (tmpvpcidev) { - nextvpcidev = tmpvpcidev->next; - /* delete the vhba/vnic at tmpvpcidev */ - DELETE_ONE_VPCIDEV(tmpvpcidev); - tmpvpcidev = nextvpcidev; - count++; - } - - /* now delete each vbus */ - bus_for_each_dev(&virtpci_bus_type, NULL, (void *)1, - delete_vbus_device); -} - -/* deletes all vnics or vhbas - * returns 0 failure, 1 success, - */ -static int delete_all_virt(enum virtpci_dev_type devtype, - struct del_vbus_guestpart *delparams) -{ - int i; - unsigned char busid[BUS_ID_SIZE]; - struct device *vbus; - - /* find bus device with the busid that matches match_busid */ - sprintf(busid, "vbus%d", delparams->bus_no); - vbus = bus_find_device(&virtpci_bus_type, NULL, - (void *)busid, match_busid); - if (!vbus) - return 0; - - if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) - return 0; - - /* delete all vhbas/vnics */ - i = virtpci_device_del(vbus, devtype, NULL, NULL); - return 1; -} - -static int virtpci_ctrlchan_func(struct guest_msgs *msg) -{ - switch (msg->msgtype) { - case GUEST_ADD_VBUS: - return add_vbus(&msg->add_vbus); - case GUEST_ADD_VHBA: - return add_vhba(&msg->add_vhba); - case GUEST_ADD_VNIC: - return add_vnic(&msg->add_vnic); - case GUEST_DEL_VBUS: - return delete_vbus(&msg->del_vbus); - case GUEST_DEL_VHBA: - return delete_vhba(&msg->del_vhba); - case GUEST_DEL_VNIC: - return delete_vnic(&msg->del_vhba); - case GUEST_DEL_ALL_VHBAS: - return delete_all_virt(VIRTHBA_TYPE, &msg->del_all_vhbas); - case GUEST_DEL_ALL_VNICS: - return delete_all_virt(VIRTNIC_TYPE, &msg->del_all_vnics); - case GUEST_DEL_ALL_VBUSES: - delete_all(); - return 1; - case GUEST_PAUSE_VHBA: - return pause_vhba(&msg->pause_vhba); - case GUEST_PAUSE_VNIC: - return pause_vnic(&msg->pause_vnic); - case GUEST_RESUME_VHBA: - return resume_vhba(&msg->resume_vhba); - case GUEST_RESUME_VNIC: - return resume_vnic(&msg->resume_vnic); - default: - return 0; - } -} - -/* same as driver_helper in bus.c linux */ -static int match_busid(struct device *dev, void *data) -{ - const char *name = data; - - if (strcmp(name, BUS_ID(dev)) == 0) - return 1; - return 0; -} - -/*****************************************************/ -/* Bus functions */ -/*****************************************************/ - -static const struct pci_device_id * -virtpci_match_device(const struct pci_device_id *ids, - const struct virtpci_dev *dev) -{ - while (ids->vendor || ids->subvendor || ids->class_mask) { - if ((ids->vendor == dev->vendor) && - (ids->device == dev->device)) - return ids; - - ids++; - } - return NULL; -} - -/* NOTE: !!!!!! This function is called when a new device is added -* for this bus. Or, it is called for existing devices when a new -* driver is added for this bus. It returns nonzero if a given device -* can be handled by the given driver. -*/ -static int virtpci_bus_match(struct device *dev, struct device_driver *drv) -{ - struct virtpci_dev *virtpcidev = device_to_virtpci_dev(dev); - struct virtpci_driver *virtpcidrv = driver_to_virtpci_driver(drv); - int match = 0; - - /* check ids list for a match */ - if (virtpci_match_device(virtpcidrv->id_table, virtpcidev)) - match = 1; - - return match; /* 0 - no match; 1 - yes it matches */ -} - -static int virtpci_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - /* add variables to the environment prior to the generation of - * hotplug events to user space - */ - if (add_uevent_var(env, "VIRTPCI_VERSION=%s", VIRTPCI_VERSION)) - return -ENOMEM; - return 0; -} - -/* For a child device just created on a client bus, fill in - * information about the driver that is controlling this device into - * the appropriate slot within the vbus channel of the bus - * instance. - */ -static void fix_vbus_dev_info(struct device *dev, int dev_no, int dev_type, - struct virtpci_driver *virtpcidrv) -{ - struct device *vbus; - void *chan; - struct ultra_vbus_deviceinfo dev_info; - const char *stype; - - if (!dev) - return; - if (!virtpcidrv) - return; - - vbus = dev->parent; - if (!vbus) - return; - - chan = vbus->platform_data; - if (!chan) - return; - - switch (dev_type) { - case PCI_DEVICE_ID_VIRTHBA: - stype = "vHBA"; - break; - case PCI_DEVICE_ID_VIRTNIC: - stype = "vNIC"; - break; - default: - stype = "unknown"; - break; - } - bus_device_info_init(&dev_info, stype, - virtpcidrv->name, - virtpcidrv->version, - virtpcidrv->vertag); - write_vbus_dev_info(chan, &dev_info, dev_no); - - /* Re-write bus+chipset info, because it is possible that this - * was previously written by our good counterpart, visorbus. - */ - write_vbus_chp_info(chan, &chipset_driver_info); - write_vbus_bus_info(chan, &bus_driver_info); -} - -/* This function is called to query the existence of a specific device -* and whether this driver can work with it. It should return -ENODEV -* in case of failure. -*/ -static int virtpci_device_probe(struct device *dev) -{ - struct virtpci_dev *virtpcidev = device_to_virtpci_dev(dev); - struct virtpci_driver *virtpcidrv = - driver_to_virtpci_driver(dev->driver); - const struct pci_device_id *id; - int error = 0; - - POSTCODE_LINUX_2(VPCI_PROBE_ENTRY_PC, POSTCODE_SEVERITY_INFO); - /* static match and static probe vs dynamic match & dynamic - * probe - do we care?. - */ - if (!virtpcidrv->id_table) - return -ENODEV; - - id = virtpci_match_device(virtpcidrv->id_table, virtpcidev); - if (!id) - return -ENODEV; - - /* increment reference count */ - get_device(dev); - - /* if virtpcidev is not already claimed & probe function is - * valid, probe it - */ - if (!virtpcidev->mydriver && virtpcidrv->probe) { - /* call the probe function - virthba or virtnic probe - * is what it should be - */ - error = virtpcidrv->probe(virtpcidev, id); - if (!error) { - fix_vbus_dev_info(dev, virtpcidev->device_no, - virtpcidev->device, virtpcidrv); - virtpcidev->mydriver = virtpcidrv; - POSTCODE_LINUX_2(VPCI_PROBE_EXIT_PC, - POSTCODE_SEVERITY_INFO); - } else { - put_device(dev); - } - } - POSTCODE_LINUX_2(VPCI_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR); - return error; /* -ENODEV for probe failure */ -} - -static int virtpci_device_remove(struct device *dev_) -{ - /* dev_ passed in is the HBA device which we called - * generic_dev in our virtpcidev struct - */ - struct virtpci_dev *virtpcidev = device_to_virtpci_dev(dev_); - struct virtpci_driver *virtpcidrv = virtpcidev->mydriver; - - if (virtpcidrv) { - /* TEMP: assuming we have only one such driver for now */ - if (virtpcidrv->remove) - virtpcidrv->remove(virtpcidev); - virtpcidev->mydriver = NULL; - } - - put_device(dev_); - return 0; -} - -/*****************************************************/ -/* Bus functions */ -/*****************************************************/ - -static void virtpci_bus_release(struct device *dev) -{ -} - -/*****************************************************/ -/* Adapter functions */ -/*****************************************************/ - -/* scsi is expected to be NULL for VNIC add - * net is expected to be NULL for VHBA add - */ -static int virtpci_device_add(struct device *parentbus, int devtype, - struct add_virt_guestpart *addparams, - struct scsi_adap_info *scsi, - struct net_adap_info *net) -{ - struct virtpci_dev *virtpcidev = NULL; - struct virtpci_dev *tmpvpcidev = NULL, *prev; - unsigned long flags; - int ret; - struct spar_io_channel_protocol __iomem *io_chan = NULL; - struct device *dev; - - POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO); - - if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) { - POSTCODE_LINUX_3(VPCI_CREATE_FAILURE_PC, devtype, - POSTCODE_SEVERITY_ERR); - return 0; - } - - /* add a Virtual Device */ - virtpcidev = kzalloc(sizeof(*virtpcidev), GFP_ATOMIC); - if (!virtpcidev) { - POSTCODE_LINUX_2(MALLOC_FAILURE_PC, POSTCODE_SEVERITY_ERR); - return 0; - } - - /* initialize stuff unique to virtpci_dev struct */ - virtpcidev->devtype = devtype; - if (devtype == VIRTHBA_TYPE) { - virtpcidev->device = PCI_DEVICE_ID_VIRTHBA; - virtpcidev->scsi = *scsi; - } else { - virtpcidev->device = PCI_DEVICE_ID_VIRTNIC; - virtpcidev->net = *net; - } - virtpcidev->vendor = PCI_VENDOR_ID_UNISYS; - virtpcidev->bus_no = addparams->bus_no; - virtpcidev->device_no = addparams->device_no; - - virtpcidev->queueinfo.chan = addparams->chanptr; - virtpcidev->queueinfo.send_int_if_needed = NULL; - - /* Set up safe queue... */ - io_chan = (struct spar_io_channel_protocol __iomem *) - virtpcidev->queueinfo.chan; - - virtpcidev->intr = addparams->intr; - - /* initialize stuff in the device portion of the struct */ - virtpcidev->generic_dev.bus = &virtpci_bus_type; - virtpcidev->generic_dev.parent = parentbus; - virtpcidev->generic_dev.release = virtpci_device_release; - - dev_set_name(&virtpcidev->generic_dev, "%x:%x", - addparams->bus_no, addparams->device_no); - - /* add the vhba/vnic to virtpci device list - but check for - * duplicate wwnn/macaddr first - */ - write_lock_irqsave(&vpcidev_list_lock, flags); - for (tmpvpcidev = vpcidev_list_head; tmpvpcidev; - tmpvpcidev = tmpvpcidev->next) { - if (devtype == VIRTHBA_TYPE) { - if ((tmpvpcidev->scsi.wwnn.wwnn1 == scsi->wwnn.wwnn1) && - (tmpvpcidev->scsi.wwnn.wwnn2 == scsi->wwnn.wwnn2)) { - /* duplicate - already have vpcidev - with this wwnn */ - break; - } - } else - if (memcmp - (tmpvpcidev->net.mac_addr, net->mac_addr, - MAX_MACADDR_LEN) == 0) { - /* duplicate - already have vnic with this wwnn */ - break; - } - } - if (tmpvpcidev) { - /* found a vhba/vnic already in the list with same - * wwnn or macaddr - reject add - */ - write_unlock_irqrestore(&vpcidev_list_lock, flags); - kfree(virtpcidev); - POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR); - return 0; - } - - /* add it at the head */ - if (!vpcidev_list_head) { - vpcidev_list_head = virtpcidev; - } else { - /* insert virtpcidev at the head of our linked list of - * vpcidevs - */ - virtpcidev->next = vpcidev_list_head; - vpcidev_list_head = virtpcidev; - } - - write_unlock_irqrestore(&vpcidev_list_lock, flags); - - /* Must transition channel to ATTACHED state BEFORE - * registering the device, because polling of the channel - * queues can begin at any time after device_register(). - */ - dev = &virtpcidev->generic_dev; - SPAR_CHANNEL_CLIENT_TRANSITION(addparams->chanptr, - BUS_ID(dev), - CHANNELCLI_ATTACHED, NULL); - - /* don't register until device has been added to - * list. Otherwise, a device_unregister from this function can - * cause a "scheduling while atomic". - */ - ret = device_register(&virtpcidev->generic_dev); - /* NOTE: THIS IS CALLING HOTPLUG virtpci_hotplug!!! - * This call to device_register results in virtpci_bus_match - * being called !!!!! And, if match returns success, then - * virtpcidev->generic_dev.driver is setup to core_driver, - * i.e., virtpci and the probe function - * virtpcidev->generic_dev.driver->probe is called which - * results in virtpci_device_probe being called. And if - * virtpci_device_probe is successful - */ - if (ret) { - dev = &virtpcidev->generic_dev; - SPAR_CHANNEL_CLIENT_TRANSITION(addparams->chanptr, - BUS_ID(dev), - CHANNELCLI_DETACHED, NULL); - /* remove virtpcidev, the one we just added, from the list */ - write_lock_irqsave(&vpcidev_list_lock, flags); - for (tmpvpcidev = vpcidev_list_head, prev = NULL; - tmpvpcidev; - prev = tmpvpcidev, tmpvpcidev = tmpvpcidev->next) { - if (tmpvpcidev == virtpcidev) { - if (prev) - prev->next = tmpvpcidev->next; - else - vpcidev_list_head = tmpvpcidev->next; - break; - } - } - write_unlock_irqrestore(&vpcidev_list_lock, flags); - kfree(virtpcidev); - return 0; - } - - POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO); - return 1; -} - -static int virtpci_device_serverdown(struct device *parentbus, - int devtype, - struct vhba_wwnn *wwnn, - unsigned char macaddr[]) -{ - int pausethisone = 0; - bool found = false; - struct virtpci_dev *tmpvpcidev, *prevvpcidev; - struct virtpci_driver *vpcidriver; - unsigned long flags; - int rc = 0; - - if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) - return 0; - - /* find the vhba or vnic in virtpci device list */ - write_lock_irqsave(&vpcidev_list_lock, flags); - - for (tmpvpcidev = vpcidev_list_head, prevvpcidev = NULL; - (tmpvpcidev && !found); - prevvpcidev = tmpvpcidev, tmpvpcidev = tmpvpcidev->next) { - if (tmpvpcidev->devtype != devtype) - continue; - - if (devtype == VIRTHBA_TYPE) { - pausethisone = - ((tmpvpcidev->scsi.wwnn.wwnn1 == wwnn->wwnn1) && - (tmpvpcidev->scsi.wwnn.wwnn2 == wwnn->wwnn2)); - /* devtype is vhba, we're pausing vhba whose - * wwnn matches the current device's wwnn - */ - } else { /* VIRTNIC_TYPE */ - pausethisone = - memcmp(tmpvpcidev->net.mac_addr, macaddr, - MAX_MACADDR_LEN) == 0; - /* devtype is vnic, we're pausing vnic whose - * macaddr matches the current device's macaddr */ - } - - if (!pausethisone) - continue; - - found = true; - vpcidriver = tmpvpcidev->mydriver; - rc = vpcidriver->suspend(tmpvpcidev, 0); - } - write_unlock_irqrestore(&vpcidev_list_lock, flags); - - if (!found) - return 0; - - return rc; -} - -static int virtpci_device_serverup(struct device *parentbus, - int devtype, - struct vhba_wwnn *wwnn, - unsigned char macaddr[]) -{ - int resumethisone = 0; - bool found = false; - struct virtpci_dev *tmpvpcidev, *prevvpcidev; - struct virtpci_driver *vpcidriver; - unsigned long flags; - int rc = 0; - - if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) - return 0; - - - /* find the vhba or vnic in virtpci device list */ - write_lock_irqsave(&vpcidev_list_lock, flags); - - for (tmpvpcidev = vpcidev_list_head, prevvpcidev = NULL; - (tmpvpcidev && !found); - prevvpcidev = tmpvpcidev, tmpvpcidev = tmpvpcidev->next) { - if (tmpvpcidev->devtype != devtype) - continue; - - if (devtype == VIRTHBA_TYPE) { - resumethisone = - ((tmpvpcidev->scsi.wwnn.wwnn1 == wwnn->wwnn1) && - (tmpvpcidev->scsi.wwnn.wwnn2 == wwnn->wwnn2)); - /* devtype is vhba, we're resuming vhba whose - * wwnn matches the current device's wwnn */ - } else { /* VIRTNIC_TYPE */ - resumethisone = - memcmp(tmpvpcidev->net.mac_addr, macaddr, - MAX_MACADDR_LEN) == 0; - /* devtype is vnic, we're resuming vnic whose - * macaddr matches the current device's macaddr */ - } - - if (!resumethisone) - continue; - - found = true; - vpcidriver = tmpvpcidev->mydriver; - /* This should be done at BUS resume time, but an - * existing problem prevents us from ever getting a bus - * resume... This hack would fail to work should we - * ever have a bus that contains NO devices, since we - * would never even get here in that case. - */ - fix_vbus_dev_info(&tmpvpcidev->generic_dev, - tmpvpcidev->device_no, - tmpvpcidev->device, vpcidriver); - rc = vpcidriver->resume(tmpvpcidev); - } - - write_unlock_irqrestore(&vpcidev_list_lock, flags); - - if (!found) - return 0; - - return rc; -} - -static int virtpci_device_del(struct device *parentbus, - int devtype, struct vhba_wwnn *wwnn, - unsigned char macaddr[]) -{ - int count = 0, all = 0, delthisone; - struct virtpci_dev *tmpvpcidev, *prevvpcidev, *dellist = NULL; - unsigned long flags; - -#define DEL_CONTINUE { \ - prevvpcidev = tmpvpcidev;\ - tmpvpcidev = tmpvpcidev->next;\ - continue; \ -} - - if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) - return 0; - - /* see if we are to delete all - NOTE: all implies we have a - * valid parentbus - */ - all = ((devtype == VIRTHBA_TYPE) && (!wwnn)) || - ((devtype == VIRTNIC_TYPE) && (!macaddr)); - - /* find all the vhba or vnic or both in virtpci device list - * keep list of ones we are deleting so we can call - * device_unregister after we release the lock; otherwise we - * encounter "schedule while atomic" - */ - write_lock_irqsave(&vpcidev_list_lock, flags); - for (tmpvpcidev = vpcidev_list_head, prevvpcidev = NULL; tmpvpcidev;) { - if (tmpvpcidev->devtype != devtype) - DEL_CONTINUE; - - if (all) { - delthisone = - (tmpvpcidev->generic_dev.parent == parentbus); - /* we're deleting all vhbas or vnics on the - * specified parent bus - */ - } else if (devtype == VIRTHBA_TYPE) { - delthisone = - ((tmpvpcidev->scsi.wwnn.wwnn1 == wwnn->wwnn1) && - (tmpvpcidev->scsi.wwnn.wwnn2 == wwnn->wwnn2)); - /* devtype is vhba, we're deleting vhba whose - * wwnn matches the current device's wwnn - */ - } else { /* VIRTNIC_TYPE */ - delthisone = - memcmp(tmpvpcidev->net.mac_addr, macaddr, - MAX_MACADDR_LEN) == 0; - /* devtype is vnic, we're deleting vnic whose - * macaddr matches the current device's macaddr - */ - } - - if (!delthisone) - DEL_CONTINUE; - - /* take vhba/vnic out of the list */ - if (prevvpcidev) - /* not at head */ - prevvpcidev->next = tmpvpcidev->next; - else - vpcidev_list_head = tmpvpcidev->next; - - /* add it to our deletelist */ - tmpvpcidev->next = dellist; - dellist = tmpvpcidev; - - count++; - if (!all) - break; /* done */ - /* going to top of loop again - set tmpvpcidev to next - * one we're to process - */ - if (prevvpcidev) - tmpvpcidev = prevvpcidev->next; - else - tmpvpcidev = vpcidev_list_head; - } - write_unlock_irqrestore(&vpcidev_list_lock, flags); - - if (!all && (count == 0)) - return 0; - - /* now delete each one from delete list */ - while (dellist) { - /* save next */ - tmpvpcidev = dellist->next; - /* delete the vhba/vnic at dellist */ - DELETE_ONE_VPCIDEV(dellist); - /* do next */ - dellist = tmpvpcidev; - } - - return count; -} - -static void virtpci_device_release(struct device *dev_) -{ - /* this function is called when the last reference to the - * device is removed - */ -} - -/*****************************************************/ -/* Driver functions */ -/*****************************************************/ - -#define kobj_to_device_driver(obj) container_of(obj, struct device_driver, kobj) -#define attribute_to_driver_attribute(obj) \ - container_of(obj, struct driver_attribute, attr) - -static ssize_t virtpci_driver_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct driver_attribute *dattr = attribute_to_driver_attribute(attr); - ssize_t ret = 0; - - struct driver_private *dprivate = to_driver(kobj); - struct device_driver *driver = dprivate->driver; - - if (dattr->show) - ret = dattr->show(driver, buf); - - return ret; -} - -static ssize_t virtpci_driver_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, size_t count) -{ - struct driver_attribute *dattr = attribute_to_driver_attribute(attr); - ssize_t ret = 0; - - struct driver_private *dprivate = to_driver(kobj); - struct device_driver *driver = dprivate->driver; - - if (dattr->store) - ret = dattr->store(driver, buf, count); - - return ret; -} - -/* register a new virtpci driver */ -int virtpci_register_driver(struct virtpci_driver *drv) -{ - int result = 0; - - if (!drv->id_table) - return 1; - /* initialize core driver fields needed to call driver_register */ - drv->core_driver.name = drv->name; /* name of driver in sysfs */ - drv->core_driver.bus = &virtpci_bus_type; /* type of bus this - * driver works with */ - drv->core_driver.probe = virtpci_device_probe; /* called to query the - * existence of a - * specific device and - * whether this driver - *can work with it */ - drv->core_driver.remove = virtpci_device_remove; /* called when the - * device is removed - * from the system */ - /* register with core */ - result = driver_register(&drv->core_driver); - /* calls bus_add_driver which calls driver_attach and - * module_add_driver - */ - if (result) - return result; /* failed */ - - drv->core_driver.p->kobj.ktype = &virtpci_driver_kobj_type; - - return 0; -} -EXPORT_SYMBOL_GPL(virtpci_register_driver); - -void virtpci_unregister_driver(struct virtpci_driver *drv) -{ - driver_unregister(&drv->core_driver); - /* driver_unregister calls bus_remove_driver - * bus_remove_driver calls device_detach - * device_detach calls device_release_driver for each of the - * driver's devices - * device_release driver calls drv->remove which is - * virtpci_device_remove - * virtpci_device_remove calls virthba_remove - */ -} -EXPORT_SYMBOL_GPL(virtpci_unregister_driver); - -/*****************************************************/ -/* debugfs filesystem functions */ -/*****************************************************/ -struct print_vbus_info { - int *str_pos; - char *buf; - size_t *len; -}; - -static int print_vbus(struct device *vbus, void *data) -{ - struct print_vbus_info *p = (struct print_vbus_info *)data; - - *p->str_pos += scnprintf(p->buf + *p->str_pos, *p->len - *p->str_pos, - "bus_id:%s\n", dev_name(vbus)); - return 0; -} - -static ssize_t info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset) -{ - ssize_t bytes_read = 0; - int str_pos = 0; - struct virtpci_dev *tmpvpcidev; - unsigned long flags; - struct print_vbus_info printparam; - char *vbuf; - - if (len > MAX_BUF) - len = MAX_BUF; - vbuf = kzalloc(len, GFP_KERNEL); - if (!vbuf) - return -ENOMEM; - - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " Virtual PCI Bus devices\n"); - printparam.str_pos = &str_pos; - printparam.buf = vbuf; - printparam.len = &len; - bus_for_each_dev(&virtpci_bus_type, NULL, (void *)&printparam, - print_vbus); - - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - "\n Virtual PCI devices\n"); - read_lock_irqsave(&vpcidev_list_lock, flags); - tmpvpcidev = vpcidev_list_head; - while (tmpvpcidev) { - if (tmpvpcidev->devtype == VIRTHBA_TYPE) { - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - "[%d:%d] VHba:%08x:%08x max-config:%d-%d-%d-%d", - tmpvpcidev->bus_no, - tmpvpcidev->device_no, - tmpvpcidev->scsi.wwnn.wwnn1, - tmpvpcidev->scsi.wwnn.wwnn2, - tmpvpcidev->scsi.max.max_channel, - tmpvpcidev->scsi.max.max_id, - tmpvpcidev->scsi.max.max_lun, - tmpvpcidev->scsi.max.cmd_per_lun); - } else { - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - "[%d:%d] VNic:%pM num_rcv_bufs:%d mtu:%d", - tmpvpcidev->bus_no, - tmpvpcidev->device_no, - tmpvpcidev->net.mac_addr, - tmpvpcidev->net.num_rcv_bufs, - tmpvpcidev->net.mtu); - } - str_pos += scnprintf(vbuf + str_pos, - len - str_pos, " chanptr:%p\n", - tmpvpcidev->queueinfo.chan); - tmpvpcidev = tmpvpcidev->next; - } - read_unlock_irqrestore(&vpcidev_list_lock, flags); - - str_pos += scnprintf(vbuf + str_pos, len - str_pos, "\n"); - bytes_read = simple_read_from_buffer(buf, len, offset, vbuf, str_pos); - kfree(vbuf); - return bytes_read; -} - -/*****************************************************/ -/* Module Init & Exit functions */ -/*****************************************************/ - -static int __init virtpci_mod_init(void) -{ - int ret; - - if (!unisys_spar_platform) - return -ENODEV; - - POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO); - - ret = bus_register(&virtpci_bus_type); - /* creates /sys/bus/uisvirtpci which contains devices & - * drivers directory - */ - if (ret) { - POSTCODE_LINUX_3(VPCI_CREATE_FAILURE_PC, ret, - POSTCODE_SEVERITY_ERR); - return ret; - } - bus_device_info_init(&bus_driver_info, "clientbus", "virtpci", - VERSION, NULL); - - /* create a root bus used to parent all the virtpci buses. */ - ret = device_register(&virtpci_rootbus_device); - if (ret) { - bus_unregister(&virtpci_bus_type); - POSTCODE_LINUX_3(VPCI_CREATE_FAILURE_PC, ret, - POSTCODE_SEVERITY_ERR); - return ret; - } - - if (!uisctrl_register_req_handler(2, (void *)&virtpci_ctrlchan_func, - &chipset_driver_info)) { - POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR); - device_unregister(&virtpci_rootbus_device); - bus_unregister(&virtpci_bus_type); - return -1; - } - - /* create debugfs directory and info file inside. */ - virtpci_debugfs_dir = debugfs_create_dir("virtpci", NULL); - debugfs_create_file("info", S_IRUSR, virtpci_debugfs_dir, - NULL, &debugfs_info_fops); - POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO); - return 0; -} - -static void __exit virtpci_mod_exit(void) -{ - /* unregister the callback function */ - device_unregister(&virtpci_rootbus_device); - bus_unregister(&virtpci_bus_type); - debugfs_remove_recursive(virtpci_debugfs_dir); -} - -module_init(virtpci_mod_init); -module_exit(virtpci_mod_exit); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Usha Srinivasan"); -MODULE_ALIAS("uisvirtpci"); - diff --git a/drivers/staging/unisys/virtpci/virtpci.h b/drivers/staging/unisys/virtpci/virtpci.h deleted file mode 100644 index 9d85f55e81696f..00000000000000 --- a/drivers/staging/unisys/virtpci/virtpci.h +++ /dev/null @@ -1,103 +0,0 @@ -/* virtpci.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* - * Unisys Virtual PCI driver header - */ - -#ifndef __VIRTPCI_H__ -#define __VIRTPCI_H__ - -#include "uisqueue.h" -#include -#include - -#define PCI_DEVICE_ID_VIRTHBA 0xAA00 -#define PCI_DEVICE_ID_VIRTNIC 0xAB00 - -struct scsi_adap_info { - void *scsihost; /* scsi host if this device is a scsi hba */ - struct vhba_wwnn wwnn; /* the world wide node name of vhba */ - struct vhba_config_max max; /* various max specifications used - * to config vhba */ -}; - -struct net_adap_info { - struct net_device *netdev; /* network device if this - * device is a NIC */ - u8 mac_addr[MAX_MACADDR_LEN]; - int num_rcv_bufs; - unsigned mtu; - uuid_le zone_uuid; -}; - -enum virtpci_dev_type { - VIRTHBA_TYPE = 0, - VIRTNIC_TYPE = 1, - VIRTBUS_TYPE = 6, -}; - -struct virtpci_dev { - enum virtpci_dev_type devtype; /* indicates type of the - * virtual pci device */ - struct virtpci_driver *mydriver; /* which driver has allocated - * this device */ - unsigned short vendor; /* vendor id for device */ - unsigned short device; /* device id for device */ - u32 bus_no; /* number of bus on which device exists */ - u32 device_no; /* device's number on the bus */ - struct irq_info intr; /* interrupt info */ - struct device generic_dev; /* generic device */ - union { - struct scsi_adap_info scsi; - struct net_adap_info net; - }; - - struct uisqueue_info queueinfo; /* holds ptr to channel where cmds & - * rsps are queued & retrieved */ - struct virtpci_dev *next; /* points to next virtpci device */ -}; - -struct virtpci_driver { - struct list_head node; - const char *name; /* the name of the driver in sysfs */ - const char *version; - const char *vertag; - const struct pci_device_id *id_table; /* must be non-NULL for probe - * to be called */ - int (*probe)(struct virtpci_dev *dev, - const struct pci_device_id *id); /* device inserted */ - void (*remove)(struct virtpci_dev *dev); /* Device removed (NULL if - * not a hot-plug capable - * driver) */ - int (*suspend)(struct virtpci_dev *dev, - u32 state); /* Device suspended */ - int (*resume)(struct virtpci_dev *dev); /* Device woken up */ - int (*enable_wake)(struct virtpci_dev *dev, - u32 state, int enable); /* Enable wake event */ - struct device_driver core_driver; /* VIRTPCI core fills this in */ -}; - -#define driver_to_virtpci_driver(in_drv) \ - container_of(in_drv, struct virtpci_driver, core_driver) -#define device_to_virtpci_dev(in_dev) \ - container_of(in_dev, struct virtpci_dev, generic_dev) - -int virtpci_register_driver(struct virtpci_driver *); -void virtpci_unregister_driver(struct virtpci_driver *); - -#endif /* __VIRTPCI_H__ */ From 6a7d8a418400f8bfaa1830759ef075bbed68cfe1 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Mon, 13 Apr 2015 21:16:51 -0400 Subject: [PATCH 0434/3798] staging: unisys: remove uislib module from staging tree This module is being removed completely, because it contained wrapper functions and utility functions that were used in virtpci and virthba. Since these two drivers are being rewritten to not use these wrappers and utilities, uislib needs to go. Signed-off-by: Benjamin Romer Reviewed-by: Don Zickus Reviewed-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/Kconfig | 1 - drivers/staging/unisys/Makefile | 1 - drivers/staging/unisys/uislib/Kconfig | 10 - drivers/staging/unisys/uislib/Makefile | 12 - drivers/staging/unisys/uislib/uislib.c | 1372 --------------------- drivers/staging/unisys/uislib/uisqueue.c | 322 ----- drivers/staging/unisys/uislib/uisthread.c | 69 -- drivers/staging/unisys/uislib/uisutils.c | 137 -- 8 files changed, 1924 deletions(-) delete mode 100644 drivers/staging/unisys/uislib/Kconfig delete mode 100644 drivers/staging/unisys/uislib/Makefile delete mode 100644 drivers/staging/unisys/uislib/uislib.c delete mode 100644 drivers/staging/unisys/uislib/uisqueue.c delete mode 100644 drivers/staging/unisys/uislib/uisthread.c delete mode 100644 drivers/staging/unisys/uislib/uisutils.c diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig index 1de86d147b39d1..14e1ea6803f81b 100644 --- a/drivers/staging/unisys/Kconfig +++ b/drivers/staging/unisys/Kconfig @@ -12,6 +12,5 @@ if UNISYSSPAR source "drivers/staging/unisys/visorutil/Kconfig" source "drivers/staging/unisys/visorchannel/Kconfig" source "drivers/staging/unisys/visorchipset/Kconfig" -source "drivers/staging/unisys/uislib/Kconfig" endif # UNISYSSPAR diff --git a/drivers/staging/unisys/Makefile b/drivers/staging/unisys/Makefile index 899b0cbdb5ddc9..97e750de4beffa 100644 --- a/drivers/staging/unisys/Makefile +++ b/drivers/staging/unisys/Makefile @@ -4,4 +4,3 @@ obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil/ obj-$(CONFIG_UNISYS_VISORCHANNEL) += visorchannel/ obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset/ -obj-$(CONFIG_UNISYS_UISLIB) += uislib/ diff --git a/drivers/staging/unisys/uislib/Kconfig b/drivers/staging/unisys/uislib/Kconfig deleted file mode 100644 index c39a0a21ae5fa7..00000000000000 --- a/drivers/staging/unisys/uislib/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -# -# Unisys uislib configuration -# - -config UNISYS_UISLIB - tristate "Unisys uislib driver" - select UNISYS_VISORCHIPSET - ---help--- - If you say Y here, you will enable the Unisys uislib driver. - diff --git a/drivers/staging/unisys/uislib/Makefile b/drivers/staging/unisys/uislib/Makefile deleted file mode 100644 index 860f494f132faf..00000000000000 --- a/drivers/staging/unisys/uislib/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for Unisys uislib -# - -obj-$(CONFIG_UNISYS_UISLIB) += visoruislib.o - -visoruislib-y := uislib.o uisqueue.o uisthread.o uisutils.o - -ccflags-y += -Idrivers/staging/unisys/include -ccflags-y += -Idrivers/staging/unisys/visorchipset -ccflags-y += -Idrivers/staging/unisys/common-spar/include -ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c deleted file mode 100644 index f93d0bb11b12d6..00000000000000 --- a/drivers/staging/unisys/uislib/uislib.c +++ /dev/null @@ -1,1372 +0,0 @@ -/* uislib.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* @ALL_INSPECTED */ -#define EXPORT_SYMTAB -#include -#include -#ifdef CONFIG_MODVERSIONS -#include -#endif -#include -#include - -#include -#include - -#include -#include "diagnostics/appos_subsystems.h" -#include "uisutils.h" -#include "vbuschannel.h" - -#include -#include /* for copy_from_user */ -#include /* for toupper */ -#include - -#include "sparstop.h" -#include "visorchipset.h" -#include "version.h" -#include "guestlinuxdebug.h" - -#define SET_PROC_OWNER(x, y) - -#define POLLJIFFIES_NORMAL 1 -/* Choose whether or not you want to wakeup the request-polling thread - * after an IO termination: - * this is shorter than using __FILE__ (full path name) in - * debug/info/error messages - */ -#define CURRENT_FILE_PC UISLIB_PC_uislib_c -#define __MYFILE__ "uislib.c" - -/* global function pointers that act as callback functions into virtpcimod */ -int (*virt_control_chan_func)(struct guest_msgs *); - -static int debug_buf_valid; -static char *debug_buf; /* Note this MUST be global, - * because the contents must */ -static unsigned int chipset_inited; - -#define WAIT_ON_CALLBACK(handle) \ - do { \ - if (handle) \ - break; \ - UIS_THREAD_WAIT; \ - } while (1) - -static struct bus_info *bus_list; -static rwlock_t bus_list_lock; -static int bus_list_count; /* number of buses in the list */ -static int max_bus_count; /* maximum number of buses expected */ -static u64 phys_data_chan; -static int platform_no; - -static struct uisthread_info incoming_ti; -static BOOL incoming_started = FALSE; -static LIST_HEAD(poll_dev_chan); -static unsigned long long tot_moved_to_tail_cnt; -static unsigned long long tot_wait_cnt; -static unsigned long long tot_wakeup_cnt; -static unsigned long long tot_schedule_cnt; -static int en_smart_wakeup = 1; -static DEFINE_SEMAPHORE(poll_dev_lock); /* unlocked */ -static DECLARE_WAIT_QUEUE_HEAD(poll_dev_wake_q); -static int poll_dev_start; - -#define CALLHOME_PROC_ENTRY_FN "callhome" -#define CALLHOME_THROTTLED_PROC_ENTRY_FN "callhome_throttled" - -#define DIR_DEBUGFS_ENTRY "uislib" -static struct dentry *dir_debugfs; - -#define PLATFORMNUMBER_DEBUGFS_ENTRY_FN "platform" -static struct dentry *platformnumber_debugfs_read; - -#define CYCLES_BEFORE_WAIT_DEBUGFS_ENTRY_FN "cycles_before_wait" -static struct dentry *cycles_before_wait_debugfs_read; - -#define SMART_WAKEUP_DEBUGFS_ENTRY_FN "smart_wakeup" -static struct dentry *smart_wakeup_debugfs_entry; - -#define INFO_DEBUGFS_ENTRY_FN "info" -static struct dentry *info_debugfs_entry; - -static unsigned long long cycles_before_wait, wait_cycles; - -/*****************************************************/ -/* local functions */ -/*****************************************************/ - -static ssize_t info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset); -static const struct file_operations debugfs_info_fops = { - .read = info_debugfs_read, -}; - -static void -init_msg_header(struct controlvm_message *msg, u32 id, uint rsp, uint svr) -{ - memset(msg, 0, sizeof(struct controlvm_message)); - msg->hdr.id = id; - msg->hdr.flags.response_expected = rsp; - msg->hdr.flags.server = svr; -} - -static __iomem void *init_vbus_channel(u64 ch_addr, u32 ch_bytes) -{ - void __iomem *ch = uislib_ioremap_cache(ch_addr, ch_bytes); - - if (!ch) - return NULL; - - if (!SPAR_VBUS_CHANNEL_OK_CLIENT(ch)) { - uislib_iounmap(ch); - return NULL; - } - return ch; -} - -static int -create_bus(struct controlvm_message *msg, char *buf) -{ - u32 bus_no, dev_count; - struct bus_info *tmp, *bus; - size_t size; - - if (max_bus_count == bus_list_count) { - POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, max_bus_count, - POSTCODE_SEVERITY_ERR); - return CONTROLVM_RESP_ERROR_MAX_BUSES; - } - - bus_no = msg->cmd.create_bus.bus_no; - dev_count = msg->cmd.create_bus.dev_count; - - POSTCODE_LINUX_4(BUS_CREATE_ENTRY_PC, bus_no, dev_count, - POSTCODE_SEVERITY_INFO); - - size = - sizeof(struct bus_info) + - (dev_count * sizeof(struct device_info *)); - bus = kzalloc(size, GFP_ATOMIC); - if (!bus) { - POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no, - POSTCODE_SEVERITY_ERR); - return CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - } - - /* Currently by default, the bus Number is the GuestHandle. - * Configure Bus message can override this. - */ - if (msg->hdr.flags.test_message) { - /* This implies we're the IOVM so set guest handle to 0... */ - bus->guest_handle = 0; - bus->bus_no = bus_no; - bus->local_vnic = 1; - } else { - bus->bus_no = bus_no; - bus->guest_handle = bus_no; - } - sprintf(bus->name, "%d", (int)bus->bus_no); - bus->device_count = dev_count; - bus->device = - (struct device_info **)((char *)bus + sizeof(struct bus_info)); - bus->bus_inst_uuid = msg->cmd.create_bus.bus_inst_uuid; - bus->bus_channel_bytes = 0; - bus->bus_channel = NULL; - - /* add bus to our bus list - but check for duplicates first */ - read_lock(&bus_list_lock); - for (tmp = bus_list; tmp; tmp = tmp->next) { - if (tmp->bus_no == bus->bus_no) - break; - } - read_unlock(&bus_list_lock); - if (tmp) { - /* found a bus already in the list with same bus_no - - * reject add - */ - POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->bus_no, - POSTCODE_SEVERITY_ERR); - kfree(bus); - return CONTROLVM_RESP_ERROR_ALREADY_DONE; - } - if ((msg->cmd.create_bus.channel_addr != 0) && - (msg->cmd.create_bus.channel_bytes != 0)) { - bus->bus_channel_bytes = msg->cmd.create_bus.channel_bytes; - bus->bus_channel = - init_vbus_channel(msg->cmd.create_bus.channel_addr, - msg->cmd.create_bus.channel_bytes); - } - /* the msg is bound for virtpci; send guest_msgs struct to callback */ - if (!msg->hdr.flags.server) { - struct guest_msgs cmd; - - cmd.msgtype = GUEST_ADD_VBUS; - cmd.add_vbus.bus_no = bus_no; - cmd.add_vbus.chanptr = bus->bus_channel; - cmd.add_vbus.dev_count = dev_count; - cmd.add_vbus.bus_uuid = msg->cmd.create_bus.bus_data_type_uuid; - cmd.add_vbus.instance_uuid = msg->cmd.create_bus.bus_inst_uuid; - if (!virt_control_chan_func) { - POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->bus_no, - POSTCODE_SEVERITY_ERR); - kfree(bus); - return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; - } - if (!virt_control_chan_func(&cmd)) { - POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->bus_no, - POSTCODE_SEVERITY_ERR); - kfree(bus); - return - CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR; - } - } - - /* add bus at the head of our list */ - write_lock(&bus_list_lock); - if (!bus_list) { - bus_list = bus; - } else { - bus->next = bus_list; - bus_list = bus; - } - bus_list_count++; - write_unlock(&bus_list_lock); - - POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus->bus_no, - POSTCODE_SEVERITY_INFO); - return CONTROLVM_RESP_SUCCESS; -} - -static int -destroy_bus(struct controlvm_message *msg, char *buf) -{ - int i; - struct bus_info *bus, *prev = NULL; - struct guest_msgs cmd; - u32 bus_no; - - bus_no = msg->cmd.destroy_bus.bus_no; - - read_lock(&bus_list_lock); - - bus = bus_list; - while (bus) { - if (bus->bus_no == bus_no) - break; - prev = bus; - bus = bus->next; - } - - if (!bus) { - read_unlock(&bus_list_lock); - return CONTROLVM_RESP_ERROR_ALREADY_DONE; - } - - /* verify that this bus has no devices. */ - for (i = 0; i < bus->device_count; i++) { - if (bus->device[i]) { - read_unlock(&bus_list_lock); - return CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED; - } - } - read_unlock(&bus_list_lock); - - if (msg->hdr.flags.server) - goto remove; - - /* client messages require us to call the virtpci callback associated - with this bus. */ - cmd.msgtype = GUEST_DEL_VBUS; - cmd.del_vbus.bus_no = bus_no; - if (!virt_control_chan_func) - return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; - - if (!virt_control_chan_func(&cmd)) - return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR; - - /* finally, remove the bus from the list */ -remove: - write_lock(&bus_list_lock); - if (prev) /* not at head */ - prev->next = bus->next; - else - bus_list = bus->next; - bus_list_count--; - write_unlock(&bus_list_lock); - - if (bus->bus_channel) { - uislib_iounmap(bus->bus_channel); - bus->bus_channel = NULL; - } - - kfree(bus); - return CONTROLVM_RESP_SUCCESS; -} - -static int create_device(struct controlvm_message *msg, char *buf) -{ - struct device_info *dev; - struct bus_info *bus; - struct guest_msgs cmd; - u32 bus_no, dev_no; - int result = CONTROLVM_RESP_SUCCESS; - u64 min_size = MIN_IO_CHANNEL_SIZE; - struct req_handler_info *req_handler; - - bus_no = msg->cmd.create_device.bus_no; - dev_no = msg->cmd.create_device.dev_no; - - POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no, - POSTCODE_SEVERITY_INFO); - - dev = kzalloc(sizeof(*dev), GFP_ATOMIC); - if (!dev) { - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, - POSTCODE_SEVERITY_ERR); - return CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - } - - dev->channel_uuid = msg->cmd.create_device.data_type_uuid; - dev->intr = msg->cmd.create_device.intr; - dev->channel_addr = msg->cmd.create_device.channel_addr; - dev->bus_no = bus_no; - dev->dev_no = dev_no; - sema_init(&dev->interrupt_callback_lock, 1); /* unlocked */ - sprintf(dev->devid, "vbus%u:dev%u", (unsigned)bus_no, (unsigned)dev_no); - /* map the channel memory for the device. */ - if (msg->hdr.flags.test_message) { - dev->chanptr = (void __iomem *)__va(dev->channel_addr); - } else { - req_handler = req_handler_find(dev->channel_uuid); - if (req_handler) - /* generic service handler registered for this - * channel - */ - min_size = req_handler->min_channel_bytes; - if (min_size > msg->cmd.create_device.channel_bytes) { - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, - bus_no, POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL; - goto cleanup; - } - dev->chanptr = - uislib_ioremap_cache(dev->channel_addr, - msg->cmd.create_device.channel_bytes); - if (!dev->chanptr) { - result = CONTROLVM_RESP_ERROR_IOREMAP_FAILED; - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, - bus_no, POSTCODE_SEVERITY_ERR); - goto cleanup; - } - } - dev->instance_uuid = msg->cmd.create_device.dev_inst_uuid; - dev->channel_bytes = msg->cmd.create_device.channel_bytes; - - read_lock(&bus_list_lock); - for (bus = bus_list; bus; bus = bus->next) { - if (bus->bus_no != bus_no) - continue; - /* make sure the device number is valid */ - if (dev_no >= bus->device_count) { - result = CONTROLVM_RESP_ERROR_MAX_DEVICES; - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, - bus_no, POSTCODE_SEVERITY_ERR); - read_unlock(&bus_list_lock); - goto cleanup; - } - /* make sure this device is not already set */ - if (bus->device[dev_no]) { - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, - dev_no, bus_no, - POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_ALREADY_DONE; - read_unlock(&bus_list_lock); - goto cleanup; - } - read_unlock(&bus_list_lock); - /* the msg is bound for virtpci; send - * guest_msgs struct to callback - */ - if (msg->hdr.flags.server) { - bus->device[dev_no] = dev; - POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, dev_no, - bus_no, POSTCODE_SEVERITY_INFO); - return CONTROLVM_RESP_SUCCESS; - } - if (uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid) == 0) { - wait_for_valid_guid(&((struct channel_header __iomem *) - (dev->chanptr))->chtype); - if (!SPAR_VHBA_CHANNEL_OK_CLIENT(dev->chanptr)) { - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, - dev_no, bus_no, - POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID; - goto cleanup; - } - cmd.msgtype = GUEST_ADD_VHBA; - cmd.add_vhba.chanptr = dev->chanptr; - cmd.add_vhba.bus_no = bus_no; - cmd.add_vhba.device_no = dev_no; - cmd.add_vhba.instance_uuid = dev->instance_uuid; - cmd.add_vhba.intr = dev->intr; - } else if (uuid_le_cmp(dev->channel_uuid, - spar_vnic_channel_protocol_uuid) == 0) { - wait_for_valid_guid(&((struct channel_header __iomem *) - (dev->chanptr))->chtype); - if (!SPAR_VNIC_CHANNEL_OK_CLIENT(dev->chanptr)) { - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, - dev_no, bus_no, - POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID; - goto cleanup; - } - cmd.msgtype = GUEST_ADD_VNIC; - cmd.add_vnic.chanptr = dev->chanptr; - cmd.add_vnic.bus_no = bus_no; - cmd.add_vnic.device_no = dev_no; - cmd.add_vnic.instance_uuid = dev->instance_uuid; - cmd.add_vhba.intr = dev->intr; - } else { - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, - bus_no, POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN; - goto cleanup; - } - - if (!virt_control_chan_func) { - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, - bus_no, POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; - goto cleanup; - } - - if (!virt_control_chan_func(&cmd)) { - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, - bus_no, POSTCODE_SEVERITY_ERR); - result = - CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR; - goto cleanup; - } - - bus->device[dev_no] = dev; - POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, dev_no, - bus_no, POSTCODE_SEVERITY_INFO); - return CONTROLVM_RESP_SUCCESS; - } - read_unlock(&bus_list_lock); - - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, - POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_BUS_INVALID; - -cleanup: - if (!msg->hdr.flags.test_message) { - uislib_iounmap(dev->chanptr); - dev->chanptr = NULL; - } - - kfree(dev); - return result; -} - -static int pause_device(struct controlvm_message *msg) -{ - u32 bus_no, dev_no; - struct bus_info *bus; - struct device_info *dev; - struct guest_msgs cmd; - int retval = CONTROLVM_RESP_SUCCESS; - - bus_no = msg->cmd.device_change_state.bus_no; - dev_no = msg->cmd.device_change_state.dev_no; - - read_lock(&bus_list_lock); - for (bus = bus_list; bus; bus = bus->next) { - if (bus->bus_no == bus_no) { - /* make sure the device number is valid */ - if (dev_no >= bus->device_count) { - retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID; - } else { - /* make sure this device exists */ - dev = bus->device[dev_no]; - if (!dev) { - retval = - CONTROLVM_RESP_ERROR_ALREADY_DONE; - } - } - break; - } - } - if (!bus) - retval = CONTROLVM_RESP_ERROR_BUS_INVALID; - - read_unlock(&bus_list_lock); - if (retval == CONTROLVM_RESP_SUCCESS) { - /* the msg is bound for virtpci; send - * guest_msgs struct to callback - */ - if (uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid) == 0) { - cmd.msgtype = GUEST_PAUSE_VHBA; - cmd.pause_vhba.chanptr = dev->chanptr; - } else if (uuid_le_cmp(dev->channel_uuid, - spar_vnic_channel_protocol_uuid) == 0) { - cmd.msgtype = GUEST_PAUSE_VNIC; - cmd.pause_vnic.chanptr = dev->chanptr; - } else { - return CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN; - } - if (!virt_control_chan_func) - return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; - if (!virt_control_chan_func(&cmd)) { - return - CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR; - } - } - return retval; -} - -static int resume_device(struct controlvm_message *msg) -{ - u32 bus_no, dev_no; - struct bus_info *bus; - struct device_info *dev; - struct guest_msgs cmd; - int retval = CONTROLVM_RESP_SUCCESS; - - bus_no = msg->cmd.device_change_state.bus_no; - dev_no = msg->cmd.device_change_state.dev_no; - - read_lock(&bus_list_lock); - for (bus = bus_list; bus; bus = bus->next) { - if (bus->bus_no == bus_no) { - /* make sure the device number is valid */ - if (dev_no >= bus->device_count) { - retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID; - } else { - /* make sure this device exists */ - dev = bus->device[dev_no]; - if (!dev) { - retval = - CONTROLVM_RESP_ERROR_ALREADY_DONE; - } - } - break; - } - } - - if (!bus) - retval = CONTROLVM_RESP_ERROR_BUS_INVALID; - - read_unlock(&bus_list_lock); - /* the msg is bound for virtpci; send - * guest_msgs struct to callback - */ - if (retval == CONTROLVM_RESP_SUCCESS) { - if (uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid) == 0) { - cmd.msgtype = GUEST_RESUME_VHBA; - cmd.resume_vhba.chanptr = dev->chanptr; - } else if (uuid_le_cmp(dev->channel_uuid, - spar_vnic_channel_protocol_uuid) == 0) { - cmd.msgtype = GUEST_RESUME_VNIC; - cmd.resume_vnic.chanptr = dev->chanptr; - } else { - return CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN; - } - if (!virt_control_chan_func) - return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; - if (!virt_control_chan_func(&cmd)) { - return - CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR; - } - } - return retval; -} - -static int destroy_device(struct controlvm_message *msg, char *buf) -{ - u32 bus_no, dev_no; - struct bus_info *bus; - struct device_info *dev; - struct guest_msgs cmd; - int retval = CONTROLVM_RESP_SUCCESS; - - bus_no = msg->cmd.destroy_device.bus_no; - dev_no = msg->cmd.destroy_device.bus_no; - - read_lock(&bus_list_lock); - for (bus = bus_list; bus; bus = bus->next) { - if (bus->bus_no == bus_no) { - /* make sure the device number is valid */ - if (dev_no >= bus->device_count) { - retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID; - } else { - /* make sure this device exists */ - dev = bus->device[dev_no]; - if (!dev) { - retval = - CONTROLVM_RESP_ERROR_ALREADY_DONE; - } - } - break; - } - } - - if (!bus) - retval = CONTROLVM_RESP_ERROR_BUS_INVALID; - read_unlock(&bus_list_lock); - if (retval == CONTROLVM_RESP_SUCCESS) { - /* the msg is bound for virtpci; send - * guest_msgs struct to callback - */ - if (uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid) == 0) { - cmd.msgtype = GUEST_DEL_VHBA; - cmd.del_vhba.chanptr = dev->chanptr; - } else if (uuid_le_cmp(dev->channel_uuid, - spar_vnic_channel_protocol_uuid) == 0) { - cmd.msgtype = GUEST_DEL_VNIC; - cmd.del_vnic.chanptr = dev->chanptr; - } else { - return - CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN; - } - if (!virt_control_chan_func) { - return - CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; - } - if (!virt_control_chan_func(&cmd)) { - return - CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR; - } -/* you must disable channel interrupts BEFORE you unmap the channel, - * because if you unmap first, there may still be some activity going - * on which accesses the channel and you will get a "unable to handle - * kernel paging request" - */ - if (dev->polling) - uislib_disable_channel_interrupts(bus_no, dev_no); - /* unmap the channel memory for the device. */ - if (!msg->hdr.flags.test_message) - uislib_iounmap(dev->chanptr); - kfree(dev); - bus->device[dev_no] = NULL; - } - return retval; -} - -static int -init_chipset(struct controlvm_message *msg, char *buf) -{ - POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO); - - max_bus_count = msg->cmd.init_chipset.bus_count; - platform_no = msg->cmd.init_chipset.platform_number; - phys_data_chan = 0; - - /* We need to make sure we have our functions registered - * before processing messages. If we are a test vehicle the - * test_message for init_chipset will be set. We can ignore the - * waits for the callbacks, since this will be manually entered - * from a user. If no test_message is set, we will wait for the - * functions. - */ - if (!msg->hdr.flags.test_message) - WAIT_ON_CALLBACK(virt_control_chan_func); - - chipset_inited = 1; - POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO); - - return CONTROLVM_RESP_SUCCESS; -} - -static int delete_bus_glue(u32 bus_no) -{ - struct controlvm_message msg; - - init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0); - msg.cmd.destroy_bus.bus_no = bus_no; - if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) - return 0; - return 1; -} - -static int delete_device_glue(u32 bus_no, u32 dev_no) -{ - struct controlvm_message msg; - - init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0); - msg.cmd.destroy_device.bus_no = bus_no; - msg.cmd.destroy_device.dev_no = dev_no; - if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) - return 0; - return 1; -} - -int -uislib_client_inject_add_bus(u32 bus_no, uuid_le inst_uuid, - u64 channel_addr, ulong n_channel_bytes) -{ - struct controlvm_message msg; - - /* step 0: init the chipset */ - POSTCODE_LINUX_3(CHIPSET_INIT_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO); - - if (!chipset_inited) { - /* step: initialize the chipset */ - init_msg_header(&msg, CONTROLVM_CHIPSET_INIT, 0, 0); - /* this change is needed so that console will come up - * OK even when the bus 0 create comes in late. If the - * bus 0 create is the first create, then the add_vnic - * will work fine, but if the bus 0 create arrives - * after number 4, then the add_vnic will fail, and the - * ultraboot will fail. - */ - msg.cmd.init_chipset.bus_count = 23; - msg.cmd.init_chipset.switch_count = 0; - if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS) - return 0; - POSTCODE_LINUX_3(CHIPSET_INIT_EXIT_PC, bus_no, - POSTCODE_SEVERITY_INFO); - } - - /* step 1: create a bus */ - POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, bus_no, - POSTCODE_SEVERITY_WARNING); - init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, 0); - msg.cmd.create_bus.bus_no = bus_no; - msg.cmd.create_bus.dev_count = 23; /* devNo+1; */ - msg.cmd.create_bus.channel_addr = channel_addr; - msg.cmd.create_bus.channel_bytes = n_channel_bytes; - if (create_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) { - POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no, - POSTCODE_SEVERITY_ERR); - return 0; - } - POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO); - - return 1; -} -EXPORT_SYMBOL_GPL(uislib_client_inject_add_bus); - -int -uislib_client_inject_del_bus(u32 bus_no) -{ - return delete_bus_glue(bus_no); -} -EXPORT_SYMBOL_GPL(uislib_client_inject_del_bus); - -int -uislib_client_inject_pause_vhba(u32 bus_no, u32 dev_no) -{ - struct controlvm_message msg; - int rc; - - init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0); - msg.cmd.device_change_state.bus_no = bus_no; - msg.cmd.device_change_state.dev_no = dev_no; - msg.cmd.device_change_state.state = segment_state_standby; - rc = pause_device(&msg); - if (rc != CONTROLVM_RESP_SUCCESS) - return rc; - return 0; -} -EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vhba); - -int -uislib_client_inject_resume_vhba(u32 bus_no, u32 dev_no) -{ - struct controlvm_message msg; - int rc; - - init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0); - msg.cmd.device_change_state.bus_no = bus_no; - msg.cmd.device_change_state.dev_no = dev_no; - msg.cmd.device_change_state.state = segment_state_running; - rc = resume_device(&msg); - if (rc != CONTROLVM_RESP_SUCCESS) - return rc; - return 0; -} -EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vhba); - -int -uislib_client_inject_add_vhba(u32 bus_no, u32 dev_no, - u64 phys_chan_addr, u32 chan_bytes, - int is_test_addr, uuid_le inst_uuid, - struct irq_info *intr) -{ - struct controlvm_message msg; - - /* chipset init'ed with bus bus has been previously created - - * Verify it still exists step 2: create the VHBA device on the - * bus - */ - POSTCODE_LINUX_4(VHBA_CREATE_ENTRY_PC, dev_no, bus_no, - POSTCODE_SEVERITY_INFO); - - init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0); - if (is_test_addr) - /* signify that the physical channel address does NOT - * need to be ioremap()ed - */ - msg.hdr.flags.test_message = 1; - msg.cmd.create_device.bus_no = bus_no; - msg.cmd.create_device.dev_no = dev_no; - msg.cmd.create_device.dev_inst_uuid = inst_uuid; - if (intr) - msg.cmd.create_device.intr = *intr; - else - memset(&msg.cmd.create_device.intr, 0, - sizeof(struct irq_info)); - msg.cmd.create_device.channel_addr = phys_chan_addr; - if (chan_bytes < MIN_IO_CHANNEL_SIZE) { - POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, chan_bytes, - MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR); - return 0; - } - msg.cmd.create_device.channel_bytes = chan_bytes; - msg.cmd.create_device.data_type_uuid = spar_vhba_channel_protocol_uuid; - if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) { - POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, dev_no, bus_no, - POSTCODE_SEVERITY_ERR); - return 0; - } - POSTCODE_LINUX_4(VHBA_CREATE_SUCCESS_PC, dev_no, bus_no, - POSTCODE_SEVERITY_INFO); - return 1; -} -EXPORT_SYMBOL_GPL(uislib_client_inject_add_vhba); - -int -uislib_client_inject_del_vhba(u32 bus_no, u32 dev_no) -{ - return delete_device_glue(bus_no, dev_no); -} -EXPORT_SYMBOL_GPL(uislib_client_inject_del_vhba); - -int -uislib_client_inject_add_vnic(u32 bus_no, u32 dev_no, - u64 phys_chan_addr, u32 chan_bytes, - int is_test_addr, uuid_le inst_uuid, - struct irq_info *intr) -{ - struct controlvm_message msg; - - /* chipset init'ed with bus bus has been previously created - - * Verify it still exists step 2: create the VNIC device on the - * bus - */ - POSTCODE_LINUX_4(VNIC_CREATE_ENTRY_PC, dev_no, bus_no, - POSTCODE_SEVERITY_INFO); - - init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0); - if (is_test_addr) - /* signify that the physical channel address does NOT - * need to be ioremap()ed - */ - msg.hdr.flags.test_message = 1; - msg.cmd.create_device.bus_no = bus_no; - msg.cmd.create_device.dev_no = dev_no; - msg.cmd.create_device.dev_inst_uuid = inst_uuid; - if (intr) - msg.cmd.create_device.intr = *intr; - else - memset(&msg.cmd.create_device.intr, 0, - sizeof(struct irq_info)); - msg.cmd.create_device.channel_addr = phys_chan_addr; - if (chan_bytes < MIN_IO_CHANNEL_SIZE) { - POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, chan_bytes, - MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR); - return 0; - } - msg.cmd.create_device.channel_bytes = chan_bytes; - msg.cmd.create_device.data_type_uuid = spar_vnic_channel_protocol_uuid; - if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) { - POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, dev_no, bus_no, - POSTCODE_SEVERITY_ERR); - return 0; - } - - POSTCODE_LINUX_4(VNIC_CREATE_SUCCESS_PC, dev_no, bus_no, - POSTCODE_SEVERITY_INFO); - return 1; -} -EXPORT_SYMBOL_GPL(uislib_client_inject_add_vnic); - -int -uislib_client_inject_pause_vnic(u32 bus_no, u32 dev_no) -{ - struct controlvm_message msg; - int rc; - - init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0); - msg.cmd.device_change_state.bus_no = bus_no; - msg.cmd.device_change_state.dev_no = dev_no; - msg.cmd.device_change_state.state = segment_state_standby; - rc = pause_device(&msg); - if (rc != CONTROLVM_RESP_SUCCESS) - return -1; - return 0; -} -EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vnic); - -int -uislib_client_inject_resume_vnic(u32 bus_no, u32 dev_no) -{ - struct controlvm_message msg; - int rc; - - init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0); - msg.cmd.device_change_state.bus_no = bus_no; - msg.cmd.device_change_state.dev_no = dev_no; - msg.cmd.device_change_state.state = segment_state_running; - rc = resume_device(&msg); - if (rc != CONTROLVM_RESP_SUCCESS) - return -1; - return 0; -} -EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vnic); - -int -uislib_client_inject_del_vnic(u32 bus_no, u32 dev_no) -{ - return delete_device_glue(bus_no, dev_no); -} -EXPORT_SYMBOL_GPL(uislib_client_inject_del_vnic); - -void * -uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln) -{ - /* __GFP_NORETRY means "ok to fail", meaning kmalloc() can - * return NULL. If you do NOT specify __GFP_NORETRY, Linux - * will go to extreme measures to get memory for you (like, - * invoke oom killer), which will probably cripple the system. - */ - void *p = kmem_cache_alloc(cur_pool, GFP_ATOMIC | __GFP_NORETRY); - - if (!p) - return NULL; - return p; -} -EXPORT_SYMBOL_GPL(uislib_cache_alloc); - -void -uislib_cache_free(struct kmem_cache *cur_pool, void *p, char *fn, int ln) -{ - if (!p) - return; - kmem_cache_free(cur_pool, p); -} -EXPORT_SYMBOL_GPL(uislib_cache_free); - -/*****************************************************/ -/* proc filesystem callback functions */ -/*****************************************************/ - -#define PLINE(...) uisutil_add_proc_line_ex(&tot, buff, \ - buff_len, __VA_ARGS__) - -static int -info_debugfs_read_helper(char **buff, int *buff_len) -{ - int i, tot = 0; - struct bus_info *bus; - - if (PLINE("\nBuses:\n") < 0) - goto err_done; - - read_lock(&bus_list_lock); - for (bus = bus_list; bus; bus = bus->next) { - if (PLINE(" bus=0x%p, busNo=%d, deviceCount=%d\n", - bus, bus->bus_no, bus->device_count) < 0) - goto err_done_unlock; - - if (PLINE(" Devices:\n") < 0) - goto err_done_unlock; - - for (i = 0; i < bus->device_count; i++) { - if (bus->device[i]) { - if (PLINE(" busNo %d, device[%i]: 0x%p, chanptr=0x%p, swtch=0x%p\n", - bus->bus_no, i, bus->device[i], - bus->device[i]->chanptr, - bus->device[i]->swtch) < 0) - goto err_done_unlock; - - if (PLINE(" first_busy_cnt=%llu, moved_to_tail_cnt=%llu, last_on_list_cnt=%llu\n", - bus->device[i]->first_busy_cnt, - bus->device[i]->moved_to_tail_cnt, - bus->device[i]->last_on_list_cnt) < 0) - goto err_done_unlock; - } - } - } - read_unlock(&bus_list_lock); - - if (PLINE("UisUtils_Registered_Services: %d\n", - atomic_read(&uisutils_registered_services)) < 0) - goto err_done; - if (PLINE("cycles_before_wait %llu wait_cycles:%llu\n", - cycles_before_wait, wait_cycles) < 0) - goto err_done; - if (PLINE("tot_wakeup_cnt %llu:tot_wait_cnt %llu:tot_schedule_cnt %llu\n", - tot_wakeup_cnt, tot_wait_cnt, tot_schedule_cnt) < 0) - goto err_done; - if (PLINE("en_smart_wakeup %d\n", en_smart_wakeup) < 0) - goto err_done; - if (PLINE("tot_moved_to_tail_cnt %llu\n", tot_moved_to_tail_cnt) < 0) - goto err_done; - - return tot; - -err_done_unlock: - read_unlock(&bus_list_lock); -err_done: - return -1; -} - -static ssize_t info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset) -{ - char *temp; - int total_bytes = 0; - int remaining_bytes = PROC_READ_BUFFER_SIZE; - -/* *start = buf; */ - if (!debug_buf) { - debug_buf = vmalloc(PROC_READ_BUFFER_SIZE); - - if (!debug_buf) - return -ENOMEM; - } - - temp = debug_buf; - - if ((*offset == 0) || (!debug_buf_valid)) { - /* if the read fails, then -1 will be returned */ - total_bytes = info_debugfs_read_helper(&temp, &remaining_bytes); - debug_buf_valid = 1; - } else { - total_bytes = strlen(debug_buf); - } - - return simple_read_from_buffer(buf, len, offset, - debug_buf, total_bytes); -} - -static struct device_info *find_dev(u32 bus_no, u32 dev_no) -{ - struct bus_info *bus; - struct device_info *dev = NULL; - - read_lock(&bus_list_lock); - for (bus = bus_list; bus; bus = bus->next) { - if (bus->bus_no == bus_no) { - /* make sure the device number is valid */ - if (dev_no >= bus->device_count) - break; - dev = bus->device[dev_no]; - break; - } - } - read_unlock(&bus_list_lock); - return dev; -} - -/* This thread calls the "interrupt" function for each device that has - * enabled such using uislib_enable_channel_interrupts(). The "interrupt" - * function typically reads and processes the devices's channel input - * queue. This thread repeatedly does this, until the thread is told to stop - * (via uisthread_stop()). Sleeping rules: - * - If we have called the "interrupt" function for all devices, and all of - * them have reported "nothing processed" (returned 0), then we will go to - * sleep for a maximum of POLLJIFFIES_NORMAL jiffies. - * - If anyone calls uislib_force_channel_interrupt(), the above jiffy - * sleep will be interrupted, and we will resume calling the "interrupt" - * function for all devices. - * - The list of devices is dynamically re-ordered in order to - * attempt to preserve fairness. Whenever we spin thru the list of - * devices and call the dev->interrupt() function, if we find - * devices which report that there is still more work to do, the - * the first such device we find is moved to the end of the device - * list. This ensures that extremely busy devices don't starve out - * less-busy ones. - * - */ -static int process_incoming(void *v) -{ - unsigned long long cur_cycles, old_cycles, idle_cycles, delta_cycles; - struct list_head *new_tail = NULL; - int i; - - UIS_DAEMONIZE("dev_incoming"); - for (i = 0; i < 16; i++) { - old_cycles = get_cycles(); - wait_event_timeout(poll_dev_wake_q, - 0, POLLJIFFIES_NORMAL); - cur_cycles = get_cycles(); - if (wait_cycles == 0) { - wait_cycles = (cur_cycles - old_cycles); - } else { - if (wait_cycles < (cur_cycles - old_cycles)) - wait_cycles = (cur_cycles - old_cycles); - } - } - cycles_before_wait = wait_cycles; - idle_cycles = 0; - poll_dev_start = 0; - while (1) { - struct list_head *lelt, *tmp; - struct device_info *dev = NULL; - - /* poll each channel for input */ - down(&poll_dev_lock); - new_tail = NULL; - list_for_each_safe(lelt, tmp, &poll_dev_chan) { - int rc = 0; - - dev = list_entry(lelt, struct device_info, - list_polling_device_channels); - down(&dev->interrupt_callback_lock); - if (dev->interrupt) - rc = dev->interrupt(dev->interrupt_context); - else - continue; - up(&dev->interrupt_callback_lock); - if (rc) { - /* dev->interrupt returned, but there - * is still more work to do. - * Reschedule work to occur as soon as - * possible. */ - idle_cycles = 0; - if (!new_tail) { - dev->first_busy_cnt++; - if (! - (list_is_last - (lelt, - &poll_dev_chan))) { - new_tail = lelt; - dev->moved_to_tail_cnt++; - } else { - dev->last_on_list_cnt++; - } - } - } - if (kthread_should_stop()) - break; - } - if (new_tail) { - tot_moved_to_tail_cnt++; - list_move_tail(new_tail, &poll_dev_chan); - } - up(&poll_dev_lock); - cur_cycles = get_cycles(); - delta_cycles = cur_cycles - old_cycles; - old_cycles = cur_cycles; - - /* At this point, we have scanned thru all of the - * channels, and at least one of the following is true: - * - there is no input waiting on any of the channels - * - we have received a signal to stop this thread - */ - if (kthread_should_stop()) - break; - if (en_smart_wakeup == 0xFF) - break; - /* wait for POLLJIFFIES_NORMAL jiffies, or until - * someone wakes up poll_dev_wake_q, - * whichever comes first only do a wait when we have - * been idle for cycles_before_wait cycles. - */ - if (idle_cycles > cycles_before_wait) { - poll_dev_start = 0; - tot_wait_cnt++; - wait_event_timeout(poll_dev_wake_q, - poll_dev_start, - POLLJIFFIES_NORMAL); - poll_dev_start = 1; - } else { - tot_schedule_cnt++; - schedule(); - idle_cycles = idle_cycles + delta_cycles; - } - } - complete_and_exit(&incoming_ti.has_stopped, 0); -} - -static BOOL -initialize_incoming_thread(void) -{ - if (incoming_started) - return TRUE; - if (!uisthread_start(&incoming_ti, - &process_incoming, NULL, "dev_incoming")) { - return FALSE; - } - incoming_started = TRUE; - return TRUE; -} - -/* Add a new device/channel to the list being processed by - * process_incoming(). - * - indicates the function to call periodically. - * - indicates the data to pass to the - * function. - */ -void -uislib_enable_channel_interrupts(u32 bus_no, u32 dev_no, - int (*interrupt)(void *), - void *interrupt_context) -{ - struct device_info *dev; - - dev = find_dev(bus_no, dev_no); - if (!dev) - return; - - down(&poll_dev_lock); - initialize_incoming_thread(); - dev->interrupt = interrupt; - dev->interrupt_context = interrupt_context; - dev->polling = TRUE; - list_add_tail(&dev->list_polling_device_channels, - &poll_dev_chan); - up(&poll_dev_lock); -} -EXPORT_SYMBOL_GPL(uislib_enable_channel_interrupts); - -/* Remove a device/channel from the list being processed by - * process_incoming(). - */ -void -uislib_disable_channel_interrupts(u32 bus_no, u32 dev_no) -{ - struct device_info *dev; - - dev = find_dev(bus_no, dev_no); - if (!dev) - return; - down(&poll_dev_lock); - list_del(&dev->list_polling_device_channels); - dev->polling = FALSE; - dev->interrupt = NULL; - up(&poll_dev_lock); -} -EXPORT_SYMBOL_GPL(uislib_disable_channel_interrupts); - -static void -do_wakeup_polling_device_channels(struct work_struct *dummy) -{ - if (!poll_dev_start) { - poll_dev_start = 1; - wake_up(&poll_dev_wake_q); - } -} - -static DECLARE_WORK(work_wakeup_polling_device_channels, - do_wakeup_polling_device_channels); - -/* Call this function when you want to send a hint to process_incoming() that - * your device might have more requests. - */ -void -uislib_force_channel_interrupt(u32 bus_no, u32 dev_no) -{ - if (en_smart_wakeup == 0) - return; - if (poll_dev_start) - return; - /* The point of using schedule_work() instead of just doing - * the work inline is to force a slight delay before waking up - * the process_incoming() thread. - */ - tot_wakeup_cnt++; - schedule_work(&work_wakeup_polling_device_channels); -} -EXPORT_SYMBOL_GPL(uislib_force_channel_interrupt); - -/*****************************************************/ -/* Module Init & Exit functions */ -/*****************************************************/ - -static int __init -uislib_mod_init(void) -{ - if (!unisys_spar_platform) - return -ENODEV; - - /* initialize global pointers to NULL */ - bus_list = NULL; - bus_list_count = 0; - max_bus_count = 0; - rwlock_init(&bus_list_lock); - virt_control_chan_func = NULL; - - /* Issue VMCALL_GET_CONTROLVM_ADDR to get CtrlChanPhysAddr and - * then map this physical address to a virtual address. */ - POSTCODE_LINUX_2(DRIVER_ENTRY_PC, POSTCODE_SEVERITY_INFO); - - dir_debugfs = debugfs_create_dir(DIR_DEBUGFS_ENTRY, NULL); - if (dir_debugfs) { - info_debugfs_entry = debugfs_create_file( - INFO_DEBUGFS_ENTRY_FN, 0444, dir_debugfs, NULL, - &debugfs_info_fops); - - platformnumber_debugfs_read = debugfs_create_u32( - PLATFORMNUMBER_DEBUGFS_ENTRY_FN, 0444, dir_debugfs, - &platform_no); - - cycles_before_wait_debugfs_read = debugfs_create_u64( - CYCLES_BEFORE_WAIT_DEBUGFS_ENTRY_FN, 0666, dir_debugfs, - &cycles_before_wait); - - smart_wakeup_debugfs_entry = debugfs_create_bool( - SMART_WAKEUP_DEBUGFS_ENTRY_FN, 0666, dir_debugfs, - &en_smart_wakeup); - } - - POSTCODE_LINUX_3(DRIVER_EXIT_PC, 0, POSTCODE_SEVERITY_INFO); - return 0; -} - -static void __exit -uislib_mod_exit(void) -{ - if (debug_buf) { - vfree(debug_buf); - debug_buf = NULL; - } - - debugfs_remove(info_debugfs_entry); - debugfs_remove(smart_wakeup_debugfs_entry); - debugfs_remove(cycles_before_wait_debugfs_read); - debugfs_remove(platformnumber_debugfs_read); - debugfs_remove(dir_debugfs); -} - -module_init(uislib_mod_init); -module_exit(uislib_mod_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Usha Srinivasan"); -MODULE_ALIAS("uislib"); - /* this is extracted during depmod and kept in modules.dep */ diff --git a/drivers/staging/unisys/uislib/uisqueue.c b/drivers/staging/unisys/uislib/uisqueue.c deleted file mode 100644 index d46dd7428a30ab..00000000000000 --- a/drivers/staging/unisys/uislib/uisqueue.c +++ /dev/null @@ -1,322 +0,0 @@ -/* uisqueue.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* @ALL_INSPECTED */ -#include -#include - -#include "uisutils.h" - -/* this is shorter than using __FILE__ (full path name) in - * debug/info/error messages */ -#define CURRENT_FILE_PC UISLIB_PC_uisqueue_c -#define __MYFILE__ "uisqueue.c" - -#define CHECK_CACHE_ALIGN 0 - -/*****************************************************/ -/* Exported functions */ -/*****************************************************/ - -/* - * Routine Description: - * Tries to insert the prebuilt signal pointed to by pSignal into the nth - * Queue of the Channel pointed to by pChannel - * - * Parameters: - * pChannel: (IN) points to the IO Channel - * Queue: (IN) nth Queue of the IO Channel - * pSignal: (IN) pointer to the signal - * - * Assumptions: - * - pChannel, Queue and pSignal are valid. - * - If insertion fails due to a full queue, the caller will determine the - * retry policy (e.g. wait & try again, report an error, etc.). - * - * Return value: - * 1 if the insertion succeeds, 0 if the queue was full. - */ -unsigned char spar_signal_insert(struct channel_header __iomem *ch, u32 queue, - void *sig) -{ - void __iomem *psignal; - unsigned int head, tail, nof; - - struct signal_queue_header __iomem *pqhdr = - (struct signal_queue_header __iomem *) - ((char __iomem *)ch + readq(&ch->ch_space_offset)) - + queue; - - /* capture current head and tail */ - head = readl(&pqhdr->head); - tail = readl(&pqhdr->tail); - - /* queue is full if (head + 1) % n equals tail */ - if (((head + 1) % readl(&pqhdr->max_slots)) == tail) { - nof = readq(&pqhdr->num_overflows) + 1; - writeq(nof, &pqhdr->num_overflows); - return 0; - } - - /* increment the head index */ - head = (head + 1) % readl(&pqhdr->max_slots); - - /* copy signal to the head location from the area pointed to - * by pSignal - */ - psignal = (char __iomem *)pqhdr + readq(&pqhdr->sig_base_offset) + - (head * readl(&pqhdr->signal_size)); - memcpy_toio(psignal, sig, readl(&pqhdr->signal_size)); - - mb(); /* channel synch */ - writel(head, &pqhdr->head); - - writeq(readq(&pqhdr->num_sent) + 1, &pqhdr->num_sent); - return 1; -} -EXPORT_SYMBOL_GPL(spar_signal_insert); - -/* - * Routine Description: - * Removes one signal from Channel pChannel's nth Queue at the - * time of the call and copies it into the memory pointed to by - * pSignal. - * - * Parameters: - * pChannel: (IN) points to the IO Channel - * Queue: (IN) nth Queue of the IO Channel - * pSignal: (IN) pointer to where the signals are to be copied - * - * Assumptions: - * - pChannel and Queue are valid. - * - pSignal points to a memory area large enough to hold queue's SignalSize - * - * Return value: - * 1 if the removal succeeds, 0 if the queue was empty. - */ -unsigned char -spar_signal_remove(struct channel_header __iomem *ch, u32 queue, void *sig) -{ - void __iomem *psource; - unsigned int head, tail; - struct signal_queue_header __iomem *pqhdr = - (struct signal_queue_header __iomem *)((char __iomem *)ch + - readq(&ch->ch_space_offset)) + queue; - - /* capture current head and tail */ - head = readl(&pqhdr->head); - tail = readl(&pqhdr->tail); - - /* queue is empty if the head index equals the tail index */ - if (head == tail) { - writeq(readq(&pqhdr->num_empty) + 1, &pqhdr->num_empty); - return 0; - } - - /* advance past the 'empty' front slot */ - tail = (tail + 1) % readl(&pqhdr->max_slots); - - /* copy signal from tail location to the area pointed to by pSignal */ - psource = (char __iomem *)pqhdr + readq(&pqhdr->sig_base_offset) + - (tail * readl(&pqhdr->signal_size)); - memcpy_fromio(sig, psource, readl(&pqhdr->signal_size)); - - mb(); /* channel synch */ - writel(tail, &pqhdr->tail); - - writeq(readq(&pqhdr->num_received) + 1, - &pqhdr->num_received); - return 1; -} -EXPORT_SYMBOL_GPL(spar_signal_remove); - -/* - * Routine Description: - * Removes all signals present in Channel pChannel's nth Queue at the - * time of the call and copies them into the memory pointed to by - * pSignal. Returns the # of signals copied as the value of the routine. - * - * Parameters: - * pChannel: (IN) points to the IO Channel - * Queue: (IN) nth Queue of the IO Channel - * pSignal: (IN) pointer to where the signals are to be copied - * - * Assumptions: - * - pChannel and Queue are valid. - * - pSignal points to a memory area large enough to hold Queue's MaxSignals - * # of signals, each of which is Queue's SignalSize. - * - * Return value: - * # of signals copied. - */ -unsigned int spar_signal_remove_all(struct channel_header *ch, u32 queue, - void *sig) -{ - void *psource; - unsigned int head, tail, count = 0; - struct signal_queue_header *pqhdr = - (struct signal_queue_header *)((char *)ch + - ch->ch_space_offset) + queue; - - /* capture current head and tail */ - head = pqhdr->head; - tail = pqhdr->tail; - - /* queue is empty if the head index equals the tail index */ - if (head == tail) - return 0; - - while (head != tail) { - /* advance past the 'empty' front slot */ - tail = (tail + 1) % pqhdr->max_slots; - - /* copy signal from tail location to the area pointed - * to by pSignal - */ - psource = - (char *)pqhdr + pqhdr->sig_base_offset + - (tail * pqhdr->signal_size); - memcpy((char *)sig + (pqhdr->signal_size * count), - psource, pqhdr->signal_size); - - mb(); /* channel synch */ - pqhdr->tail = tail; - - count++; - pqhdr->num_received++; - } - - return count; -} - -/* - * Routine Description: - * Determine whether a signal queue is empty. - * - * Parameters: - * pChannel: (IN) points to the IO Channel - * Queue: (IN) nth Queue of the IO Channel - * - * Return value: - * 1 if the signal queue is empty, 0 otherwise. - */ -unsigned char spar_signalqueue_empty(struct channel_header __iomem *ch, - u32 queue) -{ - struct signal_queue_header __iomem *pqhdr = - (struct signal_queue_header __iomem *)((char __iomem *)ch + - readq(&ch->ch_space_offset)) + queue; - return readl(&pqhdr->head) == readl(&pqhdr->tail); -} -EXPORT_SYMBOL_GPL(spar_signalqueue_empty); - -unsigned long long -uisqueue_interlocked_or(unsigned long long __iomem *tgt, - unsigned long long set) -{ - unsigned long long i; - unsigned long long j; - - j = readq(tgt); - do { - i = j; - j = cmpxchg((__force unsigned long long *)tgt, i, i | set); - - } while (i != j); - - return j; -} -EXPORT_SYMBOL_GPL(uisqueue_interlocked_or); - -unsigned long long -uisqueue_interlocked_and(unsigned long long __iomem *tgt, - unsigned long long set) -{ - unsigned long long i; - unsigned long long j; - - j = readq(tgt); - do { - i = j; - j = cmpxchg((__force unsigned long long *)tgt, i, i & set); - - } while (i != j); - - return j; -} -EXPORT_SYMBOL_GPL(uisqueue_interlocked_and); - -static u8 -do_locked_client_insert(struct uisqueue_info *queueinfo, - unsigned int whichqueue, - void *signal, - spinlock_t *lock, - u8 *channel_id) -{ - unsigned long flags; - u8 rc = 0; - - spin_lock_irqsave(lock, flags); - if (!spar_channel_client_acquire_os(queueinfo->chan, channel_id)) - goto unlock; - if (spar_signal_insert(queueinfo->chan, whichqueue, signal)) { - queueinfo->packets_sent++; - rc = 1; - } - spar_channel_client_release_os(queueinfo->chan, channel_id); -unlock: - spin_unlock_irqrestore((spinlock_t *)lock, flags); - return rc; -} - -int -uisqueue_put_cmdrsp_with_lock_client(struct uisqueue_info *queueinfo, - struct uiscmdrsp *cmdrsp, - unsigned int whichqueue, - void *insertlock, - unsigned char issue_irq_if_empty, - u64 irq_handle, - char oktowait, u8 *channel_id) -{ - while (!do_locked_client_insert(queueinfo, whichqueue, cmdrsp, - (spinlock_t *)insertlock, - channel_id)) { - if (oktowait != OK_TO_WAIT) - return 0; /* failed to queue */ - - /* try again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(10)); - } - return 1; -} -EXPORT_SYMBOL_GPL(uisqueue_put_cmdrsp_with_lock_client); - -/* uisqueue_get_cmdrsp gets the cmdrsp entry at the head of the queue - * returns NULL if queue is empty */ -int -uisqueue_get_cmdrsp(struct uisqueue_info *queueinfo, - void *cmdrsp, unsigned int whichqueue) -{ - if (!spar_signal_remove(queueinfo->chan, whichqueue, cmdrsp)) - return 0; - - queueinfo->packets_received++; - - return 1; /* Success */ -} -EXPORT_SYMBOL_GPL(uisqueue_get_cmdrsp); diff --git a/drivers/staging/unisys/uislib/uisthread.c b/drivers/staging/unisys/uislib/uisthread.c deleted file mode 100644 index d3c973b617ee7f..00000000000000 --- a/drivers/staging/unisys/uislib/uisthread.c +++ /dev/null @@ -1,69 +0,0 @@ -/* uisthread.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* @ALL_INSPECTED */ -#include -#include -#include -#include -#include "uisutils.h" -#include "uisthread.h" - -/* this is shorter than using __FILE__ (full path name) in - * debug/info/error messages - */ -#define CURRENT_FILE_PC UISLIB_PC_uisthread_c -#define __MYFILE__ "uisthread.c" - -/*****************************************************/ -/* Exported functions */ -/*****************************************************/ - -/* returns 0 for failure, 1 for success */ -int -uisthread_start(struct uisthread_info *thrinfo, - int (*threadfn)(void *), void *thrcontext, char *name) -{ - /* used to stop the thread */ - init_completion(&thrinfo->has_stopped); - thrinfo->task = kthread_run(threadfn, thrcontext, name); - if (IS_ERR(thrinfo->task)) { - thrinfo->id = 0; - return 0; /* failure */ - } - thrinfo->id = thrinfo->task->pid; - return 1; -} -EXPORT_SYMBOL_GPL(uisthread_start); - -void -uisthread_stop(struct uisthread_info *thrinfo) -{ - int stopped = 0; - - if (thrinfo->id == 0) - return; /* thread not running */ - - kthread_stop(thrinfo->task); - /* give up if the thread has NOT died in 1 minute */ - if (wait_for_completion_timeout(&thrinfo->has_stopped, 60 * HZ)) - stopped = 1; - - if (stopped) - thrinfo->id = 0; -} -EXPORT_SYMBOL_GPL(uisthread_stop); diff --git a/drivers/staging/unisys/uislib/uisutils.c b/drivers/staging/unisys/uislib/uisutils.c deleted file mode 100644 index 26ab7652681371..00000000000000 --- a/drivers/staging/unisys/uislib/uisutils.c +++ /dev/null @@ -1,137 +0,0 @@ -/* uisutils.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#include -#include -#include -#include -#include -#include -#include "uisutils.h" -#include "version.h" -#include "vbushelper.h" -#include -#ifdef CONFIG_HIGHMEM -#include -#endif - -/* this is shorter than using __FILE__ (full path name) in - * debug/info/error messages - */ -#define CURRENT_FILE_PC UISLIB_PC_uisutils_c -#define __MYFILE__ "uisutils.c" - -/* exports */ -atomic_t uisutils_registered_services = ATOMIC_INIT(0); - /* num registrations via - * uisctrl_register_req_handler() or - * uisctrl_register_req_handler_ex() */ - -/*****************************************************/ -/* Utility functions */ -/*****************************************************/ - -int -uisutil_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining, - char *format, ...) -{ - va_list args; - int len; - - va_start(args, format); - len = vsnprintf(*buffer, *buffer_remaining, format, args); - va_end(args); - if (len >= *buffer_remaining) { - *buffer += *buffer_remaining; - *total += *buffer_remaining; - *buffer_remaining = 0; - return -1; - } - *buffer_remaining -= len; - *buffer += len; - *total += len; - return len; -} -EXPORT_SYMBOL_GPL(uisutil_add_proc_line_ex); - -int -uisctrl_register_req_handler(int type, void *fptr, - struct ultra_vbus_deviceinfo *chipset_driver_info) -{ - switch (type) { - case 2: - if (fptr) { - if (!virt_control_chan_func) - atomic_inc(&uisutils_registered_services); - virt_control_chan_func = fptr; - } else { - if (virt_control_chan_func) - atomic_dec(&uisutils_registered_services); - virt_control_chan_func = NULL; - } - break; - - default: - return 0; - } - if (chipset_driver_info) - bus_device_info_init(chipset_driver_info, "chipset", "uislib", - VERSION, NULL); - - return 1; -} -EXPORT_SYMBOL_GPL(uisctrl_register_req_handler); - -/* - * unsigned int uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx, - * void *skb_in, - * unsigned int firstfraglen, - * unsigned int frags_max, - * struct phys_info frags[]) - * - * calling_ctx - input - a string that is displayed to show - * who called * this func - * void *skb_in - skb whose frag info we're copying type is hidden so we - * don't need to include skbbuff in uisutils.h which is - * included in non-networking code. - * unsigned int firstfraglen - input - length of first fragment in skb - * unsigned int frags_max - input - max len of frags array - * struct phys_info frags[] - output - frags array filled in on output - * return value indicates number of - * entries filled in frags - */ - -static LIST_HEAD(req_handler_info_list); /* list of struct req_handler_info */ -static DEFINE_SPINLOCK(req_handler_info_list_lock); - -struct req_handler_info * -req_handler_find(uuid_le switch_uuid) -{ - struct list_head *lelt, *tmp; - struct req_handler_info *entry = NULL; - - spin_lock(&req_handler_info_list_lock); - list_for_each_safe(lelt, tmp, &req_handler_info_list) { - entry = list_entry(lelt, struct req_handler_info, list_link); - if (uuid_le_cmp(entry->switch_uuid, switch_uuid) == 0) { - spin_unlock(&req_handler_info_list_lock); - return entry; - } - } - spin_unlock(&req_handler_info_list_lock); - return NULL; -} From afe11f108a6290fc03fc6028246a9759a3db104d Mon Sep 17 00:00:00 2001 From: Charlie Wong Super <1213charlie@gmail.com> Date: Sat, 4 Apr 2015 19:30:28 +0800 Subject: [PATCH 0435/3798] staging: fbtft: Replace spaces to tab Spaces at the start of the line, replace the leading space to tabs Signed-off-by: Charlie Wong Super <1213charlie@gmail.com> Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_st7735r.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/fbtft/fb_st7735r.c b/drivers/staging/fbtft/fb_st7735r.c index 9d874308447e05..f6522431861024 100644 --- a/drivers/staging/fbtft/fb_st7735r.c +++ b/drivers/staging/fbtft/fb_st7735r.c @@ -25,8 +25,8 @@ #include "fbtft.h" #define DRVNAME "fb_st7735r" -#define DEFAULT_GAMMA "0F 1A 0F 18 2F 28 20 22 1F 1B 23 37 00 07 02 10\n" \ - "0F 1B 0F 17 33 2C 29 2E 30 30 39 3F 00 07 03 10" +#define DEFAULT_GAMMA "0F 1A 0F 18 2F 28 20 22 1F 1B 23 37 00 07 02 10\n" \ + "0F 1B 0F 17 33 2C 29 2E 30 30 39 3F 00 07 03 10" static int default_init_sequence[] = { @@ -119,9 +119,9 @@ static int set_var(struct fbtft_par *par) /* MADCTL - Memory data access control RGB/BGR: 1. Mode selection pin SRGB - RGB H/W pin for color filter setting: 0=RGB, 1=BGR + RGB H/W pin for color filter setting: 0=RGB, 1=BGR 2. MADCTL RGB bit - RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR */ + RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR */ switch (par->info->var.rotate) { case 0: write_reg(par, 0x36, MX | MY | (par->bgr << 3)); From a94ac1590b28245225300aaca7ea2de4f3f1e296 Mon Sep 17 00:00:00 2001 From: Charlie Wong Super <1213charlie@gmail.com> Date: Sat, 4 Apr 2015 20:54:56 +0800 Subject: [PATCH 0436/3798] staging: fbtft: Add a blank line after declarations scripts/checkpatch.pl WARNING: Missing a blank line after declarations Signed-off-by: Charlie Wong Super <1213charlie@gmail.com> Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_tls8204.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/fbtft/fb_tls8204.c b/drivers/staging/fbtft/fb_tls8204.c index fcd38bf2ed79f9..5ea73b5ce45a4a 100644 --- a/drivers/staging/fbtft/fb_tls8204.c +++ b/drivers/staging/fbtft/fb_tls8204.c @@ -115,6 +115,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) for (x = 0; x < WIDTH; x++) { u8 ch = 0; + for (i = 0; i < 8*WIDTH; i += WIDTH) { ch >>= 1; if (vmem16[(y*8*WIDTH)+i+x]) From 8e1a4c7f718e5de5019cb5ce6ada657ce1b5ea89 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 24 Apr 2015 09:44:15 +0200 Subject: [PATCH 0437/3798] staging: fbtft: Disable DMA support if DMA is not available If NO_DMA=y: drivers/built-in.o: In function `fbtft_framebuffer_alloc': (.text+0xb53cae): undefined reference to `dmam_alloc_coherent' As DMA support is already optional, make it depend on HAS_DMA. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fbtft-core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index 53b748be271247..ce645213a5393b 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -47,9 +47,11 @@ static unsigned long debug; module_param(debug, ulong, 0); MODULE_PARM_DESC(debug, "override device debug level"); +#ifdef CONFIG_HAS_DMA static bool dma = true; module_param(dma, bool, 0); MODULE_PARM_DESC(dma, "Use DMA buffer"); +#endif void fbtft_dbg_hex(const struct device *dev, int groupsize, @@ -856,10 +858,13 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, #endif if (txbuflen > 0) { +#ifdef CONFIG_HAS_DMA if (dma) { dev->coherent_dma_mask = ~0; txbuf = dmam_alloc_coherent(dev, txbuflen, &par->txbuf.dma, GFP_DMA); - } else { + } else +#endif + { txbuf = devm_kzalloc(par->info->device, txbuflen, GFP_KERNEL); } if (!txbuf) From 27cbc73aac0d82490e2a6fd6838d21e8c08b0166 Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Fri, 17 Apr 2015 17:41:43 +0800 Subject: [PATCH 0438/3798] Staging: fbtft: fix header guard typo drivers/staging/fbtft/internal.h header guard tests for __LINUX_FBTFT__INTERNAL_H but then defines __LINUX_FBTFT_INTERNAL_H (only 1 underscore) and uses the same name for the #endif comment. Use the same name everywhere. Signed-off-by: Nicolas Iooss Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/fbtft/internal.h b/drivers/staging/fbtft/internal.h index f69db82891516a..eea0ec5ff4d39b 100644 --- a/drivers/staging/fbtft/internal.h +++ b/drivers/staging/fbtft/internal.h @@ -13,7 +13,7 @@ * */ -#ifndef __LINUX_FBTFT__INTERNAL_H +#ifndef __LINUX_FBTFT_INTERNAL_H #define __LINUX_FBTFT_INTERNAL_H void fbtft_sysfs_init(struct fbtft_par *par); From bd7de5cea225f85b218730eddf7476dd6260bafc Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 4 Apr 2015 16:59:30 +0200 Subject: [PATCH 0439/3798] staging: emxx_udc: test returned value Put NULL test on the result of the previous call instead on one of its arguments. A simplified version of the semantic match that finds this problem is as follows (http://coccinelle.lip6.fr/): // r@ expression *e1; expression *e2; identifier f; statement S1,S2; @@ e1 = f(...,e2,...); ( if (e1 == NULL || ...) S1 else S2 | *if (e2 == NULL || ...) S1 else S2 ) // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index fbf82bc735cff6..7de1e9ec226740 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -2998,7 +2998,7 @@ static void nbu2ss_ep_fifo_flush(struct usb_ep *_ep) } ep = container_of(_ep, struct nbu2ss_ep, ep); - if (!_ep) { + if (!ep) { pr_err("udc: %s, bad ep\n", __func__); return; } From 3e2bb64d1a142e7fd81b6821483044597cfe8717 Mon Sep 17 00:00:00 2001 From: "Gujulan Elango, Hari Prasath (H.)" Date: Thu, 23 Apr 2015 19:29:51 +0000 Subject: [PATCH 0440/3798] staging: emxx_udc : remove stray semicolon This patch removes a stray semicolon around closing brace of an if code block. Signed-off-by: Hari Prasath Gujulan Elango Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index 7de1e9ec226740..d205cbe897f0b6 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -2347,7 +2347,7 @@ static int _nbu2ss_enable_controller(struct nbu2ss_udc *udc) dev_err(udc->dev, "*** Reset Cancel failed\n"); return -EINVAL; } - }; + } #if 0 if ((system_rev & EMXX_REV_MASK) < EMXX_REV_ES3) From 94361655442effc78904039cb051228b3228e4cb Mon Sep 17 00:00:00 2001 From: "Gujulan Elango, Hari Prasath (H.)" Date: Thu, 23 Apr 2015 19:30:53 +0000 Subject: [PATCH 0441/3798] staging: emxx_udc: Remove dead code This patch removes few lines of commented code. Signed-off-by: Hari Prasath Gujulan Elango Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.c | 33 ----------------------------- 1 file changed, 33 deletions(-) diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index d205cbe897f0b6..2fd04e8129e460 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -2199,18 +2199,6 @@ static void _nbu2ss_ep0_enable(struct nbu2ss_udc *udc) _nbu2ss_writel(&udc->p_regs->EP0_INT_ENA, EP0_INT_EN_BIT); } -#if 0 -/*-------------------------------------------------------------------------*/ -static void _nbu2ss_ep0_disable(struct nbu2ss_udc *udc) -{ - _nbu2ss_bitclr(&udc->p_regs->EP0_INT_ENA, EP0_INT_EN_BIT); - - _nbu2ss_bitset(&udc->p_regs->EP0_CONTROL - , (EP0_BCLR | EP0_INAK | EP0_ONAK | EP0_BCLR)); - - _nbu2ss_bitclr(&udc->p_regs->EP0_CONTROL, EP0_AUTO); -} -#endif /*-------------------------------------------------------------------------*/ static int _nbu2ss_nuke(struct nbu2ss_udc *udc, @@ -2311,12 +2299,6 @@ static int _nbu2ss_enable_controller(struct nbu2ss_udc *udc) if (udc->udc_enabled) return 0; -#if 0 - emxx_open_clockgate(EMXX_CLK_USB1); - /* emxx_clkctrl_off(EMXX_CLKCTRL_USB1); */ - /* emxx_clkctrl_on(EMXX_CLKCTRL_USB1); */ - emxx_unreset_device(EMXX_RST_USB1); -#endif /* Reset */ @@ -2330,13 +2312,6 @@ static int _nbu2ss_enable_controller(struct nbu2ss_udc *udc) _nbu2ss_writel(&udc->p_regs->AHBSCTR, WAIT_MODE); -#if 0 - /* DMA Mode Setting */ - if ((system_rev & EMXX_REV_MASK) == EMXX_REV_ES1) { - _nbu2ss_bitset(&udc->p_regs->AHBMCTR, BURST_TYPE); - _nbu2ss_bitclr(&udc->p_regs->AHBMCTR, HTRANS_MODE); - } else -#endif _nbu2ss_writel(&udc->p_regs->AHBMCTR, HBUSREQ_MODE | HTRANS_MODE | WBURST_TYPE); @@ -2349,9 +2324,6 @@ static int _nbu2ss_enable_controller(struct nbu2ss_udc *udc) } } -#if 0 - if ((system_rev & EMXX_REV_MASK) < EMXX_REV_ES3) -#endif _nbu2ss_bitset(&udc->p_regs->UTMI_CHARACTER_1, USB_SQUSET); _nbu2ss_bitset(&udc->p_regs->USB_CONTROL, (INT_SEL | SOF_RCV)); @@ -2383,11 +2355,6 @@ static void _nbu2ss_disable_controller(struct nbu2ss_udc *udc) _nbu2ss_reset_controller(udc); _nbu2ss_bitset(&udc->p_regs->EPCTR, (DIRPD | EPC_RST)); } -#if 0 - emxx_reset_device(EMXX_RST_USB1); - /* emxx_clkctrl_on(EMXX_CLKCTRL_USB1); */ - emxx_close_clockgate(EMXX_CLK_USB1); -#endif } /*-------------------------------------------------------------------------*/ From aeda3b2d4a6760bda799feeaac391a7bdcdbbdb5 Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 8 Apr 2015 20:24:43 +0100 Subject: [PATCH 0442/3798] iio: example code is buggy Shock horror, example template code that has never been used in reality is in fact a hazard. This fixes the obvious bug, probably these kind of "examples" should be deleted so real (working) examples are followed. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/iio_simple_dummy_events.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c index a5cd3bb219fe78..c32ef78d8e5f38 100644 --- a/drivers/staging/iio/iio_simple_dummy_events.c +++ b/drivers/staging/iio/iio_simple_dummy_events.c @@ -84,6 +84,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, default: return -EINVAL; } + break; case IIO_STEPS: switch (type) { case IIO_EV_TYPE_CHANGE: @@ -92,6 +93,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, default: return -EINVAL; } + break; default: return -EINVAL; } From 32b249b0f54fb304c5f90be00ebcb9c1a32d415c Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 6 Apr 2015 21:19:48 +0100 Subject: [PATCH 0443/3798] staging: vt6655: device_intr check for vif on while loop vif should never be or go null while in loop. Fixes race condition where interrupts are late and when interface is not present. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device_main.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 4bb4f8ee41321a..5b3de43bde99d3 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1090,7 +1090,7 @@ static irqreturn_t device_intr(int irq, void *dev_instance) * update ISR counter */ STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic, dwMIBCounter); - while (pDevice->dwIsr != 0) { + while (pDevice->dwIsr && pDevice->vif) { STAvUpdateIsrStatCounter(&pDevice->scStatistic, pDevice->dwIsr); MACvWriteISR(pDevice->PortOffset, pDevice->dwIsr); @@ -1102,8 +1102,7 @@ static irqreturn_t device_intr(int irq, void *dev_instance) } if (pDevice->dwIsr & ISR_TBTT) { - if (pDevice->vif && - pDevice->op_mode != NL80211_IFTYPE_ADHOC) + if (pDevice->op_mode != NL80211_IFTYPE_ADHOC) vnt_check_bb_vga(pDevice); pDevice->bBeaconSent = false; @@ -1143,19 +1142,15 @@ static irqreturn_t device_intr(int irq, void *dev_instance) max_count += device_tx_srv(pDevice, TYPE_AC0DMA); if (pDevice->dwIsr & ISR_SOFTTIMER1) { - if (pDevice->vif) { - if (pDevice->vif->bss_conf.enable_beacon) - vnt_beacon_make(pDevice, pDevice->vif); - } + if (pDevice->vif->bss_conf.enable_beacon) + vnt_beacon_make(pDevice, pDevice->vif); } /* If both buffers available wake the queue */ - if (pDevice->vif) { - if (AVAIL_TD(pDevice, TYPE_TXDMA0) && - AVAIL_TD(pDevice, TYPE_AC0DMA) && - ieee80211_queue_stopped(pDevice->hw, 0)) - ieee80211_wake_queues(pDevice->hw); - } + if (AVAIL_TD(pDevice, TYPE_TXDMA0) && + AVAIL_TD(pDevice, TYPE_AC0DMA) && + ieee80211_queue_stopped(pDevice->hw, 0)) + ieee80211_wake_queues(pDevice->hw); MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); From 9e3ae4f9aecffcc376a714d5088a1275054f9dbf Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:02 +0300 Subject: [PATCH 0444/3798] staging: octeon-ethernet: consolidate ndo_open functions ndo_open for rgmii, sgmii and xaui are almost identical. Put the common code in a single function. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-rgmii.c | 32 +------------------ drivers/staging/octeon/ethernet-sgmii.c | 33 +------------------- drivers/staging/octeon/ethernet-xaui.c | 33 +------------------- drivers/staging/octeon/ethernet.c | 39 ++++++++++++++++++++++++ drivers/staging/octeon/octeon-ethernet.h | 2 ++ 5 files changed, 44 insertions(+), 95 deletions(-) diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index e36f9bc695430b..88889d30cc0317 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -298,37 +298,7 @@ static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id) int cvm_oct_rgmii_open(struct net_device *dev) { - union cvmx_gmxx_prtx_cfg gmx_cfg; - struct octeon_ethernet *priv = netdev_priv(dev); - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - cvmx_helper_link_info_t link_info; - int rv; - - rv = cvm_oct_phy_setup_device(dev); - if (rv) - return rv; - - gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); - gmx_cfg.s.en = 1; - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); - - if (!octeon_is_simulation()) { - if (priv->phydev) { - int r = phy_read_status(priv->phydev); - - if (r == 0 && priv->phydev->link == 0) - netif_carrier_off(dev); - cvm_oct_adjust_link(dev); - } else { - link_info = cvmx_helper_link_get(priv->port); - if (!link_info.s.link_up) - netif_carrier_off(dev); - priv->poll = cvm_oct_rgmii_poll; - } - } - - return 0; + return cvm_oct_common_open(dev, cvm_oct_rgmii_poll, false); } int cvm_oct_rgmii_stop(struct net_device *dev) diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c index 21a7a17acb79ca..a6a831510151bb 100644 --- a/drivers/staging/octeon/ethernet-sgmii.c +++ b/drivers/staging/octeon/ethernet-sgmii.c @@ -79,38 +79,7 @@ static void cvm_oct_sgmii_poll(struct net_device *dev) int cvm_oct_sgmii_open(struct net_device *dev) { - union cvmx_gmxx_prtx_cfg gmx_cfg; - struct octeon_ethernet *priv = netdev_priv(dev); - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - cvmx_helper_link_info_t link_info; - int rv; - - rv = cvm_oct_phy_setup_device(dev); - if (rv) - return rv; - - gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); - gmx_cfg.s.en = 1; - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); - - if (octeon_is_simulation()) - return 0; - - if (priv->phydev) { - int r = phy_read_status(priv->phydev); - - if (r == 0 && priv->phydev->link == 0) - netif_carrier_off(dev); - cvm_oct_adjust_link(dev); - } else { - link_info = cvmx_helper_link_get(priv->port); - if (!link_info.s.link_up) - netif_carrier_off(dev); - priv->poll = cvm_oct_sgmii_poll; - cvm_oct_sgmii_poll(dev); - } - return 0; + return cvm_oct_common_open(dev, cvm_oct_sgmii_poll, true); } int cvm_oct_sgmii_stop(struct net_device *dev) diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c index fd9d103d8e56cc..365b01a4df0dc7 100644 --- a/drivers/staging/octeon/ethernet-xaui.c +++ b/drivers/staging/octeon/ethernet-xaui.c @@ -79,38 +79,7 @@ static void cvm_oct_xaui_poll(struct net_device *dev) int cvm_oct_xaui_open(struct net_device *dev) { - union cvmx_gmxx_prtx_cfg gmx_cfg; - struct octeon_ethernet *priv = netdev_priv(dev); - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - cvmx_helper_link_info_t link_info; - int rv; - - rv = cvm_oct_phy_setup_device(dev); - if (rv) - return rv; - - gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); - gmx_cfg.s.en = 1; - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); - - if (octeon_is_simulation()) - return 0; - - if (priv->phydev) { - int r = phy_read_status(priv->phydev); - - if (r == 0 && priv->phydev->link == 0) - netif_carrier_off(dev); - cvm_oct_adjust_link(dev); - } else { - link_info = cvmx_helper_link_get(priv->port); - if (!link_info.s.link_up) - netif_carrier_off(dev); - priv->poll = cvm_oct_xaui_poll; - cvm_oct_xaui_poll(dev); - } - return 0; + return cvm_oct_common_open(dev, cvm_oct_xaui_poll, true); } int cvm_oct_xaui_stop(struct net_device *dev) diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index fbbe866485c7c3..3ca8b7a30d3273 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -499,6 +499,45 @@ void cvm_oct_common_uninit(struct net_device *dev) phy_disconnect(priv->phydev); } +int cvm_oct_common_open(struct net_device *dev, + void (*link_poll)(struct net_device *), bool poll_now) +{ + union cvmx_gmxx_prtx_cfg gmx_cfg; + struct octeon_ethernet *priv = netdev_priv(dev); + int interface = INTERFACE(priv->port); + int index = INDEX(priv->port); + cvmx_helper_link_info_t link_info; + int rv; + + rv = cvm_oct_phy_setup_device(dev); + if (rv) + return rv; + + gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); + gmx_cfg.s.en = 1; + cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); + + if (octeon_is_simulation()) + return 0; + + if (priv->phydev) { + int r = phy_read_status(priv->phydev); + + if (r == 0 && priv->phydev->link == 0) + netif_carrier_off(dev); + cvm_oct_adjust_link(dev); + } else { + link_info = cvmx_helper_link_get(priv->port); + if (!link_info.s.link_up) + netif_carrier_off(dev); + priv->poll = link_poll; + if (poll_now) + link_poll(dev); + } + + return 0; +} + static const struct net_device_ops cvm_oct_npi_netdev_ops = { .ndo_init = cvm_oct_common_init, .ndo_uninit = cvm_oct_common_uninit, diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index f48dc766fadae3..7818873536d8ba 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -89,6 +89,8 @@ extern int cvm_oct_common_init(struct net_device *dev); extern void cvm_oct_common_uninit(struct net_device *dev); void cvm_oct_adjust_link(struct net_device *dev); int cvm_oct_common_stop(struct net_device *dev); +int cvm_oct_common_open(struct net_device *dev, + void (*link_poll)(struct net_device *), bool poll_now); extern int always_use_pow; extern int pow_send_group; From 96217ebff7f2fda012f755cdb28f34400fd5f99c Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:03 +0300 Subject: [PATCH 0445/3798] staging: octeon-ethernet: consolidate ndo_stop functions All ndo_stop functions are identical. Get rid of duplicated code. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-mdio.c | 9 ++++++++- drivers/staging/octeon/ethernet-rgmii.c | 13 ------------- drivers/staging/octeon/ethernet-sgmii.c | 13 ------------- drivers/staging/octeon/ethernet-xaui.c | 13 ------------- drivers/staging/octeon/ethernet.c | 6 +++--- drivers/staging/octeon/octeon-ethernet.h | 3 --- 6 files changed, 11 insertions(+), 46 deletions(-) diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index 40dab11e533382..ec38cb07eb7c19 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -40,7 +40,7 @@ #include "ethernet-util.h" #include - +#include #include static void cvm_oct_get_drvinfo(struct net_device *dev, @@ -150,7 +150,14 @@ void cvm_oct_adjust_link(struct net_device *dev) int cvm_oct_common_stop(struct net_device *dev) { struct octeon_ethernet *priv = netdev_priv(dev); + int interface = INTERFACE(priv->port); cvmx_helper_link_info_t link_info; + union cvmx_gmxx_prtx_cfg gmx_cfg; + int index = INDEX(priv->port); + + gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); + gmx_cfg.s.en = 0; + cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); priv->poll = NULL; diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index 88889d30cc0317..c428a452ddbe5d 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -301,19 +301,6 @@ int cvm_oct_rgmii_open(struct net_device *dev) return cvm_oct_common_open(dev, cvm_oct_rgmii_poll, false); } -int cvm_oct_rgmii_stop(struct net_device *dev) -{ - union cvmx_gmxx_prtx_cfg gmx_cfg; - struct octeon_ethernet *priv = netdev_priv(dev); - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - - gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); - gmx_cfg.s.en = 0; - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); - return cvm_oct_common_stop(dev); -} - static void cvm_oct_rgmii_immediate_poll(struct work_struct *work) { struct octeon_ethernet *priv = diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c index a6a831510151bb..ece2880b991080 100644 --- a/drivers/staging/octeon/ethernet-sgmii.c +++ b/drivers/staging/octeon/ethernet-sgmii.c @@ -82,19 +82,6 @@ int cvm_oct_sgmii_open(struct net_device *dev) return cvm_oct_common_open(dev, cvm_oct_sgmii_poll, true); } -int cvm_oct_sgmii_stop(struct net_device *dev) -{ - union cvmx_gmxx_prtx_cfg gmx_cfg; - struct octeon_ethernet *priv = netdev_priv(dev); - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - - gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); - gmx_cfg.s.en = 0; - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); - return cvm_oct_common_stop(dev); -} - int cvm_oct_sgmii_init(struct net_device *dev) { cvm_oct_common_init(dev); diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c index 365b01a4df0dc7..e8e51ed779d58f 100644 --- a/drivers/staging/octeon/ethernet-xaui.c +++ b/drivers/staging/octeon/ethernet-xaui.c @@ -82,19 +82,6 @@ int cvm_oct_xaui_open(struct net_device *dev) return cvm_oct_common_open(dev, cvm_oct_xaui_poll, true); } -int cvm_oct_xaui_stop(struct net_device *dev) -{ - union cvmx_gmxx_prtx_cfg gmx_cfg; - struct octeon_ethernet *priv = netdev_priv(dev); - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - - gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); - gmx_cfg.s.en = 0; - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); - return cvm_oct_common_stop(dev); -} - int cvm_oct_xaui_init(struct net_device *dev) { struct octeon_ethernet *priv = netdev_priv(dev); diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 3ca8b7a30d3273..2a3f9e2acbaa11 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -555,7 +555,7 @@ static const struct net_device_ops cvm_oct_xaui_netdev_ops = { .ndo_init = cvm_oct_xaui_init, .ndo_uninit = cvm_oct_xaui_uninit, .ndo_open = cvm_oct_xaui_open, - .ndo_stop = cvm_oct_xaui_stop, + .ndo_stop = cvm_oct_common_stop, .ndo_start_xmit = cvm_oct_xmit, .ndo_set_rx_mode = cvm_oct_common_set_multicast_list, .ndo_set_mac_address = cvm_oct_common_set_mac_address, @@ -570,7 +570,7 @@ static const struct net_device_ops cvm_oct_sgmii_netdev_ops = { .ndo_init = cvm_oct_sgmii_init, .ndo_uninit = cvm_oct_sgmii_uninit, .ndo_open = cvm_oct_sgmii_open, - .ndo_stop = cvm_oct_sgmii_stop, + .ndo_stop = cvm_oct_common_stop, .ndo_start_xmit = cvm_oct_xmit, .ndo_set_rx_mode = cvm_oct_common_set_multicast_list, .ndo_set_mac_address = cvm_oct_common_set_mac_address, @@ -598,7 +598,7 @@ static const struct net_device_ops cvm_oct_rgmii_netdev_ops = { .ndo_init = cvm_oct_rgmii_init, .ndo_uninit = cvm_oct_rgmii_uninit, .ndo_open = cvm_oct_rgmii_open, - .ndo_stop = cvm_oct_rgmii_stop, + .ndo_stop = cvm_oct_common_stop, .ndo_start_xmit = cvm_oct_xmit, .ndo_set_rx_mode = cvm_oct_common_set_multicast_list, .ndo_set_mac_address = cvm_oct_common_set_mac_address, diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index 7818873536d8ba..2581554de0b32c 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -71,19 +71,16 @@ int cvm_oct_free_work(void *work_queue_entry); extern int cvm_oct_rgmii_init(struct net_device *dev); extern void cvm_oct_rgmii_uninit(struct net_device *dev); extern int cvm_oct_rgmii_open(struct net_device *dev); -extern int cvm_oct_rgmii_stop(struct net_device *dev); extern int cvm_oct_sgmii_init(struct net_device *dev); extern void cvm_oct_sgmii_uninit(struct net_device *dev); extern int cvm_oct_sgmii_open(struct net_device *dev); -extern int cvm_oct_sgmii_stop(struct net_device *dev); extern int cvm_oct_spi_init(struct net_device *dev); extern void cvm_oct_spi_uninit(struct net_device *dev); extern int cvm_oct_xaui_init(struct net_device *dev); extern void cvm_oct_xaui_uninit(struct net_device *dev); extern int cvm_oct_xaui_open(struct net_device *dev); -extern int cvm_oct_xaui_stop(struct net_device *dev); extern int cvm_oct_common_init(struct net_device *dev); extern void cvm_oct_common_uninit(struct net_device *dev); From be76400c31194d759b621bc2b70f0c61882fbaec Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:04 +0300 Subject: [PATCH 0446/3798] staging: octeon-ethernet: move ndo_stop to common init All init functions call ndo_stop if it's defined, so move it to common function. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-rgmii.c | 1 - drivers/staging/octeon/ethernet-sgmii.c | 1 - drivers/staging/octeon/ethernet-xaui.c | 1 - drivers/staging/octeon/ethernet.c | 3 +++ 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index c428a452ddbe5d..a6b853118bc53d 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -314,7 +314,6 @@ int cvm_oct_rgmii_init(struct net_device *dev) int r; cvm_oct_common_init(dev); - dev->netdev_ops->ndo_stop(dev); INIT_WORK(&priv->port_work, cvm_oct_rgmii_immediate_poll); /* * Due to GMX errata in CN3XXX series chips, it is necessary diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c index ece2880b991080..cd791c36227325 100644 --- a/drivers/staging/octeon/ethernet-sgmii.c +++ b/drivers/staging/octeon/ethernet-sgmii.c @@ -85,7 +85,6 @@ int cvm_oct_sgmii_open(struct net_device *dev) int cvm_oct_sgmii_init(struct net_device *dev) { cvm_oct_common_init(dev); - dev->netdev_ops->ndo_stop(dev); /* FIXME: Need autoneg logic */ return 0; diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c index e8e51ed779d58f..5782c38a9c9cad 100644 --- a/drivers/staging/octeon/ethernet-xaui.c +++ b/drivers/staging/octeon/ethernet-xaui.c @@ -87,7 +87,6 @@ int cvm_oct_xaui_init(struct net_device *dev) struct octeon_ethernet *priv = netdev_priv(dev); cvm_oct_common_init(dev); - dev->netdev_ops->ndo_stop(dev); if (!octeon_is_simulation() && priv->phydev == NULL) priv->poll = cvm_oct_xaui_poll; diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 2a3f9e2acbaa11..fdd23bfa62d1cd 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -488,6 +488,9 @@ int cvm_oct_common_init(struct net_device *dev) memset(dev->netdev_ops->ndo_get_stats(dev), 0, sizeof(struct net_device_stats)); + if (dev->netdev_ops->ndo_stop) + dev->netdev_ops->ndo_stop(dev); + return 0; } From 3c33914558cc22f9a51a7a15da1e991e49fcb1b3 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:05 +0300 Subject: [PATCH 0447/3798] staging: octeon-ethernet: delete sgmii and xaui specific uninit functions Delete redundant wrappers. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-sgmii.c | 5 ----- drivers/staging/octeon/ethernet-xaui.c | 5 ----- drivers/staging/octeon/ethernet.c | 4 ++-- drivers/staging/octeon/octeon-ethernet.h | 2 -- 4 files changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c index cd791c36227325..1158eacc57bbfa 100644 --- a/drivers/staging/octeon/ethernet-sgmii.c +++ b/drivers/staging/octeon/ethernet-sgmii.c @@ -89,8 +89,3 @@ int cvm_oct_sgmii_init(struct net_device *dev) /* FIXME: Need autoneg logic */ return 0; } - -void cvm_oct_sgmii_uninit(struct net_device *dev) -{ - cvm_oct_common_uninit(dev); -} diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c index 5782c38a9c9cad..3714fae201d494 100644 --- a/drivers/staging/octeon/ethernet-xaui.c +++ b/drivers/staging/octeon/ethernet-xaui.c @@ -92,8 +92,3 @@ int cvm_oct_xaui_init(struct net_device *dev) return 0; } - -void cvm_oct_xaui_uninit(struct net_device *dev) -{ - cvm_oct_common_uninit(dev); -} diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index fdd23bfa62d1cd..a7f1fcb4762a8d 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -556,7 +556,7 @@ static const struct net_device_ops cvm_oct_npi_netdev_ops = { }; static const struct net_device_ops cvm_oct_xaui_netdev_ops = { .ndo_init = cvm_oct_xaui_init, - .ndo_uninit = cvm_oct_xaui_uninit, + .ndo_uninit = cvm_oct_common_uninit, .ndo_open = cvm_oct_xaui_open, .ndo_stop = cvm_oct_common_stop, .ndo_start_xmit = cvm_oct_xmit, @@ -571,7 +571,7 @@ static const struct net_device_ops cvm_oct_xaui_netdev_ops = { }; static const struct net_device_ops cvm_oct_sgmii_netdev_ops = { .ndo_init = cvm_oct_sgmii_init, - .ndo_uninit = cvm_oct_sgmii_uninit, + .ndo_uninit = cvm_oct_common_uninit, .ndo_open = cvm_oct_sgmii_open, .ndo_stop = cvm_oct_common_stop, .ndo_start_xmit = cvm_oct_xmit, diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index 2581554de0b32c..3ad713fb4725f1 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -73,13 +73,11 @@ extern void cvm_oct_rgmii_uninit(struct net_device *dev); extern int cvm_oct_rgmii_open(struct net_device *dev); extern int cvm_oct_sgmii_init(struct net_device *dev); -extern void cvm_oct_sgmii_uninit(struct net_device *dev); extern int cvm_oct_sgmii_open(struct net_device *dev); extern int cvm_oct_spi_init(struct net_device *dev); extern void cvm_oct_spi_uninit(struct net_device *dev); extern int cvm_oct_xaui_init(struct net_device *dev); -extern void cvm_oct_xaui_uninit(struct net_device *dev); extern int cvm_oct_xaui_open(struct net_device *dev); extern int cvm_oct_common_init(struct net_device *dev); From 36a14572415459877933857f67d93d3e053180a2 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:06 +0300 Subject: [PATCH 0448/3798] staging: octeon-ethernet: add queue information to carrier note Add queue information to carrier note. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-mdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index ec38cb07eb7c19..604fb581f1c314 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -120,10 +120,10 @@ static void cvm_oct_note_carrier(struct octeon_ethernet *priv, cvmx_helper_link_info_t li) { if (li.s.link_up) { - pr_notice_ratelimited("%s: %u Mbps %s duplex, port %d\n", + pr_notice_ratelimited("%s: %u Mbps %s duplex, port %d, queue %d\n", netdev_name(priv->netdev), li.s.speed, (li.s.full_duplex) ? "Full" : "Half", - priv->port); + priv->port, priv->queue); } else { pr_notice_ratelimited("%s: Link down\n", netdev_name(priv->netdev)); From 2638f71307f649532f613a4bcb3b163b7b63017a Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:07 +0300 Subject: [PATCH 0449/3798] staging: octeon-ethernet: consolidate carrier notifications Always use cvm_oct_note_carrier() to avoid copy-pasted code. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-mdio.c | 5 ++--- drivers/staging/octeon/ethernet-rgmii.c | 19 +++---------------- drivers/staging/octeon/ethernet-sgmii.c | 20 +++----------------- drivers/staging/octeon/ethernet-xaui.c | 20 +++----------------- drivers/staging/octeon/octeon-ethernet.h | 4 ++++ 5 files changed, 15 insertions(+), 53 deletions(-) diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index 604fb581f1c314..6322d0dd4238d7 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -39,7 +39,6 @@ #include "ethernet-mdio.h" #include "ethernet-util.h" -#include #include #include @@ -116,8 +115,8 @@ int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return phy_mii_ioctl(priv->phydev, rq, cmd); } -static void cvm_oct_note_carrier(struct octeon_ethernet *priv, - cvmx_helper_link_info_t li) +void cvm_oct_note_carrier(struct octeon_ethernet *priv, + cvmx_helper_link_info_t li) { if (li.s.link_up) { pr_notice_ratelimited("%s: %u Mbps %s duplex, port %d, queue %d\n", diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index a6b853118bc53d..65edfbf251c495 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -176,23 +176,10 @@ static void cvm_oct_rgmii_poll(struct net_device *dev) if (link_info.s.link_up) { if (!netif_carrier_ok(dev)) netif_carrier_on(dev); - if (priv->queue != -1) - printk_ratelimited("%s: %u Mbps %s duplex, port %2d, queue %2d\n", - dev->name, link_info.s.speed, - (link_info.s.full_duplex) ? - "Full" : "Half", - priv->port, priv->queue); - else - printk_ratelimited("%s: %u Mbps %s duplex, port %2d, POW\n", - dev->name, link_info.s.speed, - (link_info.s.full_duplex) ? - "Full" : "Half", - priv->port); - } else { - if (netif_carrier_ok(dev)) - netif_carrier_off(dev); - printk_ratelimited("%s: Link down\n", dev->name); + } else if (netif_carrier_ok(dev)) { + netif_carrier_off(dev); } + cvm_oct_note_carrier(priv, link_info); } } diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c index 1158eacc57bbfa..9a747f94d48c2a 100644 --- a/drivers/staging/octeon/ethernet-sgmii.c +++ b/drivers/staging/octeon/ethernet-sgmii.c @@ -55,26 +55,12 @@ static void cvm_oct_sgmii_poll(struct net_device *dev) /* Tell Linux */ if (link_info.s.link_up) { - if (!netif_carrier_ok(dev)) netif_carrier_on(dev); - if (priv->queue != -1) - printk_ratelimited - ("%s: %u Mbps %s duplex, port %2d, queue %2d\n", - dev->name, link_info.s.speed, - (link_info.s.full_duplex) ? "Full" : "Half", - priv->port, priv->queue); - else - printk_ratelimited - ("%s: %u Mbps %s duplex, port %2d, POW\n", - dev->name, link_info.s.speed, - (link_info.s.full_duplex) ? "Full" : "Half", - priv->port); - } else { - if (netif_carrier_ok(dev)) - netif_carrier_off(dev); - printk_ratelimited("%s: Link down\n", dev->name); + } else if (netif_carrier_ok(dev)) { + netif_carrier_off(dev); } + cvm_oct_note_carrier(priv, link_info); } int cvm_oct_sgmii_open(struct net_device *dev) diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c index 3714fae201d494..888b70b93a7b3d 100644 --- a/drivers/staging/octeon/ethernet-xaui.c +++ b/drivers/staging/octeon/ethernet-xaui.c @@ -55,26 +55,12 @@ static void cvm_oct_xaui_poll(struct net_device *dev) /* Tell Linux */ if (link_info.s.link_up) { - if (!netif_carrier_ok(dev)) netif_carrier_on(dev); - if (priv->queue != -1) - printk_ratelimited - ("%s: %u Mbps %s duplex, port %2d, queue %2d\n", - dev->name, link_info.s.speed, - (link_info.s.full_duplex) ? "Full" : "Half", - priv->port, priv->queue); - else - printk_ratelimited - ("%s: %u Mbps %s duplex, port %2d, POW\n", - dev->name, link_info.s.speed, - (link_info.s.full_duplex) ? "Full" : "Half", - priv->port); - } else { - if (netif_carrier_ok(dev)) - netif_carrier_off(dev); - printk_ratelimited("%s: Link down\n", dev->name); + } else if (netif_carrier_ok(dev)) { + netif_carrier_off(dev); } + cvm_oct_note_carrier(priv, link_info); } int cvm_oct_xaui_open(struct net_device *dev) diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index 3ad713fb4725f1..1e77f1d23c7410 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -33,6 +33,8 @@ #include +#include + /** * This is the definition of the Ethernet driver's private * driver state stored in netdev_priv(dev). @@ -86,6 +88,8 @@ void cvm_oct_adjust_link(struct net_device *dev); int cvm_oct_common_stop(struct net_device *dev); int cvm_oct_common_open(struct net_device *dev, void (*link_poll)(struct net_device *), bool poll_now); +void cvm_oct_note_carrier(struct octeon_ethernet *priv, + cvmx_helper_link_info_t li); extern int always_use_pow; extern int pow_send_group; From a8d2e8171082854dadea64b808af4b54f78c0384 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:08 +0300 Subject: [PATCH 0450/3798] staging: octeon-ethernet: sgmii/xaui: make link poll generic Make link poll generic to avoid copy paste. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-sgmii.c | 24 +--------------------- drivers/staging/octeon/ethernet-xaui.c | 26 ++---------------------- drivers/staging/octeon/ethernet.c | 21 +++++++++++++++++++ drivers/staging/octeon/octeon-ethernet.h | 1 + 4 files changed, 25 insertions(+), 47 deletions(-) diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c index 9a747f94d48c2a..1940f4b72a66eb 100644 --- a/drivers/staging/octeon/ethernet-sgmii.c +++ b/drivers/staging/octeon/ethernet-sgmii.c @@ -41,31 +41,9 @@ #include -static void cvm_oct_sgmii_poll(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - cvmx_helper_link_info_t link_info; - - link_info = cvmx_helper_link_get(priv->port); - if (link_info.u64 == priv->link_info) - return; - - link_info = cvmx_helper_link_autoconf(priv->port); - priv->link_info = link_info.u64; - - /* Tell Linux */ - if (link_info.s.link_up) { - if (!netif_carrier_ok(dev)) - netif_carrier_on(dev); - } else if (netif_carrier_ok(dev)) { - netif_carrier_off(dev); - } - cvm_oct_note_carrier(priv, link_info); -} - int cvm_oct_sgmii_open(struct net_device *dev) { - return cvm_oct_common_open(dev, cvm_oct_sgmii_poll, true); + return cvm_oct_common_open(dev, cvm_oct_link_poll, true); } int cvm_oct_sgmii_init(struct net_device *dev) diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c index 888b70b93a7b3d..42a4d2be0cffb6 100644 --- a/drivers/staging/octeon/ethernet-xaui.c +++ b/drivers/staging/octeon/ethernet-xaui.c @@ -41,31 +41,9 @@ #include -static void cvm_oct_xaui_poll(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - cvmx_helper_link_info_t link_info; - - link_info = cvmx_helper_link_get(priv->port); - if (link_info.u64 == priv->link_info) - return; - - link_info = cvmx_helper_link_autoconf(priv->port); - priv->link_info = link_info.u64; - - /* Tell Linux */ - if (link_info.s.link_up) { - if (!netif_carrier_ok(dev)) - netif_carrier_on(dev); - } else if (netif_carrier_ok(dev)) { - netif_carrier_off(dev); - } - cvm_oct_note_carrier(priv, link_info); -} - int cvm_oct_xaui_open(struct net_device *dev) { - return cvm_oct_common_open(dev, cvm_oct_xaui_poll, true); + return cvm_oct_common_open(dev, cvm_oct_link_poll, true); } int cvm_oct_xaui_init(struct net_device *dev) @@ -74,7 +52,7 @@ int cvm_oct_xaui_init(struct net_device *dev) cvm_oct_common_init(dev); if (!octeon_is_simulation() && priv->phydev == NULL) - priv->poll = cvm_oct_xaui_poll; + priv->poll = cvm_oct_link_poll; return 0; } diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index a7f1fcb4762a8d..d395bf527d916d 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -541,6 +541,27 @@ int cvm_oct_common_open(struct net_device *dev, return 0; } +void cvm_oct_link_poll(struct net_device *dev) +{ + struct octeon_ethernet *priv = netdev_priv(dev); + cvmx_helper_link_info_t link_info; + + link_info = cvmx_helper_link_get(priv->port); + if (link_info.u64 == priv->link_info) + return; + + link_info = cvmx_helper_link_autoconf(priv->port); + priv->link_info = link_info.u64; + + if (link_info.s.link_up) { + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); + } else if (netif_carrier_ok(dev)) { + netif_carrier_off(dev); + } + cvm_oct_note_carrier(priv, link_info); +} + static const struct net_device_ops cvm_oct_npi_netdev_ops = { .ndo_init = cvm_oct_common_init, .ndo_uninit = cvm_oct_common_uninit, diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index 1e77f1d23c7410..22d726e0d2d03b 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -90,6 +90,7 @@ int cvm_oct_common_open(struct net_device *dev, void (*link_poll)(struct net_device *), bool poll_now); void cvm_oct_note_carrier(struct octeon_ethernet *priv, cvmx_helper_link_info_t li); +void cvm_oct_link_poll(struct net_device *dev); extern int always_use_pow; extern int pow_send_group; From 67d2ee257392372e889ece8526eef9941e982512 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:09 +0300 Subject: [PATCH 0451/3798] staging: octeon-ethernet: rgmii: refactor gmx block interrupt handling Code for gmx0 and gmx1 block is identical, move it into a function. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-rgmii.c | 123 ++++++++---------------- 1 file changed, 41 insertions(+), 82 deletions(-) diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index 65edfbf251c495..0101fcd5d348ec 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -183,104 +183,63 @@ static void cvm_oct_rgmii_poll(struct net_device *dev) } } -static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id) +static int cmv_oct_rgmii_gmx_interrupt(int interface) { - union cvmx_npi_rsl_int_blocks rsl_int_blocks; int index; - irqreturn_t return_status = IRQ_NONE; + int count = 0; - rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS); - - /* Check and see if this interrupt was caused by the GMX0 block */ - if (rsl_int_blocks.s.gmx0) { + /* Loop through every port of this interface */ + for (index = 0; + index < cvmx_helper_ports_on_interface(interface); + index++) { + union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg; - int interface = 0; - /* Loop through every port of this interface */ - for (index = 0; - index < cvmx_helper_ports_on_interface(interface); - index++) { - - /* Read the GMX interrupt status bits */ - union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg; - - gmx_rx_int_reg.u64 = - cvmx_read_csr(CVMX_GMXX_RXX_INT_REG + /* Read the GMX interrupt status bits */ + gmx_rx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG (index, interface)); - gmx_rx_int_reg.u64 &= - cvmx_read_csr(CVMX_GMXX_RXX_INT_EN + gmx_rx_int_reg.u64 &= cvmx_read_csr(CVMX_GMXX_RXX_INT_EN (index, interface)); - /* Poll the port if inband status changed */ - if (gmx_rx_int_reg.s.phy_dupx - || gmx_rx_int_reg.s.phy_link - || gmx_rx_int_reg.s.phy_spd) { - struct net_device *dev = + /* Poll the port if inband status changed */ + if (gmx_rx_int_reg.s.phy_dupx || gmx_rx_int_reg.s.phy_link || + gmx_rx_int_reg.s.phy_spd) { + struct net_device *dev = cvm_oct_device[cvmx_helper_get_ipd_port (interface, index)]; - struct octeon_ethernet *priv = netdev_priv(dev); - - if (dev && - !atomic_read(&cvm_oct_poll_queue_stopping)) - queue_work(cvm_oct_poll_queue, - &priv->port_work); - - gmx_rx_int_reg.u64 = 0; - gmx_rx_int_reg.s.phy_dupx = 1; - gmx_rx_int_reg.s.phy_link = 1; - gmx_rx_int_reg.s.phy_spd = 1; - cvmx_write_csr(CVMX_GMXX_RXX_INT_REG - (index, interface), - gmx_rx_int_reg.u64); - return_status = IRQ_HANDLED; - } + struct octeon_ethernet *priv = netdev_priv(dev); + + if (dev && !atomic_read(&cvm_oct_poll_queue_stopping)) + queue_work(cvm_oct_poll_queue, + &priv->port_work); + + gmx_rx_int_reg.u64 = 0; + gmx_rx_int_reg.s.phy_dupx = 1; + gmx_rx_int_reg.s.phy_link = 1; + gmx_rx_int_reg.s.phy_spd = 1; + cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), + gmx_rx_int_reg.u64); + count++; } } + return count; +} - /* Check and see if this interrupt was caused by the GMX1 block */ - if (rsl_int_blocks.s.gmx1) { - - int interface = 1; - /* Loop through every port of this interface */ - for (index = 0; - index < cvmx_helper_ports_on_interface(interface); - index++) { - - /* Read the GMX interrupt status bits */ - union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg; +static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id) +{ + union cvmx_npi_rsl_int_blocks rsl_int_blocks; + int count = 0; - gmx_rx_int_reg.u64 = - cvmx_read_csr(CVMX_GMXX_RXX_INT_REG - (index, interface)); - gmx_rx_int_reg.u64 &= - cvmx_read_csr(CVMX_GMXX_RXX_INT_EN - (index, interface)); - /* Poll the port if inband status changed */ - if (gmx_rx_int_reg.s.phy_dupx - || gmx_rx_int_reg.s.phy_link - || gmx_rx_int_reg.s.phy_spd) { + rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS); - struct net_device *dev = - cvm_oct_device[cvmx_helper_get_ipd_port - (interface, index)]; - struct octeon_ethernet *priv = netdev_priv(dev); + /* Check and see if this interrupt was caused by the GMX0 block */ + if (rsl_int_blocks.s.gmx0) + count += cmv_oct_rgmii_gmx_interrupt(0); - if (dev && - !atomic_read(&cvm_oct_poll_queue_stopping)) - queue_work(cvm_oct_poll_queue, - &priv->port_work); + /* Check and see if this interrupt was caused by the GMX1 block */ + if (rsl_int_blocks.s.gmx1) + count += cmv_oct_rgmii_gmx_interrupt(1); - gmx_rx_int_reg.u64 = 0; - gmx_rx_int_reg.s.phy_dupx = 1; - gmx_rx_int_reg.s.phy_link = 1; - gmx_rx_int_reg.s.phy_spd = 1; - cvmx_write_csr(CVMX_GMXX_RXX_INT_REG - (index, interface), - gmx_rx_int_reg.u64); - return_status = IRQ_HANDLED; - } - } - } - return return_status; + return count ? IRQ_HANDLED : IRQ_NONE; } int cvm_oct_rgmii_open(struct net_device *dev) From 01d3007a5de1bb3f6c84dcc836dc5bffee91a7e3 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:10 +0300 Subject: [PATCH 0452/3798] staging: octeon-ethernet: rgmii: use function to configure hw preamble Use a function to enable/disable HW preamble checking to avoid copy paste. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-rgmii.c | 84 +++++++++++-------------- 1 file changed, 35 insertions(+), 49 deletions(-) diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index 0101fcd5d348ec..ba2ad2aaca3ebc 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -48,6 +48,37 @@ static DEFINE_SPINLOCK(global_register_lock); static int number_rgmii_ports; +static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable) +{ + union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; + union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs; + union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; + int interface = INTERFACE(priv->port); + int index = INDEX(priv->port); + + /* Set preamble checking. */ + gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, + interface)); + gmxx_rxx_frm_ctl.s.pre_chk = enable; + cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface), + gmxx_rxx_frm_ctl.u64); + + /* Set FCS stripping. */ + ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS); + if (enable) + ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port; + else + ipd_sub_port_fcs.s.port_bit &= + 0xffffffffull ^ (1ull << priv->port); + cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64); + + /* Clear any error bits. */ + gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, + interface)); + cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), + gmxx_rxx_int_reg.u64); +} + static void cvm_oct_rgmii_poll(struct net_device *dev) { struct octeon_ethernet *priv = netdev_priv(dev); @@ -88,7 +119,6 @@ static void cvm_oct_rgmii_poll(struct net_device *dev) cvmx_read_csr(CVMX_GMXX_RXX_INT_REG (index, interface)); if (gmxx_rxx_int_reg.s.pcterr) { - /* * We are getting preamble errors at * 10Mbps. Most likely the PHY is @@ -97,30 +127,7 @@ static void cvm_oct_rgmii_poll(struct net_device *dev) * packets we need to disable preamble * checking and do it in software. */ - union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; - union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs; - - /* Disable preamble checking */ - gmxx_rxx_frm_ctl.u64 = - cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL - (index, interface)); - gmxx_rxx_frm_ctl.s.pre_chk = 0; - cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL - (index, interface), - gmxx_rxx_frm_ctl.u64); - - /* Disable FCS stripping */ - ipd_sub_port_fcs.u64 = - cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS); - ipd_sub_port_fcs.s.port_bit &= - 0xffffffffull ^ (1ull << priv->port); - cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, - ipd_sub_port_fcs.u64); - - /* Clear any error bits */ - cvmx_write_csr(CVMX_GMXX_RXX_INT_REG - (index, interface), - gmxx_rxx_int_reg.u64); + cvm_oct_set_hw_preamble(priv, false); printk_ratelimited("%s: Using 10Mbps with software preamble removal\n", dev->name); } @@ -137,30 +144,9 @@ static void cvm_oct_rgmii_poll(struct net_device *dev) preamble checking, FCS stripping, and clear error bits on every speed change. If errors occur during 10Mbps operation the above code will change this stuff */ - if (USE_10MBPS_PREAMBLE_WORKAROUND) { - - union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; - union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs; - union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - - /* Enable preamble checking */ - gmxx_rxx_frm_ctl.u64 = - cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface)); - gmxx_rxx_frm_ctl.s.pre_chk = 1; - cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface), - gmxx_rxx_frm_ctl.u64); - /* Enable FCS stripping */ - ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS); - ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port; - cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64); - /* Clear any error bits */ - gmxx_rxx_int_reg.u64 = - cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface)); - cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), - gmxx_rxx_int_reg.u64); - } + if (USE_10MBPS_PREAMBLE_WORKAROUND) + cvm_oct_set_hw_preamble(priv, true); + if (priv->phydev == NULL) { link_info = cvmx_helper_link_autoconf(priv->port); priv->link_info = link_info.u64; From 8884ceeb4b8ea400468683b9b4d0bf5f2b9ac7e7 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:11 +0300 Subject: [PATCH 0453/3798] staging: octeon-ethernet: spi: move spx interrupt dumps into a function Move interrupt printouts into a common function to avoid copy paste. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-spi.c | 80 ++++++++++++--------------- 1 file changed, 34 insertions(+), 46 deletions(-) diff --git a/drivers/staging/octeon/ethernet-spi.c b/drivers/staging/octeon/ethernet-spi.c index 5108bc0bb573e0..6ecbfb5f22dcf2 100644 --- a/drivers/staging/octeon/ethernet-spi.c +++ b/drivers/staging/octeon/ethernet-spi.c @@ -44,6 +44,38 @@ static int number_spi_ports; static int need_retrain[2] = { 0, 0 }; +static void cvm_oct_spxx_int_pr(union cvmx_spxx_int_reg spx_int_reg, int index) +{ + if (spx_int_reg.s.spf) + pr_err("SPI%d: SRX Spi4 interface down\n", index); + if (spx_int_reg.s.calerr) + pr_err("SPI%d: SRX Spi4 Calendar table parity error\n", index); + if (spx_int_reg.s.syncerr) + pr_err("SPI%d: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n", + index); + if (spx_int_reg.s.diperr) + pr_err("SPI%d: SRX Spi4 DIP4 error\n", index); + if (spx_int_reg.s.tpaovr) + pr_err("SPI%d: SRX Selected port has hit TPA overflow\n", + index); + if (spx_int_reg.s.rsverr) + pr_err("SPI%d: SRX Spi4 reserved control word detected\n", + index); + if (spx_int_reg.s.drwnng) + pr_err("SPI%d: SRX Spi4 receive FIFO drowning/overflow\n", + index); + if (spx_int_reg.s.clserr) + pr_err("SPI%d: SRX Spi4 packet closed on non-16B alignment without EOP\n", + index); + if (spx_int_reg.s.spiovr) + pr_err("SPI%d: SRX Spi4 async FIFO overflow\n", index); + if (spx_int_reg.s.abnorm) + pr_err("SPI%d: SRX Abnormal packet termination (ERR bit)\n", + index); + if (spx_int_reg.s.prtnxa) + pr_err("SPI%d: SRX Port out of range\n", index); +} + static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) { irqreturn_t return_status = IRQ_NONE; @@ -59,30 +91,8 @@ static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(1)); cvmx_write_csr(CVMX_SPXX_INT_REG(1), spx_int_reg.u64); if (!need_retrain[1]) { - spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(1)); - if (spx_int_reg.s.spf) - pr_err("SPI1: SRX Spi4 interface down\n"); - if (spx_int_reg.s.calerr) - pr_err("SPI1: SRX Spi4 Calendar table parity error\n"); - if (spx_int_reg.s.syncerr) - pr_err("SPI1: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n"); - if (spx_int_reg.s.diperr) - pr_err("SPI1: SRX Spi4 DIP4 error\n"); - if (spx_int_reg.s.tpaovr) - pr_err("SPI1: SRX Selected port has hit TPA overflow\n"); - if (spx_int_reg.s.rsverr) - pr_err("SPI1: SRX Spi4 reserved control word detected\n"); - if (spx_int_reg.s.drwnng) - pr_err("SPI1: SRX Spi4 receive FIFO drowning/overflow\n"); - if (spx_int_reg.s.clserr) - pr_err("SPI1: SRX Spi4 packet closed on non-16B alignment without EOP\n"); - if (spx_int_reg.s.spiovr) - pr_err("SPI1: SRX Spi4 async FIFO overflow\n"); - if (spx_int_reg.s.abnorm) - pr_err("SPI1: SRX Abnormal packet termination (ERR bit)\n"); - if (spx_int_reg.s.prtnxa) - pr_err("SPI1: SRX Port out of range\n"); + cvm_oct_spxx_int_pr(spx_int_reg, 1); } stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(1)); @@ -123,30 +133,8 @@ static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(0)); cvmx_write_csr(CVMX_SPXX_INT_REG(0), spx_int_reg.u64); if (!need_retrain[0]) { - spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(0)); - if (spx_int_reg.s.spf) - pr_err("SPI0: SRX Spi4 interface down\n"); - if (spx_int_reg.s.calerr) - pr_err("SPI0: SRX Spi4 Calendar table parity error\n"); - if (spx_int_reg.s.syncerr) - pr_err("SPI0: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n"); - if (spx_int_reg.s.diperr) - pr_err("SPI0: SRX Spi4 DIP4 error\n"); - if (spx_int_reg.s.tpaovr) - pr_err("SPI0: SRX Selected port has hit TPA overflow\n"); - if (spx_int_reg.s.rsverr) - pr_err("SPI0: SRX Spi4 reserved control word detected\n"); - if (spx_int_reg.s.drwnng) - pr_err("SPI0: SRX Spi4 receive FIFO drowning/overflow\n"); - if (spx_int_reg.s.clserr) - pr_err("SPI0: SRX Spi4 packet closed on non-16B alignment without EOP\n"); - if (spx_int_reg.s.spiovr) - pr_err("SPI0: SRX Spi4 async FIFO overflow\n"); - if (spx_int_reg.s.abnorm) - pr_err("SPI0: SRX Abnormal packet termination (ERR bit)\n"); - if (spx_int_reg.s.prtnxa) - pr_err("SPI0: SRX Port out of range\n"); + cvm_oct_spxx_int_pr(spx_int_reg, 0); } stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(0)); From 124bcc5e74fe4cc761d759dac8f8c041e1d3ad96 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:12 +0300 Subject: [PATCH 0454/3798] staging: octeon-ethernet: spi: move stx interrupt dumps into a function Move interrupt printouts into a common function to avoid copy paste. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-spi.c | 68 ++++++++++++--------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/drivers/staging/octeon/ethernet-spi.c b/drivers/staging/octeon/ethernet-spi.c index 6ecbfb5f22dcf2..6579e1ac55424c 100644 --- a/drivers/staging/octeon/ethernet-spi.c +++ b/drivers/staging/octeon/ethernet-spi.c @@ -76,6 +76,34 @@ static void cvm_oct_spxx_int_pr(union cvmx_spxx_int_reg spx_int_reg, int index) pr_err("SPI%d: SRX Port out of range\n", index); } +static void cvm_oct_stxx_int_pr(union cvmx_stxx_int_reg stx_int_reg, int index) +{ + if (stx_int_reg.s.syncerr) + pr_err("SPI%d: STX Interface encountered a fatal error\n", + index); + if (stx_int_reg.s.frmerr) + pr_err("SPI%d: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n", + index); + if (stx_int_reg.s.unxfrm) + pr_err("SPI%d: STX Unexpected framing sequence\n", index); + if (stx_int_reg.s.nosync) + pr_err("SPI%d: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n", + index); + if (stx_int_reg.s.diperr) + pr_err("SPI%d: STX DIP2 error on the Spi4 Status channel\n", + index); + if (stx_int_reg.s.datovr) + pr_err("SPI%d: STX Spi4 FIFO overflow error\n", index); + if (stx_int_reg.s.ovrbst) + pr_err("SPI%d: STX Transmit packet burst too big\n", index); + if (stx_int_reg.s.calpar1) + pr_err("SPI%d: STX Calendar Table Parity Error Bank%d\n", + index, 1); + if (stx_int_reg.s.calpar0) + pr_err("SPI%d: STX Calendar Table Parity Error Bank%d\n", + index, 0); +} + static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) { irqreturn_t return_status = IRQ_NONE; @@ -98,26 +126,8 @@ static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(1)); cvmx_write_csr(CVMX_STXX_INT_REG(1), stx_int_reg.u64); if (!need_retrain[1]) { - stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(1)); - if (stx_int_reg.s.syncerr) - pr_err("SPI1: STX Interface encountered a fatal error\n"); - if (stx_int_reg.s.frmerr) - pr_err("SPI1: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n"); - if (stx_int_reg.s.unxfrm) - pr_err("SPI1: STX Unexpected framing sequence\n"); - if (stx_int_reg.s.nosync) - pr_err("SPI1: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n"); - if (stx_int_reg.s.diperr) - pr_err("SPI1: STX DIP2 error on the Spi4 Status channel\n"); - if (stx_int_reg.s.datovr) - pr_err("SPI1: STX Spi4 FIFO overflow error\n"); - if (stx_int_reg.s.ovrbst) - pr_err("SPI1: STX Transmit packet burst too big\n"); - if (stx_int_reg.s.calpar1) - pr_err("SPI1: STX Calendar Table Parity Error Bank1\n"); - if (stx_int_reg.s.calpar0) - pr_err("SPI1: STX Calendar Table Parity Error Bank0\n"); + cvm_oct_stxx_int_pr(stx_int_reg, 1); } cvmx_write_csr(CVMX_SPXX_INT_MSK(1), 0); @@ -140,26 +150,8 @@ static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(0)); cvmx_write_csr(CVMX_STXX_INT_REG(0), stx_int_reg.u64); if (!need_retrain[0]) { - stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(0)); - if (stx_int_reg.s.syncerr) - pr_err("SPI0: STX Interface encountered a fatal error\n"); - if (stx_int_reg.s.frmerr) - pr_err("SPI0: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n"); - if (stx_int_reg.s.unxfrm) - pr_err("SPI0: STX Unexpected framing sequence\n"); - if (stx_int_reg.s.nosync) - pr_err("SPI0: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n"); - if (stx_int_reg.s.diperr) - pr_err("SPI0: STX DIP2 error on the Spi4 Status channel\n"); - if (stx_int_reg.s.datovr) - pr_err("SPI0: STX Spi4 FIFO overflow error\n"); - if (stx_int_reg.s.ovrbst) - pr_err("SPI0: STX Transmit packet burst too big\n"); - if (stx_int_reg.s.calpar1) - pr_err("SPI0: STX Calendar Table Parity Error Bank1\n"); - if (stx_int_reg.s.calpar0) - pr_err("SPI0: STX Calendar Table Parity Error Bank0\n"); + cvm_oct_stxx_int_pr(stx_int_reg, 0); } cvmx_write_csr(CVMX_SPXX_INT_MSK(0), 0); From 81f56d332050084dccdff61bbf819d97f28abe70 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:13 +0300 Subject: [PATCH 0455/3798] staging: octeon-ethernet: spi: refactor spx block interrupt handling Code for spx1 and spx0 block are identical, move it into a function. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-spi.c | 77 +++++++++++---------------- 1 file changed, 30 insertions(+), 47 deletions(-) diff --git a/drivers/staging/octeon/ethernet-spi.c b/drivers/staging/octeon/ethernet-spi.c index 6579e1ac55424c..5313ac54d863e2 100644 --- a/drivers/staging/octeon/ethernet-spi.c +++ b/drivers/staging/octeon/ethernet-spi.c @@ -104,6 +104,32 @@ static void cvm_oct_stxx_int_pr(union cvmx_stxx_int_reg stx_int_reg, int index) index, 0); } +static irqreturn_t cvm_oct_spi_spx_int(int index) +{ + union cvmx_spxx_int_reg spx_int_reg; + union cvmx_stxx_int_reg stx_int_reg; + + spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(index)); + cvmx_write_csr(CVMX_SPXX_INT_REG(index), spx_int_reg.u64); + if (!need_retrain[index]) { + spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(index)); + cvm_oct_spxx_int_pr(spx_int_reg, index); + } + + stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(index)); + cvmx_write_csr(CVMX_STXX_INT_REG(index), stx_int_reg.u64); + if (!need_retrain[index]) { + stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(index)); + cvm_oct_stxx_int_pr(stx_int_reg, index); + } + + cvmx_write_csr(CVMX_SPXX_INT_MSK(index), 0); + cvmx_write_csr(CVMX_STXX_INT_MSK(index), 0); + need_retrain[index] = 1; + + return IRQ_HANDLED; +} + static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) { irqreturn_t return_status = IRQ_NONE; @@ -111,54 +137,11 @@ static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) /* Check and see if this interrupt was caused by the GMX block */ rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS); - if (rsl_int_blocks.s.spx1) { /* 19 - SPX1_INT_REG & STX1_INT_REG */ - - union cvmx_spxx_int_reg spx_int_reg; - union cvmx_stxx_int_reg stx_int_reg; - - spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(1)); - cvmx_write_csr(CVMX_SPXX_INT_REG(1), spx_int_reg.u64); - if (!need_retrain[1]) { - spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(1)); - cvm_oct_spxx_int_pr(spx_int_reg, 1); - } + if (rsl_int_blocks.s.spx1) /* 19 - SPX1_INT_REG & STX1_INT_REG */ + return_status = cvm_oct_spi_spx_int(1); - stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(1)); - cvmx_write_csr(CVMX_STXX_INT_REG(1), stx_int_reg.u64); - if (!need_retrain[1]) { - stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(1)); - cvm_oct_stxx_int_pr(stx_int_reg, 1); - } - - cvmx_write_csr(CVMX_SPXX_INT_MSK(1), 0); - cvmx_write_csr(CVMX_STXX_INT_MSK(1), 0); - need_retrain[1] = 1; - return_status = IRQ_HANDLED; - } - - if (rsl_int_blocks.s.spx0) { /* 18 - SPX0_INT_REG & STX0_INT_REG */ - union cvmx_spxx_int_reg spx_int_reg; - union cvmx_stxx_int_reg stx_int_reg; - - spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(0)); - cvmx_write_csr(CVMX_SPXX_INT_REG(0), spx_int_reg.u64); - if (!need_retrain[0]) { - spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(0)); - cvm_oct_spxx_int_pr(spx_int_reg, 0); - } - - stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(0)); - cvmx_write_csr(CVMX_STXX_INT_REG(0), stx_int_reg.u64); - if (!need_retrain[0]) { - stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(0)); - cvm_oct_stxx_int_pr(stx_int_reg, 0); - } - - cvmx_write_csr(CVMX_SPXX_INT_MSK(0), 0); - cvmx_write_csr(CVMX_STXX_INT_MSK(0), 0); - need_retrain[0] = 1; - return_status = IRQ_HANDLED; - } + if (rsl_int_blocks.s.spx0) /* 18 - SPX0_INT_REG & STX0_INT_REG */ + return_status = cvm_oct_spi_spx_int(0); return return_status; } From 280eb5b528fa49c141cafcc1b86bb24d1760b2d4 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:14 +0300 Subject: [PATCH 0456/3798] staging: octeon-ethernet: delete references to CONFIG_CAVIUM_RESERVE32 Delete references to CONFIG_CAVIUM_RESERVE32. Kernel does not have such option and the driver does not use it for anything. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-defines.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h index 2a98a2153e1646..d61955cb438cfb 100644 --- a/drivers/staging/octeon/ethernet-defines.h +++ b/drivers/staging/octeon/ethernet-defines.h @@ -27,12 +27,6 @@ /* * A few defines are used to control the operation of this driver: - * CONFIG_CAVIUM_RESERVE32 - * This kernel config options controls the amount of memory configured - * in a wired TLB entry for all processes to share. If this is set, the - * driver will use this memory instead of kernel memory for pools. This - * allows 32bit userspace application to access the buffers, but also - * requires all received packets to be copied. * USE_SKBUFFS_IN_HW * Tells the driver to populate the packet buffers with kernel skbuffs. * This allows the driver to receive packets without copying them. It also @@ -60,10 +54,6 @@ #define OCTEON_ETHERNET_VERSION "1.9" -#ifndef CONFIG_CAVIUM_RESERVE32 -#define CONFIG_CAVIUM_RESERVE32 0 -#endif - #define USE_SKBUFFS_IN_HW 1 #ifdef CONFIG_NETFILTER #define REUSE_SKBUFFS_WITHOUT_FREE 0 From 25efe08e849baeac40b9216bae6a5e0299872306 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:15 +0300 Subject: [PATCH 0457/3798] staging: octeon-ethernet: eliminate USE_10MBPS_PREAMBLE_WORKAROUND define We have the workaround always enabled, so eliminate a redundant #define. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-defines.h | 5 ----- drivers/staging/octeon/ethernet-rgmii.c | 14 +++----------- drivers/staging/octeon/ethernet-rx.c | 7 ++----- 3 files changed, 5 insertions(+), 21 deletions(-) diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h index d61955cb438cfb..de6ae6bf918a6f 100644 --- a/drivers/staging/octeon/ethernet-defines.h +++ b/drivers/staging/octeon/ethernet-defines.h @@ -67,11 +67,6 @@ #define USE_RED 1 #define USE_ASYNC_IOBDMA (CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0) -/* - * Allow SW based preamble removal at 10Mbps to workaround PHYs giving - * us bad preambles. - */ -#define USE_10MBPS_PREAMBLE_WORKAROUND 1 /* * Use this to have all FPA frees also tell the L2 not to write data * to memory. diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index ba2ad2aaca3ebc..ad332c3e154661 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -99,14 +99,7 @@ static void cvm_oct_rgmii_poll(struct net_device *dev) link_info = cvmx_helper_link_get(priv->port); if (link_info.u64 == priv->link_info) { - - /* - * If the 10Mbps preamble workaround is supported and we're - * at 10Mbps we may need to do some special checking. - */ - if (USE_10MBPS_PREAMBLE_WORKAROUND && - (link_info.s.speed == 10)) { - + if (link_info.s.speed == 10) { /* * Read the GMXX_RXX_INT_REG[PCTERR] bit and * see if we are getting preamble errors. @@ -140,12 +133,11 @@ static void cvm_oct_rgmii_poll(struct net_device *dev) return; } - /* If the 10Mbps preamble workaround is allowed we need to on + /* Since the 10Mbps preamble workaround is allowed we need to enable preamble checking, FCS stripping, and clear error bits on every speed change. If errors occur during 10Mbps operation the above code will change this stuff */ - if (USE_10MBPS_PREAMBLE_WORKAROUND) - cvm_oct_set_hw_preamble(priv, true); + cvm_oct_set_hw_preamble(priv, true); if (priv->phydev == NULL) { link_info = cvmx_helper_link_autoconf(priv->port); diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 22667dbb10d825..8d40986f60efd1 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -93,11 +93,8 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work) * instead of 60+4FCS. Note these packets still get * counted as frame errors. */ - } else - if (USE_10MBPS_PREAMBLE_WORKAROUND - && ((work->word2.snoip.err_code == 5) - || (work->word2.snoip.err_code == 7))) { - + } else if (work->word2.snoip.err_code == 5 || + work->word2.snoip.err_code == 7) { /* * We received a packet with either an alignment error * or a FCS error. This may be signalling that we are From 6646baf7041214a9d616b55de96315179f112508 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:16 +0300 Subject: [PATCH 0458/3798] staging: octeon-ethernet: eliminate USE_HW_TCPUDP_CHECKSUM define HW checksum is always enabled, so delete a redundant define. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-defines.h | 6 ------ drivers/staging/octeon/ethernet-tx.c | 2 +- drivers/staging/octeon/ethernet.c | 7 ++----- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h index de6ae6bf918a6f..a837d895c1a5a9 100644 --- a/drivers/staging/octeon/ethernet-defines.h +++ b/drivers/staging/octeon/ethernet-defines.h @@ -31,10 +31,6 @@ * Tells the driver to populate the packet buffers with kernel skbuffs. * This allows the driver to receive packets without copying them. It also * means that 32bit userspace can't access the packet buffers. - * USE_HW_TCPUDP_CHECKSUM - * Controls if the Octeon TCP/UDP checksum engine is used for packet - * output. If this is zero, the kernel will perform the checksum in - * software. * USE_ASYNC_IOBDMA * Use asynchronous IO access to hardware. This uses Octeon's asynchronous * IOBDMAs to issue IO accesses without stalling. Set this to zero @@ -61,8 +57,6 @@ #define REUSE_SKBUFFS_WITHOUT_FREE 1 #endif -#define USE_HW_TCPUDP_CHECKSUM 1 - /* Enable Random Early Dropping under load */ #define USE_RED 1 #define USE_ASYNC_IOBDMA (CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0) diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 5b9ac1f6d6f036..94ba85ae7b50d8 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -411,7 +411,7 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) dont_put_skbuff_in_hw: /* Check if we can use the hardware checksumming */ - if (USE_HW_TCPUDP_CHECKSUM && (skb->protocol == htons(ETH_P_IP)) && + if ((skb->protocol == htons(ETH_P_IP)) && (ip_hdr(skb)->version == 4) && (ip_hdr(skb)->ihl == 5) && ((ip_hdr(skb)->frag_off == 0) || (ip_hdr(skb)->frag_off == htons(1 << 14))) && ((ip_hdr(skb)->protocol == IPPROTO_TCP) diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index d395bf527d916d..b662e2ac625f7d 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -468,11 +468,8 @@ int cvm_oct_common_init(struct net_device *dev) && (always_use_pow || strstr(pow_send_list, dev->name))) priv->queue = -1; - if (priv->queue != -1) { - dev->features |= NETIF_F_SG; - if (USE_HW_TCPUDP_CHECKSUM) - dev->features |= NETIF_F_IP_CSUM; - } + if (priv->queue != -1) + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; /* We do our own locking, Linux doesn't need to */ dev->features |= NETIF_F_LLTX; From 3a990f390ec093293c03e9542f2583c5e4c53684 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:17 +0300 Subject: [PATCH 0459/3798] staging: octeon-ethernet: eliminate USE_SKBUFFS_IN_HW define We always try to use skbuffs for packet buffers, so eliminate a redundant define. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-defines.h | 5 ----- drivers/staging/octeon/ethernet-mem.c | 4 ++-- drivers/staging/octeon/ethernet-rx.c | 4 ++-- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h index a837d895c1a5a9..b39bb3ddab1faf 100644 --- a/drivers/staging/octeon/ethernet-defines.h +++ b/drivers/staging/octeon/ethernet-defines.h @@ -27,10 +27,6 @@ /* * A few defines are used to control the operation of this driver: - * USE_SKBUFFS_IN_HW - * Tells the driver to populate the packet buffers with kernel skbuffs. - * This allows the driver to receive packets without copying them. It also - * means that 32bit userspace can't access the packet buffers. * USE_ASYNC_IOBDMA * Use asynchronous IO access to hardware. This uses Octeon's asynchronous * IOBDMAs to issue IO accesses without stalling. Set this to zero @@ -50,7 +46,6 @@ #define OCTEON_ETHERNET_VERSION "1.9" -#define USE_SKBUFFS_IN_HW 1 #ifdef CONFIG_NETFILTER #define REUSE_SKBUFFS_WITHOUT_FREE 0 #else diff --git a/drivers/staging/octeon/ethernet-mem.c b/drivers/staging/octeon/ethernet-mem.c index 964da860f4c45f..ea1232cd1a33d2 100644 --- a/drivers/staging/octeon/ethernet-mem.c +++ b/drivers/staging/octeon/ethernet-mem.c @@ -160,7 +160,7 @@ int cvm_oct_mem_fill_fpa(int pool, int size, int elements) { int freed; - if (USE_SKBUFFS_IN_HW && pool == CVMX_FPA_PACKET_POOL) + if (pool == CVMX_FPA_PACKET_POOL) freed = cvm_oct_fill_hw_skbuff(pool, size, elements); else freed = cvm_oct_fill_hw_memory(pool, size, elements); @@ -169,7 +169,7 @@ int cvm_oct_mem_fill_fpa(int pool, int size, int elements) void cvm_oct_mem_empty_fpa(int pool, int size, int elements) { - if (USE_SKBUFFS_IN_HW && pool == CVMX_FPA_PACKET_POOL) + if (pool == CVMX_FPA_PACKET_POOL) cvm_oct_free_hw_skbuff(pool, size, elements); else cvm_oct_free_hw_memory(pool, size, elements); diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 8d40986f60efd1..91043ccc61db3d 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -230,7 +230,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) } rx_count++; - skb_in_hw = USE_SKBUFFS_IN_HW && work->word2.s.bufs == 1; + skb_in_hw = work->word2.s.bufs == 1; if (likely(skb_in_hw)) { skb = *pskb; prefetch(&skb->head); @@ -391,7 +391,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) * Check to see if the skbuff and work share the same * packet buffer. */ - if (USE_SKBUFFS_IN_HW && likely(packet_not_copied)) { + if (likely(packet_not_copied)) { /* * This buffer needs to be replaced, increment * the number of buffers we need to free by From cccdb27755a3ae79a5fb98257c93d4ea80efe3f8 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:18 +0300 Subject: [PATCH 0460/3798] staging: octeon-ethernet: eliminate USE_RED define We have RED always enabled, so eliminate the #define. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-defines.h | 2 -- drivers/staging/octeon/ethernet.c | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h index b39bb3ddab1faf..58ff9ba80d6989 100644 --- a/drivers/staging/octeon/ethernet-defines.h +++ b/drivers/staging/octeon/ethernet-defines.h @@ -52,8 +52,6 @@ #define REUSE_SKBUFFS_WITHOUT_FREE 1 #endif -/* Enable Random Early Dropping under load */ -#define USE_RED 1 #define USE_ASYNC_IOBDMA (CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0) /* diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index b662e2ac625f7d..afcdce4bce1cdc 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -180,10 +180,7 @@ static void cvm_oct_configure_common_hw(void) } #endif - if (USE_RED) - cvmx_helper_setup_red(num_packet_buffers / 4, - num_packet_buffers / 8); - + cvmx_helper_setup_red(num_packet_buffers / 4, num_packet_buffers / 8); } /** From c93b0e75a819e648e7c16a5ebd503a2a36f7c1ac Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:19 +0300 Subject: [PATCH 0461/3798] staging: octeon-ethernet: eliminate DONT_WRITEBACK This feature is not used so eliminate it. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-defines.h | 8 -------- drivers/staging/octeon/ethernet-mem.c | 2 +- drivers/staging/octeon/ethernet-rx.c | 3 +-- drivers/staging/octeon/ethernet-tx.c | 2 +- drivers/staging/octeon/ethernet.c | 5 ++--- 5 files changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h index 58ff9ba80d6989..8a6f82fb3e2c8b 100644 --- a/drivers/staging/octeon/ethernet-defines.h +++ b/drivers/staging/octeon/ethernet-defines.h @@ -54,14 +54,6 @@ #define USE_ASYNC_IOBDMA (CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0) -/* - * Use this to have all FPA frees also tell the L2 not to write data - * to memory. - */ -#define DONT_WRITEBACK(x) (x) -/* Use this to not have FPA frees control L2 */ -/*#define DONT_WRITEBACK(x) 0 */ - /* Maximum number of SKBs to try to free per xmit packet. */ #define MAX_OUT_QUEUE_DEPTH 1000 diff --git a/drivers/staging/octeon/ethernet-mem.c b/drivers/staging/octeon/ethernet-mem.c index ea1232cd1a33d2..55d921917125b8 100644 --- a/drivers/staging/octeon/ethernet-mem.c +++ b/drivers/staging/octeon/ethernet-mem.c @@ -54,7 +54,7 @@ static int cvm_oct_fill_hw_skbuff(int pool, int size, int elements) break; skb_reserve(skb, 256 - (((unsigned long)skb->data) & 0x7f)); *(struct sk_buff **)(skb->data - sizeof(void *)) = skb; - cvmx_fpa_free(skb->data, pool, DONT_WRITEBACK(size / 128)); + cvmx_fpa_free(skb->data, pool, size / 128); freed--; } return elements - freed; diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 91043ccc61db3d..fbf5f946036abc 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -400,8 +400,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 1); - cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, - DONT_WRITEBACK(1)); + cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 1); } else { cvm_oct_free_work(work); } diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 94ba85ae7b50d8..25f89b6229b02a 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -576,7 +576,7 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev) if (unlikely(packet_buffer == NULL)) { printk_ratelimited("%s: Failed to allocate a packet buffer\n", dev->name); - cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1)); + cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 1); priv->stats.tx_dropped++; dev_kfree_skb_any(skb); return 0; diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index afcdce4bce1cdc..d05bdca3727858 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -203,11 +203,10 @@ int cvm_oct_free_work(void *work_queue_entry) if (unlikely(!segment_ptr.s.i)) cvmx_fpa_free(cvm_oct_get_buffer_ptr(segment_ptr), segment_ptr.s.pool, - DONT_WRITEBACK(CVMX_FPA_PACKET_POOL_SIZE / - 128)); + CVMX_FPA_PACKET_POOL_SIZE / 128); segment_ptr = next_ptr; } - cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1)); + cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 1); return 0; } From 948c251b70e7b6bbaaf8afa1f7e6049c61af7dc6 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:20 +0300 Subject: [PATCH 0462/3798] staging: octeon-ethernet: eliminate OCTEON_ETHERNET_VERSION This driver has drifted away from out-of-tree versions years ago and the version string does not provide any useful information. Instead provide the kernel version string to ethtool, so that we get useful version information e.g. for bug reports. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-defines.h | 3 --- drivers/staging/octeon/ethernet-mdio.c | 6 +++--- drivers/staging/octeon/ethernet.c | 1 - 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h index 8a6f82fb3e2c8b..2c986236f5a3de 100644 --- a/drivers/staging/octeon/ethernet-defines.h +++ b/drivers/staging/octeon/ethernet-defines.h @@ -43,9 +43,6 @@ #include - -#define OCTEON_ETHERNET_VERSION "1.9" - #ifdef CONFIG_NETFILTER #define REUSE_SKBUFFS_WITHOUT_FREE 0 #else diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index 6322d0dd4238d7..2286acac495190 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -29,7 +29,7 @@ #include #include #include - +#include #include #include @@ -45,8 +45,8 @@ static void cvm_oct_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - strlcpy(info->driver, "cavium-ethernet", sizeof(info->driver)); - strlcpy(info->version, OCTEON_ETHERNET_VERSION, sizeof(info->version)); + strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); + strlcpy(info->version, UTS_RELEASE, sizeof(info->version)); strlcpy(info->bus_info, "Builtin", sizeof(info->bus_info)); } diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index d05bdca3727858..b8cd450465a484 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -681,7 +681,6 @@ static int cvm_oct_probe(struct platform_device *pdev) struct device_node *pip; octeon_mdiobus_force_mod_depencency(); - pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION); pip = pdev->dev.of_node; if (!pip) { From 67620987c556ee70034bd71703d61d07b4d96e60 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 4 Apr 2015 22:51:21 +0300 Subject: [PATCH 0463/3798] staging: octeon-ethernet: update boilerplate comments Update boilerplate comments to be more terse by removing redundant information. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-defines.h | 23 +++------------------- drivers/staging/octeon/ethernet-mdio.c | 24 ++++------------------- drivers/staging/octeon/ethernet-mdio.h | 24 ++++------------------- drivers/staging/octeon/ethernet-mem.c | 24 ++++------------------- drivers/staging/octeon/ethernet-mem.h | 23 +++------------------- drivers/staging/octeon/ethernet-rgmii.c | 24 ++++------------------- drivers/staging/octeon/ethernet-rx.c | 24 ++++------------------- drivers/staging/octeon/ethernet-rx.h | 24 ++++------------------- drivers/staging/octeon/ethernet-sgmii.c | 24 ++++------------------- drivers/staging/octeon/ethernet-spi.c | 24 ++++------------------- drivers/staging/octeon/ethernet-tx.c | 24 ++++------------------- drivers/staging/octeon/ethernet-tx.h | 23 +++------------------- drivers/staging/octeon/ethernet-util.h | 23 +++------------------- drivers/staging/octeon/ethernet-xaui.c | 24 ++++------------------- drivers/staging/octeon/ethernet.c | 24 ++++------------------- drivers/staging/octeon/octeon-ethernet.h | 23 +++------------------- 16 files changed, 59 insertions(+), 320 deletions(-) diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h index 2c986236f5a3de..f92e0c478e1686 100644 --- a/drivers/staging/octeon/ethernet-defines.h +++ b/drivers/staging/octeon/ethernet-defines.h @@ -1,29 +1,12 @@ -/********************************************************************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2007 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -**********************************************************************/ + */ /* * A few defines are used to control the operation of this driver: diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index 2286acac495190..fd9b3d899c1ffc 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -1,29 +1,13 @@ -/********************************************************************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2007 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -**********************************************************************/ + */ + #include #include #include diff --git a/drivers/staging/octeon/ethernet-mdio.h b/drivers/staging/octeon/ethernet-mdio.h index 6191b085064606..a530b55f27d89d 100644 --- a/drivers/staging/octeon/ethernet-mdio.h +++ b/drivers/staging/octeon/ethernet-mdio.h @@ -1,29 +1,13 @@ -/********************************************************************* - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2007 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -*********************************************************************/ + */ + #include #include #include diff --git a/drivers/staging/octeon/ethernet-mem.c b/drivers/staging/octeon/ethernet-mem.c index 55d921917125b8..5a5cdb3cd740b2 100644 --- a/drivers/staging/octeon/ethernet-mem.c +++ b/drivers/staging/octeon/ethernet-mem.c @@ -1,29 +1,13 @@ -/********************************************************************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2010 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -**********************************************************************/ + */ + #include #include #include diff --git a/drivers/staging/octeon/ethernet-mem.h b/drivers/staging/octeon/ethernet-mem.h index 713f2edc8b4fd4..62d07c426f89fd 100644 --- a/drivers/staging/octeon/ethernet-mem.h +++ b/drivers/staging/octeon/ethernet-mem.h @@ -1,29 +1,12 @@ -/********************************************************************* - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2007 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -********************************************************************/ + */ int cvm_oct_mem_fill_fpa(int pool, int size, int elements); void cvm_oct_mem_empty_fpa(int pool, int size, int elements); diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index ad332c3e154661..beb7aac9c28907 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -1,29 +1,13 @@ -/********************************************************************* - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2007 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -**********************************************************************/ + */ + #include #include #include diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index fbf5f946036abc..22853d33da0525 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -1,29 +1,13 @@ -/********************************************************************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2010 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -**********************************************************************/ + */ + #include #include #include diff --git a/drivers/staging/octeon/ethernet-rx.h b/drivers/staging/octeon/ethernet-rx.h index 9240c85ce24178..a5973fd015fc7c 100644 --- a/drivers/staging/octeon/ethernet-rx.h +++ b/drivers/staging/octeon/ethernet-rx.h @@ -1,29 +1,13 @@ -/********************************************************************* - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2007 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -*********************************************************************/ + */ + #include void cvm_oct_poll_controller(struct net_device *dev); diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c index 1940f4b72a66eb..8bceb769166cd0 100644 --- a/drivers/staging/octeon/ethernet-sgmii.c +++ b/drivers/staging/octeon/ethernet-sgmii.c @@ -1,29 +1,13 @@ -/********************************************************************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2007 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -**********************************************************************/ + */ + #include #include #include diff --git a/drivers/staging/octeon/ethernet-spi.c b/drivers/staging/octeon/ethernet-spi.c index 5313ac54d863e2..2ae1944b3a1bfb 100644 --- a/drivers/staging/octeon/ethernet-spi.c +++ b/drivers/staging/octeon/ethernet-spi.c @@ -1,29 +1,13 @@ -/********************************************************************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2007 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -**********************************************************************/ + */ + #include #include #include diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 25f89b6229b02a..7c1c1b052b7d17 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -1,29 +1,13 @@ -/********************************************************************* - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2010 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -*********************************************************************/ + */ + #include #include #include diff --git a/drivers/staging/octeon/ethernet-tx.h b/drivers/staging/octeon/ethernet-tx.h index 547680c6c371e0..84848e4c166421 100644 --- a/drivers/staging/octeon/ethernet-tx.h +++ b/drivers/staging/octeon/ethernet-tx.h @@ -1,29 +1,12 @@ -/********************************************************************* - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2007 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -*********************************************************************/ + */ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev); int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev); diff --git a/drivers/staging/octeon/ethernet-util.h b/drivers/staging/octeon/ethernet-util.h index 0f9b4a18fc27ce..1ba789a7741bd2 100644 --- a/drivers/staging/octeon/ethernet-util.h +++ b/drivers/staging/octeon/ethernet-util.h @@ -1,29 +1,12 @@ -/********************************************************************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2007 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -*********************************************************************/ + */ /** * cvm_oct_get_buffer_ptr - convert packet data address to pointer diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c index 42a4d2be0cffb6..4b47bcfaabb15a 100644 --- a/drivers/staging/octeon/ethernet-xaui.c +++ b/drivers/staging/octeon/ethernet-xaui.c @@ -1,29 +1,13 @@ -/********************************************************************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2007 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -**********************************************************************/ + */ + #include #include #include diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index b8cd450465a484..f9dba23a375914 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -1,29 +1,13 @@ -/********************************************************************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2007 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -**********************************************************************/ + */ + #include #include #include diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index 22d726e0d2d03b..e9d3e9a7e8a78b 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -1,29 +1,12 @@ -/********************************************************************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK +/* + * This file is based on code from OCTEON SDK by Cavium Networks. * * Copyright (c) 2003-2010 Cavium Networks * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information -**********************************************************************/ + */ /* * External interface for the Cavium Octeon ethernet driver. From 9059c615a8ba503cb5a7823d7f943a384e6063e3 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 7 Apr 2015 13:55:01 +0530 Subject: [PATCH 0464/3798] staging: panel: remove duplicate code both the misc_deregister(), parport_release() and parport_unregister_device() is there in the module_exit function also. detach is called from parport_unregister_driver() and by the time detach executes misc_deregister(), parport_release() and parport_unregister_device() has already executed marking keypad_initialized and lcd.initialized as false. so this part of the code will never execute. Signed-off-by: Sudip Mukherjee Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index ea54fb4ec837ea..1d8ed8b35375da 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -2252,20 +2252,6 @@ static void panel_detach(struct parport *port) } unregister_reboot_notifier(&panel_notifier); - - if (keypad.enabled && keypad_initialized) { - misc_deregister(&keypad_dev); - keypad_initialized = 0; - } - - if (lcd.enabled && lcd.initialized) { - misc_deregister(&lcd_dev); - lcd.initialized = false; - } - - parport_release(pprt); - parport_unregister_device(pprt); - pprt = NULL; } static struct parport_driver panel_driver = { From 351f6689cc2941f4e1ec588b8b4673457acf2e58 Mon Sep 17 00:00:00 2001 From: Andrei Maresu Date: Thu, 9 Apr 2015 23:29:31 +0300 Subject: [PATCH 0465/3798] Staging: comedi: daqboard2000.c fixed trailing whitespace Fixed a coding style issue. Signed-off-by: Andrei Maresu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/daqboard2000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index f97d18d92255bf..64a87039b8024d 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -40,7 +40,7 @@ Configuration options: not applicable, uses PCI auto config for the card, and here are the findings so far. 1. A good document that describes the PCI interface chip is 9080db-106.pdf - available from http://www.plxtech.com/products/io/pci9080 + available from http://www.plxtech.com/products/io/pci9080 2. The initialization done so far is: a. program the FPGA (windows code sans a lot of error messages) From b3ab6fbfd8625232c54d70e29f7274118726ba45 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 20 Apr 2015 11:49:04 -0700 Subject: [PATCH 0466/3798] staging: comedi: comedi_bond: fix 'b_mask' calc in bonding_dio_insn_bits() 'b_chans' may be a valud up to 32. 'b_mask' is an unsigned int and a left shift of more than 31 bits has undefined behavior. Fix the calc so it works correctly with a 'b_chans' of 32.. Reported-by: coverity (CID 1192244) Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/comedi_bond.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index 96db0c2686a1e6..50b76eccb7d708 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -101,7 +101,8 @@ static int bonding_dio_insn_bits(struct comedi_device *dev, b_chans = bdev->nchans - base_chan; if (b_chans > n_left) b_chans = n_left; - b_mask = (1U << b_chans) - 1; + b_mask = (b_chans < 32) ? ((1 << b_chans) - 1) + : 0xffffffff; b_write_mask = (write_mask >> n_done) & b_mask; b_data_bits = (data_bits >> n_done) & b_mask; /* Read/Write the new digital lines. */ From accb298fb2e3d09a84bd92595b115232f14a5e60 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 20 Apr 2015 11:49:05 -0700 Subject: [PATCH 0467/3798] staging: comedi: ni_nio_common: don't write non-existing caldac's ni_write_caldac() checks the boardinfo 'caldac' array to determine what caldac is used for a given 'addr'. It then calculates the 'bitstring' and number of 'bits' used to write a value to that caldac address. After checking the caldac array, if the number of bits is 0 there is no caldac associated with the address. If this happens we shouldn't try writing to the non-existing caldac. Reported-by: coverity (CID 1192116) Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index c66affd993aa98..69d71f32800672 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -4355,6 +4355,10 @@ static void ni_write_caldac(struct comedi_device *dev, int addr, int val) addr -= caldacs[type].n_chans; } + /* bits will be 0 if there is no caldac for the given addr */ + if (bits == 0) + return; + for (bit = 1 << (bits - 1); bit; bit >>= 1) { ni_writeb(dev, ((bit & bitstring) ? 0x02 : 0), Serial_Command); udelay(1); From a437dee5335e3b5fdb82199f11eebf3f41bf5b8e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 20 Apr 2015 11:49:06 -0700 Subject: [PATCH 0468/3798] staging: comedi: serial2002: fix Coverity "Explicit null dereference" serial2002_setup_subdevices() initializes each subdevice based on the config read from the attached serial device. Part of this initialization is to setup the subdevice range_table_list for the non digital subdevices. The range_table_list is allocated only when a 'range' is passed to the functions. Each channel of the subdevice then has it's 'range' initialized and that range is added to the range_table_list. The logic of this function works but causes Coverity complain about an Explicit null dereference of the allocated 'range_table_list'. Add a check for the 'range_table_list' to quiet the Coverity issue. Reported-by: coverity (CID 1011632) Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/serial2002.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index 304ebff119eeac..83da162deb526c 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -373,7 +373,7 @@ static int serial2002_setup_subdevice(struct comedi_subdevice *s, if (cfg[j].kind == kind) { if (mapping) mapping[chan] = j; - if (range) { + if (range && range_table_list) { range[j].length = 1; range[j].range.min = cfg[j].min; range[j].range.max = cfg[j].max; From 8fc369ae38ff281d38e9ea11805a5cae862989bc Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 21 Apr 2015 13:18:10 +0100 Subject: [PATCH 0469/3798] staging: comedi: wrap COMEDI_SRF_FREE_SPRIV usage The `COMEDI_SRF_FREE_SPRIV` flag in the `runflags` member of `struct comedi_subdevice` indicates that the memory pointed to by the `private` member can be automatically freed by the comedi core on subdevice clean-up (when the low-level comedi device is being "detached"). the flag doesn't really belong in `runflags`, but it was somewhere convenient to keep it without having to add a new member to the structure. Rather than access the `COMEDI_SRF_FREE_SPRIV` flag directly, use some new wrapper functions: * comedi_can_auto_free_spriv(s) - checks whether the subdevice's `s->private` points to memory that can be freed automatically. * comedi_set_spriv_auto_free(s) - marks the subdevice as having a `s->private` that points to memory that can be freed automatically. Export `comedi_set_spriv_auto_free()` for use by the low-level comedi driver modules, in particular the "amplc_dio200_common" module. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 24 +++++++++++++++++-- drivers/staging/comedi/comedi_internal.h | 1 + drivers/staging/comedi/comedidev.h | 1 + drivers/staging/comedi/drivers.c | 2 +- .../comedi/drivers/amplc_dio200_common.c | 6 ++--- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index e78ddbe5a954f9..fc339c5c50fca5 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -679,8 +679,28 @@ static bool comedi_is_subdevice_idle(struct comedi_subdevice *s) return !(runflags & COMEDI_SRF_BUSY_MASK); } +bool comedi_can_auto_free_spriv(struct comedi_subdevice *s) +{ + unsigned runflags = __comedi_get_subdevice_runflags(s); + + return runflags & COMEDI_SRF_FREE_SPRIV; +} + +/** + * comedi_set_spriv_auto_free - mark subdevice private data as freeable + * @s: comedi_subdevice struct + * + * Mark the subdevice as having a pointer to private data that can be + * automatically freed by the comedi core during the detach. + */ +void comedi_set_spriv_auto_free(struct comedi_subdevice *s) +{ + __comedi_set_subdevice_runflags(s, COMEDI_SRF_FREE_SPRIV); +} +EXPORT_SYMBOL_GPL(comedi_set_spriv_auto_free); + /** - * comedi_alloc_spriv() - Allocate memory for the subdevice private data. + * comedi_alloc_spriv - Allocate memory for the subdevice private data. * @s: comedi_subdevice struct * @size: size of the memory to allocate * @@ -691,7 +711,7 @@ void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size) { s->private = kzalloc(size, GFP_KERNEL); if (s->private) - s->runflags |= COMEDI_SRF_FREE_SPRIV; + comedi_set_spriv_auto_free(s); return s->private; } EXPORT_SYMBOL_GPL(comedi_alloc_spriv); diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h index 3b918538847e61..cd9437f72c3535 100644 --- a/drivers/staging/comedi/comedi_internal.h +++ b/drivers/staging/comedi/comedi_internal.h @@ -33,6 +33,7 @@ struct comedi_buf_map *comedi_buf_map_from_subdev_get( struct comedi_subdevice *s); unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s); void comedi_device_cancel_all(struct comedi_device *dev); +bool comedi_can_auto_free_spriv(struct comedi_subdevice *s); extern unsigned int comedi_default_buf_size_kb; extern unsigned int comedi_default_buf_maxsize_kb; diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index dfab5a84b011f5..52071f7494c450 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -323,6 +323,7 @@ int comedi_dev_put(struct comedi_device *dev); bool comedi_is_subdevice_running(struct comedi_subdevice *s); void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size); +void comedi_set_spriv_auto_free(struct comedi_subdevice *s); int comedi_check_chanlist(struct comedi_subdevice *s, int n, diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 57dcffe0020458..ed0b60c925def8 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -125,7 +125,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev) if (dev->subdevices) { for (i = 0; i < dev->n_subdevices; i++) { s = &dev->subdevices[i]; - if (s->runflags & COMEDI_SRF_FREE_SPRIV) + if (comedi_can_auto_free_spriv(s)) kfree(s->private); comedi_free_subdevice_minor(s); if (s->async) { diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index d15a3dc1216a0a..3a8b3f27b5259a 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -593,10 +593,10 @@ static int dio200_subdev_8254_init(struct comedi_device *dev, * There could be multiple timers so this driver does not * use dev->pacer to save the i8254 pointer. Instead, * comedi_8254_subdevice_init() saved the i8254 pointer in - * s->private. Set the runflag bit so that the core will - * automatically free it when the driver is detached. + * s->private. Mark the subdevice as having private data + * to be automatically freed when the device is detached. */ - s->runflags |= COMEDI_SRF_FREE_SPRIV; + comedi_set_spriv_auto_free(s); /* Initialize channels. */ if (board->has_clk_gat_sce) { From eb340acaca5eea5f87a4a1b037a32e257d8509b5 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 21 Apr 2015 13:18:11 +0100 Subject: [PATCH 0470/3798] staging: comedi: move COMEDI_SRF_... macros to "comedi_fops.c" The `COMEDI_SRF_...` macros define flag combinations in the `runflags` member of `struct comedi_subdevice`. They are only used directly in "comedi_fops.c", so move them to there. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 17 +++++++++++++++++ drivers/staging/comedi/comedidev.h | 17 ----------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index fc339c5c50fca5..6f269cc3563341 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -43,6 +43,23 @@ #include "comedi_internal.h" +/** + * comedi_subdevice "runflags" + * @COMEDI_SRF_RT: DEPRECATED: command is running real-time + * @COMEDI_SRF_ERROR: indicates an COMEDI_CB_ERROR event has occurred + * since the last command was started + * @COMEDI_SRF_RUNNING: command is running + * @COMEDI_SRF_FREE_SPRIV: free s->private on detach + * + * @COMEDI_SRF_BUSY_MASK: runflags that indicate the subdevice is "busy" + */ +#define COMEDI_SRF_RT BIT(1) +#define COMEDI_SRF_ERROR BIT(2) +#define COMEDI_SRF_RUNNING BIT(27) +#define COMEDI_SRF_FREE_SPRIV BIT(31) + +#define COMEDI_SRF_BUSY_MASK (COMEDI_SRF_ERROR | COMEDI_SRF_RUNNING) + /** * struct comedi_file - per-file private data for comedi device * @dev: comedi_device struct diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 52071f7494c450..28f26062a54c75 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -303,23 +303,6 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s); struct comedi_device *comedi_dev_get_from_minor(unsigned minor); int comedi_dev_put(struct comedi_device *dev); -/** - * comedi_subdevice "runflags" - * @COMEDI_SRF_RT: DEPRECATED: command is running real-time - * @COMEDI_SRF_ERROR: indicates an COMEDI_CB_ERROR event has occurred - * since the last command was started - * @COMEDI_SRF_RUNNING: command is running - * @COMEDI_SRF_FREE_SPRIV: free s->private on detach - * - * @COMEDI_SRF_BUSY_MASK: runflags that indicate the subdevice is "busy" - */ -#define COMEDI_SRF_RT BIT(1) -#define COMEDI_SRF_ERROR BIT(2) -#define COMEDI_SRF_RUNNING BIT(27) -#define COMEDI_SRF_FREE_SPRIV BIT(31) - -#define COMEDI_SRF_BUSY_MASK (COMEDI_SRF_ERROR | COMEDI_SRF_RUNNING) - bool comedi_is_subdevice_running(struct comedi_subdevice *s); void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size); From e6f2804d580667515cee34812aa92e84cc142e55 Mon Sep 17 00:00:00 2001 From: "Gujulan Elango, Hari Prasath (H.)" Date: Thu, 23 Apr 2015 19:14:21 +0000 Subject: [PATCH 0471/3798] staging: comedi: Remove unwanted lines of code This patch removes a few lines of code & retains the same functionality Signed-off-by: Hari Prasath Gujulan Elango Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcimdda.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index a4781dbbdd82e6..19210d89f2b23d 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -164,11 +164,7 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev, s = &dev->subdevices[1]; /* digital i/o subdevice */ - ret = subdev_8255_init(dev, s, NULL, PCIMDDA_8255_BASE_REG); - if (ret) - return ret; - - return 0; + return subdev_8255_init(dev, s, NULL, PCIMDDA_8255_BASE_REG); } static struct comedi_driver cb_pcimdda_driver = { From f17ca811835cf69e734ab189a942964c2f32006d Mon Sep 17 00:00:00 2001 From: Gbenga Adalumo Date: Wed, 22 Apr 2015 00:39:48 -0700 Subject: [PATCH 0472/3798] Staging: comedi: fix code indent coding style issues in daqboard2000.c This is a patch to daqboard2000.c file that fixes code indent errors found by the checkpatch.pl tool Signed-off-by: Gbenga Adalumo Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/daqboard2000.c | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 64a87039b8024d..2ca8d3eec74254 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -43,7 +43,7 @@ Configuration options: not applicable, uses PCI auto config available from http://www.plxtech.com/products/io/pci9080 2. The initialization done so far is: - a. program the FPGA (windows code sans a lot of error messages) + a. program the FPGA (windows code sans a lot of error messages) b. 3. Analog out seems to work OK with DAC's disabled, if DAC's are enabled, @@ -52,52 +52,52 @@ Configuration options: not applicable, uses PCI auto config gives me no clues. I'll keep it simple so far. 4. Analog in. - Each channel in the scanlist seems to be controlled by four + Each channel in the scanlist seems to be controlled by four control words: - Word0: - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! | | | ! | | | ! | | | ! | | | ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Word0: + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! | | | ! | | | ! | | | ! | | | ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - Word1: - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! | | | ! | | | ! | | | ! | | | ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Word1: + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! | | | ! | | | ! | | | ! | | | ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | | | | | - +------+------+ | | | | +-- Digital input (??) + +------+------+ | | | | +-- Digital input (??) | | | | +---- 10 us settling time | | | +------ Suspend acquisition (last to scan) | | +-------- Simultaneous sample and hold | +---------- Signed data format +------------------------- Correction offset low - Word2: - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! | | | ! | | | ! | | | ! | | | ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | | | | | | | | | - +-----+ +--+--+ +++ +++ +--+--+ - | | | | +----- Expansion channel + Word2: + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! | | | ! | | | ! | | | ! | | | ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | | | | | | | | | + +-----+ +--+--+ +++ +++ +--+--+ + | | | | +----- Expansion channel | | | +----------- Expansion gain - | | +--------------- Channel (low) + | | +--------------- Channel (low) | +--------------------- Correction offset high +----------------------------- Correction gain low - Word3: - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! | | | ! | | | ! | | | ! | | | ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | | | | | | | | - +------+------+ | | +-+-+ | | +-- Low bank enable - | | | | | +---- High bank enable - | | | | +------ Hi/low select + Word3: + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! | | | ! | | | ! | | | ! | | | ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | | | | | | | | + +------+------+ | | +-+-+ | | +-- Low bank enable + | | | | | +---- High bank enable + | | | | +------ Hi/low select | | | +---------- Gain (1,?,2,4,8,16,32,64) | | +-------------- differential/single ended | +---------------- Unipolar +------------------------- Correction gain high 999. The card seems to have an incredible amount of capabilities, but - trying to reverse engineer them from the Windows source is beyond my + trying to reverse engineer them from the Windows source is beyond my patience. */ From c93f5463e35a95c8cad5deb4ad5d32b0eb913abd Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Fri, 1 May 2015 00:27:35 +0800 Subject: [PATCH 0473/3798] staging: lustre: fix ifnullfree.cocci warnings drivers/staging/lustre/lustre/lov/lov_obd.c:574:3-8: WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values. NULL check before some freeing functions is not needed. Based on checkpatch warning "kfree(NULL) is safe this check is probably not required" and kfreeaddr.cocci by Julia Lawall. Generated by: scripts/coccinelle/free/ifnullfree.cocci CC: Julia Lawall Signed-off-by: Fengguang Wu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_obd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 7e125380970872..054ca32099c826 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -570,8 +570,7 @@ static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp, lov->lov_tgts = newtgts; lov->lov_tgt_size = newsize; smp_rmb(); - if (old) - kfree(old); + kfree(old); CDEBUG(D_CONFIG, "tgts: %p size: %d\n", lov->lov_tgts, lov->lov_tgt_size); From 25e428999c0de31f966e9e4b61ec69d8dc033f70 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Fri, 1 May 2015 00:27:35 +0800 Subject: [PATCH 0474/3798] staging: lustre: fix ifnullfree.cocci warnings drivers/staging/lustre/lustre/lov/lov_request.c:74:3-8: WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values. NULL check before some freeing functions is not needed. Based on checkpatch warning "kfree(NULL) is safe this check is probably not required" and kfreeaddr.cocci by Julia Lawall. Generated by: scripts/coccinelle/free/ifnullfree.cocci CC: Julia Lawall Signed-off-by: Fengguang Wu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_request.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 0a8cdbe1a537dc..f6e13149d2ad37 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -70,8 +70,7 @@ void lov_finish_set(struct lov_request_set *set) OBDO_FREE(req->rq_oi.oi_oa); if (req->rq_oi.oi_md) OBD_FREE_LARGE(req->rq_oi.oi_md, req->rq_buflen); - if (req->rq_oi.oi_osfs) - kfree(req->rq_oi.oi_osfs); + kfree(req->rq_oi.oi_osfs); kfree(req); } From 0550db925bf79707b5612c2769075f3fac713c3a Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Fri, 1 May 2015 00:21:55 +0800 Subject: [PATCH 0475/3798] staging: lustre: llite: fix ifnullfree.cocci warnings drivers/staging/lustre/lustre/llite/llite_lib.c:989:2-7: WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values. drivers/staging/lustre/lustre/llite/llite_lib.c:991:2-7: WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values. NULL check before some freeing functions is not needed. Based on checkpatch warning "kfree(NULL) is safe this check is probably not required" and kfreeaddr.cocci by Julia Lawall. Generated by: scripts/coccinelle/free/ifnullfree.cocci CC: Julia Lawall Signed-off-by: Fengguang Wu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_lib.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index f44abb6614047a..e5bac94f690b32 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -985,10 +985,8 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) err = client_common_fill_super(sb, md, dt, mnt); out_free: - if (md) - kfree(md); - if (dt) - kfree(dt); + kfree(md); + kfree(dt); if (err) ll_put_super(sb); else if (sbi->ll_flags & LL_SBI_VERBOSE) From fd5e2fd053e1042b12343fb6649449081ec1bab4 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Fri, 1 May 2015 00:21:55 +0800 Subject: [PATCH 0476/3798] staging: lustre: llite: fix ifnullfree.cocci warnings drivers/staging/lustre/lustre/llite/dir.c:1440:3-8: WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values. NULL check before some freeing functions is not needed. Based on checkpatch warning "kfree(NULL) is safe this check is probably not required" and kfreeaddr.cocci by Julia Lawall. Generated by: scripts/coccinelle/free/ifnullfree.cocci CC: Julia Lawall Signed-off-by: Fengguang Wu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 0f5d57cb149ad8..f17154aaa3297c 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1436,8 +1436,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) goto free_lmv; } free_lmv: - if (tmp) - kfree(tmp); + kfree(tmp); return rc; } case LL_IOC_REMOVE_ENTRY: { From 6920ccf65d0964f7f6c6c36c551151e0fcd62327 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Thu, 16 Apr 2015 22:20:59 +0300 Subject: [PATCH 0477/3798] staging: iio: light: isl29018: Use standard sysfs attributes for scale and integration time This patch refactors the isl29018 driver code in order to use standard sysfs attributes for scale and integration time. ISL29018 light sensor uses four ranges and four ADC's resolutions which influence the calculated lux. Adc resolution is strongly connected to integration time and range should be controlled by scale. This patch introduces the usage of integration time and scale instead of adc resolution and range. Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 226 +++++++++++++++++++++------ 1 file changed, 177 insertions(+), 49 deletions(-) diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index ffc3d1b2ee9a72..08ca9a4172e355 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -66,6 +66,39 @@ #define ISL29035_BOUT_SHIFT 0x07 #define ISL29035_BOUT_MASK (0x01 << ISL29035_BOUT_SHIFT) +#define ISL29018_INT_TIME_AVAIL "0.090000 0.005630 0.000351 0.000021" +#define ISL29023_INT_TIME_AVAIL "0.090000 0.005600 0.000352 0.000022" +#define ISL29035_INT_TIME_AVAIL "0.105000 0.006500 0.000410 0.000025" + +static const char * const int_time_avail[] = { + ISL29018_INT_TIME_AVAIL, + ISL29023_INT_TIME_AVAIL, + ISL29035_INT_TIME_AVAIL, +}; + +enum isl29018_int_time { + ISL29018_INT_TIME_16, + ISL29018_INT_TIME_12, + ISL29018_INT_TIME_8, + ISL29018_INT_TIME_4, +}; + +static const unsigned int isl29018_int_utimes[3][4] = { + {90000, 5630, 351, 21}, + {90000, 5600, 352, 22}, + {105000, 6500, 410, 25}, +}; + +static const struct isl29018_scale { + unsigned int scale; + unsigned int uscale; +} isl29018_scales[4][4] = { + { {0, 15258}, {0, 61035}, {0, 244140}, {0, 976562} }, + { {0, 244140}, {0, 976562}, {3, 906250}, {15, 625000} }, + { {3, 906250}, {15, 625000}, {62, 500000}, {250, 0} }, + { {62, 500000}, {250, 0}, {1000, 0}, {4000, 0} } +}; + struct isl29018_chip { struct device *dev; struct regmap *regmap; @@ -73,51 +106,75 @@ struct isl29018_chip { int type; unsigned int calibscale; unsigned int ucalibscale; - unsigned int range; - unsigned int adc_bit; + unsigned int int_time; + struct isl29018_scale scale; int prox_scheme; bool suspended; }; -static int isl29018_set_range(struct isl29018_chip *chip, unsigned long range, - unsigned int *new_range) +static int isl29018_set_integration_time(struct isl29018_chip *chip, + unsigned int utime) { - static const unsigned long supp_ranges[] = {1000, 4000, 16000, 64000}; - int i; - - for (i = 0; i < ARRAY_SIZE(supp_ranges); ++i) { - if (range <= supp_ranges[i]) { - *new_range = (unsigned int)supp_ranges[i]; + int i, ret; + unsigned int int_time, new_int_time; + struct isl29018_scale new_scale; + + for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) { + if (utime == isl29018_int_utimes[chip->type][i]) { + new_int_time = i; + new_scale = isl29018_scales[new_int_time][0]; break; } } - if (i >= ARRAY_SIZE(supp_ranges)) + if (i >= ARRAY_SIZE(isl29018_int_utimes[chip->type])) return -EINVAL; - return regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, - COMMANDII_RANGE_MASK, i << COMMANDII_RANGE_SHIFT); + ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, + COMMANDII_RESOLUTION_MASK, + i << COMMANDII_RESOLUTION_SHIFT); + if (ret < 0) + return ret; + + /* keep the same range when integration time changes */ + int_time = chip->int_time; + for (i = 0; i < ARRAY_SIZE(isl29018_scales[int_time]); ++i) { + if (chip->scale.scale == isl29018_scales[int_time][i].scale && + chip->scale.uscale == isl29018_scales[int_time][i].uscale) { + chip->scale = isl29018_scales[new_int_time][i]; + break; + } + } + chip->int_time = new_int_time; + + return 0; } -static int isl29018_set_resolution(struct isl29018_chip *chip, - unsigned long adcbit, unsigned int *conf_adc_bit) +static int isl29018_set_scale(struct isl29018_chip *chip, int scale, int uscale) { - static const unsigned long supp_adcbit[] = {16, 12, 8, 4}; - int i; + int i, ret; + struct isl29018_scale new_scale; - for (i = 0; i < ARRAY_SIZE(supp_adcbit); ++i) { - if (adcbit >= supp_adcbit[i]) { - *conf_adc_bit = (unsigned int)supp_adcbit[i]; + for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) { + if (scale == isl29018_scales[chip->int_time][i].scale && + uscale == isl29018_scales[chip->int_time][i].uscale) { + new_scale = isl29018_scales[chip->int_time][i]; break; } } - if (i >= ARRAY_SIZE(supp_adcbit)) + if (i >= ARRAY_SIZE(isl29018_scales[chip->int_time])) return -EINVAL; - return regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, - COMMANDII_RESOLUTION_MASK, - i << COMMANDII_RESOLUTION_SHIFT); + ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, + COMMANDII_RANGE_MASK, + i << COMMANDII_RANGE_SHIFT); + if (ret < 0) + return ret; + + chip->scale = new_scale; + + return 0; } static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode) @@ -156,22 +213,17 @@ static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode) static int isl29018_read_lux(struct isl29018_chip *chip, int *lux) { int lux_data; - unsigned int data_x_range, lux_unshifted; + unsigned int data_x_range; lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE); if (lux_data < 0) return lux_data; - /* To support fractional scaling, separate the unshifted lux - * into two calculations: int scaling and micro-scaling. - * ucalibscale ranges from 0-999999, so about 20 bits. Split - * the /1,000,000 in two to reduce the risk of over/underflow. - */ - data_x_range = lux_data * chip->range; - lux_unshifted = data_x_range * chip->calibscale; - lux_unshifted += data_x_range / 1000 * chip->ucalibscale / 1000; - *lux = lux_unshifted >> chip->adc_bit; + data_x_range = lux_data * chip->scale.scale + + lux_data * chip->scale.uscale / 1000000; + *lux = data_x_range * chip->calibscale + + data_x_range * chip->ucalibscale / 1000000; return 0; } @@ -229,7 +281,39 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, return 0; } -/* Sysfs interface */ +static ssize_t show_scale_available(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct isl29018_chip *chip = iio_priv(indio_dev); + int i, len = 0; + + for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) + len += sprintf(buf + len, "%d.%06d ", + isl29018_scales[chip->int_time][i].scale, + isl29018_scales[chip->int_time][i].uscale); + + buf[len - 1] = '\n'; + + return len; +} + +static ssize_t show_int_time_available(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct isl29018_chip *chip = iio_priv(indio_dev); + int i, len = 0; + + for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) + len += sprintf(buf + len, "0.%06d ", + isl29018_int_utimes[chip->type][i]); + + buf[len - 1] = '\n'; + + return len; +} + /* proximity scheme */ static ssize_t show_prox_infrared_suppression(struct device *dev, struct device_attribute *attr, char *buf) @@ -276,11 +360,28 @@ static int isl29018_write_raw(struct iio_dev *indio_dev, int ret = -EINVAL; mutex_lock(&chip->lock); - if (mask == IIO_CHAN_INFO_CALIBSCALE && chan->type == IIO_LIGHT) { - chip->calibscale = val; - /* With no write_raw_get_fmt(), val2 is a MICRO fraction. */ - chip->ucalibscale = val2; - ret = 0; + switch (mask) { + case IIO_CHAN_INFO_CALIBSCALE: + if (chan->type == IIO_LIGHT) { + chip->calibscale = val; + chip->ucalibscale = val2; + ret = 0; + } + break; + case IIO_CHAN_INFO_INT_TIME: + if (chan->type == IIO_LIGHT) + if (val != 0) { + mutex_unlock(&chip->lock); + return -EINVAL; + } + ret = isl29018_set_integration_time(chip, val2); + break; + case IIO_CHAN_INFO_SCALE: + if (chan->type == IIO_LIGHT) + ret = isl29018_set_scale(chip, val, val2); + break; + default: + break; } mutex_unlock(&chip->lock); @@ -321,6 +422,20 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, if (!ret) ret = IIO_VAL_INT; break; + case IIO_CHAN_INFO_INT_TIME: + if (chan->type == IIO_LIGHT) { + *val = 0; + *val2 = isl29018_int_utimes[chip->type][chip->int_time]; + ret = IIO_VAL_INT_PLUS_MICRO; + } + break; + case IIO_CHAN_INFO_SCALE: + if (chan->type == IIO_LIGHT) { + *val = chip->scale.scale; + *val2 = chip->scale.uscale; + ret = IIO_VAL_INT_PLUS_MICRO; + } + break; case IIO_CHAN_INFO_CALIBSCALE: if (chan->type == IIO_LIGHT) { *val = chip->calibscale; @@ -340,7 +455,9 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, .indexed = 1, \ .channel = 0, \ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | \ - BIT(IIO_CHAN_INFO_CALIBSCALE), \ + BIT(IIO_CHAN_INFO_CALIBSCALE) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_INT_TIME), \ } #define ISL29018_IR_CHANNEL { \ @@ -366,19 +483,27 @@ static const struct iio_chan_spec isl29023_channels[] = { ISL29018_IR_CHANNEL, }; +static IIO_DEVICE_ATTR(in_illuminance_integration_time_available, S_IRUGO, + show_int_time_available, NULL, 0); +static IIO_DEVICE_ATTR(in_illuminance_scale_available, S_IRUGO, + show_scale_available, NULL, 0); static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression, S_IRUGO | S_IWUSR, show_prox_infrared_suppression, store_prox_infrared_suppression, 0); #define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) -#define ISL29018_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr) + static struct attribute *isl29018_attributes[] = { + ISL29018_DEV_ATTR(in_illuminance_scale_available), + ISL29018_DEV_ATTR(in_illuminance_integration_time_available), ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_suppression), NULL }; static struct attribute *isl29023_attributes[] = { + ISL29018_DEV_ATTR(in_illuminance_scale_available), + ISL29018_DEV_ATTR(in_illuminance_integration_time_available), NULL }; @@ -422,8 +547,6 @@ enum { static int isl29018_chip_init(struct isl29018_chip *chip) { int status; - unsigned int new_adc_bit; - unsigned int new_range; if (chip->type == isl29035) { status = isl29035_detect(chip); @@ -472,14 +595,19 @@ static int isl29018_chip_init(struct isl29018_chip *chip) usleep_range(1000, 2000); /* per data sheet, page 10 */ /* set defaults */ - status = isl29018_set_range(chip, chip->range, &new_range); + status = isl29018_set_scale(chip, chip->scale.scale, + chip->scale.uscale); if (status < 0) { dev_err(chip->dev, "Init of isl29018 fails\n"); return status; } - status = isl29018_set_resolution(chip, chip->adc_bit, - &new_adc_bit); + status = isl29018_set_integration_time(chip, + isl29018_int_utimes[chip->type][chip->int_time]); + if (status < 0) { + dev_err(chip->dev, "Init of isl29018 fails\n"); + return status; + } return 0; } @@ -609,8 +737,8 @@ static int isl29018_probe(struct i2c_client *client, chip->type = dev_id; chip->calibscale = 1; chip->ucalibscale = 0; - chip->range = 1000; - chip->adc_bit = 16; + chip->int_time = ISL29018_INT_TIME_16; + chip->scale = isl29018_scales[chip->int_time][0]; chip->suspended = false; chip->regmap = devm_regmap_init_i2c(client, From 90037558d5ed25a63499c3973cc1af25da02f673 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 28 Apr 2015 14:08:03 +0200 Subject: [PATCH 0478/3798] ARM: shmobile: defconfig: Replace USB_RCAR_GEN2_PHY by PHY_RCAR_GEN2 The legacy-only USB_RCAR_GEN2_PHY driver was replaced by the DT-only PHY_RCAR_GEN2 driver. Refresh the defconfig using "make savedefconfig" while we're at it. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/configs/shmobile_defconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index b58618e2d13c51..9961fbd633f8d1 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -121,7 +121,6 @@ CONFIG_WATCHDOG=y CONFIG_DA9063_WATCHDOG=y CONFIG_MFD_AS3711=y CONFIG_MFD_DA9063=y -CONFIG_REGULATOR=y CONFIG_REGULATOR_AS3711=y CONFIG_REGULATOR_DA9210=y CONFIG_REGULATOR_GPIO=y @@ -160,7 +159,6 @@ CONFIG_USB_OHCI_HCD=y CONFIG_USB_R8A66597_HCD=y CONFIG_USB_RENESAS_USBHS=y CONFIG_USB_RCAR_PHY=y -CONFIG_USB_RCAR_GEN2_PHY=y CONFIG_USB_GADGET=y CONFIG_USB_RENESAS_USBHS_UDC=y CONFIG_USB_ETH=y @@ -182,6 +180,8 @@ CONFIG_IIO=y CONFIG_AK8975=y CONFIG_PWM=y CONFIG_PWM_RENESAS_TPU=y +CONFIG_GENERIC_PHY=y +CONFIG_PHY_RCAR_GEN2=y # CONFIG_DNOTIFY is not set CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y From 086cc672e1cb600b9c17688a4aa44560db858c03 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 1 May 2015 09:36:00 -0500 Subject: [PATCH 0479/3798] GFS2: mark the journal idle to fix ro mounts When gfs2 was mounted read-only and then unmounted, it was writing a header block to the journal in the syncing gfs2_log_flush() call from kill_sb(). This is because the journal was not being marked as idle until the first log header was written out, and on a read-only mount there never was a log header written out. Since the journal was not marked idle, gfs2_log_flush() was writing out a header lock to make sure it was empty during the sync. Not only did this cause IO to a read-only filesystem, but the journalling isn't completely initialized on read-only mounts, and so gfs2 was writing out the wrong sequence number in the log header. Now, the journal is marked idle on mount, and gfs2_log_flush() won't write out anything until there starts being transactions to flush. Signed-off-by: Benjamin Marzinski Signed-off-by: Bob Peterson Acked-by: Steven Whitehouse --- fs/gfs2/ops_fstype.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index efc8e254787cb3..e4fdeccd50cd1b 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -756,6 +756,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) } } + sdp->sd_log_idle = 1; set_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags); gfs2_glock_dq_uninit(&ji_gh); jindex = 0; From a18f8e97fe69195823d7fb5c68a8d6565f39db4b Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Thu, 2 Apr 2015 18:50:32 +0100 Subject: [PATCH 0480/3798] bus: arm-ccn: Fix node->XP config conversion Events defined as watchpoints on nodes must have their config values converted so that they apply to the respective node's XP. The function setting new values was using wrong mask for the "port" field, resulting in corrupted value. Fixed now. Cc: stable@vger.kernel.org # 3.17+ Signed-off-by: Pawel Moll --- drivers/bus/arm-ccn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c index aaa0f2a871185f..60397ec77ff7bb 100644 --- a/drivers/bus/arm-ccn.c +++ b/drivers/bus/arm-ccn.c @@ -212,7 +212,7 @@ static int arm_ccn_node_to_xp_port(int node) static void arm_ccn_pmu_config_set(u64 *config, u32 node_xp, u32 type, u32 port) { - *config &= ~((0xff << 0) | (0xff << 8) | (0xff << 24)); + *config &= ~((0xff << 0) | (0xff << 8) | (0x3 << 24)); *config |= (node_xp << 0) | (type << 8) | (port << 24); } From ffa415245b8666c44ddfb5ba1bca5b940828ecdd Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Thu, 16 Apr 2015 12:14:35 +0100 Subject: [PATCH 0481/3798] bus: arm-ccn: cpumask attribute This patch adds a "cpumask" attribute to CCN's event_source class sysfs directory. Perf user tool uses it to restrict events to the processor(s) enumerated in this mask. This patch provides a single CPU mask, making it possible to run "-a" perf session (previously it would request the same CCN event, for example cycle counter, on each available core and most likely fail). Initially the mask is set to the CPU that happened to probe the driver, but it will be changed when it is hot-un-plugged (active events are migrated to another CPU then). Example: Performance counter stats for 'system wide': CPU0 2968148 cycles CPU1 2236736 cycles CPU2 1797968 cycles CPU3 1831715 cycles CPU1 1201850868 ccn/cycles/ 1.001241383 seconds time elapsed Signed-off-by: Pawel Moll --- Documentation/arm/CCN.txt | 15 +++-- drivers/bus/arm-ccn.c | 128 ++++++++++++++++++++++++++++++++++---- 2 files changed, 126 insertions(+), 17 deletions(-) diff --git a/Documentation/arm/CCN.txt b/Documentation/arm/CCN.txt index 0632b3aad83e70..3a76048747623a 100644 --- a/Documentation/arm/CCN.txt +++ b/Documentation/arm/CCN.txt @@ -33,6 +33,13 @@ directory, with first 8 configurable by user and additional Cycle counter is described by a "type" value 0xff and does not require any other settings. +The driver also provides a "cpumask" sysfs attribute, which contains +a single CPU ID, of the processor which will be used to handle all +the CCN PMU events. It is recommended that the user space tools +request the events on this processor (if not, the perf_event->cpu value +will be overwritten anyway). In case of this processor being offlined, +the events are migrated to another one and the attribute is updated. + Example of perf tool use: / # perf list | grep ccn @@ -41,12 +48,8 @@ Example of perf tool use: ccn/xp_valid_flit/ [Kernel PMU event] <...> -/ # perf stat -C 0 -e ccn/cycles/,ccn/xp_valid_flit,xp=1,port=0,vc=1,dir=1/ \ +/ # perf stat -a -e ccn/cycles/,ccn/xp_valid_flit,xp=1,port=0,vc=1,dir=1/ \ sleep 1 The driver does not support sampling, therefore "perf record" will -not work. Also notice that only single cpu is being selected -("-C 0") - this is because perf framework does not support -"non-CPU related" counters (yet?) so system-wide session ("-a") -would try (and in most cases fail) to set up the same event -per each CPU. +not work. Per-task (without "-a") perf sessions are not supported. diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c index 60397ec77ff7bb..3374dcb12f1e3d 100644 --- a/drivers/bus/arm-ccn.c +++ b/drivers/bus/arm-ccn.c @@ -166,13 +166,17 @@ struct arm_ccn_dt { struct hrtimer hrtimer; + cpumask_t cpu; + struct notifier_block cpu_nb; + struct pmu pmu; }; struct arm_ccn { struct device *dev; void __iomem *base; - unsigned irq_used:1; + unsigned int irq; + unsigned sbas_present:1; unsigned sbsx_present:1; @@ -521,6 +525,25 @@ static struct attribute_group arm_ccn_pmu_cmp_mask_attr_group = { .attrs = arm_ccn_pmu_cmp_mask_attrs, }; +static ssize_t arm_ccn_pmu_cpumask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev)); + + return cpumap_print_to_pagebuf(true, buf, &ccn->dt.cpu); +} + +static struct device_attribute arm_ccn_pmu_cpumask_attr = + __ATTR(cpumask, S_IRUGO, arm_ccn_pmu_cpumask_show, NULL); + +static struct attribute *arm_ccn_pmu_cpumask_attrs[] = { + &arm_ccn_pmu_cpumask_attr.attr, + NULL, +}; + +static struct attribute_group arm_ccn_pmu_cpumask_attr_group = { + .attrs = arm_ccn_pmu_cpumask_attrs, +}; /* * Default poll period is 10ms, which is way over the top anyway, @@ -542,6 +565,7 @@ static const struct attribute_group *arm_ccn_pmu_attr_groups[] = { &arm_ccn_pmu_events_attr_group, &arm_ccn_pmu_format_attr_group, &arm_ccn_pmu_cmp_mask_attr_group, + &arm_ccn_pmu_cpumask_attr_group, NULL }; @@ -642,6 +666,16 @@ static int arm_ccn_pmu_event_init(struct perf_event *event) dev_warn(ccn->dev, "Can't provide per-task data!\n"); return -EOPNOTSUPP; } + /* + * Many perf core operations (eg. events rotation) operate on a + * single CPU context. This is obvious for CPU PMUs, where one + * expects the same sets of events being observed on all CPUs, + * but can lead to issues for off-core PMUs, like CCN, where each + * event could be theoretically assigned to a different CPU. To + * mitigate this, we enforce CPU assignment to one, selected + * processor (the one described in the "cpumask" attribute). + */ + event->cpu = cpumask_first(&ccn->dt.cpu); node_xp = CCN_CONFIG_NODE(event->attr.config); type = CCN_CONFIG_TYPE(event->attr.config); @@ -835,9 +869,15 @@ static void arm_ccn_pmu_event_start(struct perf_event *event, int flags) arm_ccn_pmu_read_counter(ccn, hw->idx)); hw->state = 0; - if (!ccn->irq_used) - hrtimer_start(&ccn->dt.hrtimer, arm_ccn_pmu_timer_period(), - HRTIMER_MODE_REL); + /* + * Pin the timer, so that the overflows are handled by the chosen + * event->cpu (this is the same one as presented in "cpumask" + * attribute). + */ + if (!ccn->irq) + __hrtimer_start_range_ns(&ccn->dt.hrtimer, + arm_ccn_pmu_timer_period(), 0, + HRTIMER_MODE_REL_PINNED, 0); /* Set the DT bus input, engaging the counter */ arm_ccn_pmu_xp_dt_config(event, 1); @@ -852,7 +892,7 @@ static void arm_ccn_pmu_event_stop(struct perf_event *event, int flags) /* Disable counting, setting the DT bus to pass-through mode */ arm_ccn_pmu_xp_dt_config(event, 0); - if (!ccn->irq_used) + if (!ccn->irq) hrtimer_cancel(&ccn->dt.hrtimer); /* Let the DT bus drain */ @@ -1079,12 +1119,39 @@ static enum hrtimer_restart arm_ccn_pmu_timer_handler(struct hrtimer *hrtimer) } +static int arm_ccn_pmu_cpu_notifier(struct notifier_block *nb, + unsigned long action, void *hcpu) +{ + struct arm_ccn_dt *dt = container_of(nb, struct arm_ccn_dt, cpu_nb); + struct arm_ccn *ccn = container_of(dt, struct arm_ccn, dt); + unsigned int cpu = (long)hcpu; /* for (long) see kernel/cpu.c */ + unsigned int target; + + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_DOWN_PREPARE: + if (!cpumask_test_and_clear_cpu(cpu, &dt->cpu)) + break; + target = cpumask_any_but(cpu_online_mask, cpu); + if (target < 0) + break; + perf_pmu_migrate_context(&dt->pmu, cpu, target); + cpumask_set_cpu(target, &dt->cpu); + WARN_ON(irq_set_affinity(ccn->irq, &dt->cpu) != 0); + default: + break; + } + + return NOTIFY_OK; +} + + static DEFINE_IDA(arm_ccn_pmu_ida); static int arm_ccn_pmu_init(struct arm_ccn *ccn) { int i; char *name; + int err; /* Initialize DT subsystem */ ccn->dt.base = ccn->base + CCN_REGION_SIZE; @@ -1136,20 +1203,58 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn) }; /* No overflow interrupt? Have to use a timer instead. */ - if (!ccn->irq_used) { + if (!ccn->irq) { dev_info(ccn->dev, "No access to interrupts, using timer.\n"); hrtimer_init(&ccn->dt.hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ccn->dt.hrtimer.function = arm_ccn_pmu_timer_handler; } - return perf_pmu_register(&ccn->dt.pmu, name, -1); + /* Pick one CPU which we will use to collect data from CCN... */ + cpumask_set_cpu(smp_processor_id(), &ccn->dt.cpu); + + /* + * ... and change the selection when it goes offline. Priority is + * picked to have a chance to migrate events before perf is notified. + */ + ccn->dt.cpu_nb.notifier_call = arm_ccn_pmu_cpu_notifier; + ccn->dt.cpu_nb.priority = CPU_PRI_PERF + 1, + err = register_cpu_notifier(&ccn->dt.cpu_nb); + if (err) + goto error_cpu_notifier; + + /* Also make sure that the overflow interrupt is handled by this CPU */ + if (ccn->irq) { + err = irq_set_affinity(ccn->irq, &ccn->dt.cpu); + if (err) { + dev_err(ccn->dev, "Failed to set interrupt affinity!\n"); + goto error_set_affinity; + } + } + + err = perf_pmu_register(&ccn->dt.pmu, name, -1); + if (err) + goto error_pmu_register; + + return 0; + +error_pmu_register: +error_set_affinity: + unregister_cpu_notifier(&ccn->dt.cpu_nb); +error_cpu_notifier: + ida_simple_remove(&arm_ccn_pmu_ida, ccn->dt.id); + for (i = 0; i < ccn->num_xps; i++) + writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL); + writel(0, ccn->dt.base + CCN_DT_PMCR); + return err; } static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn) { int i; + irq_set_affinity(ccn->irq, cpu_possible_mask); + unregister_cpu_notifier(&ccn->dt.cpu_nb); for (i = 0; i < ccn->num_xps; i++) writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL); writel(0, ccn->dt.base + CCN_DT_PMCR); @@ -1285,6 +1390,7 @@ static int arm_ccn_probe(struct platform_device *pdev) { struct arm_ccn *ccn; struct resource *res; + unsigned int irq; int err; ccn = devm_kzalloc(&pdev->dev, sizeof(*ccn), GFP_KERNEL); @@ -1309,6 +1415,7 @@ static int arm_ccn_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) return -EINVAL; + irq = res->start; /* Check if we can use the interrupt */ writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLE, @@ -1318,13 +1425,12 @@ static int arm_ccn_probe(struct platform_device *pdev) /* Can set 'disable' bits, so can acknowledge interrupts */ writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__ENABLE, ccn->base + CCN_MN_ERRINT_STATUS); - err = devm_request_irq(ccn->dev, res->start, - arm_ccn_irq_handler, 0, dev_name(ccn->dev), - ccn); + err = devm_request_irq(ccn->dev, irq, arm_ccn_irq_handler, 0, + dev_name(ccn->dev), ccn); if (err) return err; - ccn->irq_used = 1; + ccn->irq = irq; } From 8f06c51fac1ca4104b8b64872f310e28186aea42 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Thu, 2 Apr 2015 14:01:06 +0100 Subject: [PATCH 0482/3798] bus: arm-ccn: Provide required event arguments Since 688d4dfcdd624192cbf03c08402e444d1d11f294 "perf tools: Support parsing parameterized events" the perf userspace tools understands "argument=?" syntax in the events file, making sure that required arguments are provided by the user and not defaulting to 0, causing confusion. This patch adds the required arguments lists for CCN events. Signed-off-by: Pawel Moll --- Documentation/arm/CCN.txt | 2 +- drivers/bus/arm-ccn.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Documentation/arm/CCN.txt b/Documentation/arm/CCN.txt index 3a76048747623a..ffca443a19b426 100644 --- a/Documentation/arm/CCN.txt +++ b/Documentation/arm/CCN.txt @@ -45,7 +45,7 @@ Example of perf tool use: / # perf list | grep ccn ccn/cycles/ [Kernel PMU event] <...> - ccn/xp_valid_flit/ [Kernel PMU event] + ccn/xp_valid_flit,xp=?,port=?,vc=?,dir=?/ [Kernel PMU event] <...> / # perf stat -a -e ccn/cycles/,ccn/xp_valid_flit,xp=1,port=0,vc=1,dir=1/ \ diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c index 3374dcb12f1e3d..572360f1f493ed 100644 --- a/drivers/bus/arm-ccn.c +++ b/drivers/bus/arm-ccn.c @@ -340,6 +340,23 @@ static ssize_t arm_ccn_pmu_event_show(struct device *dev, if (event->mask) res += snprintf(buf + res, PAGE_SIZE - res, ",mask=0x%x", event->mask); + + /* Arguments required by an event */ + switch (event->type) { + case CCN_TYPE_CYCLES: + break; + case CCN_TYPE_XP: + res += snprintf(buf + res, PAGE_SIZE - res, + ",xp=?,port=?,vc=?,dir=?"); + if (event->event == CCN_EVENT_WATCHPOINT) + res += snprintf(buf + res, PAGE_SIZE - res, + ",cmp_l=?,cmp_h=?,mask=?"); + break; + default: + res += snprintf(buf + res, PAGE_SIZE - res, ",node=?"); + break; + } + res += snprintf(buf + res, PAGE_SIZE - res, "\n"); return res; From 9ce1aa869e69cff8db1369e6849af9bd555b4f1d Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Fri, 17 Apr 2015 12:15:56 +0100 Subject: [PATCH 0483/3798] bus: arm-ccn: Do not group CCN events with other PMUs Groups must not mix events from different PMUs (software events are allowed). Unfortunately the core does not ensures that, so it is necessary to validate the group at the PMU driver level. Signed-off-by: Pawel Moll --- drivers/bus/arm-ccn.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c index 572360f1f493ed..fb589d4dbaf6c1 100644 --- a/drivers/bus/arm-ccn.c +++ b/drivers/bus/arm-ccn.c @@ -660,6 +660,7 @@ static int arm_ccn_pmu_event_init(struct perf_event *event) int valid, bit; struct arm_ccn_component *source; int i; + struct perf_event *sibling; if (event->attr.type != event->pmu->type) return -ENOENT; @@ -762,6 +763,21 @@ static int arm_ccn_pmu_event_init(struct perf_event *event) node_xp, type, port); } + /* + * We must NOT create groups containing mixed PMUs, although software + * events are acceptable (for example to create a CCN group + * periodically read when a hrtimer aka cpu-clock leader triggers). + */ + if (event->group_leader->pmu != event->pmu && + !is_software_event(event->group_leader)) + return -EINVAL; + + list_for_each_entry(sibling, &event->group_leader->sibling_list, + group_entry) + if (sibling->pmu != event->pmu && + !is_software_event(sibling)) + return -EINVAL; + /* Allocate the cycle counter */ if (type == CCN_TYPE_CYCLES) { if (test_and_set_bit(CCN_IDX_PMU_CYCLE_COUNTER, From 57006d3e6f62def53c01ae3ffc338caebd866e89 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Fri, 17 Apr 2015 12:37:36 +0100 Subject: [PATCH 0484/3798] bus: arm-ccn: Allocate event when it is being added, not initialised To make events rotation possible, they should be allocated when event is being ->added(), not during initialisation. This patch moves the respective code. Signed-off-by: Pawel Moll --- drivers/bus/arm-ccn.c | 114 +++++++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 47 deletions(-) diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c index fb589d4dbaf6c1..df5f307f324443 100644 --- a/drivers/bus/arm-ccn.c +++ b/drivers/bus/arm-ccn.c @@ -628,7 +628,65 @@ static int arm_ccn_pmu_type_eq(u32 a, u32 b) return 0; } -static void arm_ccn_pmu_event_destroy(struct perf_event *event) +static int arm_ccn_pmu_event_alloc(struct perf_event *event) +{ + struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu); + struct hw_perf_event *hw = &event->hw; + u32 node_xp, type, event_id; + struct arm_ccn_component *source; + int bit; + + node_xp = CCN_CONFIG_NODE(event->attr.config); + type = CCN_CONFIG_TYPE(event->attr.config); + event_id = CCN_CONFIG_EVENT(event->attr.config); + + /* Allocate the cycle counter */ + if (type == CCN_TYPE_CYCLES) { + if (test_and_set_bit(CCN_IDX_PMU_CYCLE_COUNTER, + ccn->dt.pmu_counters_mask)) + return -EAGAIN; + + hw->idx = CCN_IDX_PMU_CYCLE_COUNTER; + ccn->dt.pmu_counters[CCN_IDX_PMU_CYCLE_COUNTER].event = event; + + return 0; + } + + /* Allocate an event counter */ + hw->idx = arm_ccn_pmu_alloc_bit(ccn->dt.pmu_counters_mask, + CCN_NUM_PMU_EVENT_COUNTERS); + if (hw->idx < 0) { + dev_dbg(ccn->dev, "No more counters available!\n"); + return -EAGAIN; + } + + if (type == CCN_TYPE_XP) + source = &ccn->xp[node_xp]; + else + source = &ccn->node[node_xp]; + ccn->dt.pmu_counters[hw->idx].source = source; + + /* Allocate an event source or a watchpoint */ + if (type == CCN_TYPE_XP && event_id == CCN_EVENT_WATCHPOINT) + bit = arm_ccn_pmu_alloc_bit(source->xp.dt_cmp_mask, + CCN_NUM_XP_WATCHPOINTS); + else + bit = arm_ccn_pmu_alloc_bit(source->pmu_events_mask, + CCN_NUM_PMU_EVENTS); + if (bit < 0) { + dev_dbg(ccn->dev, "No more event sources/watchpoints on node/XP %d!\n", + node_xp); + clear_bit(hw->idx, ccn->dt.pmu_counters_mask); + return -EAGAIN; + } + hw->config_base = bit; + + ccn->dt.pmu_counters[hw->idx].event = event; + + return 0; +} + +static void arm_ccn_pmu_event_release(struct perf_event *event) { struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu); struct hw_perf_event *hw = &event->hw; @@ -657,8 +715,7 @@ static int arm_ccn_pmu_event_init(struct perf_event *event) struct arm_ccn *ccn; struct hw_perf_event *hw = &event->hw; u32 node_xp, type, event_id; - int valid, bit; - struct arm_ccn_component *source; + int valid; int i; struct perf_event *sibling; @@ -666,7 +723,6 @@ static int arm_ccn_pmu_event_init(struct perf_event *event) return -ENOENT; ccn = pmu_to_arm_ccn(event->pmu); - event->destroy = arm_ccn_pmu_event_destroy; if (hw->sample_period) { dev_warn(ccn->dev, "Sampling not supported!\n"); @@ -778,49 +834,6 @@ static int arm_ccn_pmu_event_init(struct perf_event *event) !is_software_event(sibling)) return -EINVAL; - /* Allocate the cycle counter */ - if (type == CCN_TYPE_CYCLES) { - if (test_and_set_bit(CCN_IDX_PMU_CYCLE_COUNTER, - ccn->dt.pmu_counters_mask)) - return -EAGAIN; - - hw->idx = CCN_IDX_PMU_CYCLE_COUNTER; - ccn->dt.pmu_counters[CCN_IDX_PMU_CYCLE_COUNTER].event = event; - - return 0; - } - - /* Allocate an event counter */ - hw->idx = arm_ccn_pmu_alloc_bit(ccn->dt.pmu_counters_mask, - CCN_NUM_PMU_EVENT_COUNTERS); - if (hw->idx < 0) { - dev_warn(ccn->dev, "No more counters available!\n"); - return -EAGAIN; - } - - if (type == CCN_TYPE_XP) - source = &ccn->xp[node_xp]; - else - source = &ccn->node[node_xp]; - ccn->dt.pmu_counters[hw->idx].source = source; - - /* Allocate an event source or a watchpoint */ - if (type == CCN_TYPE_XP && event_id == CCN_EVENT_WATCHPOINT) - bit = arm_ccn_pmu_alloc_bit(source->xp.dt_cmp_mask, - CCN_NUM_XP_WATCHPOINTS); - else - bit = arm_ccn_pmu_alloc_bit(source->pmu_events_mask, - CCN_NUM_PMU_EVENTS); - if (bit < 0) { - dev_warn(ccn->dev, "No more event sources/watchpoints on node/XP %d!\n", - node_xp); - clear_bit(hw->idx, ccn->dt.pmu_counters_mask); - return -EAGAIN; - } - hw->config_base = bit; - - ccn->dt.pmu_counters[hw->idx].event = event; - return 0; } @@ -1087,8 +1100,13 @@ static void arm_ccn_pmu_event_config(struct perf_event *event) static int arm_ccn_pmu_event_add(struct perf_event *event, int flags) { + int err; struct hw_perf_event *hw = &event->hw; + err = arm_ccn_pmu_event_alloc(event); + if (err) + return err; + arm_ccn_pmu_event_config(event); hw->state = PERF_HES_STOPPED; @@ -1102,6 +1120,8 @@ static int arm_ccn_pmu_event_add(struct perf_event *event, int flags) static void arm_ccn_pmu_event_del(struct perf_event *event, int flags) { arm_ccn_pmu_event_stop(event, PERF_EF_UPDATE); + + arm_ccn_pmu_event_release(event); } static void arm_ccn_pmu_event_read(struct perf_event *event) From 86fbca4923f956dae31247e68dc73ffdfd6e5cb0 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Fri, 1 May 2015 12:54:38 -0500 Subject: [PATCH 0485/3798] GFS2: inode.c: indent with TABs, not spaces Follow the same style used for the other functions in the same file. Signed-off-by: Antonio Ospite Signed-off-by: Bob Peterson --- fs/gfs2/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 08bc84d7e768e7..2cd385d151b526 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1227,8 +1227,8 @@ static int gfs2_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, */ static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry, - struct file *file, unsigned flags, - umode_t mode, int *opened) + struct file *file, unsigned flags, + umode_t mode, int *opened) { struct dentry *d; bool excl = !!(flags & O_EXCL); From 469a22e6bad725cbd3188f37f2d119c7c7eaf510 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Sat, 2 May 2015 13:36:20 +0200 Subject: [PATCH 0486/3798] ARM: sunxi: dts: split IR pins for A10 and A20 Currently none of the target boards nor the driver supports IR TX. However this pin is used in a few instances as a GPIO. Split the pin ctrl descriptions so that only the IR RX is configured to be used. Signed-off-by: Marcus Cooper Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun4i-a10-a1000.dts | 2 +- arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts | 2 +- arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 2 +- arch/arm/boot/dts/sun4i-a10-hackberry.dts | 2 +- arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts | 2 +- arch/arm/boot/dts/sun4i-a10-mini-xplus.dts | 4 ++-- arch/arm/boot/dts/sun4i-a10.dtsi | 22 +++++++++++++++---- arch/arm/boot/dts/sun7i-a20-bananapi.dts | 2 +- arch/arm/boot/dts/sun7i-a20-bananapro.dts | 2 +- arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 2 +- arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 2 +- arch/arm/boot/dts/sun7i-a20-hummingbird.dts | 2 +- arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts | 2 +- arch/arm/boot/dts/sun7i-a20-m3.dts | 2 +- arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts | 2 +- arch/arm/boot/dts/sun7i-a20-orangepi.dts | 2 +- arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts | 2 +- arch/arm/boot/dts/sun7i-a20-pcduino3.dts | 2 +- arch/arm/boot/dts/sun7i-a20.dtsi | 22 +++++++++++++++---- 19 files changed, 54 insertions(+), 26 deletions(-) diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts index f03281434e593f..57970d06527d9c 100644 --- a/arch/arm/boot/dts/sun4i-a10-a1000.dts +++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts @@ -130,7 +130,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts b/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts index 1a3c7ddc538a9d..62e4b36b7364f2 100644 --- a/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts +++ b/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts @@ -96,7 +96,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts index 0ba67d79c2b4a8..db204b185d22d8 100644 --- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts @@ -126,7 +126,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/sun4i-a10-hackberry.dts index f4437883fba7a5..835eb30c14217c 100644 --- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts +++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts @@ -93,7 +93,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts index 1b0452fea273bf..4281782fe913a5 100644 --- a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts +++ b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts @@ -126,7 +126,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts index 0f24914c1a6e44..132ace5c9d1880 100644 --- a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts +++ b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts @@ -92,11 +92,11 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; -&ir0_pins_a { +&ir0_rx_pins_a { /* The ir receiver is not always populated */ allwinner,pull = ; }; diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 1d7fd68bea1dc0..7529857794141f 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -797,15 +797,29 @@ allwinner,pull = ; }; - ir0_pins_a: ir0@0 { - allwinner,pins = "PB3","PB4"; + ir0_rx_pins_a: ir0@0 { + allwinner,pins = "PB4"; allwinner,function = "ir0"; allwinner,drive = ; allwinner,pull = ; }; - ir1_pins_a: ir1@0 { - allwinner,pins = "PB22","PB23"; + ir0_tx_pins_a: ir0@1 { + allwinner,pins = "PB3"; + allwinner,function = "ir0"; + allwinner,drive = ; + allwinner,pull = ; + }; + + ir1_rx_pins_a: ir1@0 { + allwinner,pins = "PB23"; + allwinner,function = "ir1"; + allwinner,drive = ; + allwinner,pull = ; + }; + + ir1_tx_pins_a: ir1@1 { + allwinner,pins = "PB22"; allwinner,function = "ir1"; allwinner,drive = ; allwinner,pull = ; diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi.dts b/arch/arm/boot/dts/sun7i-a20-bananapi.dts index b952ac445504c2..ecc2a4d045da29 100644 --- a/arch/arm/boot/dts/sun7i-a20-bananapi.dts +++ b/arch/arm/boot/dts/sun7i-a20-bananapi.dts @@ -142,7 +142,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun7i-a20-bananapro.dts b/arch/arm/boot/dts/sun7i-a20-bananapro.dts index 9d9027f25a4401..d408bbcbe91723 100644 --- a/arch/arm/boot/dts/sun7i-a20-bananapro.dts +++ b/arch/arm/boot/dts/sun7i-a20-bananapro.dts @@ -154,7 +154,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts index 3c817ac9360bd2..930ea80d9bfda2 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts @@ -133,7 +133,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts index 613a19e63e5895..8a83c99cf97661 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts @@ -160,7 +160,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts index d3f15c2e721eb5..9a4d7836f6d2f1 100644 --- a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts +++ b/arch/arm/boot/dts/sun7i-a20-hummingbird.dts @@ -160,7 +160,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts index 3f99b3f222a7f4..d9782c4e798d1b 100644 --- a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts +++ b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts @@ -157,7 +157,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun7i-a20-m3.dts b/arch/arm/boot/dts/sun7i-a20-m3.dts index f2fb26e7d6e5e0..39b4a8023d2d37 100644 --- a/arch/arm/boot/dts/sun7i-a20-m3.dts +++ b/arch/arm/boot/dts/sun7i-a20-m3.dts @@ -117,7 +117,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts b/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts index 0556938a5d4d63..bf6dd25edddb6e 100644 --- a/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts +++ b/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts @@ -137,7 +137,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi.dts b/arch/arm/boot/dts/sun7i-a20-orangepi.dts index 7e6405c5448f23..b282dda6f6aa98 100644 --- a/arch/arm/boot/dts/sun7i-a20-orangepi.dts +++ b/arch/arm/boot/dts/sun7i-a20-orangepi.dts @@ -132,7 +132,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts index 810c5f76459519..f14cd603fa8625 100644 --- a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts +++ b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts @@ -125,7 +125,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts index cd05267781fb22..2578959bccaa59 100644 --- a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts +++ b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts @@ -154,7 +154,7 @@ &ir0 { pinctrl-names = "default"; - pinctrl-0 = <&ir0_pins_a>; + pinctrl-0 = <&ir0_rx_pins_a>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 4163ade867cb7d..89d720660b80b9 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -1000,15 +1000,29 @@ allwinner,pull = ; }; - ir0_pins_a: ir0@0 { - allwinner,pins = "PB3","PB4"; + ir0_rx_pins_a: ir0@0 { + allwinner,pins = "PB4"; allwinner,function = "ir0"; allwinner,drive = ; allwinner,pull = ; }; - ir1_pins_a: ir1@0 { - allwinner,pins = "PB22","PB23"; + ir0_tx_pins_a: ir0@1 { + allwinner,pins = "PB3"; + allwinner,function = "ir0"; + allwinner,drive = ; + allwinner,pull = ; + }; + + ir1_rx_pins_a: ir1@0 { + allwinner,pins = "PB23"; + allwinner,function = "ir1"; + allwinner,drive = ; + allwinner,pull = ; + }; + + ir1_tx_pins_a: ir1@1 { + allwinner,pins = "PB22"; allwinner,function = "ir1"; allwinner,drive = ; allwinner,pull = ; From 2fdaf3f4f8c718a5023db69e2d391d978e94703e Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 2 May 2015 11:25:48 +0100 Subject: [PATCH 0487/3798] iio:light:ltr501 bug in parameter sanity check. Clearly the intent was to error if the value was not 0 or 1. As implemented we have (A != 0 || A != 1) which is always true as A is never both 0 and 1 at the same time. As the autobuilder suggested, && makes more sense for this error check. Reported-by: kbuild test robot Acked-by: Kuppuswamy Sathyanarayanan Cc: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/light/ltr501.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index ca4bf470a3325a..280eff19b87243 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -976,7 +976,7 @@ static int ltr501_write_event_config(struct iio_dev *indio_dev, int ret; /* only 1 and 0 are valid inputs */ - if (state != 1 || state != 0) + if (state != 1 && state != 0) return -EINVAL; switch (chan->type) { From 6769b93c082afb7241708685f1c23cbaf5bf00eb Mon Sep 17 00:00:00 2001 From: Yingjoe Chen Date: Fri, 1 May 2015 14:49:31 +0800 Subject: [PATCH 0488/3798] arm64: dts: mt8173: Fixup pinctrl nodes The 8173 pinctrl node doesn't follow dts convention. Fix them. Also add a comment to explain pinctrl register usage to make it more clear. Signed-off-by: Yingjoe Chen Reviewed-by: Daniel Kurtz Signed-off-by: Matthias Brugger --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 924fdb6673ff62..45951964965a47 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -106,14 +106,13 @@ compatible = "simple-bus"; ranges; - syscfg_pctl_a: syscfg_pctl_a@10005000 { - compatible = "mediatek,mt8173-pctl-a-syscfg", "syscon"; - reg = <0 0x10005000 0 0x1000>; - }; - - pio: pinctrl@0x10005000 { + /* + * Pinctrl access register at 0x10005000 through regmap. + * Register 0x1000b000 is used by EINT. + */ + pio: pinctrl@10005000 { compatible = "mediatek,mt8173-pinctrl"; - reg = <0 0x1000B000 0 0x1000>; + reg = <0 0x1000b000 0 0x1000>; mediatek,pctl-regmap = <&syscfg_pctl_a>; pins-are-numbered; gpio-controller; @@ -121,8 +120,13 @@ interrupt-controller; #interrupt-cells = <2>; interrupts = , - , - ; + , + ; + }; + + syscfg_pctl_a: syscfg_pctl_a@10005000 { + compatible = "mediatek,mt8173-pctl-a-syscfg", "syscon"; + reg = <0 0x10005000 0 0x1000>; }; sysirq: intpol-controller@10200620 { From cfb1167126613230f38f4c45b9e9bcb22791df8b Mon Sep 17 00:00:00 2001 From: Hongzhou Yang Date: Fri, 1 May 2015 14:49:30 +0800 Subject: [PATCH 0489/3798] ARM: dts: mt8135: Add pinctrl/GPIO/EINT node for mt8135. Add pinctrl,GPIO and EINT node to mt8135.dtsi. Signed-off-by: Hongzhou Yang Acked-by: Linus Walleij Signed-off-by: Matthias Brugger --- arch/arm/boot/dts/mt8135-pinfunc.h | 1302 ++++++++++++++++++++++++++++ arch/arm/boot/dts/mt8135.dtsi | 29 + 2 files changed, 1331 insertions(+) create mode 100644 arch/arm/boot/dts/mt8135-pinfunc.h diff --git a/arch/arm/boot/dts/mt8135-pinfunc.h b/arch/arm/boot/dts/mt8135-pinfunc.h new file mode 100644 index 00000000000000..5a609875cb1827 --- /dev/null +++ b/arch/arm/boot/dts/mt8135-pinfunc.h @@ -0,0 +1,1302 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Hongzhou.Yang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __DTS_MT8135_PINFUNC_H +#define __DTS_MT8135_PINFUNC_H + +#include + +#define MT8135_PIN_0_MSDC0_DAT7__FUNC_GPIO0 (MTK_PIN_NO(0) | 0) +#define MT8135_PIN_0_MSDC0_DAT7__FUNC_MSDC0_DAT7 (MTK_PIN_NO(0) | 1) +#define MT8135_PIN_0_MSDC0_DAT7__FUNC_EINT49 (MTK_PIN_NO(0) | 2) +#define MT8135_PIN_0_MSDC0_DAT7__FUNC_I2SOUT_DAT (MTK_PIN_NO(0) | 3) +#define MT8135_PIN_0_MSDC0_DAT7__FUNC_DAC_DAT_OUT (MTK_PIN_NO(0) | 4) +#define MT8135_PIN_0_MSDC0_DAT7__FUNC_PCM1_DO (MTK_PIN_NO(0) | 5) +#define MT8135_PIN_0_MSDC0_DAT7__FUNC_SPI1_MO (MTK_PIN_NO(0) | 6) +#define MT8135_PIN_0_MSDC0_DAT7__FUNC_NALE (MTK_PIN_NO(0) | 7) + +#define MT8135_PIN_1_MSDC0_DAT6__FUNC_GPIO1 (MTK_PIN_NO(1) | 0) +#define MT8135_PIN_1_MSDC0_DAT6__FUNC_MSDC0_DAT6 (MTK_PIN_NO(1) | 1) +#define MT8135_PIN_1_MSDC0_DAT6__FUNC_EINT48 (MTK_PIN_NO(1) | 2) +#define MT8135_PIN_1_MSDC0_DAT6__FUNC_I2SIN_WS (MTK_PIN_NO(1) | 3) +#define MT8135_PIN_1_MSDC0_DAT6__FUNC_DAC_WS (MTK_PIN_NO(1) | 4) +#define MT8135_PIN_1_MSDC0_DAT6__FUNC_PCM1_WS (MTK_PIN_NO(1) | 5) +#define MT8135_PIN_1_MSDC0_DAT6__FUNC_SPI1_CSN (MTK_PIN_NO(1) | 6) +#define MT8135_PIN_1_MSDC0_DAT6__FUNC_NCLE (MTK_PIN_NO(1) | 7) + +#define MT8135_PIN_2_MSDC0_DAT5__FUNC_GPIO2 (MTK_PIN_NO(2) | 0) +#define MT8135_PIN_2_MSDC0_DAT5__FUNC_MSDC0_DAT5 (MTK_PIN_NO(2) | 1) +#define MT8135_PIN_2_MSDC0_DAT5__FUNC_EINT47 (MTK_PIN_NO(2) | 2) +#define MT8135_PIN_2_MSDC0_DAT5__FUNC_I2SIN_CK (MTK_PIN_NO(2) | 3) +#define MT8135_PIN_2_MSDC0_DAT5__FUNC_DAC_CK (MTK_PIN_NO(2) | 4) +#define MT8135_PIN_2_MSDC0_DAT5__FUNC_PCM1_CK (MTK_PIN_NO(2) | 5) +#define MT8135_PIN_2_MSDC0_DAT5__FUNC_SPI1_CLK (MTK_PIN_NO(2) | 6) +#define MT8135_PIN_2_MSDC0_DAT5__FUNC_NLD4 (MTK_PIN_NO(2) | 7) + +#define MT8135_PIN_3_MSDC0_DAT4__FUNC_GPIO3 (MTK_PIN_NO(3) | 0) +#define MT8135_PIN_3_MSDC0_DAT4__FUNC_MSDC0_DAT4 (MTK_PIN_NO(3) | 1) +#define MT8135_PIN_3_MSDC0_DAT4__FUNC_EINT46 (MTK_PIN_NO(3) | 2) +#define MT8135_PIN_3_MSDC0_DAT4__FUNC_A_FUNC_CK (MTK_PIN_NO(3) | 3) +#define MT8135_PIN_3_MSDC0_DAT4__FUNC_LSCE1B_2X (MTK_PIN_NO(3) | 6) +#define MT8135_PIN_3_MSDC0_DAT4__FUNC_NLD5 (MTK_PIN_NO(3) | 7) + +#define MT8135_PIN_4_MSDC0_CMD__FUNC_GPIO4 (MTK_PIN_NO(4) | 0) +#define MT8135_PIN_4_MSDC0_CMD__FUNC_MSDC0_CMD (MTK_PIN_NO(4) | 1) +#define MT8135_PIN_4_MSDC0_CMD__FUNC_EINT41 (MTK_PIN_NO(4) | 2) +#define MT8135_PIN_4_MSDC0_CMD__FUNC_A_FUNC_DOUT_0 (MTK_PIN_NO(4) | 3) +#define MT8135_PIN_4_MSDC0_CMD__FUNC_USB_TEST_IO_0 (MTK_PIN_NO(4) | 5) +#define MT8135_PIN_4_MSDC0_CMD__FUNC_LRSTB_2X (MTK_PIN_NO(4) | 6) +#define MT8135_PIN_4_MSDC0_CMD__FUNC_NRNB (MTK_PIN_NO(4) | 7) + +#define MT8135_PIN_5_MSDC0_CLK__FUNC_GPIO5 (MTK_PIN_NO(5) | 0) +#define MT8135_PIN_5_MSDC0_CLK__FUNC_MSDC0_CLK (MTK_PIN_NO(5) | 1) +#define MT8135_PIN_5_MSDC0_CLK__FUNC_EINT40 (MTK_PIN_NO(5) | 2) +#define MT8135_PIN_5_MSDC0_CLK__FUNC_A_FUNC_DOUT_1 (MTK_PIN_NO(5) | 3) +#define MT8135_PIN_5_MSDC0_CLK__FUNC_USB_TEST_IO_1 (MTK_PIN_NO(5) | 5) +#define MT8135_PIN_5_MSDC0_CLK__FUNC_LPTE (MTK_PIN_NO(5) | 6) +#define MT8135_PIN_5_MSDC0_CLK__FUNC_NREB (MTK_PIN_NO(5) | 7) + +#define MT8135_PIN_6_MSDC0_DAT3__FUNC_GPIO6 (MTK_PIN_NO(6) | 0) +#define MT8135_PIN_6_MSDC0_DAT3__FUNC_MSDC0_DAT3 (MTK_PIN_NO(6) | 1) +#define MT8135_PIN_6_MSDC0_DAT3__FUNC_EINT45 (MTK_PIN_NO(6) | 2) +#define MT8135_PIN_6_MSDC0_DAT3__FUNC_A_FUNC_DOUT_2 (MTK_PIN_NO(6) | 3) +#define MT8135_PIN_6_MSDC0_DAT3__FUNC_USB_TEST_IO_2 (MTK_PIN_NO(6) | 5) +#define MT8135_PIN_6_MSDC0_DAT3__FUNC_LSCE0B_2X (MTK_PIN_NO(6) | 6) +#define MT8135_PIN_6_MSDC0_DAT3__FUNC_NLD7 (MTK_PIN_NO(6) | 7) + +#define MT8135_PIN_7_MSDC0_DAT2__FUNC_GPIO7 (MTK_PIN_NO(7) | 0) +#define MT8135_PIN_7_MSDC0_DAT2__FUNC_MSDC0_DAT2 (MTK_PIN_NO(7) | 1) +#define MT8135_PIN_7_MSDC0_DAT2__FUNC_EINT44 (MTK_PIN_NO(7) | 2) +#define MT8135_PIN_7_MSDC0_DAT2__FUNC_A_FUNC_DOUT_3 (MTK_PIN_NO(7) | 3) +#define MT8135_PIN_7_MSDC0_DAT2__FUNC_USB_TEST_IO_3 (MTK_PIN_NO(7) | 5) +#define MT8135_PIN_7_MSDC0_DAT2__FUNC_LSA0_2X (MTK_PIN_NO(7) | 6) +#define MT8135_PIN_7_MSDC0_DAT2__FUNC_NLD14 (MTK_PIN_NO(7) | 7) + +#define MT8135_PIN_8_MSDC0_DAT1__FUNC_GPIO8 (MTK_PIN_NO(8) | 0) +#define MT8135_PIN_8_MSDC0_DAT1__FUNC_MSDC0_DAT1 (MTK_PIN_NO(8) | 1) +#define MT8135_PIN_8_MSDC0_DAT1__FUNC_EINT43 (MTK_PIN_NO(8) | 2) +#define MT8135_PIN_8_MSDC0_DAT1__FUNC_USB_TEST_IO_4 (MTK_PIN_NO(8) | 5) +#define MT8135_PIN_8_MSDC0_DAT1__FUNC_LSCK_2X (MTK_PIN_NO(8) | 6) +#define MT8135_PIN_8_MSDC0_DAT1__FUNC_NLD11 (MTK_PIN_NO(8) | 7) + +#define MT8135_PIN_9_MSDC0_DAT0__FUNC_GPIO9 (MTK_PIN_NO(9) | 0) +#define MT8135_PIN_9_MSDC0_DAT0__FUNC_MSDC0_DAT0 (MTK_PIN_NO(9) | 1) +#define MT8135_PIN_9_MSDC0_DAT0__FUNC_EINT42 (MTK_PIN_NO(9) | 2) +#define MT8135_PIN_9_MSDC0_DAT0__FUNC_USB_TEST_IO_5 (MTK_PIN_NO(9) | 5) +#define MT8135_PIN_9_MSDC0_DAT0__FUNC_LSDA_2X (MTK_PIN_NO(9) | 6) + +#define MT8135_PIN_10_NCEB0__FUNC_GPIO10 (MTK_PIN_NO(10) | 0) +#define MT8135_PIN_10_NCEB0__FUNC_NCEB0 (MTK_PIN_NO(10) | 1) +#define MT8135_PIN_10_NCEB0__FUNC_EINT139 (MTK_PIN_NO(10) | 2) +#define MT8135_PIN_10_NCEB0__FUNC_TESTA_OUT4 (MTK_PIN_NO(10) | 7) + +#define MT8135_PIN_11_NCEB1__FUNC_GPIO11 (MTK_PIN_NO(11) | 0) +#define MT8135_PIN_11_NCEB1__FUNC_NCEB1 (MTK_PIN_NO(11) | 1) +#define MT8135_PIN_11_NCEB1__FUNC_EINT140 (MTK_PIN_NO(11) | 2) +#define MT8135_PIN_11_NCEB1__FUNC_USB_DRVVBUS (MTK_PIN_NO(11) | 6) +#define MT8135_PIN_11_NCEB1__FUNC_TESTA_OUT5 (MTK_PIN_NO(11) | 7) + +#define MT8135_PIN_12_NRNB__FUNC_GPIO12 (MTK_PIN_NO(12) | 0) +#define MT8135_PIN_12_NRNB__FUNC_NRNB (MTK_PIN_NO(12) | 1) +#define MT8135_PIN_12_NRNB__FUNC_EINT141 (MTK_PIN_NO(12) | 2) +#define MT8135_PIN_12_NRNB__FUNC_A_FUNC_DOUT_4 (MTK_PIN_NO(12) | 3) +#define MT8135_PIN_12_NRNB__FUNC_TESTA_OUT6 (MTK_PIN_NO(12) | 7) + +#define MT8135_PIN_13_NCLE__FUNC_GPIO13 (MTK_PIN_NO(13) | 0) +#define MT8135_PIN_13_NCLE__FUNC_NCLE (MTK_PIN_NO(13) | 1) +#define MT8135_PIN_13_NCLE__FUNC_EINT142 (MTK_PIN_NO(13) | 2) +#define MT8135_PIN_13_NCLE__FUNC_A_FUNC_DOUT_5 (MTK_PIN_NO(13) | 3) +#define MT8135_PIN_13_NCLE__FUNC_CM2PDN_1X (MTK_PIN_NO(13) | 4) +#define MT8135_PIN_13_NCLE__FUNC_NALE (MTK_PIN_NO(13) | 6) +#define MT8135_PIN_13_NCLE__FUNC_TESTA_OUT7 (MTK_PIN_NO(13) | 7) + +#define MT8135_PIN_14_NALE__FUNC_GPIO14 (MTK_PIN_NO(14) | 0) +#define MT8135_PIN_14_NALE__FUNC_NALE (MTK_PIN_NO(14) | 1) +#define MT8135_PIN_14_NALE__FUNC_EINT143 (MTK_PIN_NO(14) | 2) +#define MT8135_PIN_14_NALE__FUNC_A_FUNC_DOUT_6 (MTK_PIN_NO(14) | 3) +#define MT8135_PIN_14_NALE__FUNC_CM2MCLK_1X (MTK_PIN_NO(14) | 4) +#define MT8135_PIN_14_NALE__FUNC_IRDA_RXD (MTK_PIN_NO(14) | 5) +#define MT8135_PIN_14_NALE__FUNC_NCLE (MTK_PIN_NO(14) | 6) +#define MT8135_PIN_14_NALE__FUNC_TESTA_OUT8 (MTK_PIN_NO(14) | 7) + +#define MT8135_PIN_15_NREB__FUNC_GPIO15 (MTK_PIN_NO(15) | 0) +#define MT8135_PIN_15_NREB__FUNC_NREB (MTK_PIN_NO(15) | 1) +#define MT8135_PIN_15_NREB__FUNC_EINT144 (MTK_PIN_NO(15) | 2) +#define MT8135_PIN_15_NREB__FUNC_A_FUNC_DOUT_7 (MTK_PIN_NO(15) | 3) +#define MT8135_PIN_15_NREB__FUNC_CM2RST_1X (MTK_PIN_NO(15) | 4) +#define MT8135_PIN_15_NREB__FUNC_IRDA_TXD (MTK_PIN_NO(15) | 5) +#define MT8135_PIN_15_NREB__FUNC_TESTA_OUT9 (MTK_PIN_NO(15) | 7) + +#define MT8135_PIN_16_NWEB__FUNC_GPIO16 (MTK_PIN_NO(16) | 0) +#define MT8135_PIN_16_NWEB__FUNC_NWEB (MTK_PIN_NO(16) | 1) +#define MT8135_PIN_16_NWEB__FUNC_EINT145 (MTK_PIN_NO(16) | 2) +#define MT8135_PIN_16_NWEB__FUNC_A_FUNC_DIN_0 (MTK_PIN_NO(16) | 3) +#define MT8135_PIN_16_NWEB__FUNC_CM2PCLK_1X (MTK_PIN_NO(16) | 4) +#define MT8135_PIN_16_NWEB__FUNC_IRDA_PDN (MTK_PIN_NO(16) | 5) +#define MT8135_PIN_16_NWEB__FUNC_TESTA_OUT10 (MTK_PIN_NO(16) | 7) + +#define MT8135_PIN_17_NLD0__FUNC_GPIO17 (MTK_PIN_NO(17) | 0) +#define MT8135_PIN_17_NLD0__FUNC_NLD0 (MTK_PIN_NO(17) | 1) +#define MT8135_PIN_17_NLD0__FUNC_EINT146 (MTK_PIN_NO(17) | 2) +#define MT8135_PIN_17_NLD0__FUNC_A_FUNC_DIN_1 (MTK_PIN_NO(17) | 3) +#define MT8135_PIN_17_NLD0__FUNC_CM2DAT_1X_0 (MTK_PIN_NO(17) | 4) +#define MT8135_PIN_17_NLD0__FUNC_I2SIN_CK (MTK_PIN_NO(17) | 5) +#define MT8135_PIN_17_NLD0__FUNC_DAC_CK (MTK_PIN_NO(17) | 6) +#define MT8135_PIN_17_NLD0__FUNC_TESTA_OUT11 (MTK_PIN_NO(17) | 7) + +#define MT8135_PIN_18_NLD1__FUNC_GPIO18 (MTK_PIN_NO(18) | 0) +#define MT8135_PIN_18_NLD1__FUNC_NLD1 (MTK_PIN_NO(18) | 1) +#define MT8135_PIN_18_NLD1__FUNC_EINT147 (MTK_PIN_NO(18) | 2) +#define MT8135_PIN_18_NLD1__FUNC_A_FUNC_DIN_2 (MTK_PIN_NO(18) | 3) +#define MT8135_PIN_18_NLD1__FUNC_CM2DAT_1X_1 (MTK_PIN_NO(18) | 4) +#define MT8135_PIN_18_NLD1__FUNC_I2SIN_WS (MTK_PIN_NO(18) | 5) +#define MT8135_PIN_18_NLD1__FUNC_DAC_WS (MTK_PIN_NO(18) | 6) +#define MT8135_PIN_18_NLD1__FUNC_TESTA_OUT12 (MTK_PIN_NO(18) | 7) + +#define MT8135_PIN_19_NLD2__FUNC_GPIO19 (MTK_PIN_NO(19) | 0) +#define MT8135_PIN_19_NLD2__FUNC_NLD2 (MTK_PIN_NO(19) | 1) +#define MT8135_PIN_19_NLD2__FUNC_EINT148 (MTK_PIN_NO(19) | 2) +#define MT8135_PIN_19_NLD2__FUNC_A_FUNC_DIN_3 (MTK_PIN_NO(19) | 3) +#define MT8135_PIN_19_NLD2__FUNC_CM2DAT_1X_2 (MTK_PIN_NO(19) | 4) +#define MT8135_PIN_19_NLD2__FUNC_I2SOUT_DAT (MTK_PIN_NO(19) | 5) +#define MT8135_PIN_19_NLD2__FUNC_DAC_DAT_OUT (MTK_PIN_NO(19) | 6) +#define MT8135_PIN_19_NLD2__FUNC_TESTA_OUT13 (MTK_PIN_NO(19) | 7) + +#define MT8135_PIN_20_NLD3__FUNC_GPIO20 (MTK_PIN_NO(20) | 0) +#define MT8135_PIN_20_NLD3__FUNC_NLD3 (MTK_PIN_NO(20) | 1) +#define MT8135_PIN_20_NLD3__FUNC_EINT149 (MTK_PIN_NO(20) | 2) +#define MT8135_PIN_20_NLD3__FUNC_A_FUNC_DIN_4 (MTK_PIN_NO(20) | 3) +#define MT8135_PIN_20_NLD3__FUNC_CM2DAT_1X_3 (MTK_PIN_NO(20) | 4) +#define MT8135_PIN_20_NLD3__FUNC_TESTA_OUT14 (MTK_PIN_NO(20) | 7) + +#define MT8135_PIN_21_NLD4__FUNC_GPIO21 (MTK_PIN_NO(21) | 0) +#define MT8135_PIN_21_NLD4__FUNC_NLD4 (MTK_PIN_NO(21) | 1) +#define MT8135_PIN_21_NLD4__FUNC_EINT150 (MTK_PIN_NO(21) | 2) +#define MT8135_PIN_21_NLD4__FUNC_A_FUNC_DIN_5 (MTK_PIN_NO(21) | 3) +#define MT8135_PIN_21_NLD4__FUNC_CM2DAT_1X_4 (MTK_PIN_NO(21) | 4) +#define MT8135_PIN_21_NLD4__FUNC_TESTA_OUT15 (MTK_PIN_NO(21) | 7) + +#define MT8135_PIN_22_NLD5__FUNC_GPIO22 (MTK_PIN_NO(22) | 0) +#define MT8135_PIN_22_NLD5__FUNC_NLD5 (MTK_PIN_NO(22) | 1) +#define MT8135_PIN_22_NLD5__FUNC_EINT151 (MTK_PIN_NO(22) | 2) +#define MT8135_PIN_22_NLD5__FUNC_A_FUNC_DIN_6 (MTK_PIN_NO(22) | 3) +#define MT8135_PIN_22_NLD5__FUNC_CM2DAT_1X_5 (MTK_PIN_NO(22) | 4) +#define MT8135_PIN_22_NLD5__FUNC_TESTA_OUT16 (MTK_PIN_NO(22) | 7) + +#define MT8135_PIN_23_NLD6__FUNC_GPIO23 (MTK_PIN_NO(23) | 0) +#define MT8135_PIN_23_NLD6__FUNC_NLD6 (MTK_PIN_NO(23) | 1) +#define MT8135_PIN_23_NLD6__FUNC_EINT152 (MTK_PIN_NO(23) | 2) +#define MT8135_PIN_23_NLD6__FUNC_A_FUNC_DIN_7 (MTK_PIN_NO(23) | 3) +#define MT8135_PIN_23_NLD6__FUNC_CM2DAT_1X_6 (MTK_PIN_NO(23) | 4) +#define MT8135_PIN_23_NLD6__FUNC_TESTA_OUT17 (MTK_PIN_NO(23) | 7) + +#define MT8135_PIN_24_NLD7__FUNC_GPIO24 (MTK_PIN_NO(24) | 0) +#define MT8135_PIN_24_NLD7__FUNC_NLD7 (MTK_PIN_NO(24) | 1) +#define MT8135_PIN_24_NLD7__FUNC_EINT153 (MTK_PIN_NO(24) | 2) +#define MT8135_PIN_24_NLD7__FUNC_A_FUNC_DIN_8 (MTK_PIN_NO(24) | 3) +#define MT8135_PIN_24_NLD7__FUNC_CM2DAT_1X_7 (MTK_PIN_NO(24) | 4) +#define MT8135_PIN_24_NLD7__FUNC_TESTA_OUT18 (MTK_PIN_NO(24) | 7) + +#define MT8135_PIN_25_NLD8__FUNC_GPIO25 (MTK_PIN_NO(25) | 0) +#define MT8135_PIN_25_NLD8__FUNC_NLD8 (MTK_PIN_NO(25) | 1) +#define MT8135_PIN_25_NLD8__FUNC_EINT154 (MTK_PIN_NO(25) | 2) +#define MT8135_PIN_25_NLD8__FUNC_CM2DAT_1X_8 (MTK_PIN_NO(25) | 4) + +#define MT8135_PIN_26_NLD9__FUNC_GPIO26 (MTK_PIN_NO(26) | 0) +#define MT8135_PIN_26_NLD9__FUNC_NLD9 (MTK_PIN_NO(26) | 1) +#define MT8135_PIN_26_NLD9__FUNC_EINT155 (MTK_PIN_NO(26) | 2) +#define MT8135_PIN_26_NLD9__FUNC_CM2DAT_1X_9 (MTK_PIN_NO(26) | 4) +#define MT8135_PIN_26_NLD9__FUNC_PWM1 (MTK_PIN_NO(26) | 5) + +#define MT8135_PIN_27_NLD10__FUNC_GPIO27 (MTK_PIN_NO(27) | 0) +#define MT8135_PIN_27_NLD10__FUNC_NLD10 (MTK_PIN_NO(27) | 1) +#define MT8135_PIN_27_NLD10__FUNC_EINT156 (MTK_PIN_NO(27) | 2) +#define MT8135_PIN_27_NLD10__FUNC_CM2VSYNC_1X (MTK_PIN_NO(27) | 4) +#define MT8135_PIN_27_NLD10__FUNC_PWM2 (MTK_PIN_NO(27) | 5) + +#define MT8135_PIN_28_NLD11__FUNC_GPIO28 (MTK_PIN_NO(28) | 0) +#define MT8135_PIN_28_NLD11__FUNC_NLD11 (MTK_PIN_NO(28) | 1) +#define MT8135_PIN_28_NLD11__FUNC_EINT157 (MTK_PIN_NO(28) | 2) +#define MT8135_PIN_28_NLD11__FUNC_CM2HSYNC_1X (MTK_PIN_NO(28) | 4) +#define MT8135_PIN_28_NLD11__FUNC_PWM3 (MTK_PIN_NO(28) | 5) + +#define MT8135_PIN_29_NLD12__FUNC_GPIO29 (MTK_PIN_NO(29) | 0) +#define MT8135_PIN_29_NLD12__FUNC_NLD12 (MTK_PIN_NO(29) | 1) +#define MT8135_PIN_29_NLD12__FUNC_EINT158 (MTK_PIN_NO(29) | 2) +#define MT8135_PIN_29_NLD12__FUNC_I2SIN_CK (MTK_PIN_NO(29) | 3) +#define MT8135_PIN_29_NLD12__FUNC_DAC_CK (MTK_PIN_NO(29) | 4) +#define MT8135_PIN_29_NLD12__FUNC_PCM1_CK (MTK_PIN_NO(29) | 5) + +#define MT8135_PIN_30_NLD13__FUNC_GPIO30 (MTK_PIN_NO(30) | 0) +#define MT8135_PIN_30_NLD13__FUNC_NLD13 (MTK_PIN_NO(30) | 1) +#define MT8135_PIN_30_NLD13__FUNC_EINT159 (MTK_PIN_NO(30) | 2) +#define MT8135_PIN_30_NLD13__FUNC_I2SIN_WS (MTK_PIN_NO(30) | 3) +#define MT8135_PIN_30_NLD13__FUNC_DAC_WS (MTK_PIN_NO(30) | 4) +#define MT8135_PIN_30_NLD13__FUNC_PCM1_WS (MTK_PIN_NO(30) | 5) + +#define MT8135_PIN_31_NLD14__FUNC_GPIO31 (MTK_PIN_NO(31) | 0) +#define MT8135_PIN_31_NLD14__FUNC_NLD14 (MTK_PIN_NO(31) | 1) +#define MT8135_PIN_31_NLD14__FUNC_EINT160 (MTK_PIN_NO(31) | 2) +#define MT8135_PIN_31_NLD14__FUNC_I2SOUT_DAT (MTK_PIN_NO(31) | 3) +#define MT8135_PIN_31_NLD14__FUNC_DAC_DAT_OUT (MTK_PIN_NO(31) | 4) +#define MT8135_PIN_31_NLD14__FUNC_PCM1_DO (MTK_PIN_NO(31) | 5) + +#define MT8135_PIN_32_NLD15__FUNC_GPIO32 (MTK_PIN_NO(32) | 0) +#define MT8135_PIN_32_NLD15__FUNC_NLD15 (MTK_PIN_NO(32) | 1) +#define MT8135_PIN_32_NLD15__FUNC_EINT161 (MTK_PIN_NO(32) | 2) +#define MT8135_PIN_32_NLD15__FUNC_DISP_PWM (MTK_PIN_NO(32) | 3) +#define MT8135_PIN_32_NLD15__FUNC_PWM4 (MTK_PIN_NO(32) | 4) +#define MT8135_PIN_32_NLD15__FUNC_PCM1_DI (MTK_PIN_NO(32) | 5) + +#define MT8135_PIN_33_MSDC0_RSTB__FUNC_GPIO33 (MTK_PIN_NO(33) | 0) +#define MT8135_PIN_33_MSDC0_RSTB__FUNC_MSDC0_RSTB (MTK_PIN_NO(33) | 1) +#define MT8135_PIN_33_MSDC0_RSTB__FUNC_EINT50 (MTK_PIN_NO(33) | 2) +#define MT8135_PIN_33_MSDC0_RSTB__FUNC_I2SIN_DAT (MTK_PIN_NO(33) | 3) +#define MT8135_PIN_33_MSDC0_RSTB__FUNC_PCM1_DI (MTK_PIN_NO(33) | 5) +#define MT8135_PIN_33_MSDC0_RSTB__FUNC_SPI1_MI (MTK_PIN_NO(33) | 6) +#define MT8135_PIN_33_MSDC0_RSTB__FUNC_NLD10 (MTK_PIN_NO(33) | 7) + +#define MT8135_PIN_34_IDDIG__FUNC_GPIO34 (MTK_PIN_NO(34) | 0) +#define MT8135_PIN_34_IDDIG__FUNC_IDDIG (MTK_PIN_NO(34) | 1) +#define MT8135_PIN_34_IDDIG__FUNC_EINT34 (MTK_PIN_NO(34) | 2) + +#define MT8135_PIN_35_SCL3__FUNC_GPIO35 (MTK_PIN_NO(35) | 0) +#define MT8135_PIN_35_SCL3__FUNC_SCL3 (MTK_PIN_NO(35) | 1) +#define MT8135_PIN_35_SCL3__FUNC_EINT96 (MTK_PIN_NO(35) | 2) +#define MT8135_PIN_35_SCL3__FUNC_CLKM6 (MTK_PIN_NO(35) | 3) +#define MT8135_PIN_35_SCL3__FUNC_PWM6 (MTK_PIN_NO(35) | 4) + +#define MT8135_PIN_36_SDA3__FUNC_GPIO36 (MTK_PIN_NO(36) | 0) +#define MT8135_PIN_36_SDA3__FUNC_SDA3 (MTK_PIN_NO(36) | 1) +#define MT8135_PIN_36_SDA3__FUNC_EINT97 (MTK_PIN_NO(36) | 2) + +#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_GPIO37 (MTK_PIN_NO(37) | 0) +#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_AUD_CLK (MTK_PIN_NO(37) | 1) +#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_ADC_CK (MTK_PIN_NO(37) | 2) +#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_HDMI_SDATA0 (MTK_PIN_NO(37) | 3) +#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_EINT19 (MTK_PIN_NO(37) | 4) +#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_USB_TEST_IO_6 (MTK_PIN_NO(37) | 5) +#define MT8135_PIN_37_AUD_CLK_MOSI__FUNC_TESTA_OUT19 (MTK_PIN_NO(37) | 7) + +#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_GPIO38 (MTK_PIN_NO(38) | 0) +#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_AUD_DAT_MOSI (MTK_PIN_NO(38) | 1) +#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_ADC_WS (MTK_PIN_NO(38) | 2) +#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_AUD_DAT_MISO (MTK_PIN_NO(38) | 3) +#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_EINT21 (MTK_PIN_NO(38) | 4) +#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_USB_TEST_IO_7 (MTK_PIN_NO(38) | 5) +#define MT8135_PIN_38_AUD_DAT_MOSI__FUNC_TESTA_OUT20 (MTK_PIN_NO(38) | 7) + +#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_GPIO39 (MTK_PIN_NO(39) | 0) +#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_AUD_DAT_MISO (MTK_PIN_NO(39) | 1) +#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_ADC_DAT_IN (MTK_PIN_NO(39) | 2) +#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_AUD_DAT_MOSI (MTK_PIN_NO(39) | 3) +#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_EINT20 (MTK_PIN_NO(39) | 4) +#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_USB_TEST_IO_8 (MTK_PIN_NO(39) | 5) +#define MT8135_PIN_39_AUD_DAT_MISO__FUNC_TESTA_OUT21 (MTK_PIN_NO(39) | 7) + +#define MT8135_PIN_40_DAC_CLK__FUNC_GPIO40 (MTK_PIN_NO(40) | 0) +#define MT8135_PIN_40_DAC_CLK__FUNC_DAC_CK (MTK_PIN_NO(40) | 1) +#define MT8135_PIN_40_DAC_CLK__FUNC_EINT22 (MTK_PIN_NO(40) | 2) +#define MT8135_PIN_40_DAC_CLK__FUNC_HDMI_SDATA1 (MTK_PIN_NO(40) | 3) +#define MT8135_PIN_40_DAC_CLK__FUNC_USB_TEST_IO_9 (MTK_PIN_NO(40) | 5) +#define MT8135_PIN_40_DAC_CLK__FUNC_TESTA_OUT22 (MTK_PIN_NO(40) | 7) + +#define MT8135_PIN_41_DAC_WS__FUNC_GPIO41 (MTK_PIN_NO(41) | 0) +#define MT8135_PIN_41_DAC_WS__FUNC_DAC_WS (MTK_PIN_NO(41) | 1) +#define MT8135_PIN_41_DAC_WS__FUNC_EINT24 (MTK_PIN_NO(41) | 2) +#define MT8135_PIN_41_DAC_WS__FUNC_HDMI_SDATA2 (MTK_PIN_NO(41) | 3) +#define MT8135_PIN_41_DAC_WS__FUNC_USB_TEST_IO_10 (MTK_PIN_NO(41) | 5) +#define MT8135_PIN_41_DAC_WS__FUNC_TESTA_OUT23 (MTK_PIN_NO(41) | 7) + +#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_GPIO42 (MTK_PIN_NO(42) | 0) +#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_DAC_DAT_OUT (MTK_PIN_NO(42) | 1) +#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_EINT23 (MTK_PIN_NO(42) | 2) +#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_HDMI_SDATA3 (MTK_PIN_NO(42) | 3) +#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_USB_TEST_IO_11 (MTK_PIN_NO(42) | 5) +#define MT8135_PIN_42_DAC_DAT_OUT__FUNC_TESTA_OUT24 (MTK_PIN_NO(42) | 7) + +#define MT8135_PIN_43_PWRAP_SPI0_MO__FUNC_GPIO43 (MTK_PIN_NO(43) | 0) +#define MT8135_PIN_43_PWRAP_SPI0_MO__FUNC_PWRAP_SPIDI (MTK_PIN_NO(43) | 1) +#define MT8135_PIN_43_PWRAP_SPI0_MO__FUNC_EINT29 (MTK_PIN_NO(43) | 2) + +#define MT8135_PIN_44_PWRAP_SPI0_MI__FUNC_GPIO44 (MTK_PIN_NO(44) | 0) +#define MT8135_PIN_44_PWRAP_SPI0_MI__FUNC_PWRAP_SPIDO (MTK_PIN_NO(44) | 1) +#define MT8135_PIN_44_PWRAP_SPI0_MI__FUNC_EINT28 (MTK_PIN_NO(44) | 2) + +#define MT8135_PIN_45_PWRAP_SPI0_CSN__FUNC_GPIO45 (MTK_PIN_NO(45) | 0) +#define MT8135_PIN_45_PWRAP_SPI0_CSN__FUNC_PWRAP_SPICS_B_I (MTK_PIN_NO(45) | 1) +#define MT8135_PIN_45_PWRAP_SPI0_CSN__FUNC_EINT27 (MTK_PIN_NO(45) | 2) + +#define MT8135_PIN_46_PWRAP_SPI0_CLK__FUNC_GPIO46 (MTK_PIN_NO(46) | 0) +#define MT8135_PIN_46_PWRAP_SPI0_CLK__FUNC_PWRAP_SPICK_I (MTK_PIN_NO(46) | 1) +#define MT8135_PIN_46_PWRAP_SPI0_CLK__FUNC_EINT26 (MTK_PIN_NO(46) | 2) + +#define MT8135_PIN_47_PWRAP_EVENT__FUNC_GPIO47 (MTK_PIN_NO(47) | 0) +#define MT8135_PIN_47_PWRAP_EVENT__FUNC_PWRAP_EVENT_IN (MTK_PIN_NO(47) | 1) +#define MT8135_PIN_47_PWRAP_EVENT__FUNC_EINT25 (MTK_PIN_NO(47) | 2) +#define MT8135_PIN_47_PWRAP_EVENT__FUNC_TESTA_OUT2 (MTK_PIN_NO(47) | 7) + +#define MT8135_PIN_48_RTC32K_CK__FUNC_GPIO48 (MTK_PIN_NO(48) | 0) +#define MT8135_PIN_48_RTC32K_CK__FUNC_RTC32K_CK (MTK_PIN_NO(48) | 1) + +#define MT8135_PIN_49_WATCHDOG__FUNC_GPIO49 (MTK_PIN_NO(49) | 0) +#define MT8135_PIN_49_WATCHDOG__FUNC_WATCHDOG (MTK_PIN_NO(49) | 1) +#define MT8135_PIN_49_WATCHDOG__FUNC_EINT36 (MTK_PIN_NO(49) | 2) + +#define MT8135_PIN_50_SRCLKENA__FUNC_GPIO50 (MTK_PIN_NO(50) | 0) +#define MT8135_PIN_50_SRCLKENA__FUNC_SRCLKENA (MTK_PIN_NO(50) | 1) +#define MT8135_PIN_50_SRCLKENA__FUNC_EINT38 (MTK_PIN_NO(50) | 2) + +#define MT8135_PIN_51_SRCVOLTEN__FUNC_GPIO51 (MTK_PIN_NO(51) | 0) +#define MT8135_PIN_51_SRCVOLTEN__FUNC_SRCVOLTEN (MTK_PIN_NO(51) | 1) +#define MT8135_PIN_51_SRCVOLTEN__FUNC_EINT37 (MTK_PIN_NO(51) | 2) + +#define MT8135_PIN_52_EINT0__FUNC_GPIO52 (MTK_PIN_NO(52) | 0) +#define MT8135_PIN_52_EINT0__FUNC_EINT0 (MTK_PIN_NO(52) | 1) +#define MT8135_PIN_52_EINT0__FUNC_PWM1 (MTK_PIN_NO(52) | 2) +#define MT8135_PIN_52_EINT0__FUNC_CLKM0 (MTK_PIN_NO(52) | 3) +#define MT8135_PIN_52_EINT0__FUNC_SPDIF_OUT (MTK_PIN_NO(52) | 4) +#define MT8135_PIN_52_EINT0__FUNC_USB_TEST_IO_12 (MTK_PIN_NO(52) | 5) +#define MT8135_PIN_52_EINT0__FUNC_USB_SCL (MTK_PIN_NO(52) | 7) + +#define MT8135_PIN_53_URXD2__FUNC_GPIO53 (MTK_PIN_NO(53) | 0) +#define MT8135_PIN_53_URXD2__FUNC_URXD2 (MTK_PIN_NO(53) | 1) +#define MT8135_PIN_53_URXD2__FUNC_EINT83 (MTK_PIN_NO(53) | 2) +#define MT8135_PIN_53_URXD2__FUNC_HDMI_LRCK (MTK_PIN_NO(53) | 4) +#define MT8135_PIN_53_URXD2__FUNC_CLKM3 (MTK_PIN_NO(53) | 5) +#define MT8135_PIN_53_URXD2__FUNC_UTXD2 (MTK_PIN_NO(53) | 7) + +#define MT8135_PIN_54_UTXD2__FUNC_GPIO54 (MTK_PIN_NO(54) | 0) +#define MT8135_PIN_54_UTXD2__FUNC_UTXD2 (MTK_PIN_NO(54) | 1) +#define MT8135_PIN_54_UTXD2__FUNC_EINT82 (MTK_PIN_NO(54) | 2) +#define MT8135_PIN_54_UTXD2__FUNC_HDMI_BCK_OUT (MTK_PIN_NO(54) | 4) +#define MT8135_PIN_54_UTXD2__FUNC_CLKM2 (MTK_PIN_NO(54) | 5) +#define MT8135_PIN_54_UTXD2__FUNC_URXD2 (MTK_PIN_NO(54) | 7) + +#define MT8135_PIN_55_UCTS2__FUNC_GPIO55 (MTK_PIN_NO(55) | 0) +#define MT8135_PIN_55_UCTS2__FUNC_UCTS2 (MTK_PIN_NO(55) | 1) +#define MT8135_PIN_55_UCTS2__FUNC_EINT84 (MTK_PIN_NO(55) | 2) +#define MT8135_PIN_55_UCTS2__FUNC_PWM1 (MTK_PIN_NO(55) | 5) +#define MT8135_PIN_55_UCTS2__FUNC_URTS2 (MTK_PIN_NO(55) | 7) + +#define MT8135_PIN_56_URTS2__FUNC_GPIO56 (MTK_PIN_NO(56) | 0) +#define MT8135_PIN_56_URTS2__FUNC_URTS2 (MTK_PIN_NO(56) | 1) +#define MT8135_PIN_56_URTS2__FUNC_EINT85 (MTK_PIN_NO(56) | 2) +#define MT8135_PIN_56_URTS2__FUNC_PWM2 (MTK_PIN_NO(56) | 5) +#define MT8135_PIN_56_URTS2__FUNC_UCTS2 (MTK_PIN_NO(56) | 7) + +#define MT8135_PIN_57_JTCK__FUNC_GPIO57 (MTK_PIN_NO(57) | 0) +#define MT8135_PIN_57_JTCK__FUNC_JTCK (MTK_PIN_NO(57) | 1) +#define MT8135_PIN_57_JTCK__FUNC_EINT188 (MTK_PIN_NO(57) | 2) +#define MT8135_PIN_57_JTCK__FUNC_DSP1_ICK (MTK_PIN_NO(57) | 3) + +#define MT8135_PIN_58_JTDO__FUNC_GPIO58 (MTK_PIN_NO(58) | 0) +#define MT8135_PIN_58_JTDO__FUNC_JTDO (MTK_PIN_NO(58) | 1) +#define MT8135_PIN_58_JTDO__FUNC_EINT190 (MTK_PIN_NO(58) | 2) +#define MT8135_PIN_58_JTDO__FUNC_DSP2_IMS (MTK_PIN_NO(58) | 3) + +#define MT8135_PIN_59_JTRST_B__FUNC_GPIO59 (MTK_PIN_NO(59) | 0) +#define MT8135_PIN_59_JTRST_B__FUNC_JTRST_B (MTK_PIN_NO(59) | 1) +#define MT8135_PIN_59_JTRST_B__FUNC_EINT0 (MTK_PIN_NO(59) | 2) +#define MT8135_PIN_59_JTRST_B__FUNC_DSP2_ICK (MTK_PIN_NO(59) | 3) + +#define MT8135_PIN_60_JTDI__FUNC_GPIO60 (MTK_PIN_NO(60) | 0) +#define MT8135_PIN_60_JTDI__FUNC_JTDI (MTK_PIN_NO(60) | 1) +#define MT8135_PIN_60_JTDI__FUNC_EINT189 (MTK_PIN_NO(60) | 2) +#define MT8135_PIN_60_JTDI__FUNC_DSP1_IMS (MTK_PIN_NO(60) | 3) + +#define MT8135_PIN_61_JRTCK__FUNC_GPIO61 (MTK_PIN_NO(61) | 0) +#define MT8135_PIN_61_JRTCK__FUNC_JRTCK (MTK_PIN_NO(61) | 1) +#define MT8135_PIN_61_JRTCK__FUNC_EINT187 (MTK_PIN_NO(61) | 2) +#define MT8135_PIN_61_JRTCK__FUNC_DSP1_ID (MTK_PIN_NO(61) | 3) + +#define MT8135_PIN_62_JTMS__FUNC_GPIO62 (MTK_PIN_NO(62) | 0) +#define MT8135_PIN_62_JTMS__FUNC_JTMS (MTK_PIN_NO(62) | 1) +#define MT8135_PIN_62_JTMS__FUNC_EINT191 (MTK_PIN_NO(62) | 2) +#define MT8135_PIN_62_JTMS__FUNC_DSP2_ID (MTK_PIN_NO(62) | 3) + +#define MT8135_PIN_63_MSDC1_INSI__FUNC_GPIO63 (MTK_PIN_NO(63) | 0) +#define MT8135_PIN_63_MSDC1_INSI__FUNC_MSDC1_INSI (MTK_PIN_NO(63) | 1) +#define MT8135_PIN_63_MSDC1_INSI__FUNC_SCL5 (MTK_PIN_NO(63) | 3) +#define MT8135_PIN_63_MSDC1_INSI__FUNC_PWM6 (MTK_PIN_NO(63) | 4) +#define MT8135_PIN_63_MSDC1_INSI__FUNC_CLKM5 (MTK_PIN_NO(63) | 5) +#define MT8135_PIN_63_MSDC1_INSI__FUNC_TESTB_OUT6 (MTK_PIN_NO(63) | 7) + +#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_GPIO64 (MTK_PIN_NO(64) | 0) +#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_MSDC1_SDWPI (MTK_PIN_NO(64) | 1) +#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_EINT58 (MTK_PIN_NO(64) | 2) +#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_SDA5 (MTK_PIN_NO(64) | 3) +#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_PWM7 (MTK_PIN_NO(64) | 4) +#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_CLKM6 (MTK_PIN_NO(64) | 5) +#define MT8135_PIN_64_MSDC1_SDWPI__FUNC_TESTB_OUT7 (MTK_PIN_NO(64) | 7) + +#define MT8135_PIN_65_MSDC2_INSI__FUNC_GPIO65 (MTK_PIN_NO(65) | 0) +#define MT8135_PIN_65_MSDC2_INSI__FUNC_MSDC2_INSI (MTK_PIN_NO(65) | 1) +#define MT8135_PIN_65_MSDC2_INSI__FUNC_USB_TEST_IO_27 (MTK_PIN_NO(65) | 5) +#define MT8135_PIN_65_MSDC2_INSI__FUNC_TESTA_OUT3 (MTK_PIN_NO(65) | 7) + +#define MT8135_PIN_66_MSDC2_SDWPI__FUNC_GPIO66 (MTK_PIN_NO(66) | 0) +#define MT8135_PIN_66_MSDC2_SDWPI__FUNC_MSDC2_SDWPI (MTK_PIN_NO(66) | 1) +#define MT8135_PIN_66_MSDC2_SDWPI__FUNC_EINT66 (MTK_PIN_NO(66) | 2) +#define MT8135_PIN_66_MSDC2_SDWPI__FUNC_USB_TEST_IO_28 (MTK_PIN_NO(66) | 5) + +#define MT8135_PIN_67_URXD4__FUNC_GPIO67 (MTK_PIN_NO(67) | 0) +#define MT8135_PIN_67_URXD4__FUNC_URXD4 (MTK_PIN_NO(67) | 1) +#define MT8135_PIN_67_URXD4__FUNC_EINT89 (MTK_PIN_NO(67) | 2) +#define MT8135_PIN_67_URXD4__FUNC_URXD1 (MTK_PIN_NO(67) | 3) +#define MT8135_PIN_67_URXD4__FUNC_UTXD4 (MTK_PIN_NO(67) | 6) +#define MT8135_PIN_67_URXD4__FUNC_TESTB_OUT10 (MTK_PIN_NO(67) | 7) + +#define MT8135_PIN_68_UTXD4__FUNC_GPIO68 (MTK_PIN_NO(68) | 0) +#define MT8135_PIN_68_UTXD4__FUNC_UTXD4 (MTK_PIN_NO(68) | 1) +#define MT8135_PIN_68_UTXD4__FUNC_EINT88 (MTK_PIN_NO(68) | 2) +#define MT8135_PIN_68_UTXD4__FUNC_UTXD1 (MTK_PIN_NO(68) | 3) +#define MT8135_PIN_68_UTXD4__FUNC_URXD4 (MTK_PIN_NO(68) | 6) +#define MT8135_PIN_68_UTXD4__FUNC_TESTB_OUT11 (MTK_PIN_NO(68) | 7) + +#define MT8135_PIN_69_URXD1__FUNC_GPIO69 (MTK_PIN_NO(69) | 0) +#define MT8135_PIN_69_URXD1__FUNC_URXD1 (MTK_PIN_NO(69) | 1) +#define MT8135_PIN_69_URXD1__FUNC_EINT79 (MTK_PIN_NO(69) | 2) +#define MT8135_PIN_69_URXD1__FUNC_URXD4 (MTK_PIN_NO(69) | 3) +#define MT8135_PIN_69_URXD1__FUNC_UTXD1 (MTK_PIN_NO(69) | 6) +#define MT8135_PIN_69_URXD1__FUNC_TESTB_OUT24 (MTK_PIN_NO(69) | 7) + +#define MT8135_PIN_70_UTXD1__FUNC_GPIO70 (MTK_PIN_NO(70) | 0) +#define MT8135_PIN_70_UTXD1__FUNC_UTXD1 (MTK_PIN_NO(70) | 1) +#define MT8135_PIN_70_UTXD1__FUNC_EINT78 (MTK_PIN_NO(70) | 2) +#define MT8135_PIN_70_UTXD1__FUNC_UTXD4 (MTK_PIN_NO(70) | 3) +#define MT8135_PIN_70_UTXD1__FUNC_URXD1 (MTK_PIN_NO(70) | 6) +#define MT8135_PIN_70_UTXD1__FUNC_TESTB_OUT25 (MTK_PIN_NO(70) | 7) + +#define MT8135_PIN_71_UCTS1__FUNC_GPIO71 (MTK_PIN_NO(71) | 0) +#define MT8135_PIN_71_UCTS1__FUNC_UCTS1 (MTK_PIN_NO(71) | 1) +#define MT8135_PIN_71_UCTS1__FUNC_EINT80 (MTK_PIN_NO(71) | 2) +#define MT8135_PIN_71_UCTS1__FUNC_CLKM0 (MTK_PIN_NO(71) | 5) +#define MT8135_PIN_71_UCTS1__FUNC_URTS1 (MTK_PIN_NO(71) | 6) +#define MT8135_PIN_71_UCTS1__FUNC_TESTB_OUT31 (MTK_PIN_NO(71) | 7) + +#define MT8135_PIN_72_URTS1__FUNC_GPIO72 (MTK_PIN_NO(72) | 0) +#define MT8135_PIN_72_URTS1__FUNC_URTS1 (MTK_PIN_NO(72) | 1) +#define MT8135_PIN_72_URTS1__FUNC_EINT81 (MTK_PIN_NO(72) | 2) +#define MT8135_PIN_72_URTS1__FUNC_CLKM1 (MTK_PIN_NO(72) | 5) +#define MT8135_PIN_72_URTS1__FUNC_UCTS1 (MTK_PIN_NO(72) | 6) +#define MT8135_PIN_72_URTS1__FUNC_TESTB_OUT21 (MTK_PIN_NO(72) | 7) + +#define MT8135_PIN_73_PWM1__FUNC_GPIO73 (MTK_PIN_NO(73) | 0) +#define MT8135_PIN_73_PWM1__FUNC_PWM1 (MTK_PIN_NO(73) | 1) +#define MT8135_PIN_73_PWM1__FUNC_EINT73 (MTK_PIN_NO(73) | 2) +#define MT8135_PIN_73_PWM1__FUNC_USB_DRVVBUS (MTK_PIN_NO(73) | 5) +#define MT8135_PIN_73_PWM1__FUNC_DISP_PWM (MTK_PIN_NO(73) | 6) +#define MT8135_PIN_73_PWM1__FUNC_TESTB_OUT8 (MTK_PIN_NO(73) | 7) + +#define MT8135_PIN_74_PWM2__FUNC_GPIO74 (MTK_PIN_NO(74) | 0) +#define MT8135_PIN_74_PWM2__FUNC_PWM2 (MTK_PIN_NO(74) | 1) +#define MT8135_PIN_74_PWM2__FUNC_EINT74 (MTK_PIN_NO(74) | 2) +#define MT8135_PIN_74_PWM2__FUNC_DPI33_CK (MTK_PIN_NO(74) | 3) +#define MT8135_PIN_74_PWM2__FUNC_PWM5 (MTK_PIN_NO(74) | 4) +#define MT8135_PIN_74_PWM2__FUNC_URXD2 (MTK_PIN_NO(74) | 5) +#define MT8135_PIN_74_PWM2__FUNC_DISP_PWM (MTK_PIN_NO(74) | 6) +#define MT8135_PIN_74_PWM2__FUNC_TESTB_OUT9 (MTK_PIN_NO(74) | 7) + +#define MT8135_PIN_75_PWM3__FUNC_GPIO75 (MTK_PIN_NO(75) | 0) +#define MT8135_PIN_75_PWM3__FUNC_PWM3 (MTK_PIN_NO(75) | 1) +#define MT8135_PIN_75_PWM3__FUNC_EINT75 (MTK_PIN_NO(75) | 2) +#define MT8135_PIN_75_PWM3__FUNC_DPI33_D0 (MTK_PIN_NO(75) | 3) +#define MT8135_PIN_75_PWM3__FUNC_PWM6 (MTK_PIN_NO(75) | 4) +#define MT8135_PIN_75_PWM3__FUNC_UTXD2 (MTK_PIN_NO(75) | 5) +#define MT8135_PIN_75_PWM3__FUNC_DISP_PWM (MTK_PIN_NO(75) | 6) +#define MT8135_PIN_75_PWM3__FUNC_TESTB_OUT12 (MTK_PIN_NO(75) | 7) + +#define MT8135_PIN_76_PWM4__FUNC_GPIO76 (MTK_PIN_NO(76) | 0) +#define MT8135_PIN_76_PWM4__FUNC_PWM4 (MTK_PIN_NO(76) | 1) +#define MT8135_PIN_76_PWM4__FUNC_EINT76 (MTK_PIN_NO(76) | 2) +#define MT8135_PIN_76_PWM4__FUNC_DPI33_D1 (MTK_PIN_NO(76) | 3) +#define MT8135_PIN_76_PWM4__FUNC_PWM7 (MTK_PIN_NO(76) | 4) +#define MT8135_PIN_76_PWM4__FUNC_DISP_PWM (MTK_PIN_NO(76) | 6) +#define MT8135_PIN_76_PWM4__FUNC_TESTB_OUT13 (MTK_PIN_NO(76) | 7) + +#define MT8135_PIN_77_MSDC2_DAT2__FUNC_GPIO77 (MTK_PIN_NO(77) | 0) +#define MT8135_PIN_77_MSDC2_DAT2__FUNC_MSDC2_DAT2 (MTK_PIN_NO(77) | 1) +#define MT8135_PIN_77_MSDC2_DAT2__FUNC_EINT63 (MTK_PIN_NO(77) | 2) +#define MT8135_PIN_77_MSDC2_DAT2__FUNC_DSP2_IMS (MTK_PIN_NO(77) | 4) +#define MT8135_PIN_77_MSDC2_DAT2__FUNC_DPI33_D6 (MTK_PIN_NO(77) | 6) +#define MT8135_PIN_77_MSDC2_DAT2__FUNC_TESTA_OUT25 (MTK_PIN_NO(77) | 7) + +#define MT8135_PIN_78_MSDC2_DAT3__FUNC_GPIO78 (MTK_PIN_NO(78) | 0) +#define MT8135_PIN_78_MSDC2_DAT3__FUNC_MSDC2_DAT3 (MTK_PIN_NO(78) | 1) +#define MT8135_PIN_78_MSDC2_DAT3__FUNC_EINT64 (MTK_PIN_NO(78) | 2) +#define MT8135_PIN_78_MSDC2_DAT3__FUNC_DSP2_ID (MTK_PIN_NO(78) | 4) +#define MT8135_PIN_78_MSDC2_DAT3__FUNC_DPI33_D7 (MTK_PIN_NO(78) | 6) +#define MT8135_PIN_78_MSDC2_DAT3__FUNC_TESTA_OUT26 (MTK_PIN_NO(78) | 7) + +#define MT8135_PIN_79_MSDC2_CMD__FUNC_GPIO79 (MTK_PIN_NO(79) | 0) +#define MT8135_PIN_79_MSDC2_CMD__FUNC_MSDC2_CMD (MTK_PIN_NO(79) | 1) +#define MT8135_PIN_79_MSDC2_CMD__FUNC_EINT60 (MTK_PIN_NO(79) | 2) +#define MT8135_PIN_79_MSDC2_CMD__FUNC_DSP1_IMS (MTK_PIN_NO(79) | 4) +#define MT8135_PIN_79_MSDC2_CMD__FUNC_PCM1_WS (MTK_PIN_NO(79) | 5) +#define MT8135_PIN_79_MSDC2_CMD__FUNC_DPI33_D3 (MTK_PIN_NO(79) | 6) +#define MT8135_PIN_79_MSDC2_CMD__FUNC_TESTA_OUT0 (MTK_PIN_NO(79) | 7) + +#define MT8135_PIN_80_MSDC2_CLK__FUNC_GPIO80 (MTK_PIN_NO(80) | 0) +#define MT8135_PIN_80_MSDC2_CLK__FUNC_MSDC2_CLK (MTK_PIN_NO(80) | 1) +#define MT8135_PIN_80_MSDC2_CLK__FUNC_EINT59 (MTK_PIN_NO(80) | 2) +#define MT8135_PIN_80_MSDC2_CLK__FUNC_DSP1_ICK (MTK_PIN_NO(80) | 4) +#define MT8135_PIN_80_MSDC2_CLK__FUNC_PCM1_CK (MTK_PIN_NO(80) | 5) +#define MT8135_PIN_80_MSDC2_CLK__FUNC_DPI33_D2 (MTK_PIN_NO(80) | 6) +#define MT8135_PIN_80_MSDC2_CLK__FUNC_TESTA_OUT1 (MTK_PIN_NO(80) | 7) + +#define MT8135_PIN_81_MSDC2_DAT1__FUNC_GPIO81 (MTK_PIN_NO(81) | 0) +#define MT8135_PIN_81_MSDC2_DAT1__FUNC_MSDC2_DAT1 (MTK_PIN_NO(81) | 1) +#define MT8135_PIN_81_MSDC2_DAT1__FUNC_EINT62 (MTK_PIN_NO(81) | 2) +#define MT8135_PIN_81_MSDC2_DAT1__FUNC_DSP2_ICK (MTK_PIN_NO(81) | 4) +#define MT8135_PIN_81_MSDC2_DAT1__FUNC_PCM1_DO (MTK_PIN_NO(81) | 5) +#define MT8135_PIN_81_MSDC2_DAT1__FUNC_DPI33_D5 (MTK_PIN_NO(81) | 6) + +#define MT8135_PIN_82_MSDC2_DAT0__FUNC_GPIO82 (MTK_PIN_NO(82) | 0) +#define MT8135_PIN_82_MSDC2_DAT0__FUNC_MSDC2_DAT0 (MTK_PIN_NO(82) | 1) +#define MT8135_PIN_82_MSDC2_DAT0__FUNC_EINT61 (MTK_PIN_NO(82) | 2) +#define MT8135_PIN_82_MSDC2_DAT0__FUNC_DSP1_ID (MTK_PIN_NO(82) | 4) +#define MT8135_PIN_82_MSDC2_DAT0__FUNC_PCM1_DI (MTK_PIN_NO(82) | 5) +#define MT8135_PIN_82_MSDC2_DAT0__FUNC_DPI33_D4 (MTK_PIN_NO(82) | 6) + +#define MT8135_PIN_83_MSDC1_DAT0__FUNC_GPIO83 (MTK_PIN_NO(83) | 0) +#define MT8135_PIN_83_MSDC1_DAT0__FUNC_MSDC1_DAT0 (MTK_PIN_NO(83) | 1) +#define MT8135_PIN_83_MSDC1_DAT0__FUNC_EINT53 (MTK_PIN_NO(83) | 2) +#define MT8135_PIN_83_MSDC1_DAT0__FUNC_SCL1 (MTK_PIN_NO(83) | 3) +#define MT8135_PIN_83_MSDC1_DAT0__FUNC_PWM2 (MTK_PIN_NO(83) | 4) +#define MT8135_PIN_83_MSDC1_DAT0__FUNC_CLKM1 (MTK_PIN_NO(83) | 5) +#define MT8135_PIN_83_MSDC1_DAT0__FUNC_TESTB_OUT2 (MTK_PIN_NO(83) | 7) + +#define MT8135_PIN_84_MSDC1_DAT1__FUNC_GPIO84 (MTK_PIN_NO(84) | 0) +#define MT8135_PIN_84_MSDC1_DAT1__FUNC_MSDC1_DAT1 (MTK_PIN_NO(84) | 1) +#define MT8135_PIN_84_MSDC1_DAT1__FUNC_EINT54 (MTK_PIN_NO(84) | 2) +#define MT8135_PIN_84_MSDC1_DAT1__FUNC_SDA1 (MTK_PIN_NO(84) | 3) +#define MT8135_PIN_84_MSDC1_DAT1__FUNC_PWM3 (MTK_PIN_NO(84) | 4) +#define MT8135_PIN_84_MSDC1_DAT1__FUNC_CLKM2 (MTK_PIN_NO(84) | 5) +#define MT8135_PIN_84_MSDC1_DAT1__FUNC_TESTB_OUT3 (MTK_PIN_NO(84) | 7) + +#define MT8135_PIN_85_MSDC1_CMD__FUNC_GPIO85 (MTK_PIN_NO(85) | 0) +#define MT8135_PIN_85_MSDC1_CMD__FUNC_MSDC1_CMD (MTK_PIN_NO(85) | 1) +#define MT8135_PIN_85_MSDC1_CMD__FUNC_EINT52 (MTK_PIN_NO(85) | 2) +#define MT8135_PIN_85_MSDC1_CMD__FUNC_SDA0 (MTK_PIN_NO(85) | 3) +#define MT8135_PIN_85_MSDC1_CMD__FUNC_PWM1 (MTK_PIN_NO(85) | 4) +#define MT8135_PIN_85_MSDC1_CMD__FUNC_CLKM0 (MTK_PIN_NO(85) | 5) +#define MT8135_PIN_85_MSDC1_CMD__FUNC_TESTB_OUT1 (MTK_PIN_NO(85) | 7) + +#define MT8135_PIN_86_MSDC1_CLK__FUNC_GPIO86 (MTK_PIN_NO(86) | 0) +#define MT8135_PIN_86_MSDC1_CLK__FUNC_MSDC1_CLK (MTK_PIN_NO(86) | 1) +#define MT8135_PIN_86_MSDC1_CLK__FUNC_EINT51 (MTK_PIN_NO(86) | 2) +#define MT8135_PIN_86_MSDC1_CLK__FUNC_SCL0 (MTK_PIN_NO(86) | 3) +#define MT8135_PIN_86_MSDC1_CLK__FUNC_DISP_PWM (MTK_PIN_NO(86) | 4) +#define MT8135_PIN_86_MSDC1_CLK__FUNC_TESTB_OUT0 (MTK_PIN_NO(86) | 7) + +#define MT8135_PIN_87_MSDC1_DAT2__FUNC_GPIO87 (MTK_PIN_NO(87) | 0) +#define MT8135_PIN_87_MSDC1_DAT2__FUNC_MSDC1_DAT2 (MTK_PIN_NO(87) | 1) +#define MT8135_PIN_87_MSDC1_DAT2__FUNC_EINT55 (MTK_PIN_NO(87) | 2) +#define MT8135_PIN_87_MSDC1_DAT2__FUNC_SCL4 (MTK_PIN_NO(87) | 3) +#define MT8135_PIN_87_MSDC1_DAT2__FUNC_PWM4 (MTK_PIN_NO(87) | 4) +#define MT8135_PIN_87_MSDC1_DAT2__FUNC_CLKM3 (MTK_PIN_NO(87) | 5) +#define MT8135_PIN_87_MSDC1_DAT2__FUNC_TESTB_OUT4 (MTK_PIN_NO(87) | 7) + +#define MT8135_PIN_88_MSDC1_DAT3__FUNC_GPIO88 (MTK_PIN_NO(88) | 0) +#define MT8135_PIN_88_MSDC1_DAT3__FUNC_MSDC1_DAT3 (MTK_PIN_NO(88) | 1) +#define MT8135_PIN_88_MSDC1_DAT3__FUNC_EINT56 (MTK_PIN_NO(88) | 2) +#define MT8135_PIN_88_MSDC1_DAT3__FUNC_SDA4 (MTK_PIN_NO(88) | 3) +#define MT8135_PIN_88_MSDC1_DAT3__FUNC_PWM5 (MTK_PIN_NO(88) | 4) +#define MT8135_PIN_88_MSDC1_DAT3__FUNC_CLKM4 (MTK_PIN_NO(88) | 5) +#define MT8135_PIN_88_MSDC1_DAT3__FUNC_TESTB_OUT5 (MTK_PIN_NO(88) | 7) + +#define MT8135_PIN_89_MSDC4_DAT0__FUNC_GPIO89 (MTK_PIN_NO(89) | 0) +#define MT8135_PIN_89_MSDC4_DAT0__FUNC_MSDC4_DAT0 (MTK_PIN_NO(89) | 1) +#define MT8135_PIN_89_MSDC4_DAT0__FUNC_EINT133 (MTK_PIN_NO(89) | 2) +#define MT8135_PIN_89_MSDC4_DAT0__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(89) | 4) +#define MT8135_PIN_89_MSDC4_DAT0__FUNC_USB_DRVVBUS (MTK_PIN_NO(89) | 5) +#define MT8135_PIN_89_MSDC4_DAT0__FUNC_A_FUNC_DIN_9 (MTK_PIN_NO(89) | 6) +#define MT8135_PIN_89_MSDC4_DAT0__FUNC_LPTE (MTK_PIN_NO(89) | 7) + +#define MT8135_PIN_90_MSDC4_DAT1__FUNC_GPIO90 (MTK_PIN_NO(90) | 0) +#define MT8135_PIN_90_MSDC4_DAT1__FUNC_MSDC4_DAT1 (MTK_PIN_NO(90) | 1) +#define MT8135_PIN_90_MSDC4_DAT1__FUNC_EINT134 (MTK_PIN_NO(90) | 2) +#define MT8135_PIN_90_MSDC4_DAT1__FUNC_A_FUNC_DIN_10 (MTK_PIN_NO(90) | 6) +#define MT8135_PIN_90_MSDC4_DAT1__FUNC_LRSTB_1X (MTK_PIN_NO(90) | 7) + +#define MT8135_PIN_91_MSDC4_DAT5__FUNC_GPIO91 (MTK_PIN_NO(91) | 0) +#define MT8135_PIN_91_MSDC4_DAT5__FUNC_MSDC4_DAT5 (MTK_PIN_NO(91) | 1) +#define MT8135_PIN_91_MSDC4_DAT5__FUNC_EINT136 (MTK_PIN_NO(91) | 2) +#define MT8135_PIN_91_MSDC4_DAT5__FUNC_I2SIN_WS (MTK_PIN_NO(91) | 3) +#define MT8135_PIN_91_MSDC4_DAT5__FUNC_DAC_WS (MTK_PIN_NO(91) | 4) +#define MT8135_PIN_91_MSDC4_DAT5__FUNC_PCM1_WS (MTK_PIN_NO(91) | 5) +#define MT8135_PIN_91_MSDC4_DAT5__FUNC_A_FUNC_DIN_11 (MTK_PIN_NO(91) | 6) +#define MT8135_PIN_91_MSDC4_DAT5__FUNC_SPI1_CSN (MTK_PIN_NO(91) | 7) + +#define MT8135_PIN_92_MSDC4_DAT6__FUNC_GPIO92 (MTK_PIN_NO(92) | 0) +#define MT8135_PIN_92_MSDC4_DAT6__FUNC_MSDC4_DAT6 (MTK_PIN_NO(92) | 1) +#define MT8135_PIN_92_MSDC4_DAT6__FUNC_EINT137 (MTK_PIN_NO(92) | 2) +#define MT8135_PIN_92_MSDC4_DAT6__FUNC_I2SOUT_DAT (MTK_PIN_NO(92) | 3) +#define MT8135_PIN_92_MSDC4_DAT6__FUNC_DAC_DAT_OUT (MTK_PIN_NO(92) | 4) +#define MT8135_PIN_92_MSDC4_DAT6__FUNC_PCM1_DO (MTK_PIN_NO(92) | 5) +#define MT8135_PIN_92_MSDC4_DAT6__FUNC_A_FUNC_DIN_12 (MTK_PIN_NO(92) | 6) +#define MT8135_PIN_92_MSDC4_DAT6__FUNC_SPI1_MO (MTK_PIN_NO(92) | 7) + +#define MT8135_PIN_93_MSDC4_DAT7__FUNC_GPIO93 (MTK_PIN_NO(93) | 0) +#define MT8135_PIN_93_MSDC4_DAT7__FUNC_MSDC4_DAT7 (MTK_PIN_NO(93) | 1) +#define MT8135_PIN_93_MSDC4_DAT7__FUNC_EINT138 (MTK_PIN_NO(93) | 2) +#define MT8135_PIN_93_MSDC4_DAT7__FUNC_I2SIN_DAT (MTK_PIN_NO(93) | 3) +#define MT8135_PIN_93_MSDC4_DAT7__FUNC_PCM1_DI (MTK_PIN_NO(93) | 5) +#define MT8135_PIN_93_MSDC4_DAT7__FUNC_A_FUNC_DIN_13 (MTK_PIN_NO(93) | 6) +#define MT8135_PIN_93_MSDC4_DAT7__FUNC_SPI1_MI (MTK_PIN_NO(93) | 7) + +#define MT8135_PIN_94_MSDC4_DAT4__FUNC_GPIO94 (MTK_PIN_NO(94) | 0) +#define MT8135_PIN_94_MSDC4_DAT4__FUNC_MSDC4_DAT4 (MTK_PIN_NO(94) | 1) +#define MT8135_PIN_94_MSDC4_DAT4__FUNC_EINT135 (MTK_PIN_NO(94) | 2) +#define MT8135_PIN_94_MSDC4_DAT4__FUNC_I2SIN_CK (MTK_PIN_NO(94) | 3) +#define MT8135_PIN_94_MSDC4_DAT4__FUNC_DAC_CK (MTK_PIN_NO(94) | 4) +#define MT8135_PIN_94_MSDC4_DAT4__FUNC_PCM1_CK (MTK_PIN_NO(94) | 5) +#define MT8135_PIN_94_MSDC4_DAT4__FUNC_A_FUNC_DIN_14 (MTK_PIN_NO(94) | 6) +#define MT8135_PIN_94_MSDC4_DAT4__FUNC_SPI1_CLK (MTK_PIN_NO(94) | 7) + +#define MT8135_PIN_95_MSDC4_DAT2__FUNC_GPIO95 (MTK_PIN_NO(95) | 0) +#define MT8135_PIN_95_MSDC4_DAT2__FUNC_MSDC4_DAT2 (MTK_PIN_NO(95) | 1) +#define MT8135_PIN_95_MSDC4_DAT2__FUNC_EINT131 (MTK_PIN_NO(95) | 2) +#define MT8135_PIN_95_MSDC4_DAT2__FUNC_I2SIN_WS (MTK_PIN_NO(95) | 3) +#define MT8135_PIN_95_MSDC4_DAT2__FUNC_CM2PDN_2X (MTK_PIN_NO(95) | 4) +#define MT8135_PIN_95_MSDC4_DAT2__FUNC_DAC_WS (MTK_PIN_NO(95) | 5) +#define MT8135_PIN_95_MSDC4_DAT2__FUNC_PCM1_WS (MTK_PIN_NO(95) | 6) +#define MT8135_PIN_95_MSDC4_DAT2__FUNC_LSCE0B_1X (MTK_PIN_NO(95) | 7) + +#define MT8135_PIN_96_MSDC4_CLK__FUNC_GPIO96 (MTK_PIN_NO(96) | 0) +#define MT8135_PIN_96_MSDC4_CLK__FUNC_MSDC4_CLK (MTK_PIN_NO(96) | 1) +#define MT8135_PIN_96_MSDC4_CLK__FUNC_EINT129 (MTK_PIN_NO(96) | 2) +#define MT8135_PIN_96_MSDC4_CLK__FUNC_DPI1_CK_2X (MTK_PIN_NO(96) | 3) +#define MT8135_PIN_96_MSDC4_CLK__FUNC_CM2PCLK_2X (MTK_PIN_NO(96) | 4) +#define MT8135_PIN_96_MSDC4_CLK__FUNC_PWM4 (MTK_PIN_NO(96) | 5) +#define MT8135_PIN_96_MSDC4_CLK__FUNC_PCM1_DI (MTK_PIN_NO(96) | 6) +#define MT8135_PIN_96_MSDC4_CLK__FUNC_LSCK_1X (MTK_PIN_NO(96) | 7) + +#define MT8135_PIN_97_MSDC4_DAT3__FUNC_GPIO97 (MTK_PIN_NO(97) | 0) +#define MT8135_PIN_97_MSDC4_DAT3__FUNC_MSDC4_DAT3 (MTK_PIN_NO(97) | 1) +#define MT8135_PIN_97_MSDC4_DAT3__FUNC_EINT132 (MTK_PIN_NO(97) | 2) +#define MT8135_PIN_97_MSDC4_DAT3__FUNC_I2SOUT_DAT (MTK_PIN_NO(97) | 3) +#define MT8135_PIN_97_MSDC4_DAT3__FUNC_CM2RST_2X (MTK_PIN_NO(97) | 4) +#define MT8135_PIN_97_MSDC4_DAT3__FUNC_DAC_DAT_OUT (MTK_PIN_NO(97) | 5) +#define MT8135_PIN_97_MSDC4_DAT3__FUNC_PCM1_DO (MTK_PIN_NO(97) | 6) +#define MT8135_PIN_97_MSDC4_DAT3__FUNC_LSCE1B_1X (MTK_PIN_NO(97) | 7) + +#define MT8135_PIN_98_MSDC4_CMD__FUNC_GPIO98 (MTK_PIN_NO(98) | 0) +#define MT8135_PIN_98_MSDC4_CMD__FUNC_MSDC4_CMD (MTK_PIN_NO(98) | 1) +#define MT8135_PIN_98_MSDC4_CMD__FUNC_EINT128 (MTK_PIN_NO(98) | 2) +#define MT8135_PIN_98_MSDC4_CMD__FUNC_DPI1_DE_2X (MTK_PIN_NO(98) | 3) +#define MT8135_PIN_98_MSDC4_CMD__FUNC_PWM3 (MTK_PIN_NO(98) | 5) +#define MT8135_PIN_98_MSDC4_CMD__FUNC_LSDA_1X (MTK_PIN_NO(98) | 7) + +#define MT8135_PIN_99_MSDC4_RSTB__FUNC_GPIO99 (MTK_PIN_NO(99) | 0) +#define MT8135_PIN_99_MSDC4_RSTB__FUNC_MSDC4_RSTB (MTK_PIN_NO(99) | 1) +#define MT8135_PIN_99_MSDC4_RSTB__FUNC_EINT130 (MTK_PIN_NO(99) | 2) +#define MT8135_PIN_99_MSDC4_RSTB__FUNC_I2SIN_CK (MTK_PIN_NO(99) | 3) +#define MT8135_PIN_99_MSDC4_RSTB__FUNC_CM2MCLK_2X (MTK_PIN_NO(99) | 4) +#define MT8135_PIN_99_MSDC4_RSTB__FUNC_DAC_CK (MTK_PIN_NO(99) | 5) +#define MT8135_PIN_99_MSDC4_RSTB__FUNC_PCM1_CK (MTK_PIN_NO(99) | 6) +#define MT8135_PIN_99_MSDC4_RSTB__FUNC_LSA0_1X (MTK_PIN_NO(99) | 7) + +#define MT8135_PIN_100_SDA0__FUNC_GPIO100 (MTK_PIN_NO(100) | 0) +#define MT8135_PIN_100_SDA0__FUNC_SDA0 (MTK_PIN_NO(100) | 1) +#define MT8135_PIN_100_SDA0__FUNC_EINT91 (MTK_PIN_NO(100) | 2) +#define MT8135_PIN_100_SDA0__FUNC_CLKM1 (MTK_PIN_NO(100) | 3) +#define MT8135_PIN_100_SDA0__FUNC_PWM1 (MTK_PIN_NO(100) | 4) +#define MT8135_PIN_100_SDA0__FUNC_A_FUNC_DIN_15 (MTK_PIN_NO(100) | 7) + +#define MT8135_PIN_101_SCL0__FUNC_GPIO101 (MTK_PIN_NO(101) | 0) +#define MT8135_PIN_101_SCL0__FUNC_SCL0 (MTK_PIN_NO(101) | 1) +#define MT8135_PIN_101_SCL0__FUNC_EINT90 (MTK_PIN_NO(101) | 2) +#define MT8135_PIN_101_SCL0__FUNC_CLKM0 (MTK_PIN_NO(101) | 3) +#define MT8135_PIN_101_SCL0__FUNC_DISP_PWM (MTK_PIN_NO(101) | 4) +#define MT8135_PIN_101_SCL0__FUNC_A_FUNC_DIN_16 (MTK_PIN_NO(101) | 7) + +#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_GPIO102 (MTK_PIN_NO(102) | 0) +#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_EINT10 (MTK_PIN_NO(102) | 1) +#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_USB_TEST_IO_16 (MTK_PIN_NO(102) | 5) +#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_TESTB_OUT16 (MTK_PIN_NO(102) | 6) +#define MT8135_PIN_102_EINT10_AUXIN2__FUNC_A_FUNC_DIN_17 (MTK_PIN_NO(102) | 7) + +#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_GPIO103 (MTK_PIN_NO(103) | 0) +#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_EINT11 (MTK_PIN_NO(103) | 1) +#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_USB_TEST_IO_17 (MTK_PIN_NO(103) | 5) +#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_TESTB_OUT17 (MTK_PIN_NO(103) | 6) +#define MT8135_PIN_103_EINT11_AUXIN3__FUNC_A_FUNC_DIN_18 (MTK_PIN_NO(103) | 7) + +#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_GPIO104 (MTK_PIN_NO(104) | 0) +#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_EINT16 (MTK_PIN_NO(104) | 1) +#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_USB_TEST_IO_18 (MTK_PIN_NO(104) | 5) +#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_TESTB_OUT18 (MTK_PIN_NO(104) | 6) +#define MT8135_PIN_104_EINT16_AUXIN4__FUNC_A_FUNC_DIN_19 (MTK_PIN_NO(104) | 7) + +#define MT8135_PIN_105_I2S_CLK__FUNC_GPIO105 (MTK_PIN_NO(105) | 0) +#define MT8135_PIN_105_I2S_CLK__FUNC_I2SIN_CK (MTK_PIN_NO(105) | 1) +#define MT8135_PIN_105_I2S_CLK__FUNC_EINT10 (MTK_PIN_NO(105) | 2) +#define MT8135_PIN_105_I2S_CLK__FUNC_DAC_CK (MTK_PIN_NO(105) | 3) +#define MT8135_PIN_105_I2S_CLK__FUNC_PCM1_CK (MTK_PIN_NO(105) | 4) +#define MT8135_PIN_105_I2S_CLK__FUNC_USB_TEST_IO_19 (MTK_PIN_NO(105) | 5) +#define MT8135_PIN_105_I2S_CLK__FUNC_TESTB_OUT19 (MTK_PIN_NO(105) | 6) +#define MT8135_PIN_105_I2S_CLK__FUNC_A_FUNC_DIN_20 (MTK_PIN_NO(105) | 7) + +#define MT8135_PIN_106_I2S_WS__FUNC_GPIO106 (MTK_PIN_NO(106) | 0) +#define MT8135_PIN_106_I2S_WS__FUNC_I2SIN_WS (MTK_PIN_NO(106) | 1) +#define MT8135_PIN_106_I2S_WS__FUNC_EINT13 (MTK_PIN_NO(106) | 2) +#define MT8135_PIN_106_I2S_WS__FUNC_DAC_WS (MTK_PIN_NO(106) | 3) +#define MT8135_PIN_106_I2S_WS__FUNC_PCM1_WS (MTK_PIN_NO(106) | 4) +#define MT8135_PIN_106_I2S_WS__FUNC_USB_TEST_IO_20 (MTK_PIN_NO(106) | 5) +#define MT8135_PIN_106_I2S_WS__FUNC_TESTB_OUT20 (MTK_PIN_NO(106) | 6) +#define MT8135_PIN_106_I2S_WS__FUNC_A_FUNC_DIN_21 (MTK_PIN_NO(106) | 7) + +#define MT8135_PIN_107_I2S_DATA_IN__FUNC_GPIO107 (MTK_PIN_NO(107) | 0) +#define MT8135_PIN_107_I2S_DATA_IN__FUNC_I2SIN_DAT (MTK_PIN_NO(107) | 1) +#define MT8135_PIN_107_I2S_DATA_IN__FUNC_EINT11 (MTK_PIN_NO(107) | 2) +#define MT8135_PIN_107_I2S_DATA_IN__FUNC_PCM1_DI (MTK_PIN_NO(107) | 4) +#define MT8135_PIN_107_I2S_DATA_IN__FUNC_USB_TEST_IO_21 (MTK_PIN_NO(107) | 5) +#define MT8135_PIN_107_I2S_DATA_IN__FUNC_TESTB_OUT22 (MTK_PIN_NO(107) | 6) +#define MT8135_PIN_107_I2S_DATA_IN__FUNC_A_FUNC_DIN_22 (MTK_PIN_NO(107) | 7) + +#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_GPIO108 (MTK_PIN_NO(108) | 0) +#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_I2SOUT_DAT (MTK_PIN_NO(108) | 1) +#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_EINT12 (MTK_PIN_NO(108) | 2) +#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_DAC_DAT_OUT (MTK_PIN_NO(108) | 3) +#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_PCM1_DO (MTK_PIN_NO(108) | 4) +#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_USB_TEST_IO_22 (MTK_PIN_NO(108) | 5) +#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_TESTB_OUT23 (MTK_PIN_NO(108) | 6) +#define MT8135_PIN_108_I2S_DATA_OUT__FUNC_A_FUNC_DIN_23 (MTK_PIN_NO(108) | 7) + +#define MT8135_PIN_109_EINT5__FUNC_GPIO109 (MTK_PIN_NO(109) | 0) +#define MT8135_PIN_109_EINT5__FUNC_EINT5 (MTK_PIN_NO(109) | 1) +#define MT8135_PIN_109_EINT5__FUNC_PWM5 (MTK_PIN_NO(109) | 2) +#define MT8135_PIN_109_EINT5__FUNC_CLKM3 (MTK_PIN_NO(109) | 3) +#define MT8135_PIN_109_EINT5__FUNC_GPU_JTRSTB (MTK_PIN_NO(109) | 4) +#define MT8135_PIN_109_EINT5__FUNC_USB_TEST_IO_23 (MTK_PIN_NO(109) | 5) +#define MT8135_PIN_109_EINT5__FUNC_TESTB_OUT26 (MTK_PIN_NO(109) | 6) +#define MT8135_PIN_109_EINT5__FUNC_A_FUNC_DIN_24 (MTK_PIN_NO(109) | 7) + +#define MT8135_PIN_110_EINT6__FUNC_GPIO110 (MTK_PIN_NO(110) | 0) +#define MT8135_PIN_110_EINT6__FUNC_EINT6 (MTK_PIN_NO(110) | 1) +#define MT8135_PIN_110_EINT6__FUNC_PWM6 (MTK_PIN_NO(110) | 2) +#define MT8135_PIN_110_EINT6__FUNC_CLKM4 (MTK_PIN_NO(110) | 3) +#define MT8135_PIN_110_EINT6__FUNC_GPU_JTMS (MTK_PIN_NO(110) | 4) +#define MT8135_PIN_110_EINT6__FUNC_USB_TEST_IO_24 (MTK_PIN_NO(110) | 5) +#define MT8135_PIN_110_EINT6__FUNC_TESTB_OUT27 (MTK_PIN_NO(110) | 6) +#define MT8135_PIN_110_EINT6__FUNC_A_FUNC_DIN_25 (MTK_PIN_NO(110) | 7) + +#define MT8135_PIN_111_EINT7__FUNC_GPIO111 (MTK_PIN_NO(111) | 0) +#define MT8135_PIN_111_EINT7__FUNC_EINT7 (MTK_PIN_NO(111) | 1) +#define MT8135_PIN_111_EINT7__FUNC_PWM7 (MTK_PIN_NO(111) | 2) +#define MT8135_PIN_111_EINT7__FUNC_CLKM5 (MTK_PIN_NO(111) | 3) +#define MT8135_PIN_111_EINT7__FUNC_GPU_JTDO (MTK_PIN_NO(111) | 4) +#define MT8135_PIN_111_EINT7__FUNC_USB_TEST_IO_25 (MTK_PIN_NO(111) | 5) +#define MT8135_PIN_111_EINT7__FUNC_TESTB_OUT28 (MTK_PIN_NO(111) | 6) +#define MT8135_PIN_111_EINT7__FUNC_A_FUNC_DIN_26 (MTK_PIN_NO(111) | 7) + +#define MT8135_PIN_112_EINT8__FUNC_GPIO112 (MTK_PIN_NO(112) | 0) +#define MT8135_PIN_112_EINT8__FUNC_EINT8 (MTK_PIN_NO(112) | 1) +#define MT8135_PIN_112_EINT8__FUNC_DISP_PWM (MTK_PIN_NO(112) | 2) +#define MT8135_PIN_112_EINT8__FUNC_CLKM6 (MTK_PIN_NO(112) | 3) +#define MT8135_PIN_112_EINT8__FUNC_GPU_JTDI (MTK_PIN_NO(112) | 4) +#define MT8135_PIN_112_EINT8__FUNC_USB_TEST_IO_26 (MTK_PIN_NO(112) | 5) +#define MT8135_PIN_112_EINT8__FUNC_TESTB_OUT29 (MTK_PIN_NO(112) | 6) +#define MT8135_PIN_112_EINT8__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(112) | 7) + +#define MT8135_PIN_113_EINT9__FUNC_GPIO113 (MTK_PIN_NO(113) | 0) +#define MT8135_PIN_113_EINT9__FUNC_EINT9 (MTK_PIN_NO(113) | 1) +#define MT8135_PIN_113_EINT9__FUNC_GPU_JTCK (MTK_PIN_NO(113) | 4) +#define MT8135_PIN_113_EINT9__FUNC_USB_DRVVBUS (MTK_PIN_NO(113) | 5) +#define MT8135_PIN_113_EINT9__FUNC_TESTB_OUT30 (MTK_PIN_NO(113) | 6) +#define MT8135_PIN_113_EINT9__FUNC_A_FUNC_DIN_27 (MTK_PIN_NO(113) | 7) + +#define MT8135_PIN_114_LPCE1B__FUNC_GPIO114 (MTK_PIN_NO(114) | 0) +#define MT8135_PIN_114_LPCE1B__FUNC_LPCE1B (MTK_PIN_NO(114) | 1) +#define MT8135_PIN_114_LPCE1B__FUNC_EINT127 (MTK_PIN_NO(114) | 2) +#define MT8135_PIN_114_LPCE1B__FUNC_PWM2 (MTK_PIN_NO(114) | 5) +#define MT8135_PIN_114_LPCE1B__FUNC_TESTB_OUT14 (MTK_PIN_NO(114) | 6) +#define MT8135_PIN_114_LPCE1B__FUNC_A_FUNC_DIN_28 (MTK_PIN_NO(114) | 7) + +#define MT8135_PIN_115_LPCE0B__FUNC_GPIO115 (MTK_PIN_NO(115) | 0) +#define MT8135_PIN_115_LPCE0B__FUNC_LPCE0B (MTK_PIN_NO(115) | 1) +#define MT8135_PIN_115_LPCE0B__FUNC_EINT126 (MTK_PIN_NO(115) | 2) +#define MT8135_PIN_115_LPCE0B__FUNC_PWM1 (MTK_PIN_NO(115) | 5) +#define MT8135_PIN_115_LPCE0B__FUNC_TESTB_OUT15 (MTK_PIN_NO(115) | 6) +#define MT8135_PIN_115_LPCE0B__FUNC_A_FUNC_DIN_29 (MTK_PIN_NO(115) | 7) + +#define MT8135_PIN_116_DISP_PWM__FUNC_GPIO116 (MTK_PIN_NO(116) | 0) +#define MT8135_PIN_116_DISP_PWM__FUNC_DISP_PWM (MTK_PIN_NO(116) | 1) +#define MT8135_PIN_116_DISP_PWM__FUNC_EINT77 (MTK_PIN_NO(116) | 2) +#define MT8135_PIN_116_DISP_PWM__FUNC_LSDI (MTK_PIN_NO(116) | 3) +#define MT8135_PIN_116_DISP_PWM__FUNC_PWM1 (MTK_PIN_NO(116) | 4) +#define MT8135_PIN_116_DISP_PWM__FUNC_PWM2 (MTK_PIN_NO(116) | 5) +#define MT8135_PIN_116_DISP_PWM__FUNC_PWM3 (MTK_PIN_NO(116) | 7) + +#define MT8135_PIN_117_EINT1__FUNC_GPIO117 (MTK_PIN_NO(117) | 0) +#define MT8135_PIN_117_EINT1__FUNC_EINT1 (MTK_PIN_NO(117) | 1) +#define MT8135_PIN_117_EINT1__FUNC_PWM2 (MTK_PIN_NO(117) | 2) +#define MT8135_PIN_117_EINT1__FUNC_CLKM1 (MTK_PIN_NO(117) | 3) +#define MT8135_PIN_117_EINT1__FUNC_USB_TEST_IO_13 (MTK_PIN_NO(117) | 5) +#define MT8135_PIN_117_EINT1__FUNC_USB_SDA (MTK_PIN_NO(117) | 7) + +#define MT8135_PIN_118_EINT2__FUNC_GPIO118 (MTK_PIN_NO(118) | 0) +#define MT8135_PIN_118_EINT2__FUNC_EINT2 (MTK_PIN_NO(118) | 1) +#define MT8135_PIN_118_EINT2__FUNC_PWM3 (MTK_PIN_NO(118) | 2) +#define MT8135_PIN_118_EINT2__FUNC_CLKM2 (MTK_PIN_NO(118) | 3) +#define MT8135_PIN_118_EINT2__FUNC_USB_TEST_IO_14 (MTK_PIN_NO(118) | 5) +#define MT8135_PIN_118_EINT2__FUNC_SRCLKENAI2 (MTK_PIN_NO(118) | 6) +#define MT8135_PIN_118_EINT2__FUNC_A_FUNC_DIN_30 (MTK_PIN_NO(118) | 7) + +#define MT8135_PIN_119_EINT3__FUNC_GPIO119 (MTK_PIN_NO(119) | 0) +#define MT8135_PIN_119_EINT3__FUNC_EINT3 (MTK_PIN_NO(119) | 1) +#define MT8135_PIN_119_EINT3__FUNC_USB_TEST_IO_15 (MTK_PIN_NO(119) | 5) +#define MT8135_PIN_119_EINT3__FUNC_SRCLKENAI1 (MTK_PIN_NO(119) | 6) +#define MT8135_PIN_119_EINT3__FUNC_EXT_26M_CK (MTK_PIN_NO(119) | 7) + +#define MT8135_PIN_120_EINT4__FUNC_GPIO120 (MTK_PIN_NO(120) | 0) +#define MT8135_PIN_120_EINT4__FUNC_EINT4 (MTK_PIN_NO(120) | 1) +#define MT8135_PIN_120_EINT4__FUNC_PWM4 (MTK_PIN_NO(120) | 2) +#define MT8135_PIN_120_EINT4__FUNC_USB_DRVVBUS (MTK_PIN_NO(120) | 5) +#define MT8135_PIN_120_EINT4__FUNC_A_FUNC_DIN_31 (MTK_PIN_NO(120) | 7) + +#define MT8135_PIN_121_DPIDE__FUNC_GPIO121 (MTK_PIN_NO(121) | 0) +#define MT8135_PIN_121_DPIDE__FUNC_DPI0_DE (MTK_PIN_NO(121) | 1) +#define MT8135_PIN_121_DPIDE__FUNC_EINT100 (MTK_PIN_NO(121) | 2) +#define MT8135_PIN_121_DPIDE__FUNC_I2SOUT_DAT (MTK_PIN_NO(121) | 3) +#define MT8135_PIN_121_DPIDE__FUNC_DAC_DAT_OUT (MTK_PIN_NO(121) | 4) +#define MT8135_PIN_121_DPIDE__FUNC_PCM1_DO (MTK_PIN_NO(121) | 5) +#define MT8135_PIN_121_DPIDE__FUNC_IRDA_TXD (MTK_PIN_NO(121) | 6) + +#define MT8135_PIN_122_DPICK__FUNC_GPIO122 (MTK_PIN_NO(122) | 0) +#define MT8135_PIN_122_DPICK__FUNC_DPI0_CK (MTK_PIN_NO(122) | 1) +#define MT8135_PIN_122_DPICK__FUNC_EINT101 (MTK_PIN_NO(122) | 2) +#define MT8135_PIN_122_DPICK__FUNC_I2SIN_DAT (MTK_PIN_NO(122) | 3) +#define MT8135_PIN_122_DPICK__FUNC_PCM1_DI (MTK_PIN_NO(122) | 5) +#define MT8135_PIN_122_DPICK__FUNC_IRDA_PDN (MTK_PIN_NO(122) | 6) + +#define MT8135_PIN_123_DPIG4__FUNC_GPIO123 (MTK_PIN_NO(123) | 0) +#define MT8135_PIN_123_DPIG4__FUNC_DPI0_G4 (MTK_PIN_NO(123) | 1) +#define MT8135_PIN_123_DPIG4__FUNC_EINT114 (MTK_PIN_NO(123) | 2) +#define MT8135_PIN_123_DPIG4__FUNC_CM2DAT_2X_0 (MTK_PIN_NO(123) | 4) +#define MT8135_PIN_123_DPIG4__FUNC_DSP2_ID (MTK_PIN_NO(123) | 5) + +#define MT8135_PIN_124_DPIG5__FUNC_GPIO124 (MTK_PIN_NO(124) | 0) +#define MT8135_PIN_124_DPIG5__FUNC_DPI0_G5 (MTK_PIN_NO(124) | 1) +#define MT8135_PIN_124_DPIG5__FUNC_EINT115 (MTK_PIN_NO(124) | 2) +#define MT8135_PIN_124_DPIG5__FUNC_CM2DAT_2X_1 (MTK_PIN_NO(124) | 4) +#define MT8135_PIN_124_DPIG5__FUNC_DSP2_ICK (MTK_PIN_NO(124) | 5) + +#define MT8135_PIN_125_DPIR3__FUNC_GPIO125 (MTK_PIN_NO(125) | 0) +#define MT8135_PIN_125_DPIR3__FUNC_DPI0_R3 (MTK_PIN_NO(125) | 1) +#define MT8135_PIN_125_DPIR3__FUNC_EINT121 (MTK_PIN_NO(125) | 2) +#define MT8135_PIN_125_DPIR3__FUNC_CM2DAT_2X_7 (MTK_PIN_NO(125) | 4) + +#define MT8135_PIN_126_DPIG1__FUNC_GPIO126 (MTK_PIN_NO(126) | 0) +#define MT8135_PIN_126_DPIG1__FUNC_DPI0_G1 (MTK_PIN_NO(126) | 1) +#define MT8135_PIN_126_DPIG1__FUNC_EINT111 (MTK_PIN_NO(126) | 2) +#define MT8135_PIN_126_DPIG1__FUNC_DSP1_ICK (MTK_PIN_NO(126) | 5) + +#define MT8135_PIN_127_DPIVSYNC__FUNC_GPIO127 (MTK_PIN_NO(127) | 0) +#define MT8135_PIN_127_DPIVSYNC__FUNC_DPI0_VSYNC (MTK_PIN_NO(127) | 1) +#define MT8135_PIN_127_DPIVSYNC__FUNC_EINT98 (MTK_PIN_NO(127) | 2) +#define MT8135_PIN_127_DPIVSYNC__FUNC_I2SIN_CK (MTK_PIN_NO(127) | 3) +#define MT8135_PIN_127_DPIVSYNC__FUNC_DAC_CK (MTK_PIN_NO(127) | 4) +#define MT8135_PIN_127_DPIVSYNC__FUNC_PCM1_CK (MTK_PIN_NO(127) | 5) + +#define MT8135_PIN_128_DPIHSYNC__FUNC_GPIO128 (MTK_PIN_NO(128) | 0) +#define MT8135_PIN_128_DPIHSYNC__FUNC_DPI0_HSYNC (MTK_PIN_NO(128) | 1) +#define MT8135_PIN_128_DPIHSYNC__FUNC_EINT99 (MTK_PIN_NO(128) | 2) +#define MT8135_PIN_128_DPIHSYNC__FUNC_I2SIN_WS (MTK_PIN_NO(128) | 3) +#define MT8135_PIN_128_DPIHSYNC__FUNC_DAC_WS (MTK_PIN_NO(128) | 4) +#define MT8135_PIN_128_DPIHSYNC__FUNC_PCM1_WS (MTK_PIN_NO(128) | 5) +#define MT8135_PIN_128_DPIHSYNC__FUNC_IRDA_RXD (MTK_PIN_NO(128) | 6) + +#define MT8135_PIN_129_DPIB0__FUNC_GPIO129 (MTK_PIN_NO(129) | 0) +#define MT8135_PIN_129_DPIB0__FUNC_DPI0_B0 (MTK_PIN_NO(129) | 1) +#define MT8135_PIN_129_DPIB0__FUNC_EINT102 (MTK_PIN_NO(129) | 2) +#define MT8135_PIN_129_DPIB0__FUNC_SCL0 (MTK_PIN_NO(129) | 4) +#define MT8135_PIN_129_DPIB0__FUNC_DISP_PWM (MTK_PIN_NO(129) | 5) + +#define MT8135_PIN_130_DPIB1__FUNC_GPIO130 (MTK_PIN_NO(130) | 0) +#define MT8135_PIN_130_DPIB1__FUNC_DPI0_B1 (MTK_PIN_NO(130) | 1) +#define MT8135_PIN_130_DPIB1__FUNC_EINT103 (MTK_PIN_NO(130) | 2) +#define MT8135_PIN_130_DPIB1__FUNC_CLKM0 (MTK_PIN_NO(130) | 3) +#define MT8135_PIN_130_DPIB1__FUNC_SDA0 (MTK_PIN_NO(130) | 4) +#define MT8135_PIN_130_DPIB1__FUNC_PWM1 (MTK_PIN_NO(130) | 5) + +#define MT8135_PIN_131_DPIB2__FUNC_GPIO131 (MTK_PIN_NO(131) | 0) +#define MT8135_PIN_131_DPIB2__FUNC_DPI0_B2 (MTK_PIN_NO(131) | 1) +#define MT8135_PIN_131_DPIB2__FUNC_EINT104 (MTK_PIN_NO(131) | 2) +#define MT8135_PIN_131_DPIB2__FUNC_CLKM1 (MTK_PIN_NO(131) | 3) +#define MT8135_PIN_131_DPIB2__FUNC_SCL1 (MTK_PIN_NO(131) | 4) +#define MT8135_PIN_131_DPIB2__FUNC_PWM2 (MTK_PIN_NO(131) | 5) + +#define MT8135_PIN_132_DPIB3__FUNC_GPIO132 (MTK_PIN_NO(132) | 0) +#define MT8135_PIN_132_DPIB3__FUNC_DPI0_B3 (MTK_PIN_NO(132) | 1) +#define MT8135_PIN_132_DPIB3__FUNC_EINT105 (MTK_PIN_NO(132) | 2) +#define MT8135_PIN_132_DPIB3__FUNC_CLKM2 (MTK_PIN_NO(132) | 3) +#define MT8135_PIN_132_DPIB3__FUNC_SDA1 (MTK_PIN_NO(132) | 4) +#define MT8135_PIN_132_DPIB3__FUNC_PWM3 (MTK_PIN_NO(132) | 5) + +#define MT8135_PIN_133_DPIB4__FUNC_GPIO133 (MTK_PIN_NO(133) | 0) +#define MT8135_PIN_133_DPIB4__FUNC_DPI0_B4 (MTK_PIN_NO(133) | 1) +#define MT8135_PIN_133_DPIB4__FUNC_EINT106 (MTK_PIN_NO(133) | 2) +#define MT8135_PIN_133_DPIB4__FUNC_CLKM3 (MTK_PIN_NO(133) | 3) +#define MT8135_PIN_133_DPIB4__FUNC_SCL2 (MTK_PIN_NO(133) | 4) +#define MT8135_PIN_133_DPIB4__FUNC_PWM4 (MTK_PIN_NO(133) | 5) + +#define MT8135_PIN_134_DPIB5__FUNC_GPIO134 (MTK_PIN_NO(134) | 0) +#define MT8135_PIN_134_DPIB5__FUNC_DPI0_B5 (MTK_PIN_NO(134) | 1) +#define MT8135_PIN_134_DPIB5__FUNC_EINT107 (MTK_PIN_NO(134) | 2) +#define MT8135_PIN_134_DPIB5__FUNC_CLKM4 (MTK_PIN_NO(134) | 3) +#define MT8135_PIN_134_DPIB5__FUNC_SDA2 (MTK_PIN_NO(134) | 4) +#define MT8135_PIN_134_DPIB5__FUNC_PWM5 (MTK_PIN_NO(134) | 5) + +#define MT8135_PIN_135_DPIB6__FUNC_GPIO135 (MTK_PIN_NO(135) | 0) +#define MT8135_PIN_135_DPIB6__FUNC_DPI0_B6 (MTK_PIN_NO(135) | 1) +#define MT8135_PIN_135_DPIB6__FUNC_EINT108 (MTK_PIN_NO(135) | 2) +#define MT8135_PIN_135_DPIB6__FUNC_CLKM5 (MTK_PIN_NO(135) | 3) +#define MT8135_PIN_135_DPIB6__FUNC_SCL3 (MTK_PIN_NO(135) | 4) +#define MT8135_PIN_135_DPIB6__FUNC_PWM6 (MTK_PIN_NO(135) | 5) + +#define MT8135_PIN_136_DPIB7__FUNC_GPIO136 (MTK_PIN_NO(136) | 0) +#define MT8135_PIN_136_DPIB7__FUNC_DPI0_B7 (MTK_PIN_NO(136) | 1) +#define MT8135_PIN_136_DPIB7__FUNC_EINT109 (MTK_PIN_NO(136) | 2) +#define MT8135_PIN_136_DPIB7__FUNC_CLKM6 (MTK_PIN_NO(136) | 3) +#define MT8135_PIN_136_DPIB7__FUNC_SDA3 (MTK_PIN_NO(136) | 4) +#define MT8135_PIN_136_DPIB7__FUNC_PWM7 (MTK_PIN_NO(136) | 5) + +#define MT8135_PIN_137_DPIG0__FUNC_GPIO137 (MTK_PIN_NO(137) | 0) +#define MT8135_PIN_137_DPIG0__FUNC_DPI0_G0 (MTK_PIN_NO(137) | 1) +#define MT8135_PIN_137_DPIG0__FUNC_EINT110 (MTK_PIN_NO(137) | 2) +#define MT8135_PIN_137_DPIG0__FUNC_DSP1_ID (MTK_PIN_NO(137) | 5) + +#define MT8135_PIN_138_DPIG2__FUNC_GPIO138 (MTK_PIN_NO(138) | 0) +#define MT8135_PIN_138_DPIG2__FUNC_DPI0_G2 (MTK_PIN_NO(138) | 1) +#define MT8135_PIN_138_DPIG2__FUNC_EINT112 (MTK_PIN_NO(138) | 2) +#define MT8135_PIN_138_DPIG2__FUNC_DSP1_IMS (MTK_PIN_NO(138) | 5) + +#define MT8135_PIN_139_DPIG3__FUNC_GPIO139 (MTK_PIN_NO(139) | 0) +#define MT8135_PIN_139_DPIG3__FUNC_DPI0_G3 (MTK_PIN_NO(139) | 1) +#define MT8135_PIN_139_DPIG3__FUNC_EINT113 (MTK_PIN_NO(139) | 2) +#define MT8135_PIN_139_DPIG3__FUNC_DSP2_IMS (MTK_PIN_NO(139) | 5) + +#define MT8135_PIN_140_DPIG6__FUNC_GPIO140 (MTK_PIN_NO(140) | 0) +#define MT8135_PIN_140_DPIG6__FUNC_DPI0_G6 (MTK_PIN_NO(140) | 1) +#define MT8135_PIN_140_DPIG6__FUNC_EINT116 (MTK_PIN_NO(140) | 2) +#define MT8135_PIN_140_DPIG6__FUNC_CM2DAT_2X_2 (MTK_PIN_NO(140) | 4) + +#define MT8135_PIN_141_DPIG7__FUNC_GPIO141 (MTK_PIN_NO(141) | 0) +#define MT8135_PIN_141_DPIG7__FUNC_DPI0_G7 (MTK_PIN_NO(141) | 1) +#define MT8135_PIN_141_DPIG7__FUNC_EINT117 (MTK_PIN_NO(141) | 2) +#define MT8135_PIN_141_DPIG7__FUNC_CM2DAT_2X_3 (MTK_PIN_NO(141) | 4) + +#define MT8135_PIN_142_DPIR0__FUNC_GPIO142 (MTK_PIN_NO(142) | 0) +#define MT8135_PIN_142_DPIR0__FUNC_DPI0_R0 (MTK_PIN_NO(142) | 1) +#define MT8135_PIN_142_DPIR0__FUNC_EINT118 (MTK_PIN_NO(142) | 2) +#define MT8135_PIN_142_DPIR0__FUNC_CM2DAT_2X_4 (MTK_PIN_NO(142) | 4) + +#define MT8135_PIN_143_DPIR1__FUNC_GPIO143 (MTK_PIN_NO(143) | 0) +#define MT8135_PIN_143_DPIR1__FUNC_DPI0_R1 (MTK_PIN_NO(143) | 1) +#define MT8135_PIN_143_DPIR1__FUNC_EINT119 (MTK_PIN_NO(143) | 2) +#define MT8135_PIN_143_DPIR1__FUNC_CM2DAT_2X_5 (MTK_PIN_NO(143) | 4) + +#define MT8135_PIN_144_DPIR2__FUNC_GPIO144 (MTK_PIN_NO(144) | 0) +#define MT8135_PIN_144_DPIR2__FUNC_DPI0_R2 (MTK_PIN_NO(144) | 1) +#define MT8135_PIN_144_DPIR2__FUNC_EINT120 (MTK_PIN_NO(144) | 2) +#define MT8135_PIN_144_DPIR2__FUNC_CM2DAT_2X_6 (MTK_PIN_NO(144) | 4) + +#define MT8135_PIN_145_DPIR4__FUNC_GPIO145 (MTK_PIN_NO(145) | 0) +#define MT8135_PIN_145_DPIR4__FUNC_DPI0_R4 (MTK_PIN_NO(145) | 1) +#define MT8135_PIN_145_DPIR4__FUNC_EINT122 (MTK_PIN_NO(145) | 2) +#define MT8135_PIN_145_DPIR4__FUNC_CM2DAT_2X_8 (MTK_PIN_NO(145) | 4) + +#define MT8135_PIN_146_DPIR5__FUNC_GPIO146 (MTK_PIN_NO(146) | 0) +#define MT8135_PIN_146_DPIR5__FUNC_DPI0_R5 (MTK_PIN_NO(146) | 1) +#define MT8135_PIN_146_DPIR5__FUNC_EINT123 (MTK_PIN_NO(146) | 2) +#define MT8135_PIN_146_DPIR5__FUNC_CM2DAT_2X_9 (MTK_PIN_NO(146) | 4) + +#define MT8135_PIN_147_DPIR6__FUNC_GPIO147 (MTK_PIN_NO(147) | 0) +#define MT8135_PIN_147_DPIR6__FUNC_DPI0_R6 (MTK_PIN_NO(147) | 1) +#define MT8135_PIN_147_DPIR6__FUNC_EINT124 (MTK_PIN_NO(147) | 2) +#define MT8135_PIN_147_DPIR6__FUNC_CM2VSYNC_2X (MTK_PIN_NO(147) | 4) + +#define MT8135_PIN_148_DPIR7__FUNC_GPIO148 (MTK_PIN_NO(148) | 0) +#define MT8135_PIN_148_DPIR7__FUNC_DPI0_R7 (MTK_PIN_NO(148) | 1) +#define MT8135_PIN_148_DPIR7__FUNC_EINT125 (MTK_PIN_NO(148) | 2) +#define MT8135_PIN_148_DPIR7__FUNC_CM2HSYNC_2X (MTK_PIN_NO(148) | 4) + +#define MT8135_PIN_149_TDN3__FUNC_GPIO149 (MTK_PIN_NO(149) | 0) +#define MT8135_PIN_149_TDN3__FUNC_EINT36 (MTK_PIN_NO(149) | 2) + +#define MT8135_PIN_150_TDP3__FUNC_GPIO150 (MTK_PIN_NO(150) | 0) +#define MT8135_PIN_150_TDP3__FUNC_EINT35 (MTK_PIN_NO(150) | 2) + +#define MT8135_PIN_151_TDN2__FUNC_GPIO151 (MTK_PIN_NO(151) | 0) +#define MT8135_PIN_151_TDN2__FUNC_EINT169 (MTK_PIN_NO(151) | 2) + +#define MT8135_PIN_152_TDP2__FUNC_GPIO152 (MTK_PIN_NO(152) | 0) +#define MT8135_PIN_152_TDP2__FUNC_EINT168 (MTK_PIN_NO(152) | 2) + +#define MT8135_PIN_153_TCN__FUNC_GPIO153 (MTK_PIN_NO(153) | 0) +#define MT8135_PIN_153_TCN__FUNC_EINT163 (MTK_PIN_NO(153) | 2) + +#define MT8135_PIN_154_TCP__FUNC_GPIO154 (MTK_PIN_NO(154) | 0) +#define MT8135_PIN_154_TCP__FUNC_EINT162 (MTK_PIN_NO(154) | 2) + +#define MT8135_PIN_155_TDN1__FUNC_GPIO155 (MTK_PIN_NO(155) | 0) +#define MT8135_PIN_155_TDN1__FUNC_EINT167 (MTK_PIN_NO(155) | 2) + +#define MT8135_PIN_156_TDP1__FUNC_GPIO156 (MTK_PIN_NO(156) | 0) +#define MT8135_PIN_156_TDP1__FUNC_EINT166 (MTK_PIN_NO(156) | 2) + +#define MT8135_PIN_157_TDN0__FUNC_GPIO157 (MTK_PIN_NO(157) | 0) +#define MT8135_PIN_157_TDN0__FUNC_EINT165 (MTK_PIN_NO(157) | 2) + +#define MT8135_PIN_158_TDP0__FUNC_GPIO158 (MTK_PIN_NO(158) | 0) +#define MT8135_PIN_158_TDP0__FUNC_EINT164 (MTK_PIN_NO(158) | 2) + +#define MT8135_PIN_159_RDN3__FUNC_GPIO159 (MTK_PIN_NO(159) | 0) +#define MT8135_PIN_159_RDN3__FUNC_EINT18 (MTK_PIN_NO(159) | 2) + +#define MT8135_PIN_160_RDP3__FUNC_GPIO160 (MTK_PIN_NO(160) | 0) +#define MT8135_PIN_160_RDP3__FUNC_EINT30 (MTK_PIN_NO(160) | 2) + +#define MT8135_PIN_161_RDN2__FUNC_GPIO161 (MTK_PIN_NO(161) | 0) +#define MT8135_PIN_161_RDN2__FUNC_EINT31 (MTK_PIN_NO(161) | 2) + +#define MT8135_PIN_162_RDP2__FUNC_GPIO162 (MTK_PIN_NO(162) | 0) +#define MT8135_PIN_162_RDP2__FUNC_EINT32 (MTK_PIN_NO(162) | 2) + +#define MT8135_PIN_163_RCN__FUNC_GPIO163 (MTK_PIN_NO(163) | 0) +#define MT8135_PIN_163_RCN__FUNC_EINT33 (MTK_PIN_NO(163) | 2) + +#define MT8135_PIN_164_RCP__FUNC_GPIO164 (MTK_PIN_NO(164) | 0) +#define MT8135_PIN_164_RCP__FUNC_EINT39 (MTK_PIN_NO(164) | 2) + +#define MT8135_PIN_165_RDN1__FUNC_GPIO165 (MTK_PIN_NO(165) | 0) + +#define MT8135_PIN_166_RDP1__FUNC_GPIO166 (MTK_PIN_NO(166) | 0) + +#define MT8135_PIN_167_RDN0__FUNC_GPIO167 (MTK_PIN_NO(167) | 0) + +#define MT8135_PIN_168_RDP0__FUNC_GPIO168 (MTK_PIN_NO(168) | 0) + +#define MT8135_PIN_169_RDN1_A__FUNC_GPIO169 (MTK_PIN_NO(169) | 0) +#define MT8135_PIN_169_RDN1_A__FUNC_CMDAT6 (MTK_PIN_NO(169) | 1) +#define MT8135_PIN_169_RDN1_A__FUNC_EINT175 (MTK_PIN_NO(169) | 2) + +#define MT8135_PIN_170_RDP1_A__FUNC_GPIO170 (MTK_PIN_NO(170) | 0) +#define MT8135_PIN_170_RDP1_A__FUNC_CMDAT7 (MTK_PIN_NO(170) | 1) +#define MT8135_PIN_170_RDP1_A__FUNC_EINT174 (MTK_PIN_NO(170) | 2) + +#define MT8135_PIN_171_RCN_A__FUNC_GPIO171 (MTK_PIN_NO(171) | 0) +#define MT8135_PIN_171_RCN_A__FUNC_CMDAT8 (MTK_PIN_NO(171) | 1) +#define MT8135_PIN_171_RCN_A__FUNC_EINT171 (MTK_PIN_NO(171) | 2) + +#define MT8135_PIN_172_RCP_A__FUNC_GPIO172 (MTK_PIN_NO(172) | 0) +#define MT8135_PIN_172_RCP_A__FUNC_CMDAT9 (MTK_PIN_NO(172) | 1) +#define MT8135_PIN_172_RCP_A__FUNC_EINT170 (MTK_PIN_NO(172) | 2) + +#define MT8135_PIN_173_RDN0_A__FUNC_GPIO173 (MTK_PIN_NO(173) | 0) +#define MT8135_PIN_173_RDN0_A__FUNC_CMHSYNC (MTK_PIN_NO(173) | 1) +#define MT8135_PIN_173_RDN0_A__FUNC_EINT173 (MTK_PIN_NO(173) | 2) + +#define MT8135_PIN_174_RDP0_A__FUNC_GPIO174 (MTK_PIN_NO(174) | 0) +#define MT8135_PIN_174_RDP0_A__FUNC_CMVSYNC (MTK_PIN_NO(174) | 1) +#define MT8135_PIN_174_RDP0_A__FUNC_EINT172 (MTK_PIN_NO(174) | 2) + +#define MT8135_PIN_175_RDN1_B__FUNC_GPIO175 (MTK_PIN_NO(175) | 0) +#define MT8135_PIN_175_RDN1_B__FUNC_CMDAT2 (MTK_PIN_NO(175) | 1) +#define MT8135_PIN_175_RDN1_B__FUNC_EINT181 (MTK_PIN_NO(175) | 2) +#define MT8135_PIN_175_RDN1_B__FUNC_CMCSD2 (MTK_PIN_NO(175) | 3) + +#define MT8135_PIN_176_RDP1_B__FUNC_GPIO176 (MTK_PIN_NO(176) | 0) +#define MT8135_PIN_176_RDP1_B__FUNC_CMDAT3 (MTK_PIN_NO(176) | 1) +#define MT8135_PIN_176_RDP1_B__FUNC_EINT180 (MTK_PIN_NO(176) | 2) +#define MT8135_PIN_176_RDP1_B__FUNC_CMCSD3 (MTK_PIN_NO(176) | 3) + +#define MT8135_PIN_177_RCN_B__FUNC_GPIO177 (MTK_PIN_NO(177) | 0) +#define MT8135_PIN_177_RCN_B__FUNC_CMDAT4 (MTK_PIN_NO(177) | 1) +#define MT8135_PIN_177_RCN_B__FUNC_EINT177 (MTK_PIN_NO(177) | 2) + +#define MT8135_PIN_178_RCP_B__FUNC_GPIO178 (MTK_PIN_NO(178) | 0) +#define MT8135_PIN_178_RCP_B__FUNC_CMDAT5 (MTK_PIN_NO(178) | 1) +#define MT8135_PIN_178_RCP_B__FUNC_EINT176 (MTK_PIN_NO(178) | 2) + +#define MT8135_PIN_179_RDN0_B__FUNC_GPIO179 (MTK_PIN_NO(179) | 0) +#define MT8135_PIN_179_RDN0_B__FUNC_CMDAT0 (MTK_PIN_NO(179) | 1) +#define MT8135_PIN_179_RDN0_B__FUNC_EINT179 (MTK_PIN_NO(179) | 2) +#define MT8135_PIN_179_RDN0_B__FUNC_CMCSD0 (MTK_PIN_NO(179) | 3) + +#define MT8135_PIN_180_RDP0_B__FUNC_GPIO180 (MTK_PIN_NO(180) | 0) +#define MT8135_PIN_180_RDP0_B__FUNC_CMDAT1 (MTK_PIN_NO(180) | 1) +#define MT8135_PIN_180_RDP0_B__FUNC_EINT178 (MTK_PIN_NO(180) | 2) +#define MT8135_PIN_180_RDP0_B__FUNC_CMCSD1 (MTK_PIN_NO(180) | 3) + +#define MT8135_PIN_181_CMPCLK__FUNC_GPIO181 (MTK_PIN_NO(181) | 0) +#define MT8135_PIN_181_CMPCLK__FUNC_CMPCLK (MTK_PIN_NO(181) | 1) +#define MT8135_PIN_181_CMPCLK__FUNC_EINT182 (MTK_PIN_NO(181) | 2) +#define MT8135_PIN_181_CMPCLK__FUNC_CMCSK (MTK_PIN_NO(181) | 3) +#define MT8135_PIN_181_CMPCLK__FUNC_CM2MCLK_4X (MTK_PIN_NO(181) | 4) +#define MT8135_PIN_181_CMPCLK__FUNC_TS_AUXADC_SEL_3 (MTK_PIN_NO(181) | 5) +#define MT8135_PIN_181_CMPCLK__FUNC_VENC_TEST_CK (MTK_PIN_NO(181) | 6) +#define MT8135_PIN_181_CMPCLK__FUNC_TESTA_OUT27 (MTK_PIN_NO(181) | 7) + +#define MT8135_PIN_182_CMMCLK__FUNC_GPIO182 (MTK_PIN_NO(182) | 0) +#define MT8135_PIN_182_CMMCLK__FUNC_CMMCLK (MTK_PIN_NO(182) | 1) +#define MT8135_PIN_182_CMMCLK__FUNC_EINT183 (MTK_PIN_NO(182) | 2) +#define MT8135_PIN_182_CMMCLK__FUNC_TS_AUXADC_SEL_2 (MTK_PIN_NO(182) | 5) +#define MT8135_PIN_182_CMMCLK__FUNC_TESTA_OUT28 (MTK_PIN_NO(182) | 7) + +#define MT8135_PIN_183_CMRST__FUNC_GPIO183 (MTK_PIN_NO(183) | 0) +#define MT8135_PIN_183_CMRST__FUNC_CMRST (MTK_PIN_NO(183) | 1) +#define MT8135_PIN_183_CMRST__FUNC_EINT185 (MTK_PIN_NO(183) | 2) +#define MT8135_PIN_183_CMRST__FUNC_TS_AUXADC_SEL_1 (MTK_PIN_NO(183) | 5) +#define MT8135_PIN_183_CMRST__FUNC_TESTA_OUT30 (MTK_PIN_NO(183) | 7) + +#define MT8135_PIN_184_CMPDN__FUNC_GPIO184 (MTK_PIN_NO(184) | 0) +#define MT8135_PIN_184_CMPDN__FUNC_CMPDN (MTK_PIN_NO(184) | 1) +#define MT8135_PIN_184_CMPDN__FUNC_EINT184 (MTK_PIN_NO(184) | 2) +#define MT8135_PIN_184_CMPDN__FUNC_TS_AUXADC_SEL_0 (MTK_PIN_NO(184) | 5) +#define MT8135_PIN_184_CMPDN__FUNC_TESTA_OUT29 (MTK_PIN_NO(184) | 7) + +#define MT8135_PIN_185_CMFLASH__FUNC_GPIO185 (MTK_PIN_NO(185) | 0) +#define MT8135_PIN_185_CMFLASH__FUNC_CMFLASH (MTK_PIN_NO(185) | 1) +#define MT8135_PIN_185_CMFLASH__FUNC_EINT186 (MTK_PIN_NO(185) | 2) +#define MT8135_PIN_185_CMFLASH__FUNC_CM2MCLK_3X (MTK_PIN_NO(185) | 3) +#define MT8135_PIN_185_CMFLASH__FUNC_MFG_TEST_CK_1 (MTK_PIN_NO(185) | 6) +#define MT8135_PIN_185_CMFLASH__FUNC_TESTA_OUT31 (MTK_PIN_NO(185) | 7) + +#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_GPIO186 (MTK_PIN_NO(186) | 0) +#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_MRG_I2S_P_CLK (MTK_PIN_NO(186) | 1) +#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_EINT14 (MTK_PIN_NO(186) | 2) +#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_I2SIN_CK (MTK_PIN_NO(186) | 3) +#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_PCM0_CK (MTK_PIN_NO(186) | 4) +#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_DSP2_ICK (MTK_PIN_NO(186) | 5) +#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_IMG_TEST_CK (MTK_PIN_NO(186) | 6) +#define MT8135_PIN_186_MRG_I2S_PCM_CLK__FUNC_USB_SCL (MTK_PIN_NO(186) | 7) + +#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_GPIO187 (MTK_PIN_NO(187) | 0) +#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_MRG_I2S_SYNC (MTK_PIN_NO(187) | 1) +#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_EINT16 (MTK_PIN_NO(187) | 2) +#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_I2SIN_WS (MTK_PIN_NO(187) | 3) +#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_PCM0_WS (MTK_PIN_NO(187) | 4) +#define MT8135_PIN_187_MRG_I2S_PCM_SYNC__FUNC_DISP_TEST_CK (MTK_PIN_NO(187) | 6) + +#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_GPIO188 (MTK_PIN_NO(188) | 0) +#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_MRG_I2S_PCM_RX (MTK_PIN_NO(188) | 1) +#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_EINT15 (MTK_PIN_NO(188) | 2) +#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_I2SIN_DAT (MTK_PIN_NO(188) | 3) +#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_PCM0_DI (MTK_PIN_NO(188) | 4) +#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_DSP2_ID (MTK_PIN_NO(188) | 5) +#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_MFG_TEST_CK (MTK_PIN_NO(188) | 6) +#define MT8135_PIN_188_MRG_I2S_PCM_RX__FUNC_USB_SDA (MTK_PIN_NO(188) | 7) + +#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_GPIO189 (MTK_PIN_NO(189) | 0) +#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_MRG_I2S_PCM_TX (MTK_PIN_NO(189) | 1) +#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_EINT17 (MTK_PIN_NO(189) | 2) +#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_I2SOUT_DAT (MTK_PIN_NO(189) | 3) +#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_PCM0_DO (MTK_PIN_NO(189) | 4) +#define MT8135_PIN_189_MRG_I2S_PCM_TX__FUNC_VDEC_TEST_CK (MTK_PIN_NO(189) | 6) + +#define MT8135_PIN_190_SRCLKENAI__FUNC_GPIO190 (MTK_PIN_NO(190) | 0) +#define MT8135_PIN_190_SRCLKENAI__FUNC_SRCLKENAI (MTK_PIN_NO(190) | 1) + +#define MT8135_PIN_191_URXD3__FUNC_GPIO191 (MTK_PIN_NO(191) | 0) +#define MT8135_PIN_191_URXD3__FUNC_URXD3 (MTK_PIN_NO(191) | 1) +#define MT8135_PIN_191_URXD3__FUNC_EINT87 (MTK_PIN_NO(191) | 2) +#define MT8135_PIN_191_URXD3__FUNC_UTXD3 (MTK_PIN_NO(191) | 3) +#define MT8135_PIN_191_URXD3__FUNC_TS_AUX_ST (MTK_PIN_NO(191) | 5) +#define MT8135_PIN_191_URXD3__FUNC_PWM4 (MTK_PIN_NO(191) | 6) + +#define MT8135_PIN_192_UTXD3__FUNC_GPIO192 (MTK_PIN_NO(192) | 0) +#define MT8135_PIN_192_UTXD3__FUNC_UTXD3 (MTK_PIN_NO(192) | 1) +#define MT8135_PIN_192_UTXD3__FUNC_EINT86 (MTK_PIN_NO(192) | 2) +#define MT8135_PIN_192_UTXD3__FUNC_URXD3 (MTK_PIN_NO(192) | 3) +#define MT8135_PIN_192_UTXD3__FUNC_TS_AUX_CS_B (MTK_PIN_NO(192) | 5) +#define MT8135_PIN_192_UTXD3__FUNC_PWM3 (MTK_PIN_NO(192) | 6) + +#define MT8135_PIN_193_SDA2__FUNC_GPIO193 (MTK_PIN_NO(193) | 0) +#define MT8135_PIN_193_SDA2__FUNC_SDA2 (MTK_PIN_NO(193) | 1) +#define MT8135_PIN_193_SDA2__FUNC_EINT95 (MTK_PIN_NO(193) | 2) +#define MT8135_PIN_193_SDA2__FUNC_CLKM5 (MTK_PIN_NO(193) | 3) +#define MT8135_PIN_193_SDA2__FUNC_PWM5 (MTK_PIN_NO(193) | 4) +#define MT8135_PIN_193_SDA2__FUNC_TS_AUX_PWDB (MTK_PIN_NO(193) | 5) + +#define MT8135_PIN_194_SCL2__FUNC_GPIO194 (MTK_PIN_NO(194) | 0) +#define MT8135_PIN_194_SCL2__FUNC_SCL2 (MTK_PIN_NO(194) | 1) +#define MT8135_PIN_194_SCL2__FUNC_EINT94 (MTK_PIN_NO(194) | 2) +#define MT8135_PIN_194_SCL2__FUNC_CLKM4 (MTK_PIN_NO(194) | 3) +#define MT8135_PIN_194_SCL2__FUNC_PWM4 (MTK_PIN_NO(194) | 4) +#define MT8135_PIN_194_SCL2__FUNC_TS_AUXADC_TEST_CK (MTK_PIN_NO(194) | 5) + +#define MT8135_PIN_195_SDA1__FUNC_GPIO195 (MTK_PIN_NO(195) | 0) +#define MT8135_PIN_195_SDA1__FUNC_SDA1 (MTK_PIN_NO(195) | 1) +#define MT8135_PIN_195_SDA1__FUNC_EINT93 (MTK_PIN_NO(195) | 2) +#define MT8135_PIN_195_SDA1__FUNC_CLKM3 (MTK_PIN_NO(195) | 3) +#define MT8135_PIN_195_SDA1__FUNC_PWM3 (MTK_PIN_NO(195) | 4) +#define MT8135_PIN_195_SDA1__FUNC_TS_AUX_SCLK_PWDB (MTK_PIN_NO(195) | 5) + +#define MT8135_PIN_196_SCL1__FUNC_GPIO196 (MTK_PIN_NO(196) | 0) +#define MT8135_PIN_196_SCL1__FUNC_SCL1 (MTK_PIN_NO(196) | 1) +#define MT8135_PIN_196_SCL1__FUNC_EINT92 (MTK_PIN_NO(196) | 2) +#define MT8135_PIN_196_SCL1__FUNC_CLKM2 (MTK_PIN_NO(196) | 3) +#define MT8135_PIN_196_SCL1__FUNC_PWM2 (MTK_PIN_NO(196) | 4) +#define MT8135_PIN_196_SCL1__FUNC_TS_AUX_DIN (MTK_PIN_NO(196) | 5) + +#define MT8135_PIN_197_MSDC3_DAT2__FUNC_GPIO197 (MTK_PIN_NO(197) | 0) +#define MT8135_PIN_197_MSDC3_DAT2__FUNC_MSDC3_DAT2 (MTK_PIN_NO(197) | 1) +#define MT8135_PIN_197_MSDC3_DAT2__FUNC_EINT71 (MTK_PIN_NO(197) | 2) +#define MT8135_PIN_197_MSDC3_DAT2__FUNC_SCL6 (MTK_PIN_NO(197) | 3) +#define MT8135_PIN_197_MSDC3_DAT2__FUNC_PWM5 (MTK_PIN_NO(197) | 4) +#define MT8135_PIN_197_MSDC3_DAT2__FUNC_CLKM4 (MTK_PIN_NO(197) | 5) +#define MT8135_PIN_197_MSDC3_DAT2__FUNC_MFG_TEST_CK_2 (MTK_PIN_NO(197) | 6) + +#define MT8135_PIN_198_MSDC3_DAT3__FUNC_GPIO198 (MTK_PIN_NO(198) | 0) +#define MT8135_PIN_198_MSDC3_DAT3__FUNC_MSDC3_DAT3 (MTK_PIN_NO(198) | 1) +#define MT8135_PIN_198_MSDC3_DAT3__FUNC_EINT72 (MTK_PIN_NO(198) | 2) +#define MT8135_PIN_198_MSDC3_DAT3__FUNC_SDA6 (MTK_PIN_NO(198) | 3) +#define MT8135_PIN_198_MSDC3_DAT3__FUNC_PWM6 (MTK_PIN_NO(198) | 4) +#define MT8135_PIN_198_MSDC3_DAT3__FUNC_CLKM5 (MTK_PIN_NO(198) | 5) +#define MT8135_PIN_198_MSDC3_DAT3__FUNC_MFG_TEST_CK_3 (MTK_PIN_NO(198) | 6) + +#define MT8135_PIN_199_MSDC3_CMD__FUNC_GPIO199 (MTK_PIN_NO(199) | 0) +#define MT8135_PIN_199_MSDC3_CMD__FUNC_MSDC3_CMD (MTK_PIN_NO(199) | 1) +#define MT8135_PIN_199_MSDC3_CMD__FUNC_EINT68 (MTK_PIN_NO(199) | 2) +#define MT8135_PIN_199_MSDC3_CMD__FUNC_SDA2 (MTK_PIN_NO(199) | 3) +#define MT8135_PIN_199_MSDC3_CMD__FUNC_PWM2 (MTK_PIN_NO(199) | 4) +#define MT8135_PIN_199_MSDC3_CMD__FUNC_CLKM1 (MTK_PIN_NO(199) | 5) +#define MT8135_PIN_199_MSDC3_CMD__FUNC_MFG_TEST_CK_4 (MTK_PIN_NO(199) | 6) + +#define MT8135_PIN_200_MSDC3_CLK__FUNC_GPIO200 (MTK_PIN_NO(200) | 0) +#define MT8135_PIN_200_MSDC3_CLK__FUNC_MSDC3_CLK (MTK_PIN_NO(200) | 1) +#define MT8135_PIN_200_MSDC3_CLK__FUNC_EINT67 (MTK_PIN_NO(200) | 2) +#define MT8135_PIN_200_MSDC3_CLK__FUNC_SCL2 (MTK_PIN_NO(200) | 3) +#define MT8135_PIN_200_MSDC3_CLK__FUNC_PWM1 (MTK_PIN_NO(200) | 4) +#define MT8135_PIN_200_MSDC3_CLK__FUNC_CLKM0 (MTK_PIN_NO(200) | 5) + +#define MT8135_PIN_201_MSDC3_DAT1__FUNC_GPIO201 (MTK_PIN_NO(201) | 0) +#define MT8135_PIN_201_MSDC3_DAT1__FUNC_MSDC3_DAT1 (MTK_PIN_NO(201) | 1) +#define MT8135_PIN_201_MSDC3_DAT1__FUNC_EINT70 (MTK_PIN_NO(201) | 2) +#define MT8135_PIN_201_MSDC3_DAT1__FUNC_SDA3 (MTK_PIN_NO(201) | 3) +#define MT8135_PIN_201_MSDC3_DAT1__FUNC_PWM4 (MTK_PIN_NO(201) | 4) +#define MT8135_PIN_201_MSDC3_DAT1__FUNC_CLKM3 (MTK_PIN_NO(201) | 5) + +#define MT8135_PIN_202_MSDC3_DAT0__FUNC_GPIO202 (MTK_PIN_NO(202) | 0) +#define MT8135_PIN_202_MSDC3_DAT0__FUNC_MSDC3_DAT0 (MTK_PIN_NO(202) | 1) +#define MT8135_PIN_202_MSDC3_DAT0__FUNC_EINT69 (MTK_PIN_NO(202) | 2) +#define MT8135_PIN_202_MSDC3_DAT0__FUNC_SCL3 (MTK_PIN_NO(202) | 3) +#define MT8135_PIN_202_MSDC3_DAT0__FUNC_PWM3 (MTK_PIN_NO(202) | 4) +#define MT8135_PIN_202_MSDC3_DAT0__FUNC_CLKM2 (MTK_PIN_NO(202) | 5) + +#endif /* __DTS_MT8135_PINFUNC_H */ diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi index a161e99ffcc432..0aba9eb28e2b4f 100644 --- a/arch/arm/boot/dts/mt8135.dtsi +++ b/arch/arm/boot/dts/mt8135.dtsi @@ -15,6 +15,7 @@ #include #include #include "skeleton64.dtsi" +#include "mt8135-pinfunc.h" / { compatible = "mediatek,mt8135"; @@ -101,6 +102,29 @@ compatible = "simple-bus"; ranges; + /* + * Pinctrl access register at 0x10005000 and 0x1020c000 through + * regmap. Register 0x1000b000 is used by EINT. + */ + pio: pinctrl@10005000 { + compatible = "mediatek,mt8135-pinctrl"; + reg = <0 0x1000b000 0 0x1000>; + mediatek,pctl-regmap = <&syscfg_pctl_a &syscfg_pctl_b>; + pins-are-numbered; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = , + , + ; + }; + + syscfg_pctl_a: syscfg_pctl_a@10005000 { + compatible = "mediatek,mt8135-pctl-a-syscfg", "syscon"; + reg = <0 0x10005000 0 0x1000>; + }; + timer: timer@10008000 { compatible = "mediatek,mt8135-timer", "mediatek,mt6577-timer"; @@ -119,6 +143,11 @@ reg = <0 0x10200030 0 0x1c>; }; + syscfg_pctl_b: syscfg_pctl_b@1020c000 { + compatible = "mediatek,mt8135-pctl-b-syscfg", "syscon"; + reg = <0 0x1020c000 0 0x1000>; + }; + gic: interrupt-controller@10211000 { compatible = "arm,cortex-a15-gic"; interrupt-controller; From 99264a61dfcda41d86d0960cf2d4c0fc2758a773 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 15 Apr 2015 19:34:43 +0200 Subject: [PATCH 0490/3798] drm/vblank: Fixup and document timestamp update/read barriers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was a bit too much cargo-culted, so lets make it solid: - vblank->count doesn't need to be an atomic, writes are always done under the protection of dev->vblank_time_lock. Switch to an unsigned long instead and update comments. Note that atomic_read is just a normal read of a volatile variable, so no need to audit all the read-side access specifically. - The barriers for the vblank counter seqlock weren't complete: The read-side was missing the first barrier between the counter read and the timestamp read, it only had a barrier between the ts and the counter read. We need both. - Barriers weren't properly documented. Since barriers only work if you have them on boths sides of the transaction it's prudent to reference where the other side is. To avoid duplicating the write-side comment 3 times extract a little store_vblank() helper. In that helper also assert that we do indeed hold dev->vblank_time_lock, since in some cases the lock is acquired a few functions up in the callchain. Spotted while reviewing a patch from Chris Wilson to add a fastpath to the vblank_wait ioctl. v2: Add comment to better explain how store_vblank works, suggested by Chris. v3: Peter noticed that as-is the 2nd smp_wmb is redundant with the implicit barrier in the spin_unlock. But that can only be proven by auditing all callers and my point in extracting this little helper was to localize all the locking into just one place. Hence I think that additional optimization is too risky. Cc: Chris Wilson Cc: Mario Kleiner Cc: Ville Syrjälä Cc: Michel Dänzer Cc: Peter Hurley Reviewed-by: Chris Wilson Reviewed-and-tested-by: Mario Kleiner Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_irq.c | 95 +++++++++++++++++++++------------------ include/drm/drmP.h | 8 +++- 2 files changed, 57 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index c8a34476570a4e..8694b77d00023c 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -74,6 +74,36 @@ module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); +static void store_vblank(struct drm_device *dev, int crtc, + unsigned vblank_count_inc, + struct timeval *t_vblank) +{ + struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + u32 tslot; + + assert_spin_locked(&dev->vblank_time_lock); + + if (t_vblank) { + /* All writers hold the spinlock, but readers are serialized by + * the latching of vblank->count below. + */ + tslot = vblank->count + vblank_count_inc; + vblanktimestamp(dev, crtc, tslot) = *t_vblank; + } + + /* + * vblank timestamp updates are protected on the write side with + * vblank_time_lock, but on the read side done locklessly using a + * sequence-lock on the vblank counter. Ensure correct ordering using + * memory barrriers. We need the barrier both before and also after the + * counter update to synchronize with the next timestamp write. + * The read-side barriers for this are in drm_vblank_count_and_time. + */ + smp_wmb(); + vblank->count += vblank_count_inc; + smp_wmb(); +} + /** * drm_update_vblank_count - update the master vblank counter * @dev: DRM device @@ -93,7 +123,7 @@ module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); static void drm_update_vblank_count(struct drm_device *dev, int crtc) { struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; - u32 cur_vblank, diff, tslot; + u32 cur_vblank, diff; bool rc; struct timeval t_vblank; @@ -129,18 +159,12 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) if (diff == 0) return; - /* Reinitialize corresponding vblank timestamp if high-precision query - * available. Skip this step if query unsupported or failed. Will - * reinitialize delayed at next vblank interrupt in that case. + /* + * Only reinitialize corresponding vblank timestamp if high-precision query + * available and didn't fail. Will reinitialize delayed at next vblank + * interrupt in that case. */ - if (rc) { - tslot = atomic_read(&vblank->count) + diff; - vblanktimestamp(dev, crtc, tslot) = t_vblank; - } - - smp_mb__before_atomic(); - atomic_add(diff, &vblank->count); - smp_mb__after_atomic(); + store_vblank(dev, crtc, diff, rc ? &t_vblank : NULL); } /* @@ -218,7 +242,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) /* Compute time difference to stored timestamp of last vblank * as updated by last invocation of drm_handle_vblank() in vblank irq. */ - vblcount = atomic_read(&vblank->count); + vblcount = vblank->count; diff_ns = timeval_to_ns(&tvblank) - timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); @@ -234,17 +258,8 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) * available. In that case we can't account for this and just * hope for the best. */ - if (vblrc && (abs64(diff_ns) > 1000000)) { - /* Store new timestamp in ringbuffer. */ - vblanktimestamp(dev, crtc, vblcount + 1) = tvblank; - - /* Increment cooked vblank count. This also atomically commits - * the timestamp computed above. - */ - smp_mb__before_atomic(); - atomic_inc(&vblank->count); - smp_mb__after_atomic(); - } + if (vblrc && (abs64(diff_ns) > 1000000)) + store_vblank(dev, crtc, 1, &tvblank); spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); } @@ -852,7 +867,7 @@ u32 drm_vblank_count(struct drm_device *dev, int crtc) if (WARN_ON(crtc >= dev->num_crtcs)) return 0; - return atomic_read(&vblank->count); + return vblank->count; } EXPORT_SYMBOL(drm_vblank_count); @@ -897,16 +912,17 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, if (WARN_ON(crtc >= dev->num_crtcs)) return 0; - /* Read timestamp from slot of _vblank_time ringbuffer - * that corresponds to current vblank count. Retry if - * count has incremented during readout. This works like - * a seqlock. + /* + * Vblank timestamps are read lockless. To ensure consistency the vblank + * counter is rechecked and ordering is ensured using memory barriers. + * This works like a seqlock. The write-side barriers are in store_vblank. */ do { - cur_vblank = atomic_read(&vblank->count); + cur_vblank = vblank->count; + smp_rmb(); *vblanktime = vblanktimestamp(dev, crtc, cur_vblank); smp_rmb(); - } while (cur_vblank != atomic_read(&vblank->count)); + } while (cur_vblank != vblank->count); return cur_vblank; } @@ -1715,7 +1731,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) */ /* Get current timestamp and count. */ - vblcount = atomic_read(&vblank->count); + vblcount = vblank->count; drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ); /* Compute time difference to timestamp of last vblank */ @@ -1731,20 +1747,11 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) * e.g., due to spurious vblank interrupts. We need to * ignore those for accounting. */ - if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) { - /* Store new timestamp in ringbuffer. */ - vblanktimestamp(dev, crtc, vblcount + 1) = tvblank; - - /* Increment cooked vblank count. This also atomically commits - * the timestamp computed above. - */ - smp_mb__before_atomic(); - atomic_inc(&vblank->count); - smp_mb__after_atomic(); - } else { + if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) + store_vblank(dev, crtc, 1, &tvblank); + else DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n", crtc, (int) diff_ns); - } spin_unlock(&dev->vblank_time_lock); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 62c40777c00979..4c31a2cc5a3360 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -686,9 +686,13 @@ struct drm_pending_vblank_event { struct drm_vblank_crtc { struct drm_device *dev; /* pointer to the drm_device */ wait_queue_head_t queue; /**< VBLANK wait queue */ - struct timeval time[DRM_VBLANKTIME_RBSIZE]; /**< timestamp of current count */ struct timer_list disable_timer; /* delayed disable timer */ - atomic_t count; /**< number of VBLANK interrupts */ + + /* vblank counter, protected by dev->vblank_time_lock for writes */ + unsigned long count; + /* vblank timestamps, protected by dev->vblank_time_lock for writes */ + struct timeval time[DRM_VBLANKTIME_RBSIZE]; + atomic_t refcount; /* number of users of vblank interruptsper crtc */ u32 last; /* protected by dev->vbl_lock, used */ /* for wraparound handling */ From 5a8b21b222296d6bc9be0783456838e6ab6e48e4 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Mon, 4 May 2015 06:29:45 +0200 Subject: [PATCH 0491/3798] drm: Prevent invalid use of vblank_disable_immediate. (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For a kms driver to support immediate disable of vblank irq's reliably without introducing off by one errors or other mayhem for clients, it must not only support a hardware vblank counter query, but also high precision vblank timestamping, so vblank count and timestamp can be instantaneously reinitialzed to valid values. Additionally the exposed hardware counter must behave as if it is incrementing at leading edge of vblank to avoid off by one errors during reinitialization of the counter while the display happens to be inside or close to vblank. Check during drm_vblank_init that a driver which claims to be capable of vblank_disable_immediate at least supports high precision timestamping and prevent use of instant disable if that isn't present as a minimum requirement. v2: Changed from DRM_ERROR to DRM_INFO and made message more clear, as suggested by Michel Dänzer. Signed-off-by: Mario Kleiner Reviewed-by: Michel Dänzer Cc: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_irq.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 8694b77d00023c..e756485805b6db 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -352,6 +352,13 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) else DRM_INFO("No driver support for vblank timestamp query.\n"); + /* Must have precise timestamping for reliable vblank instant disable */ + if (dev->vblank_disable_immediate && !dev->driver->get_vblank_timestamp) { + dev->vblank_disable_immediate = false; + DRM_INFO("Setting vblank_disable_immediate to false because " + "get_vblank_timestamp == NULL\n"); + } + dev->vblank_disable_allowed = false; return 0; From d66a1e38280c42a06691e3df23f896273996255c Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Mon, 4 May 2015 06:29:46 +0200 Subject: [PATCH 0492/3798] drm: Zero out invalid vblank timestamp in drm_update_vblank_count. (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 844b03f27739135fe1fed2fef06da0ffc4c7a081 we make sure that after vblank irq off, we return the last valid (vblank count, vblank timestamp) pair to clients, e.g., during modesets, which is good. An overlooked side effect of that commit for kms drivers without support for precise vblank timestamping is that at vblank irq enable, when we update the vblank counter from the hw counter, we can't update the corresponding vblank timestamp, so now we have a totally mismatched timestamp for the new count to confuse clients. Restore old client visible behaviour from before Linux 3.18, but zero out the timestamp at vblank counter update (instead of disable as in original implementation) if we can't generate a meaningful timestamp immediately for the new vblank counter. This will fix this regression, so callers know they need to retry again later if they need a valid timestamp, but at the same time preserves the improvements made in the commit mentioned above. v2: Rebased on top of Daniel Vetter's fixup and documentation patch for timestamp updates. Drop request for stable kernel backport as this would be more difficult, unless the original patch would get applied to stable kernels. Signed-off-by: Mario Kleiner Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_irq.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index e756485805b6db..1967e7fc980514 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -161,10 +161,13 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) /* * Only reinitialize corresponding vblank timestamp if high-precision query - * available and didn't fail. Will reinitialize delayed at next vblank - * interrupt in that case. + * available and didn't fail. Otherwise reinitialize delayed at next vblank + * interrupt and assign 0 for now, to mark the vblanktimestamp as invalid. */ - store_vblank(dev, crtc, diff, rc ? &t_vblank : NULL); + if (!rc) + t_vblank = (struct timeval) {0, 0}; + + store_vblank(dev, crtc, diff, &t_vblank); } /* From 337eb43c8d0000fef80b88e43fee7752a84afab2 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Mon, 4 May 2015 06:29:47 +0200 Subject: [PATCH 0493/3798] drm/qxl: Fix qxl_noop_get_vblank_counter() This breaks under the vblank timestamp cleanup patch by Daniel Vetter. Also it is pointless to return anything but zero (or any other constant) if the function doesn't actually query a hw vblank counter. The bogus return of the current drm vblank counter via direct readout or via drm_vblank_count() is found in many of the new kms drivers, but it does exactly nothing different from returning any arbitrary constant - it's a no operation. Let's simply return 0 - Easy and fast. Signed-off-by: Mario Kleiner Cc: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/qxl/qxl_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index e2d07085b6a55a..83f6f0b5e9efa2 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -198,7 +198,7 @@ static int qxl_pm_restore(struct device *dev) static u32 qxl_noop_get_vblank_counter(struct drm_device *dev, int crtc) { - return dev->vblank[crtc].count.counter; + return 0; } static int qxl_noop_enable_vblank(struct drm_device *dev, int crtc) From e660df07ab90f4f61ed743522067a8dbaa6fa567 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 23 Jan 2015 09:45:35 +0100 Subject: [PATCH 0494/3798] memory: tegra: Add SWGROUP names Subsequent patches will add debugfs files that print the status of the SWGROUPs. Add a new names field and complement the SoC tables with the names of the individual SWGROUPs. Signed-off-by: Thierry Reding --- drivers/memory/tegra/tegra114.c | 32 +++++++++++------------ drivers/memory/tegra/tegra124.c | 46 ++++++++++++++++----------------- drivers/memory/tegra/tegra30.c | 32 +++++++++++------------ include/soc/tegra/mc.h | 1 + 4 files changed, 56 insertions(+), 55 deletions(-) diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c index 511e9a25c151cd..9f579589e8000a 100644 --- a/drivers/memory/tegra/tegra114.c +++ b/drivers/memory/tegra/tegra114.c @@ -896,22 +896,22 @@ static const struct tegra_mc_client tegra114_mc_clients[] = { }; static const struct tegra_smmu_swgroup tegra114_swgroups[] = { - { .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 }, - { .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 }, - { .swgroup = TEGRA_SWGROUP_EPP, .reg = 0x248 }, - { .swgroup = TEGRA_SWGROUP_G2, .reg = 0x24c }, - { .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c }, - { .swgroup = TEGRA_SWGROUP_NV, .reg = 0x268 }, - { .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 }, - { .swgroup = TEGRA_SWGROUP_HC, .reg = 0x250 }, - { .swgroup = TEGRA_SWGROUP_MSENC, .reg = 0x264 }, - { .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 }, - { .swgroup = TEGRA_SWGROUP_VDE, .reg = 0x27c }, - { .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 }, - { .swgroup = TEGRA_SWGROUP_ISP, .reg = 0x258 }, - { .swgroup = TEGRA_SWGROUP_XUSB_HOST, .reg = 0x288 }, - { .swgroup = TEGRA_SWGROUP_XUSB_DEV, .reg = 0x28c }, - { .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 }, + { .name = "dc", .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 }, + { .name = "dcb", .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 }, + { .name = "epp", .swgroup = TEGRA_SWGROUP_EPP, .reg = 0x248 }, + { .name = "g2", .swgroup = TEGRA_SWGROUP_G2, .reg = 0x24c }, + { .name = "avpc", .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c }, + { .name = "nv", .swgroup = TEGRA_SWGROUP_NV, .reg = 0x268 }, + { .name = "hda", .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 }, + { .name = "hc", .swgroup = TEGRA_SWGROUP_HC, .reg = 0x250 }, + { .name = "msenc", .swgroup = TEGRA_SWGROUP_MSENC, .reg = 0x264 }, + { .name = "ppcs", .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 }, + { .name = "vde", .swgroup = TEGRA_SWGROUP_VDE, .reg = 0x27c }, + { .name = "vi", .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 }, + { .name = "isp", .swgroup = TEGRA_SWGROUP_ISP, .reg = 0x258 }, + { .name = "xusb_host", .swgroup = TEGRA_SWGROUP_XUSB_HOST, .reg = 0x288 }, + { .name = "xusb_dev", .swgroup = TEGRA_SWGROUP_XUSB_DEV, .reg = 0x28c }, + { .name = "tsec", .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 }, }; static void tegra114_flush_dcache(struct page *page, unsigned long offset, diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index 278d40b854c15a..e63e05769d0ac8 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -934,29 +934,29 @@ static const struct tegra_mc_client tegra124_mc_clients[] = { }; static const struct tegra_smmu_swgroup tegra124_swgroups[] = { - { .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 }, - { .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 }, - { .swgroup = TEGRA_SWGROUP_AFI, .reg = 0x238 }, - { .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c }, - { .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 }, - { .swgroup = TEGRA_SWGROUP_HC, .reg = 0x250 }, - { .swgroup = TEGRA_SWGROUP_MSENC, .reg = 0x264 }, - { .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 }, - { .swgroup = TEGRA_SWGROUP_SATA, .reg = 0x274 }, - { .swgroup = TEGRA_SWGROUP_VDE, .reg = 0x27c }, - { .swgroup = TEGRA_SWGROUP_ISP2, .reg = 0x258 }, - { .swgroup = TEGRA_SWGROUP_XUSB_HOST, .reg = 0x288 }, - { .swgroup = TEGRA_SWGROUP_XUSB_DEV, .reg = 0x28c }, - { .swgroup = TEGRA_SWGROUP_ISP2B, .reg = 0xaa4 }, - { .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 }, - { .swgroup = TEGRA_SWGROUP_A9AVP, .reg = 0x290 }, - { .swgroup = TEGRA_SWGROUP_GPU, .reg = 0xaac }, - { .swgroup = TEGRA_SWGROUP_SDMMC1A, .reg = 0xa94 }, - { .swgroup = TEGRA_SWGROUP_SDMMC2A, .reg = 0xa98 }, - { .swgroup = TEGRA_SWGROUP_SDMMC3A, .reg = 0xa9c }, - { .swgroup = TEGRA_SWGROUP_SDMMC4A, .reg = 0xaa0 }, - { .swgroup = TEGRA_SWGROUP_VIC, .reg = 0x284 }, - { .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 }, + { .name = "dc", .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 }, + { .name = "dcb", .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 }, + { .name = "afi", .swgroup = TEGRA_SWGROUP_AFI, .reg = 0x238 }, + { .name = "avpc", .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c }, + { .name = "hda", .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 }, + { .name = "hc", .swgroup = TEGRA_SWGROUP_HC, .reg = 0x250 }, + { .name = "msenc", .swgroup = TEGRA_SWGROUP_MSENC, .reg = 0x264 }, + { .name = "ppcs", .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 }, + { .name = "sata", .swgroup = TEGRA_SWGROUP_SATA, .reg = 0x274 }, + { .name = "vde", .swgroup = TEGRA_SWGROUP_VDE, .reg = 0x27c }, + { .name = "isp2", .swgroup = TEGRA_SWGROUP_ISP2, .reg = 0x258 }, + { .name = "xusb_host", .swgroup = TEGRA_SWGROUP_XUSB_HOST, .reg = 0x288 }, + { .name = "xusb_dev", .swgroup = TEGRA_SWGROUP_XUSB_DEV, .reg = 0x28c }, + { .name = "isp2b", .swgroup = TEGRA_SWGROUP_ISP2B, .reg = 0xaa4 }, + { .name = "tsec", .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 }, + { .name = "a9avp", .swgroup = TEGRA_SWGROUP_A9AVP, .reg = 0x290 }, + { .name = "gpu", .swgroup = TEGRA_SWGROUP_GPU, .reg = 0xaac }, + { .name = "sdmmc1a", .swgroup = TEGRA_SWGROUP_SDMMC1A, .reg = 0xa94 }, + { .name = "sdmmc2a", .swgroup = TEGRA_SWGROUP_SDMMC2A, .reg = 0xa98 }, + { .name = "sdmmc3a", .swgroup = TEGRA_SWGROUP_SDMMC3A, .reg = 0xa9c }, + { .name = "sdmmc4a", .swgroup = TEGRA_SWGROUP_SDMMC4A, .reg = 0xaa0 }, + { .name = "vic", .swgroup = TEGRA_SWGROUP_VIC, .reg = 0x284 }, + { .name = "vi", .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 }, }; #ifdef CONFIG_ARCH_TEGRA_124_SOC diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c index 71fe9376fe5337..1abcd8f6f3ba60 100644 --- a/drivers/memory/tegra/tegra30.c +++ b/drivers/memory/tegra/tegra30.c @@ -918,22 +918,22 @@ static const struct tegra_mc_client tegra30_mc_clients[] = { }; static const struct tegra_smmu_swgroup tegra30_swgroups[] = { - { .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 }, - { .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 }, - { .swgroup = TEGRA_SWGROUP_EPP, .reg = 0x248 }, - { .swgroup = TEGRA_SWGROUP_G2, .reg = 0x24c }, - { .swgroup = TEGRA_SWGROUP_MPE, .reg = 0x264 }, - { .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 }, - { .swgroup = TEGRA_SWGROUP_AFI, .reg = 0x238 }, - { .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c }, - { .swgroup = TEGRA_SWGROUP_NV, .reg = 0x268 }, - { .swgroup = TEGRA_SWGROUP_NV2, .reg = 0x26c }, - { .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 }, - { .swgroup = TEGRA_SWGROUP_HC, .reg = 0x250 }, - { .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 }, - { .swgroup = TEGRA_SWGROUP_SATA, .reg = 0x278 }, - { .swgroup = TEGRA_SWGROUP_VDE, .reg = 0x27c }, - { .swgroup = TEGRA_SWGROUP_ISP, .reg = 0x258 }, + { .name = "dc", .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 }, + { .name = "dcb", .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 }, + { .name = "epp", .swgroup = TEGRA_SWGROUP_EPP, .reg = 0x248 }, + { .name = "g2", .swgroup = TEGRA_SWGROUP_G2, .reg = 0x24c }, + { .name = "mpe", .swgroup = TEGRA_SWGROUP_MPE, .reg = 0x264 }, + { .name = "vi", .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 }, + { .name = "afi", .swgroup = TEGRA_SWGROUP_AFI, .reg = 0x238 }, + { .name = "avpc", .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c }, + { .name = "nv", .swgroup = TEGRA_SWGROUP_NV, .reg = 0x268 }, + { .name = "nv2", .swgroup = TEGRA_SWGROUP_NV2, .reg = 0x26c }, + { .name = "hda", .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 }, + { .name = "hc", .swgroup = TEGRA_SWGROUP_HC, .reg = 0x250 }, + { .name = "ppcs", .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 }, + { .name = "sata", .swgroup = TEGRA_SWGROUP_SATA, .reg = 0x278 }, + { .name = "vde", .swgroup = TEGRA_SWGROUP_VDE, .reg = 0x27c }, + { .name = "isp", .swgroup = TEGRA_SWGROUP_ISP, .reg = 0x258 }, }; static void tegra30_flush_dcache(struct page *page, unsigned long offset, diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index 63deb8d9f82af5..b2548811e1d55b 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -40,6 +40,7 @@ struct tegra_mc_client { }; struct tegra_smmu_swgroup { + const char *name; unsigned int swgroup; unsigned int reg; }; From d1313e7896e932a92e21912850ef034e58571b66 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 23 Jan 2015 09:49:25 +0100 Subject: [PATCH 0495/3798] iommu/tegra-smmu: Add debugfs support Provide clients and swgroups files in debugfs. These files show for which clients IOMMU translation is enabled and which ASID is associated with each SWGROUP. Cc: Hiroshi Doyu Acked-by: Joerg Roedel Signed-off-by: Thierry Reding --- drivers/iommu/tegra-smmu.c | 109 +++++++++++++++++++++++++++++++++++++ include/soc/tegra/mc.h | 5 ++ 2 files changed, 114 insertions(+) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index c845d99ecf6b8c..c1f2e521dc52cd 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -31,6 +32,8 @@ struct tegra_smmu { struct mutex lock; struct list_head list; + + struct dentry *debugfs; }; struct tegra_smmu_as { @@ -673,6 +676,103 @@ static void tegra_smmu_ahb_enable(void) } } +static int tegra_smmu_swgroups_show(struct seq_file *s, void *data) +{ + struct tegra_smmu *smmu = s->private; + unsigned int i; + u32 value; + + seq_printf(s, "swgroup enabled ASID\n"); + seq_printf(s, "------------------------\n"); + + for (i = 0; i < smmu->soc->num_swgroups; i++) { + const struct tegra_smmu_swgroup *group = &smmu->soc->swgroups[i]; + const char *status; + unsigned int asid; + + value = smmu_readl(smmu, group->reg); + + if (value & SMMU_ASID_ENABLE) + status = "yes"; + else + status = "no"; + + asid = value & SMMU_ASID_MASK; + + seq_printf(s, "%-9s %-7s %#04x\n", group->name, status, + asid); + } + + return 0; +} + +static int tegra_smmu_swgroups_open(struct inode *inode, struct file *file) +{ + return single_open(file, tegra_smmu_swgroups_show, inode->i_private); +} + +static const struct file_operations tegra_smmu_swgroups_fops = { + .open = tegra_smmu_swgroups_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int tegra_smmu_clients_show(struct seq_file *s, void *data) +{ + struct tegra_smmu *smmu = s->private; + unsigned int i; + u32 value; + + seq_printf(s, "client enabled\n"); + seq_printf(s, "--------------------\n"); + + for (i = 0; i < smmu->soc->num_clients; i++) { + const struct tegra_mc_client *client = &smmu->soc->clients[i]; + const char *status; + + value = smmu_readl(smmu, client->smmu.reg); + + if (value & BIT(client->smmu.bit)) + status = "yes"; + else + status = "no"; + + seq_printf(s, "%-12s %s\n", client->name, status); + } + + return 0; +} + +static int tegra_smmu_clients_open(struct inode *inode, struct file *file) +{ + return single_open(file, tegra_smmu_clients_show, inode->i_private); +} + +static const struct file_operations tegra_smmu_clients_fops = { + .open = tegra_smmu_clients_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void tegra_smmu_debugfs_init(struct tegra_smmu *smmu) +{ + smmu->debugfs = debugfs_create_dir("smmu", NULL); + if (!smmu->debugfs) + return; + + debugfs_create_file("swgroups", S_IRUGO, smmu->debugfs, smmu, + &tegra_smmu_swgroups_fops); + debugfs_create_file("clients", S_IRUGO, smmu->debugfs, smmu, + &tegra_smmu_clients_fops); +} + +static void tegra_smmu_debugfs_exit(struct tegra_smmu *smmu) +{ + debugfs_remove_recursive(smmu->debugfs); +} + struct tegra_smmu *tegra_smmu_probe(struct device *dev, const struct tegra_smmu_soc *soc, struct tegra_mc *mc) @@ -743,5 +843,14 @@ struct tegra_smmu *tegra_smmu_probe(struct device *dev, if (err < 0) return ERR_PTR(err); + if (IS_ENABLED(CONFIG_DEBUG_FS)) + tegra_smmu_debugfs_init(smmu); + return smmu; } + +void tegra_smmu_remove(struct tegra_smmu *smmu) +{ + if (IS_ENABLED(CONFIG_DEBUG_FS)) + tegra_smmu_debugfs_exit(smmu); +} diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index b2548811e1d55b..e5ba518aaece54 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -72,6 +72,7 @@ struct tegra_smmu; struct tegra_smmu *tegra_smmu_probe(struct device *dev, const struct tegra_smmu_soc *soc, struct tegra_mc *mc); +void tegra_smmu_remove(struct tegra_smmu *smmu); #else static inline struct tegra_smmu * tegra_smmu_probe(struct device *dev, const struct tegra_smmu_soc *soc, @@ -79,6 +80,10 @@ tegra_smmu_probe(struct device *dev, const struct tegra_smmu_soc *soc, { return NULL; } + +static inline void tegra_smmu_remove(struct tegra_smmu *smmu) +{ +} #endif struct tegra_mc_soc { From 242b1d713386e8e2fd7f62cc1ed4681a12290848 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 7 Nov 2014 16:10:41 +0100 Subject: [PATCH 0496/3798] memory: tegra: Add Tegra132 support The memory controller on Tegra132 is very similar to the one found on Tegra124. But the Denver CPUs don't have an outer cache, so dcache maintenance is done slightly differently. Signed-off-by: Thierry Reding --- drivers/iommu/Kconfig | 2 +- drivers/memory/tegra/Makefile | 1 + drivers/memory/tegra/mc.c | 3 +++ drivers/memory/tegra/mc.h | 4 ++++ drivers/memory/tegra/tegra124.c | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 1ae4e547b419b9..73f918d066c628 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -219,7 +219,7 @@ config TEGRA_IOMMU_SMMU select IOMMU_API help This driver supports the IOMMU hardware (SMMU) found on NVIDIA Tegra - SoCs (Tegra30 up to Tegra124). + SoCs (Tegra30 up to Tegra132). config EXYNOS_IOMMU bool "Exynos IOMMU Support" diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile index 0d9f497b786c1d..9d4f4319b52761 100644 --- a/drivers/memory/tegra/Makefile +++ b/drivers/memory/tegra/Makefile @@ -3,5 +3,6 @@ tegra-mc-y := mc.o tegra-mc-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30.o tegra-mc-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114.o tegra-mc-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124.o +tegra-mc-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra124.o obj-$(CONFIG_TEGRA_MC) += tegra-mc.o diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index fe3c44e7e1d1bf..9b7c1645fd59ef 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -57,6 +57,9 @@ static const struct of_device_id tegra_mc_of_match[] = { #endif #ifdef CONFIG_ARCH_TEGRA_124_SOC { .compatible = "nvidia,tegra124-mc", .data = &tegra124_mc_soc }, +#endif +#ifdef CONFIG_ARCH_TEGRA_132_SOC + { .compatible = "nvidia,tegra132-mc", .data = &tegra132_mc_soc }, #endif { } }; diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index d5d21147fc7783..b7361b0a66964c 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -37,4 +37,8 @@ extern const struct tegra_mc_soc tegra114_mc_soc; extern const struct tegra_mc_soc tegra124_mc_soc; #endif +#ifdef CONFIG_ARCH_TEGRA_132_SOC +extern const struct tegra_mc_soc tegra132_mc_soc; +#endif + #endif /* MEMORY_TEGRA_MC_H */ diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index e63e05769d0ac8..b996dfb9358bcb 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -993,3 +993,36 @@ const struct tegra_mc_soc tegra124_mc_soc = { .smmu = &tegra124_smmu_soc, }; #endif /* CONFIG_ARCH_TEGRA_124_SOC */ + +#ifdef CONFIG_ARCH_TEGRA_132_SOC +static void tegra132_flush_dcache(struct page *page, unsigned long offset, + size_t size) +{ + void *virt = page_address(page) + offset; + + __flush_dcache_area(virt, size); +} + +static const struct tegra_smmu_ops tegra132_smmu_ops = { + .flush_dcache = tegra132_flush_dcache, +}; + +static const struct tegra_smmu_soc tegra132_smmu_soc = { + .clients = tegra124_mc_clients, + .num_clients = ARRAY_SIZE(tegra124_mc_clients), + .swgroups = tegra124_swgroups, + .num_swgroups = ARRAY_SIZE(tegra124_swgroups), + .supports_round_robin_arbitration = true, + .supports_request_limit = true, + .num_asids = 128, + .ops = &tegra132_smmu_ops, +}; + +const struct tegra_mc_soc tegra132_mc_soc = { + .clients = tegra124_mc_clients, + .num_clients = ARRAY_SIZE(tegra124_mc_clients), + .num_address_bits = 34, + .atom_size = 32, + .smmu = &tegra132_smmu_soc, +}; +#endif /* CONFIG_ARCH_TEGRA_132_SOC */ From 039aa4d68067161a7bd63aac9c2abc610aafab22 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Mon, 9 Mar 2015 03:12:26 -0400 Subject: [PATCH 0497/3798] soc/tegra: Watch wait_for_completion_timeout() return type The return type of the wait_for_completion_timeout() function is not int but unsigned long. An appropriately named unsigned long is added and the assignment fixed up. Signed-off-by: Nicholas Mc Guire Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/fuse-tegra20.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c b/drivers/soc/tegra/fuse/fuse-tegra20.c index 5eff6f097f980c..6acc2c44ee2c9a 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra20.c +++ b/drivers/soc/tegra/fuse/fuse-tegra20.c @@ -59,6 +59,7 @@ static u32 tegra20_fuse_readl(const unsigned int offset) int ret; u32 val = 0; struct dma_async_tx_descriptor *dma_desc; + unsigned long time_left; mutex_lock(&apb_dma_lock); @@ -82,9 +83,10 @@ static u32 tegra20_fuse_readl(const unsigned int offset) dmaengine_submit(dma_desc); dma_async_issue_pending(apb_dma_chan); - ret = wait_for_completion_timeout(&apb_dma_wait, msecs_to_jiffies(50)); + time_left = wait_for_completion_timeout(&apb_dma_wait, + msecs_to_jiffies(50)); - if (WARN(ret == 0, "apb read dma timed out")) + if (WARN(time_left == 0, "apb read dma timed out")) dmaengine_terminate_all(apb_dma_chan); else val = *apb_buffer; From 4d48edb3c3e1234d6b3fcdfb9ac24d7c6de449cb Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 15 Jan 2015 13:58:57 +0300 Subject: [PATCH 0498/3798] ARM: tegra20: Store CPU "resettable" status in IRAM Commit 7232398abc6a ("ARM: tegra: Convert PMC to a driver") changed tegra_resume() location storing from late to early and, as a result, broke suspend on Tegra20. PMC scratch register 41 is used by tegra LP1 resume code for retrieving stored physical memory address of common resume function and in the same time used by tegra20_cpu_shutdown() (shared by Tegra20 cpuidle driver and platform SMP code), which is storing CPU1 "resettable" status. It implies strict order of scratch register usage, otherwise resume function address is lost on Tegra20 after disabling non-boot CPU's on suspend. Fix it by storing "resettable" status in IRAM instead of PMC scratch register. Signed-off-by: Dmitry Osipenko Fixes: 7232398abc6a (ARM: tegra: Convert PMC to a driver) Cc: # v3.17+ Signed-off-by: Thierry Reding --- arch/arm/mach-tegra/cpuidle-tegra20.c | 5 ++-- arch/arm/mach-tegra/reset-handler.S | 10 +++++--- arch/arm/mach-tegra/reset.h | 4 +++ arch/arm/mach-tegra/sleep-tegra20.S | 37 +++++++++++++++------------ arch/arm/mach-tegra/sleep.h | 4 +++ 5 files changed, 38 insertions(+), 22 deletions(-) diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c index 88de2dce2e8722..7469347b174938 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra20.c +++ b/arch/arm/mach-tegra/cpuidle-tegra20.c @@ -34,6 +34,7 @@ #include "iomap.h" #include "irq.h" #include "pm.h" +#include "reset.h" #include "sleep.h" #ifdef CONFIG_PM_SLEEP @@ -70,15 +71,13 @@ static struct cpuidle_driver tegra_idle_driver = { #ifdef CONFIG_PM_SLEEP #ifdef CONFIG_SMP -static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); - static int tegra20_reset_sleeping_cpu_1(void) { int ret = 0; tegra_pen_lock(); - if (readl(pmc + PMC_SCRATCH41) == CPU_RESETTABLE) + if (readb(tegra20_cpu1_resettable_status) == CPU_RESETTABLE) tegra20_cpu_shutdown(1); else ret = -EINVAL; diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S index 71be4af5e975be..e3070fdab80b8b 100644 --- a/arch/arm/mach-tegra/reset-handler.S +++ b/arch/arm/mach-tegra/reset-handler.S @@ -169,10 +169,10 @@ after_errata: cmp r6, #TEGRA20 bne 1f /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */ - mov32 r5, TEGRA_PMC_BASE - mov r0, #0 + mov32 r5, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + mov r0, #CPU_NOT_RESETTABLE cmp r10, #0 - strne r0, [r5, #PMC_SCRATCH41] + strneb r0, [r5, #__tegra20_cpu1_resettable_status_offset] 1: #endif @@ -281,6 +281,10 @@ __tegra_cpu_reset_handler_data: .rept TEGRA_RESET_DATA_SIZE .long 0 .endr + .globl __tegra20_cpu1_resettable_status_offset + .equ __tegra20_cpu1_resettable_status_offset, \ + . - __tegra_cpu_reset_handler_start + .byte 0 .align L1_CACHE_SHIFT ENTRY(__tegra_cpu_reset_handler_end) diff --git a/arch/arm/mach-tegra/reset.h b/arch/arm/mach-tegra/reset.h index 76a93434c6ee07..29c3dec0126a41 100644 --- a/arch/arm/mach-tegra/reset.h +++ b/arch/arm/mach-tegra/reset.h @@ -35,6 +35,7 @@ extern unsigned long __tegra_cpu_reset_handler_data[TEGRA_RESET_DATA_SIZE]; void __tegra_cpu_reset_handler_start(void); void __tegra_cpu_reset_handler(void); +void __tegra20_cpu1_resettable_status_offset(void); void __tegra_cpu_reset_handler_end(void); void tegra_secondary_startup(void); @@ -47,6 +48,9 @@ void tegra_secondary_startup(void); (IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \ ((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_LP2] - \ (u32)__tegra_cpu_reset_handler_start))) +#define tegra20_cpu1_resettable_status \ + (IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \ + (u32)__tegra20_cpu1_resettable_status_offset)) #endif #define tegra_cpu_reset_handler_offset \ diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S index be4bc5f853f5c3..e6b684e14322ce 100644 --- a/arch/arm/mach-tegra/sleep-tegra20.S +++ b/arch/arm/mach-tegra/sleep-tegra20.S @@ -97,9 +97,10 @@ ENDPROC(tegra20_hotplug_shutdown) ENTRY(tegra20_cpu_shutdown) cmp r0, #0 reteq lr @ must not be called for CPU 0 - mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 + mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT + ldr r2, =__tegra20_cpu1_resettable_status_offset mov r12, #CPU_RESETTABLE - str r12, [r1] + strb r12, [r1, r2] cpu_to_halt_reg r1, r0 ldr r3, =TEGRA_FLOW_CTRL_VIRT @@ -182,38 +183,41 @@ ENDPROC(tegra_pen_unlock) /* * tegra20_cpu_clear_resettable(void) * - * Called to clear the "resettable soon" flag in PMC_SCRATCH41 when + * Called to clear the "resettable soon" flag in IRAM variable when * it is expected that the secondary CPU will be idle soon. */ ENTRY(tegra20_cpu_clear_resettable) - mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 + mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT + ldr r2, =__tegra20_cpu1_resettable_status_offset mov r12, #CPU_NOT_RESETTABLE - str r12, [r1] + strb r12, [r1, r2] ret lr ENDPROC(tegra20_cpu_clear_resettable) /* * tegra20_cpu_set_resettable_soon(void) * - * Called to set the "resettable soon" flag in PMC_SCRATCH41 when + * Called to set the "resettable soon" flag in IRAM variable when * it is expected that the secondary CPU will be idle soon. */ ENTRY(tegra20_cpu_set_resettable_soon) - mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 + mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT + ldr r2, =__tegra20_cpu1_resettable_status_offset mov r12, #CPU_RESETTABLE_SOON - str r12, [r1] + strb r12, [r1, r2] ret lr ENDPROC(tegra20_cpu_set_resettable_soon) /* * tegra20_cpu_is_resettable_soon(void) * - * Returns true if the "resettable soon" flag in PMC_SCRATCH41 has been + * Returns true if the "resettable soon" flag in IRAM variable has been * set because it is expected that the secondary CPU will be idle soon. */ ENTRY(tegra20_cpu_is_resettable_soon) - mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 - ldr r12, [r1] + mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT + ldr r2, =__tegra20_cpu1_resettable_status_offset + ldrb r12, [r1, r2] cmp r12, #CPU_RESETTABLE_SOON moveq r0, #1 movne r0, #0 @@ -256,9 +260,10 @@ ENTRY(tegra20_sleep_cpu_secondary_finish) mov r0, #TEGRA_FLUSH_CACHE_LOUIS bl tegra_disable_clean_inv_dcache - mov32 r0, TEGRA_PMC_VIRT + PMC_SCRATCH41 + mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT + ldr r4, =__tegra20_cpu1_resettable_status_offset mov r3, #CPU_RESETTABLE - str r3, [r0] + strb r3, [r0, r4] bl tegra_cpu_do_idle @@ -274,10 +279,10 @@ ENTRY(tegra20_sleep_cpu_secondary_finish) bl tegra_pen_lock - mov32 r3, TEGRA_PMC_VIRT - add r0, r3, #PMC_SCRATCH41 + mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT + ldr r4, =__tegra20_cpu1_resettable_status_offset mov r3, #CPU_NOT_RESETTABLE - str r3, [r0] + strb r3, [r0, r4] bl tegra_pen_unlock diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h index 92d46ec1361abb..0d59360d891da8 100644 --- a/arch/arm/mach-tegra/sleep.h +++ b/arch/arm/mach-tegra/sleep.h @@ -18,6 +18,7 @@ #define __MACH_TEGRA_SLEEP_H #include "iomap.h" +#include "irammap.h" #define TEGRA_ARM_PERIF_VIRT (TEGRA_ARM_PERIF_BASE - IO_CPU_PHYS \ + IO_CPU_VIRT) @@ -29,6 +30,9 @@ + IO_APB_VIRT) #define TEGRA_PMC_VIRT (TEGRA_PMC_BASE - IO_APB_PHYS + IO_APB_VIRT) +#define TEGRA_IRAM_RESET_BASE_VIRT (IO_IRAM_VIRT + \ + TEGRA_IRAM_RESET_HANDLER_OFFSET) + /* PMC_SCRATCH37-39 and 41 are used for tegra_pen_lock and idle */ #define PMC_SCRATCH37 0x130 #define PMC_SCRATCH38 0x134 From 5431b0fdadfec7aa61c916d6978544727a00b5fe Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 29 Apr 2015 13:53:21 +0200 Subject: [PATCH 0499/3798] ARM: tegra: Use lower-case hexadecimal digits For consistency with other device tree content, use lower-case hexadecimal digits in register region specifications. Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt | 2 +- arch/arm/boot/dts/tegra124.dtsi | 2 +- arch/arm/boot/dts/tegra20.dtsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt b/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt index 23e1d3194174ab..41372d441131aa 100644 --- a/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt +++ b/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt @@ -29,7 +29,7 @@ Example: fuse@7000f800 { compatible = "nvidia,tegra20-efuse"; - reg = <0x7000F800 0x400>, + reg = <0x7000f800 0x400>, <0x70000000 0x400>; clocks = <&tegra_car TEGRA20_CLK_FUSE>; clock-names = "fuse"; diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi index cf01c818b8ea41..0d9f9ae73149a5 100644 --- a/arch/arm/boot/dts/tegra124.dtsi +++ b/arch/arm/boot/dts/tegra124.dtsi @@ -300,7 +300,7 @@ apbmisc@0,70000800 { compatible = "nvidia,tegra124-apbmisc", "nvidia,tegra20-apbmisc"; reg = <0x0 0x70000800 0x0 0x64>, /* Chip revision */ - <0x0 0x7000E864 0x0 0x04>; /* Strapping options */ + <0x0 0x7000e864 0x0 0x04>; /* Strapping options */ }; pinmux: pinmux@0,70000868 { diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index adf6b048d0bb52..f444b67f55c6be 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -563,7 +563,7 @@ fuse@7000f800 { compatible = "nvidia,tegra20-efuse"; - reg = <0x7000F800 0x400>; + reg = <0x7000f800 0x400>; clocks = <&tegra_car TEGRA20_CLK_FUSE>; clock-names = "fuse"; resets = <&tegra_car 39>; From 85aa5047e369d963b88af3e817dd40e692175153 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 26 Feb 2015 11:21:58 +0100 Subject: [PATCH 0500/3798] ARM: tegra: Fix typo (reset -> rest) in comment Easy typo to make when you're working in this area of the code. Signed-off-by: Thierry Reding --- arch/arm/mach-tegra/sleep-tegra30.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S index 5d8d13aeab937f..9a2f0b051e1035 100644 --- a/arch/arm/mach-tegra/sleep-tegra30.S +++ b/arch/arm/mach-tegra/sleep-tegra30.S @@ -223,7 +223,7 @@ wfe_war: b __cpu_reset_again /* - * 38 nop's, which fills reset of wfe cache line and + * 38 nop's, which fills rest of wfe cache line and * 4 more cachelines with nop */ .rept 38 From 5780c20664db63033190c4d74c7f1ec2d13e91fe Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 18 Dec 2014 14:58:20 +0100 Subject: [PATCH 0501/3798] ARM: tegra: cardhu: Add power and volume keys The Cardhu has a power key on the top-right as well as volume up and volume down keys on the right side. Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra30-cardhu.dtsi | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi index a1b682ea01bd70..439634183e2530 100644 --- a/arch/arm/boot/dts/tegra30-cardhu.dtsi +++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi @@ -1,3 +1,4 @@ +#include #include "tegra30.dtsi" /** @@ -615,4 +616,31 @@ <&tegra_car TEGRA30_CLK_EXTERN1>; clock-names = "pll_a", "pll_a_out0", "mclk"; }; + + gpio-keys { + compatible = "gpio-keys"; + + power { + label = "Power"; + interrupt-parent = <&pmic>; + interrupts = <2 0>; + linux,code = ; + debounce-interval = <100>; + gpio-key,wakeup; + }; + + volume-down { + label = "Volume Down"; + gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <10>; + }; + + volume-up { + label = "Volume Up"; + gpios = <&gpio TEGRA_GPIO(R, 1) GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <10>; + }; + }; }; From 5264d2749fa3a52bc3adf3937c284590cf0b3ecf Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 24 Apr 2015 11:57:06 +0200 Subject: [PATCH 0502/3798] ARM: tegra: Add missing HDMI +5V regulator Commit fb50a116bbbc ("drm/tegra: hdmi - Add connector supply support") introduced a new supply for HDMI connectors that is used to control the voltage on the +5V pin. Not all boards have had the corresponding supply added to their device tree files, causing the following warning message during boot: [ 0.859698] 54280000.hdmi supply hdmi not found, using dummy regulator Add such a regulator to the Seaboard DTS to enable the driver to control this voltage and get rid of the warning. Reported-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra20-seaboard.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts index e2fed27122497b..aea8994b35f27d 100644 --- a/arch/arm/boot/dts/tegra20-seaboard.dts +++ b/arch/arm/boot/dts/tegra20-seaboard.dts @@ -31,6 +31,7 @@ vdd-supply = <&hdmi_vdd_reg>; pll-supply = <&hdmi_pll_reg>; + hdmi-supply = <&vdd_hdmi>; nvidia,ddc-i2c-bus = <&hdmi_ddc>; nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7) @@ -893,6 +894,17 @@ gpio = <&gpio TEGRA_GPIO(W, 0) GPIO_ACTIVE_HIGH>; enable-active-high; }; + + vdd_hdmi: regulator@6 { + compatible = "regulator-fixed"; + reg = <6>; + regulator-name = "VDDIO_HDMI"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio TEGRA_GPIO(V, 5) GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <&vdd_5v0_reg>; + }; }; sound { From 4c84472e3a4ddba063b09c695fde09b3260e67e1 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 22 May 2014 09:38:31 +0200 Subject: [PATCH 0503/3798] ARM: tegra: jetson-tk1: Enable HDA support The HDA controller can be used to play back audio via HDMI. Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra124-jetson-tk1.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts index ed8a8acd3d34b4..bd43ed6d6ec7c0 100644 --- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts +++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts @@ -1647,6 +1647,10 @@ target-12v-supply = <&vdd_12v0_sata>; }; + hda@0,70030000 { + status = "okay"; + }; + padctl@0,7009f000 { pinctrl-0 = <&padctl_default>; pinctrl-names = "default"; From 405990c7e834913554482538321f16f457dda50e Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Thu, 12 Mar 2015 15:47:54 +0100 Subject: [PATCH 0504/3798] of: Document long-ram-code property in nvidia,tegra20-apbmisc Needed to properly decode the RAM code register. Signed-off-by: Tomeu Vizoso Signed-off-by: Thierry Reding --- .../devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt b/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt index 47b205cc9cc7ac..4556359c58763b 100644 --- a/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt +++ b/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt @@ -10,3 +10,5 @@ Required properties: The second entry gives the physical address and length of the registers indicating the strapping options. +Optional properties: +- nvidia,long-ram-code: If present, the RAM code is long (4 bit). If not, short (2 bit). From 6ea2609ab386f6bfeebc39e1418b7497a9deb55c Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Thu, 12 Mar 2015 15:47:55 +0100 Subject: [PATCH 0505/3798] soc/tegra: fuse: Add RAM code reader helper Needed for the EMC and MC drivers to know what timings from the DT to use. Signed-off-by: Mikko Perttunen Signed-off-by: Tomeu Vizoso Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/tegra-apbmisc.c | 21 +++++++++++++++++++++ include/soc/tegra/fuse.h | 1 + 2 files changed, 22 insertions(+) diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 3bf5aba4caaa8b..73fad05d8f2cf7 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -28,8 +28,15 @@ #define APBMISC_SIZE 0x64 #define FUSE_SKU_INFO 0x10 +#define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT 4 +#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG \ + (0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT) +#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT \ + (0x3 << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT) + static void __iomem *apbmisc_base; static void __iomem *strapping_base; +static bool long_ram_code; u32 tegra_read_chipid(void) { @@ -54,6 +61,18 @@ u32 tegra_read_straps(void) return 0; } +u32 tegra_read_ram_code(void) +{ + u32 straps = tegra_read_straps(); + + if (long_ram_code) + straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG; + else + straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT; + + return straps >> PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT; +} + static const struct of_device_id apbmisc_match[] __initconst = { { .compatible = "nvidia,tegra20-apbmisc", }, {}, @@ -112,4 +131,6 @@ void __init tegra_init_apbmisc(void) strapping_base = of_iomap(np, 1); if (!strapping_base) pr_err("ioremap tegra strapping_base failed\n"); + + long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code"); } diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h index b5f7b5f8d008f2..b019e3465f113b 100644 --- a/include/soc/tegra/fuse.h +++ b/include/soc/tegra/fuse.h @@ -56,6 +56,7 @@ struct tegra_sku_info { }; u32 tegra_read_straps(void); +u32 tegra_read_ram_code(void); u32 tegra_read_chipid(void); int tegra_fuse_readl(unsigned long offset, u32 *value); From 7892158a96629c46c46dfae52eaf951f51222cf5 Mon Sep 17 00:00:00 2001 From: David Riley Date: Wed, 18 Mar 2015 10:52:25 +0100 Subject: [PATCH 0506/3798] soc/tegra: pmc: move to using a restart handler The pmc driver was previously exporting tegra_pmc_restart, which was assigned to machine_desc.init_machine, taking precedence over the restart handlers registered through register_restart_handler(). Signed-off-by: David Riley [tomeu.vizoso@collabora.com: Rebased] Signed-off-by: Tomeu Vizoso Acked-by: Stephen Warren Reviewed-by: Alexandre Courbot [treding@nvidia.com: minor cleanups] Signed-off-by: Thierry Reding --- arch/arm/mach-tegra/tegra.c | 1 - drivers/soc/tegra/pmc.c | 23 +++++++++++++++++------ include/soc/tegra/pmc.h | 2 -- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index 861d88486dbec2..2378fa560a210b 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c @@ -163,6 +163,5 @@ DT_MACHINE_START(TEGRA_DT, "NVIDIA Tegra SoC (Flattened Device Tree)") .init_irq = tegra_dt_init_irq, .init_machine = tegra_dt_init, .init_late = tegra_dt_init_late, - .restart = tegra_pmc_restart, .dt_compat = tegra_dt_board_compat, MACHINE_END diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index c956395cf46f96..cc119d15dd1616 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -377,13 +377,10 @@ int tegra_pmc_cpu_remove_clamping(int cpuid) } #endif /* CONFIG_SMP */ -/** - * tegra_pmc_restart() - reboot the system - * @mode: which mode to reboot in - * @cmd: reboot command - */ -void tegra_pmc_restart(enum reboot_mode mode, const char *cmd) +static int tegra_pmc_restart_notify(struct notifier_block *this, + unsigned long action, void *data) { + const char *cmd = data; u32 value; value = tegra_pmc_readl(PMC_SCRATCH0); @@ -405,8 +402,15 @@ void tegra_pmc_restart(enum reboot_mode mode, const char *cmd) value = tegra_pmc_readl(0); value |= 0x10; tegra_pmc_writel(value, 0); + + return NOTIFY_DONE; } +static struct notifier_block tegra_pmc_restart_handler = { + .notifier_call = tegra_pmc_restart_notify, + .priority = 128, +}; + static int powergate_show(struct seq_file *s, void *data) { unsigned int i; @@ -837,6 +841,13 @@ static int tegra_pmc_probe(struct platform_device *pdev) return err; } + err = register_restart_handler(&tegra_pmc_restart_handler); + if (err) { + dev_err(&pdev->dev, "unable to register restart handler, %d\n", + err); + return err; + } + return 0; } diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h index 65a93273e72fe9..f5c0de43a5fad2 100644 --- a/include/soc/tegra/pmc.h +++ b/include/soc/tegra/pmc.h @@ -26,8 +26,6 @@ struct clk; struct reset_control; -void tegra_pmc_restart(enum reboot_mode mode, const char *cmd); - #ifdef CONFIG_PM_SLEEP enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void); void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode); From 6f0a4d0c26f17e93f296e43c7b9f44733ea188ae Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Thu, 12 Mar 2015 15:48:10 +0100 Subject: [PATCH 0507/3798] memory: tegra: Disable ARBITRATION_EMEM interrupt As this interrupt is just for development purposes, as the TRM says, and the sheer amount of interrupts fired can seriously disrupt userspace when testing the lower frequencies supported by the EMC. From the TRM: "There is one performance warning type interrupt: ARBITRATION_EMEM. It fires when the MC detects that a request has been pending in the Row Sorter long enough to hit the DEADLOCK_PREVENTION_SLACK_THRESHOLD. In addition to true performance problems, this interrupt may fire in situations such as clock-change where the EMC backpressures pending traffic for long periods of time. This interrupt helps developers identify and debug performance issues and configuration issues." Signed-off-by: Tomeu Vizoso Signed-off-by: Thierry Reding --- drivers/memory/tegra/mc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 9b7c1645fd59ef..918236457c1699 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -276,8 +276,8 @@ static int tegra_mc_probe(struct platform_device *pdev) value = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE | - MC_INT_ARBITRATION_EMEM | MC_INT_SECURITY_VIOLATION | - MC_INT_DECERR_EMEM; + MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM; + mc_writel(mc, value, MC_INTMASK); return 0; From 3671c580e55955e61072a6e6d0d9567abdd80b5c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 4 May 2015 15:40:52 +0200 Subject: [PATCH 0508/3798] drm/atomic-helper: Really recover pre-atomic plane/cursor behavior I've fumbled this in commit f02ad907cd9e7fe3a6405d2d005840912f1ed258 Author: Daniel Vetter Date: Thu Jan 22 16:36:23 2015 +0100 drm/atomic-helpers: Recover full cursor plane behaviour and accidentally put the assignment for legacy_cursor_upate after the atomic commit, where it is pretty useless. Reported-by: Maarten Lankhorst Cc: Maarten Lankhorst Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index d536817699c194..9f216ff61af326 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1310,13 +1310,13 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane, plane_state->src_h = src_h; plane_state->src_w = src_w; + if (plane == crtc->cursor) + state->legacy_cursor_update = true; + ret = drm_atomic_commit(state); if (ret != 0) goto fail; - if (plane == crtc->cursor) - state->legacy_cursor_update = true; - /* Driver takes ownership of state on successful commit. */ return 0; fail: From fd891454609ec036dc23e34536e45d655b4ca4db Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 28 Apr 2015 15:41:16 +0200 Subject: [PATCH 0509/3798] nfsd: remove nfsd_close Signed-off-by: Christoph Hellwig Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 2 +- fs/nfsd/vfs.c | 19 +++++-------------- fs/nfsd/vfs.h | 1 - 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 039f9c8a95e842..86f5c273c9ec4a 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -5505,7 +5505,7 @@ static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct __be32 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); if (!err) { err = nfserrno(vfs_test_lock(file, lock)); - nfsd_close(file); + fput(file); } return err; } diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 84d770be056ee7..a30e79900086f0 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -744,7 +744,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, host_err = ima_file_check(file, may_flags, 0); if (host_err) { - nfsd_close(file); + fput(file); goto out_nfserr; } @@ -761,15 +761,6 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, return err; } -/* - * Close a file. - */ -void -nfsd_close(struct file *filp) -{ - fput(filp); -} - /* * Obtain the readahead parameters for the file * specified by (dev, ino). @@ -1040,7 +1031,7 @@ void nfsd_put_tmp_read_open(struct file *file, struct raparms *ra) ra->p_count--; spin_unlock(&rab->pb_lock); } - nfsd_close(file); + fput(file); } /* @@ -1093,7 +1084,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, if (cnt) err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt, stablep); - nfsd_close(file); + fput(file); } out: return err; @@ -1138,7 +1129,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, err = nfserr_notsupp; } - nfsd_close(file); + fput(file); out: return err; } @@ -1977,7 +1968,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, if (err == nfserr_eof || err == nfserr_toosmall) err = nfs_ok; /* can still be found in ->err */ out_close: - nfsd_close(file); + fput(file); out: return err; } diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index 2050cb016998fd..17a5e0db6a77a6 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h @@ -71,7 +71,6 @@ __be32 nfsd_commit(struct svc_rqst *, struct svc_fh *, #endif /* CONFIG_NFSD_V3 */ __be32 nfsd_open(struct svc_rqst *, struct svc_fh *, umode_t, int, struct file **); -void nfsd_close(struct file *); struct raparms; __be32 nfsd_get_tmp_read_open(struct svc_rqst *, struct svc_fh *, struct file **, struct raparms **); From 72faedae8bc3504ee4252cebf14737a23677cb8f Mon Sep 17 00:00:00 2001 From: Scott Mayhew Date: Wed, 29 Apr 2015 10:38:26 -0400 Subject: [PATCH 0510/3798] Documentation: remove overloads-avoided counter from knfsd-stats.txt The 'overloads-avoided' counter itself was removed several years ago by commit 78c210e (Revert "knfsd: avoid overloading the CPU scheduler with enormous load averages"). Signed-off-by: Scott Mayhew Signed-off-by: J. Bruce Fields --- Documentation/filesystems/nfs/knfsd-stats.txt | 44 ++----------------- 1 file changed, 4 insertions(+), 40 deletions(-) diff --git a/Documentation/filesystems/nfs/knfsd-stats.txt b/Documentation/filesystems/nfs/knfsd-stats.txt index 64ced5149d3791..1a5d82180b8484 100644 --- a/Documentation/filesystems/nfs/knfsd-stats.txt +++ b/Documentation/filesystems/nfs/knfsd-stats.txt @@ -68,16 +68,10 @@ sockets-enqueued rate of change for this counter is zero; significantly non-zero values may indicate a performance limitation. - This can happen either because there are too few nfsd threads in the - thread pool for the NFS workload (the workload is thread-limited), - or because the NFS workload needs more CPU time than is available in - the thread pool (the workload is CPU-limited). In the former case, - configuring more nfsd threads will probably improve the performance - of the NFS workload. In the latter case, the sunrpc server layer is - already choosing not to wake idle nfsd threads because there are too - many nfsd threads which want to run but cannot, so configuring more - nfsd threads will make no difference whatsoever. The overloads-avoided - statistic (see below) can be used to distinguish these cases. + This can happen because there are too few nfsd threads in the thread + pool for the NFS workload (the workload is thread-limited), in which + case configuring more nfsd threads will probably improve the + performance of the NFS workload. threads-woken Counts how many times an idle nfsd thread is woken to try to @@ -88,36 +82,6 @@ threads-woken thing. The ideal rate of change for this counter will be close to but less than the rate of change of the packets-arrived counter. -overloads-avoided - Counts how many times the sunrpc server layer chose not to wake an - nfsd thread, despite the presence of idle nfsd threads, because - too many nfsd threads had been recently woken but could not get - enough CPU time to actually run. - - This statistic counts a circumstance where the sunrpc layer - heuristically avoids overloading the CPU scheduler with too many - runnable nfsd threads. The ideal rate of change for this counter - is zero. Significant non-zero values indicate that the workload - is CPU limited. Usually this is associated with heavy CPU usage - on all the CPUs in the nfsd thread pool. - - If a sustained large overloads-avoided rate is detected on a pool, - the top(1) utility should be used to check for the following - pattern of CPU usage on all the CPUs associated with the given - nfsd thread pool. - - - %us ~= 0 (as you're *NOT* running applications on your NFS server) - - - %wa ~= 0 - - - %id ~= 0 - - - %sy + %hi + %si ~= 100 - - If this pattern is seen, configuring more nfsd threads will *not* - improve the performance of the workload. If this patten is not - seen, then something more subtle is wrong. - threads-timedout Counts how many times an nfsd thread triggered an idle timeout, i.e. was not woken to handle any incoming network packets for From 11cd7b8c2773d01e4b40e38568ae62c471a2ea10 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 4 May 2015 10:48:07 -0700 Subject: [PATCH 0511/3798] ARM: OMAP2+: Remove legacy booting support for cm-t35 We've been moving all omap2+ based systems to boot in device tree only mode for a few years now. Only omap3 has legacy booting support remaining. Most omap3 boards already have related arch/arm/boot/*.dts* files for booting with device tree. This board has support for device tree based booting, and we've been printing warnings about the legacy booting being deprecated for a few merge cycles now. Let's attempt to remove the legacy booting for it. The reason for removing the legacy booting support now rather than later is we can simply revert this patch if necessary if we run into some unexpected issues that are not trivial to fix for the device tree based booting. Cc: Dmitry Lifshitz Cc: Igor Grinberg Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 10 - arch/arm/mach-omap2/Makefile | 1 - arch/arm/mach-omap2/board-cm-t35.c | 769 ----------------------------- 3 files changed, 780 deletions(-) delete mode 100644 arch/arm/mach-omap2/board-cm-t35.c diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 6468f15f060ca7..8b3aa4ca59a222 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -240,16 +240,6 @@ config MACH_NOKIA_RX51 default y select OMAP_PACKAGE_CBB -config MACH_CM_T35 - bool "CompuLab CM-T35/CM-T3730 modules" - depends on ARCH_OMAP3 - default y - select MACH_CM_T3730 - select OMAP_PACKAGE_CUS - -config MACH_CM_T3730 - bool - config OMAP3_SDRC_AC_TIMING bool "Enable SDRC AC timing register changes" depends on ARCH_OMAP3 diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index ec002bd4af7715..ff634a1c26f563 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -252,7 +252,6 @@ obj-$(CONFIG_MACH_NOKIA_N8X0) += board-n8x0.o obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o sdram-nokia.o obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51-peripherals.o obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51-video.o -obj-$(CONFIG_MACH_CM_T35) += board-cm-t35.o # Platform specific device init code diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c deleted file mode 100644 index b5dfbc1b1fc6f0..00000000000000 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ /dev/null @@ -1,769 +0,0 @@ -/* - * CompuLab CM-T35/CM-T3730 modules support - * - * Copyright (C) 2009-2011 CompuLab, Ltd. - * Authors: Mike Rapoport - * Igor Grinberg - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include