From patchwork Fri Oct 7 15:21:02 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pantelis Antoniou X-Patchwork-Id: 9366387 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7C7A36075E for ; Fri, 7 Oct 2016 15:33:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6CD12296FD for ; Fri, 7 Oct 2016 15:33:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5F4FE29702; Fri, 7 Oct 2016 15:33:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BC8A5296FD for ; Fri, 7 Oct 2016 15:33:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756849AbcJGPd0 (ORCPT ); Fri, 7 Oct 2016 11:33:26 -0400 Received: from mail-wm0-f45.google.com ([74.125.82.45]:33051 "EHLO mail-wm0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756762AbcJGPXa (ORCPT ); Fri, 7 Oct 2016 11:23:30 -0400 Received: by mail-wm0-f45.google.com with SMTP id f193so5874392wmg.0 for ; Fri, 07 Oct 2016 08:23:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=konsulko.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=/s2kCmv9cpzye491w99slbCKXW0WgF3z8ld0uVAZwyU=; b=e4US64EOuNe3MND5cvQU3Cyj8o24NnO8AWkdH30wbhTcJ2sfPQcIxN4LanNVLVt36b CcCu8KwJ+KGpbY3wQi+6dCMq8KPrVpj9wbcbe8BKNJYL1EqIufeZa9nMG8iMtI/tdmU5 veNDphLQvxJHqDkwfbi9iNaxHlxtfOSFal9UM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=/s2kCmv9cpzye491w99slbCKXW0WgF3z8ld0uVAZwyU=; b=LrAUusAw9Um+dQ0lNmqfhlrMP6swGTJ1XaKRSoInuoFbxhK9B387EndVX11kdFdLju kK1SFC2bn1gGmS0Uo3UvIVXfy/duoShXws3Cc5Dj9sCLN80w60gDjWi+ZGls+/dYJBTR a42RQpfCe9bSoY9ExzTaxeqccEZyL8L76G3kCw9kpRzbpsrAJuVewkAjxAriGdUXVavT SVCntfMuTfW4+bjcgG9n8H1YAREpWZg9UrTVmQ+MppaHEq58JFTv+3WPAfOh6YyY1a/1 lNG/O/iD5s8+/eLBO/FwHYztT15XedRzbBc87evZO6bLbNBWtrbIU8+dk1eSSX9pI1hm osgQ== X-Gm-Message-State: AA6/9Rn6dB8ZMTFdVAcVzLdIviHmrs7UoD5/cK/FzlbSl1D3gb4hsprLJGlTH/e0tRnXdQ== X-Received: by 10.28.128.19 with SMTP id b19mr20403383wmd.82.1475853808929; Fri, 07 Oct 2016 08:23:28 -0700 (PDT) Received: from localhost.localdomain ([195.97.110.117]) by smtp.gmail.com with ESMTPSA id n5sm20048269wjv.35.2016.10.07.08.23.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 07 Oct 2016 08:23:28 -0700 (PDT) From: Pantelis Antoniou To: Lee Jones Cc: Linus Walleij , Alexandre Courbot , Rob Herring , Mark Rutland , Frank Rowand , Wolfram Sang , Richard Purdie , Jacek Anaszewski , Jean Delvare , Peter Rosin , Avirup Banerjee , Georgi Vlaev , Guenter Roeck , JawaharBalaji Thirumalaisamy , Pantelis Antoniou , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-leds@vger.kernel.org, linux-hwmon@vger.kernel.org Subject: [PATCH 03/10] i2c/muxes: Juniper I2CS RE mux Date: Fri, 7 Oct 2016 18:21:02 +0300 Message-Id: <1475853669-22480-4-git-send-email-pantelis.antoniou@konsulko.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1475853669-22480-1-git-send-email-pantelis.antoniou@konsulko.com> References: <1475853669-22480-1-git-send-email-pantelis.antoniou@konsulko.com> Sender: linux-hwmon-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Georgi Vlaev Add support for Juniper I2C Slave RE multiplexer driver. This I2C multiplexer driver allows the RE to access some of the FPC I2C buses. It's compatible only with the FPC variant of the I2CS. Signed-off-by: Georgi Vlaev Signed-off-by: Guenter Roeck [Ported from Juniper kernel] Signed-off-by: Pantelis Antoniou --- drivers/i2c/muxes/Kconfig | 10 +++ drivers/i2c/muxes/Makefile | 1 + drivers/i2c/muxes/i2c-mux-i2cs.c | 155 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 drivers/i2c/muxes/i2c-mux-i2cs.c diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index f45a9cb..c95380d 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -30,6 +30,16 @@ config I2C_MUX_GPIO This driver can also be built as a module. If so, the module will be called i2c-mux-gpio. +config I2C_MUX_I2CS + tristate "Juniper I2C Slave MFD client RE multiplexer" + depends on MFD_JUNIPER_I2CS + help + Select this to enable the Juniper I2C Slave RE multiplexer driver + on the relevant Juniper platforms. + + This driver can also be built as a module. If so, the module + will be called i2c-mux-i2cs. + config I2C_MUX_PCA9541 tristate "NXP PCA9541 I2C Master Selector" help diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile index 78d8cba..45b4287 100644 --- a/drivers/i2c/muxes/Makefile +++ b/drivers/i2c/muxes/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE) += i2c-arb-gpio-challenge.o obj-$(CONFIG_I2C_DEMUX_PINCTRL) += i2c-demux-pinctrl.o obj-$(CONFIG_I2C_MUX_GPIO) += i2c-mux-gpio.o +obj-$(CONFIG_I2C_MUX_I2CS) += i2c-mux-i2cs.o obj-$(CONFIG_I2C_MUX_PCA9541) += i2c-mux-pca9541.o obj-$(CONFIG_I2C_MUX_PCA954x) += i2c-mux-pca954x.o obj-$(CONFIG_I2C_MUX_PINCTRL) += i2c-mux-pinctrl.o diff --git a/drivers/i2c/muxes/i2c-mux-i2cs.c b/drivers/i2c/muxes/i2c-mux-i2cs.c new file mode 100644 index 0000000..c498a44 --- /dev/null +++ b/drivers/i2c/muxes/i2c-mux-i2cs.c @@ -0,0 +1,155 @@ +/* + * Juniper Networks I2CS RE mux driver + * + * Copyright (C) 2012, 2013, 2014 Juniper Networks. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MISC_IO_RE_EN 0x01 + +/* + * Read/write to mux register. + * Don't use i2c_transfer()/i2c_smbus_xfer() + * for this as they will try to lock adapter a second time + */ +static int i2cs_mux_read_byte(struct i2c_client *client, + u8 offset, u8 *val) +{ + struct i2c_msg msg[2]; + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = &offset; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].len = 1; + msg[1].buf = val; + + return client->adapter->algo->master_xfer(client->adapter, msg, 2); +} + +static int i2cs_mux_write_byte(struct i2c_client *client, u8 offset, u8 val) +{ + struct i2c_msg msg; + char buf[2]; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 2; + buf[0] = offset; + buf[1] = val; + msg.buf = buf; + + return client->adapter->algo->master_xfer(client->adapter, &msg, 1); +} + +static int i2cs_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + int ret; + u8 val = 0; + struct i2c_client *client = i2c_mux_priv(muxc); + + ret = i2cs_mux_read_byte(client, I2CS_MISC_IO, &val); + if (ret < 0) + return ret; + + val |= MISC_IO_RE_EN; + ret = i2cs_mux_write_byte(client, I2CS_MISC_IO, val); + + return ret; +} + +static int i2cs_mux_deselect(struct i2c_mux_core *muxc, u32 chan) +{ + int ret; + u8 val = 0; + struct i2c_client *client = i2c_mux_priv(muxc); + + ret = i2cs_mux_read_byte(client, I2CS_MISC_IO, &val); + if (ret < 0) + return ret; + + val &= ~MISC_IO_RE_EN; + ret = i2cs_mux_write_byte(client, I2CS_MISC_IO, val); + + return 0; +} + +static int i2cs_mux_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct i2c_client *client; + struct i2c_mux_core *muxc; + int ret; + + if (!dev->parent) + return -ENODEV; + + client = i2c_verify_client(dev->parent); + if (!client) + return -ENODEV; + + muxc = i2c_mux_alloc(client->adapter, &client->dev, 1, 0, 0, + i2cs_mux_select, i2cs_mux_deselect); + if (!muxc) + return -ENOMEM; + muxc->priv = client; + + ret = i2c_mux_add_adapter(muxc, 0, 0, 0); + if (ret) + return ret; + + platform_set_drvdata(pdev, muxc); + + return 0; +} + +static int i2cs_mux_remove(struct platform_device *pdev) +{ + i2c_mux_del_adapters(platform_get_drvdata(pdev)); + + return 0; +} + +static const struct of_device_id i2cs_mux_of_match[] = { + { .compatible = "jnx,i2c-mux-i2cs", }, + {}, +}; +MODULE_DEVICE_TABLE(of, i2cs_mux_of_match); + +static struct platform_driver i2cs_mux_driver = { + .driver = { + .name = "i2c-mux-i2cs", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(i2cs_mux_of_match), + }, + .probe = i2cs_mux_probe, + .remove = i2cs_mux_remove, +}; +module_platform_driver(i2cs_mux_driver); + +MODULE_DESCRIPTION("Juniper Networks I2CS RE Mux driver"); +MODULE_AUTHOR("Georgi Vlaev "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:i2c-mux-i2cs");