From patchwork Mon May 26 09:20:12 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: George Cherian X-Patchwork-Id: 4240741 Return-Path: X-Original-To: patchwork-linux-omap@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E28F69F1E7 for ; Mon, 26 May 2014 09:22:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 01EC92016C for ; Mon, 26 May 2014 09:22:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id EB98920170 for ; Mon, 26 May 2014 09:22:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752140AbaEZJWn (ORCPT ); Mon, 26 May 2014 05:22:43 -0400 Received: from devils.ext.ti.com ([198.47.26.153]:58436 "EHLO devils.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752066AbaEZJWA (ORCPT ); Mon, 26 May 2014 05:22:00 -0400 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by devils.ext.ti.com (8.13.7/8.13.7) with ESMTP id s4Q9LwmO015548; Mon, 26 May 2014 04:21:58 -0500 Received: from DLEE71.ent.ti.com (dlee71.ent.ti.com [157.170.170.114]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id s4Q9LwwX010008; Mon, 26 May 2014 04:21:58 -0500 Received: from dlep33.itg.ti.com (157.170.170.75) by DLEE71.ent.ti.com (157.170.170.114) with Microsoft SMTP Server id 14.3.174.1; Mon, 26 May 2014 04:21:58 -0500 Received: from george-pc.apr.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep33.itg.ti.com (8.14.3/8.13.8) with ESMTP id s4Q9Lf0I006391; Mon, 26 May 2014 04:21:56 -0500 From: George Cherian To: , , CC: , , , , George Cherian Subject: [PATCH v6 5/5] usb: musb: dsps: Add the sw_babble_control() and Enable for newer silicon Date: Mon, 26 May 2014 14:50:12 +0530 Message-ID: <1401096012-6895-6-git-send-email-george.cherian@ti.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1401096012-6895-1-git-send-email-george.cherian@ti.com> References: <1401096012-6895-1-git-send-email-george.cherian@ti.com> MIME-Version: 1.0 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add sw_babble_control() logic to differentiate between transient babble and real babble condition. Also add the SW babble control register definitions. Babble control register logic is implemented in the latest revision of AM335x. Find whether we are running on newer silicon. The babble control register reads 0x4 by default in newer silicon as opposed to 0 in old versions of AM335x. Based on this enable the sw babble control logic. Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 89 +++++++++++++++++++++++++++++++++++++++++--- drivers/usb/musb/musb_regs.h | 7 ++++ 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index f6f3087..01543a9 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -136,6 +136,7 @@ struct dsps_glue { const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ struct timer_list timer; /* otg_workaround timer */ unsigned long last_timer; /* last timer data for each instance */ + bool sw_babble_enabled; struct dsps_context context; struct debugfs_regset32 regset; @@ -469,6 +470,19 @@ static int dsps_musb_init(struct musb *musb) val &= ~(1 << wrp->otg_disable); dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); + /* + * Check whether the dsps version has babble control enabled. + * In latest silicon revision the babble control logic is enabled. + * If MUSB_BABBLE_CTL returns 0x4 then we have the babble control + * logic enabled. + */ + val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + if (val == MUSB_BABBLE_RCV_DISABLE) { + glue->sw_babble_enabled = true; + val |= MUSB_BABBLE_SW_SESSION_CTRL; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); + } + ret = dsps_musb_dbg_init(musb, glue); if (ret) return ret; @@ -536,19 +550,82 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) return 0; } +static bool sw_babble_control(struct musb *musb) +{ + u8 babble_ctl; + bool session_restart = false; + + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n", + babble_ctl); + /* + * check line monitor flag to check whether babble is + * due to noise + */ + dev_dbg(musb->controller, "STUCK_J is %s\n", + babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset"); + + if (babble_ctl & MUSB_BABBLE_STUCK_J) { + int timeout = 10; + + /* + * babble is due to noise, then set transmit idle (d7 bit) + * to resume normal operation + */ + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl); + + /* wait till line monitor flag cleared */ + dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n"); + do { + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + udelay(1); + } while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--); + + /* check whether stuck_at_j bit cleared */ + if (babble_ctl & MUSB_BABBLE_STUCK_J) { + /* + * real babble condition has occurred + * restart the controller to start the + * session again + */ + dev_dbg(musb->controller, "J not cleared, misc (%x)\n", + babble_ctl); + session_restart = true; + } + } else { + session_restart = true; + } + + return session_restart; +} + static int dsps_musb_reset(struct musb *musb) { struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; + int session_restart = 0; - dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); - usleep_range(100, 200); - usb_phy_shutdown(musb->xceiv); - usleep_range(100, 200); - usb_phy_init(musb->xceiv); + if (glue->sw_babble_enabled) + session_restart = sw_babble_control(musb); + /* + * In case of new silicon version babble condition can be recovered + * without resetting the MUSB. But for older silicon versions, MUSB + * reset is needed + */ + if (session_restart || !glue->sw_babble_enabled) { + dev_info(musb->controller, "Restarting MUSB to recover from Babble\n"); + dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); + usleep_range(100, 200); + usb_phy_shutdown(musb->xceiv); + usleep_range(100, 200); + usb_phy_init(musb->xceiv); + session_restart = 1; + } - return 0; + return !session_restart; } static struct musb_platform_ops dsps_ops = { diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 03f2655..b9bcda5 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -72,6 +72,12 @@ #define MUSB_DEVCTL_HR 0x02 #define MUSB_DEVCTL_SESSION 0x01 +/* BABBLE_CTL */ +#define MUSB_BABBLE_FORCE_TXIDLE 0x80 +#define MUSB_BABBLE_SW_SESSION_CTRL 0x40 +#define MUSB_BABBLE_STUCK_J 0x20 +#define MUSB_BABBLE_RCV_DISABLE 0x04 + /* MUSB ULPI VBUSCONTROL */ #define MUSB_ULPI_USE_EXTVBUS 0x01 #define MUSB_ULPI_USE_EXTVBUSIND 0x02 @@ -246,6 +252,7 @@ */ #define MUSB_DEVCTL 0x60 /* 8 bit */ +#define MUSB_BABBLE_CTL 0x61 /* 8 bit */ /* These are always controlled through the INDEX register */ #define MUSB_TXFIFOSZ 0x62 /* 8-bit (see masks) */