Received: by 2002:a05:6a10:2726:0:0:0:0 with SMTP id ib38csp1284671pxb; Thu, 24 Mar 2022 16:53:36 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyblf543dvChREbzMaRAOMFm2xhj6FEePfEVZTSiZwsg35pE8WosQPfNEX0gApDOyvNP6jv X-Received: by 2002:a17:90b:3b89:b0:1c6:56a2:1397 with SMTP id pc9-20020a17090b3b8900b001c656a21397mr9257812pjb.239.1648166016063; Thu, 24 Mar 2022 16:53:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1648166016; cv=none; d=google.com; s=arc-20160816; b=vj+iDtD6DUkLqF1XWRPOotqdqWxP0qvRaSc3NBdxwV41CelVcb8VmujkbioQeimW3o PtqCCkc8eezqNZiCFyQkS0qHAa6vN4MlqsNpRz/JQWYlK7KvAS/eJ16oEWGzmbUn5i+P CnIdKtl5Gi+S9IdqDPIPsJrZ6MZ4gg/oFILuv30HPxX/14Fr80itl3/8wsjPIf4BPzv+ wEqjgxA7kez+v/lxrZO+6niNfewkolG8fjjsxd6lWzQjcae6YZ5YuswgS9RNLP/poa1P haWPaeRMsWiB1zYiP942cVWtHPdjULcbtilYJiQwrR/HkuFe0xlaRSm/2l9Wh+3XCyB/ Wweg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:dkim-signature; bh=a4dvkjPYRELhzllIpA0f3GYBFS79Xmkqa9OQbMC0sQc=; b=ZsBIpPPOsZkbTGxacTZWHa2iAXRV39XNDD1eckPNOTrSNASzmMLdZC7lH8VSIN1hD7 Zpb5a39qGrsSUvY7hxvudA2TCMnmLDl8p+bUN3+d8ev6m049EjHBQR/XlcRcxzJPzg36 dmildqFT5k2n7/VeDM6fO9PFUFgr4J7zoQO5CBHm1lij/t1BA0gEJlAXbJA55Y03zYEe XWqHGFIv5SQdg3+Dz5UFnlN1mN+WYMODod02n2ybSayxAIyE7FjAmU7dphysX8g1RdM8 Xh7MYUuhv/rVpmS6wUP7n5gSMjIGOQ5LNicT3/IMx+BQIehqWlvfHKZ+Jf9S7foL9wEX 9nVQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@9elements.com header.s=google header.b=BKV9SqrL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=9elements.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id n17-20020a170902d2d100b00153b2d164cbsi790656plc.211.2022.03.24.16.53.22; Thu, 24 Mar 2022 16:53:36 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@9elements.com header.s=google header.b=BKV9SqrL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=9elements.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242985AbiCWMnW (ORCPT + 99 others); Wed, 23 Mar 2022 08:43:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42636 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242871AbiCWMnR (ORCPT ); Wed, 23 Mar 2022 08:43:17 -0400 Received: from mail-pl1-x634.google.com (mail-pl1-x634.google.com [IPv6:2607:f8b0:4864:20::634]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5892F7B554 for ; Wed, 23 Mar 2022 05:41:47 -0700 (PDT) Received: by mail-pl1-x634.google.com with SMTP id g3so1403191plo.6 for ; Wed, 23 Mar 2022 05:41:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=9elements.com; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=a4dvkjPYRELhzllIpA0f3GYBFS79Xmkqa9OQbMC0sQc=; b=BKV9SqrLcCplUfT86q4wICSAi929UqoXsOYEw5LTO37EfKdTN2GtR664bQ3vyjorSZ umEsHvA9Hf69ZUhSOSj2bHwQo7CoYe2dMR3VY8RSVgE6oCwkDjPS2kQtFuqphIyDUj4Q JhPZpVN5veA4MJL1CHALKuLy77VIaGfl3oAydDYdTtl5+oro1O72+9Utv02ZjSYfJiWl 4Tlb1i3xphsC1I6jo19owV9XBgkkZvTCV2/LwprTZvQfKG/ahY//EyAZOMJLAxhZ75+s SXKAirhz68DkHMz6X8Gkd06lyWj3oYWLZMxK9/aiYcb0HsIC1hoo9f1GvlkvNeJo8Nlb +mOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=a4dvkjPYRELhzllIpA0f3GYBFS79Xmkqa9OQbMC0sQc=; b=T5N2mMYm8hBm2kBOt3+hrxOmtW9lnhCvirK0Qp7ue6+mh0IS3zQlJRFOumSYvRfp8k Edoh4U30HPncr9GncireALIpKJVTdwOzfqmpSgBmsMrgtvE2/Ls1TppuEU9lx9WQyWU1 ix+MJlh7ip0GePhmX+EqT0DMsl6LCCKNHTUnWx4qmxJF0i/QeP2tNdOVUMcr1ugjld7+ hTAtZzuDf65iKRUgqzorR5LxrM47dsiEguHvp3SyJrN5wTefwEG7ra2CoMwiG38BKTV8 blu3c4HrPnBMoDTN8kpRTW0eFUWAIqln/Eh6H+SXMJRnCKy94P+VvqQBIYTbKTypzlhk CCEA== X-Gm-Message-State: AOAM53206YNd5DaARuM1G8VmftO2FiFLkIiMJyvdP58ulF1Wa9rB1711 HVcEiDCuSeBFGaCKA6dvVupS7en7OU6AIavXlljF7g== X-Received: by 2002:a17:902:e545:b0:154:4d5b:2006 with SMTP id n5-20020a170902e54500b001544d5b2006mr16865421plf.94.1648039306634; Wed, 23 Mar 2022 05:41:46 -0700 (PDT) MIME-Version: 1.0 References: <20220216074613.235725-1-patrick.rudolph@9elements.com> <20220216074613.235725-3-patrick.rudolph@9elements.com> <5658941a-bf81-4ecf-3317-82d2a8244021@axentia.se> In-Reply-To: <5658941a-bf81-4ecf-3317-82d2a8244021@axentia.se> From: Patrick Rudolph Date: Wed, 23 Mar 2022 13:41:35 +0100 Message-ID: Subject: Re: [v6 2/3] i2c: muxes: pca954x: Add MAX735x/MAX736x support To: Peter Rosin Cc: linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Peter, thanks for the review. The MAX7358 has indeed the same registers as the MAX7357, but they need to be "unlocked" by sending a magic sequence first. As this isn't implemented by the driver it behaves like the MAX7356 with a single register. The additional registers can be hidden again by setting a bit in the config space. Which wording would you prefer to describe this feature? I'll change it to maxim_enhanced_mode. Regards, Patrick On Sat, Mar 19, 2022 at 3:41 PM Peter Rosin wrote: > > Hi! > > Sorry for the slow review and thanks for your patience... > > On 2022-02-16 08:46, Patrick Rudolph wrote: > > Add support for the following Maxim chips using the existing PCA954x > > driver: > > - MAX7356 > > - MAX7357 > > - MAX7358 > > - MAX7367 > > - MAX7368 > > - MAX7369 > > > > All added Maxim chips behave like the PCA954x, where a single SMBUS byte > > write selects up to 8 channels to be bridged to the primary bus. > > > > The MAX7357 exposes 6 additional registers at Power-On-Reset and is > > MAX7358 also has the same enhanced mode as the 7357, no? > > And what do you mean that they are exposed at POR? I can see why they > are not exposed /before/ POR, but are they ever /not/ exposed? If they > are always exposed when the chip is "alive", then I suggest that the > POR wording is dropped, otherwise that the above is reworded to > describe when the register are no longer exposed. > > > configured to: > > - Disabled interrupts on bus locked up detection > > - Enable bus locked-up clearing > > - Disconnect only locked bus instead of all channels > > > > While the MAX7357/MAX7358 have interrupt support, they don't act as > > interrupt controller like the PCA9545 does. Thus don't enable IRQ support > > and handle them like the PCA9548. > > > > Tested using the MAX7357 and verified that the stalled bus is disconnected > > while the other channels remain operational. > > > > Signed-off-by: Patrick Rudolph > > --- > > drivers/i2c/muxes/Kconfig | 4 +- > > drivers/i2c/muxes/i2c-mux-pca954x.c | 92 +++++++++++++++++++++++++++-- > > 2 files changed, 90 insertions(+), 6 deletions(-) > > > > diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig > > index 1708b1a82da2..2ac99d044199 100644 > > --- a/drivers/i2c/muxes/Kconfig > > +++ b/drivers/i2c/muxes/Kconfig > > @@ -65,11 +65,11 @@ config I2C_MUX_PCA9541 > > will be called i2c-mux-pca9541. > > > > config I2C_MUX_PCA954x > > - tristate "NXP PCA954x and PCA984x I2C Mux/switches" > > + tristate "NXP PCA954x/PCA984x and Maxim MAX735x/MAX736x I2C Mux/switches" > > depends on GPIOLIB || COMPILE_TEST > > help > > If you say yes here you get support for the NXP PCA954x > > - and PCA984x I2C mux/switch devices. > > + and PCA984x and Maxim MAX735x/MAX736x I2C mux/switch devices. > > and and and... :-) Maybe like this? > > If you say yes here you get support for NXP PCA954x/PCA984x > and Maxim MAX735x/MAX736x I2C mux/switch devices. > > > This driver can also be built as a module. If so, the module > > will be called i2c-mux-pca954x. > > diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c > > index 4ad665757dd8..33b9a6a1fffa 100644 > > --- a/drivers/i2c/muxes/i2c-mux-pca954x.c > > +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c > > @@ -4,6 +4,7 @@ > > * > > * Copyright (c) 2008-2009 Rodolfo Giometti > > * Copyright (c) 2008-2009 Eurotech S.p.A. > > + * Copyright (c) 2022 Patrick Rudolph > > * > > * This module supports the PCA954x and PCA984x series of I2C multiplexer/switch > > * chips made by NXP Semiconductors. > > @@ -11,6 +12,12 @@ > > * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547, > > * PCA9548, PCA9846, PCA9847, PCA9848 and PCA9849. > > * > > + * It's also compatible to Maxims MAX735x I2C switch chips, which are controlled > > + * as the NXP PCA9548 and the MAX736x chips that act like the PCA9544. > > + * > > + * This includes the: > > + * MAX7356, MAX7357, MAX7358, MAX7367, MAX7368 and MAX7369 > > + * > > * These chips are all controlled via the I2C bus itself, and all have a > > * single 8-bit register. The upstream "parent" bus fans out to two, > > * four, or eight downstream busses or channels; which of these > > @@ -50,7 +57,30 @@ > > > > #define PCA954X_IRQ_OFFSET 4 > > > > +/* > > + * MAX7357 exposes 7 registers on POR which allow to configure additional > > + * features. Disable interrupts, enable bus locked-up clearing, > > + * isolate only the locked channel instead of all channels. > > Same MAX7358 and POR comments as above. > > The way I understands things are: > > * MAX7357/MAX7358 exposes 7 registers which allow setup of > * enhanced mode features. The first of these registers is the > * switch control register that is present in some form on all > * chips supported by this driver. > * The second register is the configuration register, which allows > * to configure additional features. E.g. disable interrupts, > * enable bus locked-up clearing and isolate only the locked > * channel instead of all channels. > * The remaining 5 registers are left as is by this driver. > > > + */ > > +#define MAX7357_CONF_INT_ENABLE BIT(0) > > +#define MAX7357_CONF_FLUSH_OUT BIT(1) > > +#define MAX7357_CONF_RELEASE_INT BIT(2) > > +#define MAX7357_CONF_LOCK_UP_CLEAR BIT(3) > > +#define MAX7357_CONF_DISCON_SINGLE_CHAN BIT(4) > > +#define MAX7357_CONF_BUS_LOCKUP_DETECTION BIT(5) > > +#define MAX7357_CONF_ENABLE_BASIC_MODE BIT(6) > > +#define MAX7357_CONF_PRECONNECT_TEST BIT(7) > > + > > +#define MAX7357_CONF_DEFAULTS (MAX7357_CONF_FLUSH_OUT | \ > > + MAX7357_CONF_DISCON_SINGLE_CHAN) > > + > > enum pca_type { > > + max_7367, > > + max_7368, > > + max_7369, > > + max_7356, > > + max_7357, > > + max_7358, > > pca_9540, > > pca_9542, > > pca_9543, > > @@ -69,6 +99,7 @@ struct chip_desc { > > u8 nchans; > > u8 enable; /* used for muxes only */ > > u8 has_irq; > > + u8 max7357; > > Perhaps maxim_enhanced_mode is a better name? > > > enum muxtype { > > pca954x_ismux = 0, > > pca954x_isswi > > @@ -90,8 +121,42 @@ struct pca954x { > > raw_spinlock_t lock; > > }; > > > > -/* Provide specs for the PCA954x types we know about */ > > +/* Provide specs for the PCA954x and MAX735x types we know about */ > > static const struct chip_desc chips[] = { > > + [max_7356] = { > > + .nchans = 8, > > + .muxtype = pca954x_isswi, > > + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, > > + }, > > + [max_7357] = { > > + .nchans = 8, > > + .muxtype = pca954x_isswi, > > + .max7357 = 1, > > + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, > > + }, > > + [max_7358] = { > > + .nchans = 8, > > + .muxtype = pca954x_isswi, > > + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, > > + }, > > + [max_7367] = { > > + .nchans = 4, > > + .muxtype = pca954x_isswi, > > + .has_irq = 1, > > + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, > > + }, > > + [max_7368] = { > > + .nchans = 4, > > + .muxtype = pca954x_isswi, > > + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, > > + }, > > + [max_7369] = { > > + .nchans = 4, > > + .enable = 0x4, > > + .muxtype = pca954x_ismux, > > + .has_irq = 1, > > + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, > > + }, > > [pca_9540] = { > > .nchans = 2, > > .enable = 0x4, > > @@ -177,6 +242,12 @@ static const struct chip_desc chips[] = { > > }; > > > > static const struct i2c_device_id pca954x_id[] = { > > + { "max7356", max_7356 }, > > + { "max7357", max_7357 }, > > + { "max7358", max_7358 }, > > + { "max7367", max_7367 }, > > + { "max7368", max_7368 }, > > + { "max7369", max_7369 }, > > { "pca9540", pca_9540 }, > > { "pca9542", pca_9542 }, > > { "pca9543", pca_9543 }, > > @@ -194,6 +265,12 @@ static const struct i2c_device_id pca954x_id[] = { > > MODULE_DEVICE_TABLE(i2c, pca954x_id); > > > > static const struct of_device_id pca954x_of_match[] = { > > + { .compatible = "maxim,max7356", .data = &chips[max_7356] }, > > + { .compatible = "maxim,max7357", .data = &chips[max_7357] }, > > + { .compatible = "maxim,max7358", .data = &chips[max_7358] }, > > + { .compatible = "maxim,max7367", .data = &chips[max_7367] }, > > + { .compatible = "maxim,max7368", .data = &chips[max_7368] }, > > + { .compatible = "maxim,max7369", .data = &chips[max_7369] }, > > { .compatible = "nxp,pca9540", .data = &chips[pca_9540] }, > > { .compatible = "nxp,pca9542", .data = &chips[pca_9542] }, > > { .compatible = "nxp,pca9543", .data = &chips[pca_9543] }, > > @@ -401,9 +478,16 @@ static int pca954x_init(struct i2c_client *client, struct pca954x *data) > > else > > data->last_chan = 0; /* Disconnect multiplexer */ > > > > - ret = i2c_smbus_write_byte(client, data->last_chan); > > - if (ret < 0) > > - data->last_chan = 0; > > + if (data->chip->max7357) { > > + ret = i2c_smbus_write_byte_data(client, data->last_chan, > > + MAX7357_CONF_DEFAULTS); > > + if (ret < 0) > > + data->last_chan = 0; > > + } else { > > + ret = i2c_smbus_write_byte(client, data->last_chan); > > + if (ret < 0) > > + data->last_chan = 0; > > + } > > > > return ret; > > } > > The actual code is simple enough, and looks good. > > Cheers, > Peter