Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp3299813pxk; Mon, 21 Sep 2020 10:02:47 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzq5YVq9dLayAP0x3saga6EAMvIJCjILtcN/fy96Ew4j5KCJDiurDSLBk+HCY/G4cxJbC5v X-Received: by 2002:a17:906:4d57:: with SMTP id b23mr413172ejv.496.1600707766978; Mon, 21 Sep 2020 10:02:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1600707766; cv=none; d=google.com; s=arc-20160816; b=yetvb/GzMAvXkF2ME2aftGaeYHX8A1m5L/hAE/gallc9PiudL7SfaaKx6LdDxvtpoh 5Ta9KVXYFJVJwAxDaWGn6nxzW5BkvAUPH0QoThHzHlkJmgwFd7f2ifeG9hZLvzzXq0sc r8f6PSg/eVYGfB1dOf+s04IKkIf51njNAmUolTrClkDeKEv+J08Nu50rRfcjGfqmK5/x NiS5IDQFInk81E7qM5GDLWO3Y/GG3H2jrr5BjodES0UWFWXUybtpoX9hFI8FaDwm8QGM SmAkb0a81wAF8kf0r8adxhBV5uAk9zpKA8CiH6kNqy470hwH5CXU2rUYQPK/9ROlJ3+F JyCA== 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=0ZnvkBuAbAM0Rd9jwH8/89Z53Ye2wPnwD9xkTJnbI9U=; b=jxJNX+HhXNyQ+4JrLL0xgZoszHeibtZqy46OxQQmxTTBrHpuNgSNRC1pVv1rXMOw6A /Qt9oTv3sxyf3vPbvNciF7cWk3Wvqm7ySkB0PqUr2f8DNNznF0mTBkfx4WLRLws+kMoS UqpBIbbYLzQCjGi3EzzumFRTX59JpXFniAGnFwrxLFJe0jc2jvVJ7oYHQPLsGqZetE7R 3Xz9RT770+8sDvhTqbMhPL8q0orn3zMGyXTjeeaitIfYo0YcW8oi7ovicYO2cv8P6JET 6tUSPBsKZahcqRNef8ai9njhPkwsheNpdUsnHDCV3Aciu7WVr/9fxlVBu2sTWF0zu+xk VcuA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="BtdCQu/2"; 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 gs20si8737998ejb.230.2020.09.21.10.02.21; Mon, 21 Sep 2020 10:02:46 -0700 (PDT) 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="BtdCQu/2"; 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 S1730320AbgIUQ7S (ORCPT + 99 others); Mon, 21 Sep 2020 12:59:18 -0400 Received: from mail.kernel.org ([198.145.29.99]:44900 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729152AbgIUQlX (ORCPT ); Mon, 21 Sep 2020 12:41:23 -0400 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 7C05123976; Mon, 21 Sep 2020 16:41:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1600706483; bh=9riOZ9GAoOgxV0Qc8gUkznQnBBID+SRdhaHl6RzsQ/I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BtdCQu/25iNswlUG/9EDqxZEtoOZtIZNewAFdZvoS0ve77dUj/4DT9A4s0jXihb84 9CsJW9R4NXbtXsbTb3PtIxGkynkMYBvvO97Qxygn5gNQjl4RaTChNQgaOUT846PRuG 2p6Ysz/t8nh09E+KtvCyr9o6tBLjw6beK9AH8LDg= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Evan Nimmo , Chris Packham , Andy Shevchenko , Wolfram Sang , Sasha Levin Subject: [PATCH 4.19 23/49] i2c: algo: pca: Reapply i2c bus settings after reset Date: Mon, 21 Sep 2020 18:28:07 +0200 Message-Id: <20200921162035.687689292@linuxfoundation.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200921162034.660953761@linuxfoundation.org> References: <20200921162034.660953761@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: Evan Nimmo [ Upstream commit 0a355aeb24081e4538d4d424cd189f16c0bbd983 ] If something goes wrong (such as the SCL being stuck low) then we need to reset the PCA chip. The issue with this is that on reset we lose all config settings and the chip ends up in a disabled state which results in a lock up/high CPU usage. We need to re-apply any configuration that had previously been set and re-enable the chip. Signed-off-by: Evan Nimmo Reviewed-by: Chris Packham Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang Signed-off-by: Sasha Levin --- drivers/i2c/algos/i2c-algo-pca.c | 35 +++++++++++++++++++++----------- include/linux/i2c-algo-pca.h | 15 ++++++++++++++ 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 0e745f82d6a53..f328de980855d 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -50,8 +50,22 @@ static void pca_reset(struct i2c_algo_pca_data *adap) pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IPRESET); pca_outw(adap, I2C_PCA_IND, 0xA5); pca_outw(adap, I2C_PCA_IND, 0x5A); + + /* + * After a reset we need to re-apply any configuration + * (calculated in pca_init) to get the bus in a working state. + */ + pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IMODE); + pca_outw(adap, I2C_PCA_IND, adap->bus_settings.mode); + pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_ISCLL); + pca_outw(adap, I2C_PCA_IND, adap->bus_settings.tlow); + pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_ISCLH); + pca_outw(adap, I2C_PCA_IND, adap->bus_settings.thi); + + pca_set_con(adap, I2C_PCA_CON_ENSIO); } else { adap->reset_chip(adap->data); + pca_set_con(adap, I2C_PCA_CON_ENSIO | adap->bus_settings.clock_freq); } } @@ -432,13 +446,14 @@ static int pca_init(struct i2c_adapter *adap) " Use the nominal frequency.\n", adap->name); } - pca_reset(pca_data); - clock = pca_clock(pca_data); printk(KERN_INFO "%s: Clock frequency is %dkHz\n", adap->name, freqs[clock]); - pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock); + /* Store settings as these will be needed when the PCA chip is reset */ + pca_data->bus_settings.clock_freq = clock; + + pca_reset(pca_data); } else { int clock; int mode; @@ -505,19 +520,15 @@ static int pca_init(struct i2c_adapter *adap) thi = tlow * min_thi / min_tlow; } + /* Store settings as these will be needed when the PCA chip is reset */ + pca_data->bus_settings.mode = mode; + pca_data->bus_settings.tlow = tlow; + pca_data->bus_settings.thi = thi; + pca_reset(pca_data); printk(KERN_INFO "%s: Clock frequency is %dHz\n", adap->name, clock * 100); - - pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IMODE); - pca_outw(pca_data, I2C_PCA_IND, mode); - pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLL); - pca_outw(pca_data, I2C_PCA_IND, tlow); - pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLH); - pca_outw(pca_data, I2C_PCA_IND, thi); - - pca_set_con(pca_data, I2C_PCA_CON_ENSIO); } udelay(500); /* 500 us for oscillator to stabilise */ diff --git a/include/linux/i2c-algo-pca.h b/include/linux/i2c-algo-pca.h index d03071732db4a..7c522fdd9ea73 100644 --- a/include/linux/i2c-algo-pca.h +++ b/include/linux/i2c-algo-pca.h @@ -53,6 +53,20 @@ #define I2C_PCA_CON_SI 0x08 /* Serial Interrupt */ #define I2C_PCA_CON_CR 0x07 /* Clock Rate (MASK) */ +/** + * struct pca_i2c_bus_settings - The configured PCA i2c bus settings + * @mode: Configured i2c bus mode + * @tlow: Configured SCL LOW period + * @thi: Configured SCL HIGH period + * @clock_freq: The configured clock frequency + */ +struct pca_i2c_bus_settings { + int mode; + int tlow; + int thi; + int clock_freq; +}; + struct i2c_algo_pca_data { void *data; /* private low level data */ void (*write_byte) (void *data, int reg, int val); @@ -64,6 +78,7 @@ struct i2c_algo_pca_data { * For PCA9665, use the frequency you want here. */ unsigned int i2c_clock; unsigned int chip; + struct pca_i2c_bus_settings bus_settings; }; int i2c_pca_add_bus(struct i2c_adapter *); -- 2.25.1