From patchwork Thu Aug 8 18:35:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mary Strodl X-Patchwork-Id: 13758057 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 80C54C52D7D for ; Thu, 8 Aug 2024 18:36:06 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 01F686B00A0; Thu, 8 Aug 2024 14:36:06 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id F1D5B6B00A1; Thu, 8 Aug 2024 14:36:05 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id DB3E66B00A2; Thu, 8 Aug 2024 14:36:05 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0010.hostedemail.com [216.40.44.10]) by kanga.kvack.org (Postfix) with ESMTP id C22F66B00A0 for ; Thu, 8 Aug 2024 14:36:05 -0400 (EDT) Received: from smtpin16.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id 894644161F for ; Thu, 8 Aug 2024 18:36:05 +0000 (UTC) X-FDA: 82429932690.16.085AD45 Received: from greygoose-centos7.csh.rit.edu (greygoose-centos7.csh.rit.edu [129.21.49.170]) by imf16.hostedemail.com (Postfix) with ESMTP id BFA9E18001F for ; Thu, 8 Aug 2024 18:36:02 +0000 (UTC) Authentication-Results: imf16.hostedemail.com; dkim=pass header.d=csh.rit.edu header.s=mail header.b=Xn7E7UcE; dmarc=pass (policy=none) header.from=csh.rit.edu; spf=pass (imf16.hostedemail.com: domain of mstrodl@csh.rit.edu designates 129.21.49.170 as permitted sender) smtp.mailfrom=mstrodl@csh.rit.edu ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1723142114; a=rsa-sha256; cv=none; b=DS1HULNwQQhfcxYEXFw7TpeVCJshErt3HDzxco7nt6c5xsXY6CzkZaGvaGd5OHTx4q6ulY eKjrj/2pvq7/uUD4Q8odVNY3YAOIa79q/mdsAvihwqHd72b2reBJG+vON3UfbQeyUTrxEc bapQZNisxfK61nDY7x+jAcOQqXfKddQ= ARC-Authentication-Results: i=1; imf16.hostedemail.com; dkim=pass header.d=csh.rit.edu header.s=mail header.b=Xn7E7UcE; dmarc=pass (policy=none) header.from=csh.rit.edu; spf=pass (imf16.hostedemail.com: domain of mstrodl@csh.rit.edu designates 129.21.49.170 as permitted sender) smtp.mailfrom=mstrodl@csh.rit.edu ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1723142114; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=jhfmkDnY+2qXywiXv+uolzFwNAebJ+uWy+yOgBd3yz4=; b=2hpCVEGaZQK04m0B3A5PRPhQMs0jDtiSs4l3CvYDjJPKS6gVQkagiALHmWevn4gaxL4vZ5 w1wtcO7a+lDKOf7jpYuk9+rKvtWU8D1Dw6bsoyItaC94gJPwLTx/jPong3CgN1h1FZzrn9 9GsTYOXya7NflboLy5/gDq3D/S1I+TU= Received: from localhost (localhost [127.0.0.1]) by greygoose-centos7.csh.rit.edu (Postfix) with ESMTP id D7752456D91E; Thu, 8 Aug 2024 14:36:01 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=csh.rit.edu; h= content-transfer-encoding:mime-version:references:in-reply-to :x-mailer:message-id:date:date:subject:subject:from:from :received:received; s=mail; t=1723142161; x=1724956562; bh=d35Z1 ZJLNZsjqRNLG/h2LEXIWzUn4xuN6K7xgHXBkFI=; b=Xn7E7UcEH+7x0Uliq1Kdd 0vzrQ2mfI/rTnLueyzsjR0yemUhpLOL2jBPbANgHgTIJ2X3g0m6LmK09K7uzRGPr 2l39qIQHtLasigRyVb/Fl0bNhpzCPr0Olq75k2ji9sPL40DwgFaiw2T7pr0xOKnV 5EqieAks+8m4LlOIb4lfeE= X-Virus-Scanned: amavisd-new at csh.rit.edu Received: from greygoose-centos7.csh.rit.edu ([127.0.0.1]) by localhost (mail.csh.rit.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id CUu_JpEwKeQw; Thu, 8 Aug 2024 14:36:01 -0400 (EDT) Received: from freedom.csh.rit.edu (freedom.csh.rit.edu [129.21.49.182]) by greygoose-centos7.csh.rit.edu (Postfix) with ESMTP id ACEA74140103; Thu, 8 Aug 2024 14:36:00 -0400 (EDT) From: Mary Strodl To: linux-kernel@vger.kernel.org Cc: akpm@linux-foundation.org, urezki@gmail.com, hch@infradead.org, linux-mm@kvack.org, lee@kernel.org, andi.shyti@kernel.org, linux-i2c@vger.kernel.org, s.hauer@pengutronix.de, christian.gmeiner@gmail.com, Mary Strodl Subject: [PATCH v3 2/2] i2c: Add Congatec CGEB I2C driver Date: Thu, 8 Aug 2024 14:35:26 -0400 Message-ID: <20240808183527.3950120-3-mstrodl@csh.rit.edu> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240808183527.3950120-1-mstrodl@csh.rit.edu> References: <20240808183527.3950120-1-mstrodl@csh.rit.edu> MIME-Version: 1.0 X-Rspamd-Queue-Id: BFA9E18001F X-Rspam-User: X-Rspamd-Server: rspam05 X-Stat-Signature: ajcffkien6tpx7bu9f9cxkcty9yzjah6 X-HE-Tag: 1723142162-540110 X-HE-Meta: U2FsdGVkX18LnuDlqnMOAr1rQwFXLXjHi6UGvinnK/s/Zue2bwr7KS0Ir5GJoTJYpNlqQOkWQe+Uc1TXbKeQXdhDDoIMt8dSYZgEIFmNCGZ/eCWqB5bqYZbyLwjyCGwXZdsr7AgXbF6jIiD0yJh9U+BmoBQWspunCD68667YNJ7JyqTm4+6L6s0jfSXDbHSTpCMtB/JaoR9uiz+BY3K8+fG00b9NCHarSPtnhBMONSO7yzrYfsEYdjGyG1mb0rQt1XJ7QcQBhXdwLNzNaz+swI7Cr/7N0Xn3RdFXQ+aKic2qOd70OxSjE1VuFxDylVzn2EOAyoNlJZ59YkmC/f1swUxcilDUWLG5va+u2nZdcMdD/UxepJ0IInpzTeuWEgsvyOGq1SbK0/epPt9fMTCJJ/u4p0+DxII5KURM04oQGRlI+yB6NO6PnsTVGou6TYiIG7qwR7iqce7gud9Ov0sVbbFuUouT5jGYg/QGyC1hKBvf7kMYfoeI9ZLl3TkEjwjOHzhqUwW/vIRFkFNnLQgt4P2Rust/iINjbM3Xk6nTtUR5dAMvpNthrFM98cAQYV4J3MO1veic8LDDHUEPr/z0XQm6cBw/1c94SZODNi2laGoLf8EYSIYm0xbXsgYaYYQ4GuGtxq1QZWvfeRcZ1XrOqKVajUrux1xWuUR1TqQBp6hjneqHbnt7zt2oWRuWwuVYKj/NOyaXJl77wIg2Bch4p86Ritbv5Ms0cI0Dl74zzekWGsPo689uaKQvrCeQ0jgQJGOVc4E51eHNspzgUZML2NbIlTWCzhyBiDFV7Ve8c3A5TpRjpwNCadw4MEu9okOLNV+nu3GKZ4nc4SFN/rC9T5sjfA2MivJQsWTbERr2mbahvjKlEtdw5stzcZOhuLfUcAm9UT+x+E7SrxRh6PESNNQNE99B4S4UenOMKKBFgbzSxvDJHgmyREFYff9xzEfaoC7MthQGp9DsI+7CWU1 /DIoV1Fa C7GzAjkPSvP3J49bb0NMomiTHzgu5yqHFHMIbekwefWGQZPWeMunCgM3XnRdv9BLL74F5fNuANEKABnB0IIrk3k5oBN17V5/uOuneEiBIyYaHbtpEaxDssowaEDO/xment1FQNFpew7orVKP/bhMPBBxAh5H9wkglFTXTt03rVvSig/xh7zXNJGuxczc+x6XeKjKLtcaHMd9iDTI9pGD92M2jpQ== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: From: Sascha Hauer This driver provides a I2C bus driver for the CGEB interface found on some Congatec x86 modules. No devices are registered on the bus, the user has to do this via the i2c device /sys interface. Signed-off-by: Sascha Hauer Signed-off-by: Christian Gmeiner Signed-off-by: Mary Strodl --- drivers/i2c/busses/Kconfig | 10 ++ drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-congatec-cgeb.c | 190 +++++++++++++++++++++++++ 3 files changed, 201 insertions(+) create mode 100644 drivers/i2c/busses/i2c-congatec-cgeb.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index fe6e8a1bb607..0a5d348c4664 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -1261,6 +1261,16 @@ config I2C_RCAR This driver can also be built as a module. If so, the module will be called i2c-rcar. +config I2C_CONGATEC_CGEB + tristate "Congatec CGEB I2C driver" + depends on MFD_CONGATEC_CGEB + help + If you say yes to this option, support will be included for the + Congatec CGEB I2C controller. + + This driver can also be built as a module. If so, the module + will be called i2c-congatec-cgeb. + comment "External I2C/SMBus adapter drivers" config I2C_DIOLAN_U2C diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 78d0561339e5..f4e9fa7542be 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -128,6 +128,7 @@ obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o obj-$(CONFIG_I2C_GXP) += i2c-gxp.o +obj-$(CONFIG_I2C_CONGATEC_CGEB) += i2c-congatec-cgeb.o # External I2C/SMBus adapter drivers obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o diff --git a/drivers/i2c/busses/i2c-congatec-cgeb.c b/drivers/i2c/busses/i2c-congatec-cgeb.c new file mode 100644 index 000000000000..2a2ebd57285d --- /dev/null +++ b/drivers/i2c/busses/i2c-congatec-cgeb.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * CGEB i2c driver + * + * (c) 2011 Sascha Hauer, Pengutronix + * + * 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; version 2 of the License. + * + * 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 + +#define CG_I2C_FLAG_START 0x00080 /* send START condition */ +#define CG_I2C_FLAG_STOP 0x00040 /* send STOP condition */ +#define CG_I2C_FLAG_ALL_ACK 0x08000 /* send ACK on all read bytes */ +#define CG_I2C_FLAG_ALL_NAK 0x04000 /* send NAK on all read bytes */ + +struct cgeb_i2c_priv { + struct cgeb_board_data *board; + struct i2c_adapter adapter; + int unit; +}; + +static u32 cgeb_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static int cgeb_i2c_set_speed(struct cgeb_i2c_priv *priv, int speed) +{ + struct cgeb_function_parameters fps; + + memset(&fps, 0, sizeof(fps)); + + fps.unit = priv->unit; + fps.pars[0] = speed; + + return cgeb_call(priv->board, &fps, CgebI2CSetFrequency); +} + +static int cgeb_i2c_xfer(struct i2c_adapter *adapter, + struct i2c_msg *msgs, int num) +{ + struct cgeb_function_parameters fps; + int i, ret; + unsigned long flags = CG_I2C_FLAG_START; + struct cgeb_i2c_priv *priv = i2c_get_adapdata(adapter); + unsigned long rdlen, wrlen; + unsigned char *rdbuf, *wrbuf, *raw_wrbuf; + unsigned short lmax = 0; + + /* + * With cgeb the I2C address is part of the write data + * buffer, so allocate a buffer with the length of the + * longest write buffer + 1 + */ + for (i = 0; i < num; i++) + if (!(msgs[i].flags & I2C_M_RD)) + lmax = max(lmax, msgs[i].len); + + raw_wrbuf = kmalloc(lmax + 1, GFP_KERNEL); + if (!raw_wrbuf) + return -ENOMEM; + + for (i = 0; i < num; i++) { + if (msgs[i].flags & I2C_M_RD) { + rdbuf = msgs[i].buf; + rdlen = msgs[i].len; + wrbuf = NULL; + wrlen = 0; + } else { + rdbuf = NULL; + rdlen = 0; + wrbuf = msgs[i].buf; + wrlen = msgs[i].len; + } + + raw_wrbuf[0] = msgs[i].addr << 1; + if (wrlen) + memcpy(&raw_wrbuf[1], wrbuf, wrlen); + + if (msgs[i].flags & I2C_M_RD) + raw_wrbuf[0] |= 1; + + if (i == num - 1) + flags |= CG_I2C_FLAG_STOP; + + dev_dbg(&adapter->dev, + "%s: rd: %p/%ld wr: %p/%ld flags: 0x%08lx %s\n", + __func__, rdbuf, rdlen, raw_wrbuf, wrlen + 1, + flags, + msgs[i].flags & I2C_M_RD ? "READ" : "WRITE"); + + memset(&fps, 0, sizeof(fps)); + + fps.unit = priv->unit; + fps.pars[0] = wrlen + 1; + fps.pars[1] = rdlen; + fps.pars[2] = flags; + fps.iptr = raw_wrbuf; + fps.optr = rdbuf; + fps.optr_size = sizeof(*rdbuf) * rdlen; + fps.iptr_size = (wrlen + 1) * sizeof(*raw_wrbuf); + + ret = cgeb_call(priv->board, &fps, CgebI2CTransfer); + if (ret) { + ret = -EREMOTEIO; + goto out; + } + } + + ret = num; + +out: + kfree(raw_wrbuf); + + return ret; +} + +static struct i2c_algorithm cgeb_i2c_algo = { + .master_xfer = cgeb_i2c_xfer, + .functionality = cgeb_i2c_func, +}; + +static int cgeb_i2c_probe(struct platform_device *pdev) +{ + struct cgeb_i2c_priv *priv; + struct cgeb_pdata *pdata = pdev->dev.platform_data; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + strscpy(priv->adapter.name, pdev->name); + priv->adapter.owner = THIS_MODULE; + priv->adapter.algo = &cgeb_i2c_algo; + priv->adapter.dev.parent = &pdev->dev; + priv->unit = pdata->unit; + priv->board = pdata->board; + i2c_set_adapdata(&priv->adapter, priv); + + platform_set_drvdata(pdev, priv); + + ret = cgeb_i2c_set_speed(priv, 400000); + if (ret) + /* not a critical error, we can continue with the default speed. */ + dev_warn(&pdev->dev, "Could not set speed to 400KHz\n"); + + ret = i2c_add_adapter(&priv->adapter); + if (ret < 0) { + dev_err(&pdev->dev, "registration failed\n"); + return ret; + } + + dev_info(&pdev->dev, "registered\n"); + + return 0; +}; + +static int cgeb_i2c_remove(struct platform_device *pdev) +{ + struct cgeb_i2c_priv *priv = platform_get_drvdata(pdev); + + i2c_del_adapter(&priv->adapter); + + return 0; +} + +static struct platform_driver cgeb_i2c_driver = { + .probe = cgeb_i2c_probe, + .remove = cgeb_i2c_remove, + .driver = { + .name = "cgeb-i2c", + }, +}; +module_platform_driver(cgeb_i2c_driver); + +MODULE_AUTHOR("Sascha Hauer "); +MODULE_DESCRIPTION("cgeb i2c driver"); +MODULE_LICENSE("GPL");