Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp3861390pxb; Tue, 17 Nov 2020 05:38:01 -0800 (PST) X-Google-Smtp-Source: ABdhPJyqp5GtCnPHqYS/dl/Bgw6dfcYDJEuJtWNZD9gL5BWjO9/3HqlOCHO4/blhJHFGUUF6ifcR X-Received: by 2002:a17:906:8812:: with SMTP id zh18mr18506656ejb.361.1605620280893; Tue, 17 Nov 2020 05:38:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605620280; cv=none; d=google.com; s=arc-20160816; b=htIrpOyuroTQ2Ft2KqxIDzi88BGV6CFvsw1nhW0jrzXGzgRzHYgQGCpFrfcn/aZN/k qKvLSPynqpcMFoq1uRlB6URC016inqak/NA+YCgqLwplKPqh6C06c6gDX776BjZfxEIF vOPTTlFq18XBlxILTkohIl3awyeAhsDPeyNgSH+urCuQozhd3AWQIVSW86Rbj511kmgM +7GZP02fdp2z5b2me/meNojXSmN/OM+58FDneZ4eb2Zikec55hbU0s3OlGe6UUcNr5fs cmfK444FVDfoAz8zAYl7koGFSTeL1gV211d0vpdojWoFLCP/L1/7rZnn9o5hj7T+KMF4 ja3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=1qnQRwo2d9NAQ/AMfWbht8mtHtFx/tZCnwqTqcuOE5M=; b=uPCPyqhJFpTyBGYD37Tz4Kh/oypEWDqbBDq6jhAAtjY7Jgw+KPEenMlXLrehkExdX4 vUAlpyIkRqfTtssVvbvJDnR1AonE1IeWoIt+d8DRRPFuB62II2/unjOfTZy/rmflYIAz pFJgEUnEZn4Yemn8UqTfFAp4a5Cy1UyzEXlQ3UV1seP3xEoh0ts9QbWz8V27NFXc2Hem BgIiMJOxuwa45PLcsFfJCOH19JShH1sg+KidaZrlfaFdaJmswETjx+AM8yN7O2ym3g+3 3WZ/gQyKDRyB37jUIEF2b1oupsuFLn4NF7s2cfewxqRdeOPqm/iIzrFNDwLASQrSTg2F J4PQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=DWHaxgKQ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id p62si13101966edd.213.2020.11.17.05.37.37; Tue, 17 Nov 2020 05:38:00 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=DWHaxgKQ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732563AbgKQNgR (ORCPT + 99 others); Tue, 17 Nov 2020 08:36:17 -0500 Received: from mail.kernel.org ([198.145.29.99]:47134 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732551AbgKQNgM (ORCPT ); Tue, 17 Nov 2020 08:36:12 -0500 Received: from localhost (83-86-74-64.cable.dynamic.v4.ziggo.nl [83.86.74.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 54590207BC; Tue, 17 Nov 2020 13:36:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1605620170; bh=HJPSa0KmKV95ZybTLaMu/IKpYZrY18GvP37V/Fllc/A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DWHaxgKQSsZMmdPz+R5zKQcnZOHGGPsRuz5UDdZ+AzBUfx43fXjZYFS4ztuQMLV/n yTlHDeGXua79P5hvWU3cFm0DqFQaSqwR/09mAoY/0+nP6LoV0mdDhPG3yHq+6iWQBl WaDSbD2+tZ77cV1EJJonQrJHiITwnM+7knh1Gn5Y= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Ulrich Hecht , Wolfram Sang , Geert Uytterhoeven , Wolfram Sang , Sasha Levin Subject: [PATCH 5.9 122/255] i2c: sh_mobile: implement atomic transfers Date: Tue, 17 Nov 2020 14:04:22 +0100 Message-Id: <20201117122144.879152511@linuxfoundation.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201117122138.925150709@linuxfoundation.org> References: <20201117122138.925150709@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ulrich Hecht [ Upstream commit a49cc1fe9d64a2dc4e19b599204f403e5d25f44b ] Implements atomic transfers to fix reboot/shutdown on r8a7790 Lager and similar boards. Signed-off-by: Ulrich Hecht Tested-by: Wolfram Sang Tested-by: Geert Uytterhoeven [wsa: some whitespace fixing] Signed-off-by: Wolfram Sang Signed-off-by: Sasha Levin --- drivers/i2c/busses/i2c-sh_mobile.c | 86 +++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 20 deletions(-) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index cab7255599991..bdd60770779ad 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -129,6 +129,7 @@ struct sh_mobile_i2c_data { int sr; bool send_stop; bool stop_after_dma; + bool atomic_xfer; struct resource *res; struct dma_chan *dma_tx; @@ -330,13 +331,15 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, enum sh_mobile_i2c_op ret = iic_rd(pd, ICDR); break; case OP_RX_STOP: /* enable DTE interrupt, issue stop */ - iic_wr(pd, ICIC, - ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); + if (!pd->atomic_xfer) + iic_wr(pd, ICIC, + ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK); break; case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */ - iic_wr(pd, ICIC, - ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); + if (!pd->atomic_xfer) + iic_wr(pd, ICIC, + ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); ret = iic_rd(pd, ICDR); iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK); break; @@ -429,7 +432,8 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) if (wakeup) { pd->sr |= SW_DONE; - wake_up(&pd->wait); + if (!pd->atomic_xfer) + wake_up(&pd->wait); } /* defeat write posting to avoid spurious WAIT interrupts */ @@ -581,6 +585,9 @@ static void start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg, pd->pos = -1; pd->sr = 0; + if (pd->atomic_xfer) + return; + pd->dma_buf = i2c_get_dma_safe_msg_buf(pd->msg, 8); if (pd->dma_buf) sh_mobile_i2c_xfer_dma(pd); @@ -637,15 +644,13 @@ static int poll_busy(struct sh_mobile_i2c_data *pd) return i ? 0 : -ETIMEDOUT; } -static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, - struct i2c_msg *msgs, - int num) +static int sh_mobile_xfer(struct sh_mobile_i2c_data *pd, + struct i2c_msg *msgs, int num) { - struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter); struct i2c_msg *msg; int err = 0; int i; - long timeout; + long time_left; /* Wake up device and enable clock */ pm_runtime_get_sync(pd->dev); @@ -662,15 +667,35 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, if (do_start) i2c_op(pd, OP_START); - /* The interrupt handler takes care of the rest... */ - timeout = wait_event_timeout(pd->wait, - pd->sr & (ICSR_TACK | SW_DONE), - adapter->timeout); - - /* 'stop_after_dma' tells if DMA transfer was complete */ - i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg, pd->stop_after_dma); + if (pd->atomic_xfer) { + unsigned long j = jiffies + pd->adap.timeout; + + time_left = time_before_eq(jiffies, j); + while (time_left && + !(pd->sr & (ICSR_TACK | SW_DONE))) { + unsigned char sr = iic_rd(pd, ICSR); + + if (sr & (ICSR_AL | ICSR_TACK | + ICSR_WAIT | ICSR_DTE)) { + sh_mobile_i2c_isr(0, pd); + udelay(150); + } else { + cpu_relax(); + } + time_left = time_before_eq(jiffies, j); + } + } else { + /* The interrupt handler takes care of the rest... */ + time_left = wait_event_timeout(pd->wait, + pd->sr & (ICSR_TACK | SW_DONE), + pd->adap.timeout); + + /* 'stop_after_dma' tells if DMA xfer was complete */ + i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg, + pd->stop_after_dma); + } - if (!timeout) { + if (!time_left) { dev_err(pd->dev, "Transfer request timed out\n"); if (pd->dma_direction != DMA_NONE) sh_mobile_i2c_cleanup_dma(pd); @@ -696,14 +721,35 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, return err ?: num; } +static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, + struct i2c_msg *msgs, + int num) +{ + struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter); + + pd->atomic_xfer = false; + return sh_mobile_xfer(pd, msgs, num); +} + +static int sh_mobile_i2c_xfer_atomic(struct i2c_adapter *adapter, + struct i2c_msg *msgs, + int num) +{ + struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter); + + pd->atomic_xfer = true; + return sh_mobile_xfer(pd, msgs, num); +} + static u32 sh_mobile_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; } static const struct i2c_algorithm sh_mobile_i2c_algorithm = { - .functionality = sh_mobile_i2c_func, - .master_xfer = sh_mobile_i2c_xfer, + .functionality = sh_mobile_i2c_func, + .master_xfer = sh_mobile_i2c_xfer, + .master_xfer_atomic = sh_mobile_i2c_xfer_atomic, }; static const struct i2c_adapter_quirks sh_mobile_i2c_quirks = { -- 2.27.0