From patchwork Wed Sep 5 19:24:41 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Vetter X-Patchwork-Id: 1410851 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id C37CA3FC71 for ; Wed, 5 Sep 2012 20:33:50 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D11DC9E7C2 for ; Wed, 5 Sep 2012 13:33:50 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-wg0-f43.google.com (mail-wg0-f43.google.com [74.125.82.43]) by gabe.freedesktop.org (Postfix) with ESMTP id C2DE29E9DE for ; Wed, 5 Sep 2012 13:32:05 -0700 (PDT) Received: by wgbdr1 with SMTP id dr1so703454wgb.12 for ; Wed, 05 Sep 2012 13:32:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=fEbb3dk1qUSdby/aGXzZslndA3MR725pwpQ71udkteU=; b=UKe5CmUv2pe5aHYhGprLSDwLOnWGTIQl35QacsKhp0//vd28zspKnYiQUmnADmruvg BpNaBxXaM4cO7btu0mk2FioJVdIhelLIBlTA/dfzqoBmKBv3pNt0LavzVjMKzNDpdi6l xLkwZIBh1g3xQoO6PuN9EJSHvw+8ntPV7OZFE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=fEbb3dk1qUSdby/aGXzZslndA3MR725pwpQ71udkteU=; b=CZYfvQDIomxLqYCrUE6NM7msRLrRaxnM8k0Bsloh601J7qOgXiWP9ORFccrz60ymgr fRNEFrnARx7I+nOlLBTx0K8ePgp6x2EaonHTnkKZfmetDhX1ZdQwY8vyo7unc0oKg1f5 7DCUf+xt8Z+6tCAQqv7fDImrLk6zB3lRajRiHQutZI4zQX7mT/yyWZH55qvdiuEdcBLf xh09Q7nwJwwMdasT9/9Uq/Kzu48PmHGmoQ38C36v+w3iIuWFKktSbLtNtLKKbNkHyHky uYQvJj1CGLcBoTFKjUhshRnN2DVThzzOLyTZf6JHZXl4rfB4Yv62K+24bKLDoS6uFqve Gf6g== Received: by 10.180.100.37 with SMTP id ev5mr40585631wib.5.1346877124631; Wed, 05 Sep 2012 13:32:04 -0700 (PDT) Received: from wespe.ffwll.local (178-83-130-250.dynamic.hispeed.ch. [178.83.130.250]) by mx.google.com with ESMTPS id ef5sm80868wib.3.2012.09.05.13.32.03 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 05 Sep 2012 13:32:03 -0700 (PDT) From: Daniel Vetter To: Intel Graphics Development Date: Wed, 5 Sep 2012 21:24:41 +0200 Message-Id: <1346873081-1305-3-git-send-email-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 1.7.11.2 In-Reply-To: <1346873081-1305-1-git-send-email-daniel.vetter@ffwll.ch> References: <1346873081-1305-1-git-send-email-daniel.vetter@ffwll.ch> X-Gm-Message-State: ALoCoQnFKLResTvPwPUjrMtubNUlaXRs9g15qMHd2m5dOpj0vwcsJcEtJFGyT03IMoB9fe1UncmG Cc: Daniel Vetter Subject: [Intel-gfx] [PATCH 3/3] drm/i915: use the gmbus irq for waits X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org We need two special things to properly wire this up: - Add another argument to gmbus_wait_hw_status to pass in the correct interrupt bit in gmbus4. - Since we can only get an irq for one of the two events we want, hand-roll the wait_event_timeout code so that we wake up every jiffie and can check for NAKs. This way we also subsume gmbus support for platforms without interrupts (or where those are not yet enabled). The important bit really is to only enable one gmbus interrupt source at the same time - with that piece of lore figured out, this seems to work flawlessly. Cc: Daniel Kurtz Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_irq.c | 4 ++++ drivers/gpu/drm/i915/intel_i2c.c | 46 ++++++++++++++++++++++++++++------------ 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9fce782..d93ce14 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -418,6 +418,8 @@ typedef struct drm_i915_private { */ uint32_t gpio_mmio_base; + wait_queue_head_t gmbus_wait_queue; + struct pci_dev *bridge_dev; struct intel_ring_buffer ring[I915_NUM_RINGS]; uint32_t next_seqno; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8415fa6..dadc86b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -598,7 +598,11 @@ out: static void gmbus_irq_handler(struct drm_device *dev) { + struct drm_i915_private *dev_priv = (drm_i915_private_t *) dev->dev_private; + DRM_DEBUG_DRIVER("GMBUS interrupt\n"); + + wake_up_all(&dev_priv->gmbus_wait_queue); } static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir) diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 3a90b87..4d9df5e 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -205,20 +205,36 @@ intel_gpio_setup(struct intel_gmbus *bus, u32 pin) static int gmbus_wait_hw_status(struct drm_i915_private *dev_priv, - u32 gmbus2_status) + u32 gmbus2_status, + u32 gmbus4_irq_en) { - int ret; + int i; int reg_offset = dev_priv->gpio_mmio_base; - u32 gmbus2; + u32 gmbus2 = 0; + DEFINE_WAIT(wait); + + /* Important: The hw handles only the first bit, so set only one! */ + I915_WRITE(GMBUS4 + reg_offset, gmbus4_irq_en); - ret = wait_for((gmbus2 = I915_READ(GMBUS2 + reg_offset)) & - (GMBUS_SATOER | gmbus2_status), - 50); + for (i = 0; i < msecs_to_jiffies(50) + 1; i++) { + prepare_to_wait(&dev_priv->gmbus_wait_queue, &wait, + TASK_UNINTERRUPTIBLE); + + gmbus2 = I915_READ(GMBUS2 + reg_offset); + if (gmbus2 & (GMBUS_SATOER | gmbus2_status)) + break; + + schedule_timeout(1); + } + finish_wait(&dev_priv->gmbus_wait_queue, &wait); + + I915_WRITE(GMBUS4 + reg_offset, 0); if (gmbus2 & GMBUS_SATOER) return -ENXIO; - - return ret; + if (gmbus2 & gmbus2_status) + return 0; + return -ETIMEDOUT; } static int @@ -239,7 +255,8 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, int ret; u32 val, loop = 0; - ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY); + ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY, + GMBUS_HW_RDY_EN); if (ret) return ret; @@ -283,7 +300,8 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) I915_WRITE(GMBUS3 + reg_offset, val); - ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY); + ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY, + GMBUS_HW_RDY_EN); if (ret) return ret; } @@ -368,7 +386,8 @@ gmbus_xfer(struct i2c_adapter *adapter, if (ret == -ENXIO) goto clear_err; - ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_WAIT_PHASE); + ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_WAIT_PHASE, + GMBUS_HW_WAIT_EN); if (ret == -ENXIO) goto clear_err; if (ret) @@ -385,7 +404,7 @@ gmbus_xfer(struct i2c_adapter *adapter, * We will re-enable it at the start of the next xfer, * till then let it sleep. */ - if (gmbus_wait_hw_status(dev_priv, GMBUS_ACTIVE)) { + if (gmbus_wait_hw_status(dev_priv, GMBUS_ACTIVE, GMBUS_IDLE_EN)) { DRM_DEBUG_KMS("GMBUS [%s] timed out waiting for idle\n", adapter->name); ret = -ETIMEDOUT; @@ -409,7 +428,7 @@ clear_err: * it's slow responding and only answers on the 2nd retry. */ ret = -ENXIO; - if (gmbus_wait_hw_status(dev_priv, GMBUS_ACTIVE)) { + if (gmbus_wait_hw_status(dev_priv, GMBUS_ACTIVE, GMBUS_IDLE_EN)) { DRM_DEBUG_KMS("GMBUS [%s] timed out after NAK\n", adapter->name); ret = -ETIMEDOUT; @@ -472,6 +491,7 @@ int intel_setup_gmbus(struct drm_device *dev) dev_priv->gpio_mmio_base = 0; 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];