From patchwork Fri Dec 29 06:30:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Hu X-Patchwork-Id: 758888 Received: from mx1.zhaoxin.com (MX1.ZHAOXIN.COM [210.0.225.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 64B966FA9 for ; Fri, 29 Dec 2023 06:30:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=zhaoxin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zhaoxin.com X-ASG-Debug-ID: 1703831441-086e230f290a520002-PT6Irj Received: from ZXSHMBX1.zhaoxin.com (ZXSHMBX1.zhaoxin.com [10.28.252.163]) by mx1.zhaoxin.com with ESMTP id iLjsX8sVWom5yWN5 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Fri, 29 Dec 2023 14:30:46 +0800 (CST) X-Barracuda-Envelope-From: HansHu-oc@zhaoxin.com X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.163 Received: from ZXBJMBX03.zhaoxin.com (10.29.252.7) by ZXSHMBX1.zhaoxin.com (10.28.252.163) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:41 +0800 Received: from ml-HP-ProDesk-680-G4-MT.zhaoxin.com (10.28.66.68) by ZXBJMBX03.zhaoxin.com (10.29.252.7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:40 +0800 X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.163 From: Hans Hu X-Barracuda-RBL-Trusted-Forwarder: 10.29.252.7 To: , CC: , , Subject: [PATCH v6 1/8] i2c: wmt: create wmt_i2c_init for general init Date: Fri, 29 Dec 2023 14:30:32 +0800 X-ASG-Orig-Subj: [PATCH v6 1/8] i2c: wmt: create wmt_i2c_init for general init Message-ID: <19a2be1aeb0d935b433d0b0eff0dabaeaaaa3de7.1703830854.git.hanshu-oc@zhaoxin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-i2c@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: zxbjmbx1.zhaoxin.com (10.29.252.163) To ZXBJMBX03.zhaoxin.com (10.29.252.7) X-Barracuda-Connect: ZXSHMBX1.zhaoxin.com[10.28.252.163] X-Barracuda-Start-Time: 1703831441 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://10.28.252.35:4443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at zhaoxin.com X-Barracuda-Scan-Msg-Size: 3376 X-Barracuda-BRTS-Status: 0 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using global scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=9.0 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.118704 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- v4->v5: add previous prototype 'static' for wmt_i2c_init(). Some common initialization actions are put in the function wmt_i2c_init(), which is convenient to share with zhaoxin. Signed-off-by: Hans Hu Reviewed-by: Andi Shyti --- drivers/i2c/busses/i2c-wmt.c | 67 +++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c index ec2a8da134e5..f1888f100d83 100644 --- a/drivers/i2c/busses/i2c-wmt.c +++ b/drivers/i2c/busses/i2c-wmt.c @@ -286,6 +286,38 @@ static irqreturn_t wmt_i2c_isr(int irq, void *data) return IRQ_HANDLED; } +static int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c_dev **pi2c_dev) +{ + int err; + struct wmt_i2c_dev *i2c_dev; + struct device_node *np = pdev->dev.of_node; + + i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); + if (!i2c_dev) + return -ENOMEM; + + i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + if (IS_ERR(i2c_dev->base)) + return PTR_ERR(i2c_dev->base); + + i2c_dev->irq = irq_of_parse_and_map(np, 0); + if (!i2c_dev->irq) + return -EINVAL; + + err = devm_request_irq(&pdev->dev, i2c_dev->irq, wmt_i2c_isr, + 0, pdev->name, i2c_dev); + if (err) + return dev_err_probe(&pdev->dev, err, + "failed to request irq %i\n", i2c_dev->irq); + + i2c_dev->dev = &pdev->dev; + init_completion(&i2c_dev->complete); + platform_set_drvdata(pdev, i2c_dev); + + *pi2c_dev = i2c_dev; + return 0; +} + static int wmt_i2c_reset_hardware(struct wmt_i2c_dev *i2c_dev) { int err; @@ -327,19 +359,9 @@ static int wmt_i2c_probe(struct platform_device *pdev) int err; u32 clk_rate; - i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); - if (!i2c_dev) - return -ENOMEM; - - i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); - if (IS_ERR(i2c_dev->base)) - return PTR_ERR(i2c_dev->base); - - i2c_dev->irq = irq_of_parse_and_map(np, 0); - if (!i2c_dev->irq) { - dev_err(&pdev->dev, "irq missing or invalid\n"); - return -EINVAL; - } + err = wmt_i2c_init(pdev, &i2c_dev); + if (err) + return err; i2c_dev->clk = of_clk_get(np, 0); if (IS_ERR(i2c_dev->clk)) { @@ -351,15 +373,6 @@ static int wmt_i2c_probe(struct platform_device *pdev) if (!err && (clk_rate == I2C_MAX_FAST_MODE_FREQ)) i2c_dev->tcr = TCR_FAST_MODE; - i2c_dev->dev = &pdev->dev; - - err = devm_request_irq(&pdev->dev, i2c_dev->irq, wmt_i2c_isr, 0, - "i2c", i2c_dev); - if (err) { - dev_err(&pdev->dev, "failed to request irq %i\n", i2c_dev->irq); - return err; - } - adap = &i2c_dev->adapter; i2c_set_adapdata(adap, i2c_dev); strscpy(adap->name, "WMT I2C adapter", sizeof(adap->name)); @@ -368,21 +381,13 @@ static int wmt_i2c_probe(struct platform_device *pdev) adap->dev.parent = &pdev->dev; adap->dev.of_node = pdev->dev.of_node; - init_completion(&i2c_dev->complete); - err = wmt_i2c_reset_hardware(i2c_dev); if (err) { dev_err(&pdev->dev, "error initializing hardware\n"); return err; } - err = i2c_add_adapter(adap); - if (err) - return err; - - platform_set_drvdata(pdev, i2c_dev); - - return 0; + return i2c_add_adapter(adap); } static void wmt_i2c_remove(struct platform_device *pdev) From patchwork Fri Dec 29 06:30:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Hu X-Patchwork-Id: 758891 Received: from mx2.zhaoxin.com (mx2.zhaoxin.com [203.110.167.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ADE5A5688 for ; Fri, 29 Dec 2023 06:30:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=zhaoxin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zhaoxin.com X-ASG-Debug-ID: 1703831441-1eb14e0c7d09100001-PT6Irj Received: from ZXSHMBX3.zhaoxin.com (ZXSHMBX3.zhaoxin.com [10.28.252.165]) by mx2.zhaoxin.com with ESMTP id 9WuB4t8D6Vp7VGzt (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Fri, 29 Dec 2023 14:30:41 +0800 (CST) X-Barracuda-Envelope-From: HansHu-oc@zhaoxin.com X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.165 Received: from ZXBJMBX03.zhaoxin.com (10.29.252.7) by ZXSHMBX3.zhaoxin.com (10.28.252.165) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:41 +0800 Received: from ml-HP-ProDesk-680-G4-MT.zhaoxin.com (10.28.66.68) by ZXBJMBX03.zhaoxin.com (10.29.252.7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:40 +0800 X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.165 From: Hans Hu X-Barracuda-RBL-Trusted-Forwarder: 10.29.252.7 To: , CC: , , Subject: [PATCH v6 2/8] i2c: wmt: rename marcos with prefix WMTI2C_ Date: Fri, 29 Dec 2023 14:30:33 +0800 X-ASG-Orig-Subj: [PATCH v6 2/8] i2c: wmt: rename marcos with prefix WMTI2C_ Message-ID: <75978a2c47f17bf6871b92803e9c075e52aed1b6.1703830854.git.hanshu-oc@zhaoxin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-i2c@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: zxbjmbx1.zhaoxin.com (10.29.252.163) To ZXBJMBX03.zhaoxin.com (10.29.252.7) X-Barracuda-Connect: ZXSHMBX3.zhaoxin.com[10.28.252.165] X-Barracuda-Start-Time: 1703831441 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://10.28.252.36:4443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at zhaoxin.com X-Barracuda-Scan-Msg-Size: 10901 X-Barracuda-BRTS-Status: 0 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using global scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=9.0 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.118704 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Tweaked a few formatting things: rename marcos with prefix WMTI2C_ Signed-off-by: Hans Hu Reviewed-by: Andi Shyti --- drivers/i2c/busses/i2c-wmt.c | 176 +++++++++++++++++------------------ 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c index f1888f100d83..95d739fde34f 100644 --- a/drivers/i2c/busses/i2c-wmt.c +++ b/drivers/i2c/busses/i2c-wmt.c @@ -20,59 +20,59 @@ #include #include -#define REG_CR 0x00 -#define REG_TCR 0x02 -#define REG_CSR 0x04 -#define REG_ISR 0x06 -#define REG_IMR 0x08 -#define REG_CDR 0x0A -#define REG_TR 0x0C -#define REG_MCR 0x0E -#define REG_SLAVE_CR 0x10 -#define REG_SLAVE_SR 0x12 -#define REG_SLAVE_ISR 0x14 -#define REG_SLAVE_IMR 0x16 -#define REG_SLAVE_DR 0x18 -#define REG_SLAVE_TR 0x1A +#define WMTI2C_REG_CR 0x00 +#define WMTI2C_REG_TCR 0x02 +#define WMTI2C_REG_CSR 0x04 +#define WMTI2C_REG_ISR 0x06 +#define WMTI2C_REG_IMR 0x08 +#define WMTI2C_REG_CDR 0x0A +#define WMTI2C_REG_TR 0x0C +#define WMTI2C_REG_MCR 0x0E +#define WMTI2C_REG_SLAVE_CR 0x10 +#define WMTI2C_REG_SLAVE_SR 0x12 +#define WMTI2C_REG_SLAVE_ISR 0x14 +#define WMTI2C_REG_SLAVE_IMR 0x16 +#define WMTI2C_REG_SLAVE_DR 0x18 +#define WMTI2C_REG_SLAVE_TR 0x1A /* REG_CR Bit fields */ -#define CR_TX_NEXT_ACK 0x0000 -#define CR_ENABLE 0x0001 -#define CR_TX_NEXT_NO_ACK 0x0002 -#define CR_TX_END 0x0004 -#define CR_CPU_RDY 0x0008 -#define SLAV_MODE_SEL 0x8000 +#define WMTI2C_CR_TX_NEXT_ACK 0x0000 +#define WMTI2C_CR_ENABLE 0x0001 +#define WMTI2C_CR_TX_NEXT_NO_ACK 0x0002 +#define WMTI2C_CR_TX_END 0x0004 +#define WMTI2C_CR_CPU_RDY 0x0008 +#define WMTI2C_SLAV_MODE_SEL 0x8000 /* REG_TCR Bit fields */ -#define TCR_STANDARD_MODE 0x0000 -#define TCR_MASTER_WRITE 0x0000 -#define TCR_HS_MODE 0x2000 -#define TCR_MASTER_READ 0x4000 -#define TCR_FAST_MODE 0x8000 -#define TCR_SLAVE_ADDR_MASK 0x007F +#define WMTI2C_TCR_STANDARD_MODE 0x0000 +#define WMTI2C_TCR_MASTER_WRITE 0x0000 +#define WMTI2C_TCR_HS_MODE 0x2000 +#define WMTI2C_TCR_MASTER_READ 0x4000 +#define WMTI2C_TCR_FAST_MODE 0x8000 +#define WMTI2C_TCR_SLAVE_ADDR_MASK 0x007F /* REG_ISR Bit fields */ -#define ISR_NACK_ADDR 0x0001 -#define ISR_BYTE_END 0x0002 -#define ISR_SCL_TIMEOUT 0x0004 -#define ISR_WRITE_ALL 0x0007 +#define WMTI2C_ISR_NACK_ADDR 0x0001 +#define WMTI2C_ISR_BYTE_END 0x0002 +#define WMTI2C_ISR_SCL_TIMEOUT 0x0004 +#define WMTI2C_ISR_WRITE_ALL 0x0007 /* REG_IMR Bit fields */ -#define IMR_ENABLE_ALL 0x0007 +#define WMTI2C_IMR_ENABLE_ALL 0x0007 /* REG_CSR Bit fields */ -#define CSR_RCV_NOT_ACK 0x0001 -#define CSR_RCV_ACK_MASK 0x0001 -#define CSR_READY_MASK 0x0002 +#define WMTI2C_CSR_RCV_NOT_ACK 0x0001 +#define WMTI2C_CSR_RCV_ACK_MASK 0x0001 +#define WMTI2C_CSR_READY_MASK 0x0002 /* REG_TR */ -#define SCL_TIMEOUT(x) (((x) & 0xFF) << 8) -#define TR_STD 0x0064 -#define TR_HS 0x0019 +#define WMTI2C_SCL_TIMEOUT(x) (((x) & 0xFF) << 8) +#define WMTI2C_TR_STD 0x0064 +#define WMTI2C_TR_HS 0x0019 /* REG_MCR */ -#define MCR_APB_96M 7 -#define MCR_APB_166M 12 +#define WMTI2C_MCR_APB_96M 7 +#define WMTI2C_MCR_APB_166M 12 #define WMT_I2C_TIMEOUT (msecs_to_jiffies(1000)) @@ -92,7 +92,7 @@ static int wmt_i2c_wait_bus_not_busy(struct wmt_i2c_dev *i2c_dev) unsigned long timeout; timeout = jiffies + WMT_I2C_TIMEOUT; - while (!(readw(i2c_dev->base + REG_CSR) & CSR_READY_MASK)) { + while (!(readw(i2c_dev->base + WMTI2C_REG_CSR) & WMTI2C_CSR_READY_MASK)) { if (time_after(jiffies, timeout)) { dev_warn(i2c_dev->dev, "timeout waiting for bus ready\n"); return -EBUSY; @@ -113,10 +113,10 @@ static int wmt_check_status(struct wmt_i2c_dev *i2c_dev) if (!wait_result) return -ETIMEDOUT; - if (i2c_dev->cmd_status & ISR_NACK_ADDR) + if (i2c_dev->cmd_status & WMTI2C_ISR_NACK_ADDR) ret = -EIO; - if (i2c_dev->cmd_status & ISR_SCL_TIMEOUT) + if (i2c_dev->cmd_status & WMTI2C_ISR_SCL_TIMEOUT) ret = -ETIMEDOUT; return ret; @@ -135,28 +135,28 @@ static int wmt_i2c_write(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg, * start at -1 and break out early from the loop */ xfer_len = -1; - writew(0, i2c_dev->base + REG_CDR); + writew(0, i2c_dev->base + WMTI2C_REG_CDR); } else { - writew(pmsg->buf[0] & 0xFF, i2c_dev->base + REG_CDR); + writew(pmsg->buf[0] & 0xFF, i2c_dev->base + WMTI2C_REG_CDR); } if (!(pmsg->flags & I2C_M_NOSTART)) { - val = readw(i2c_dev->base + REG_CR); - val &= ~CR_TX_END; - val |= CR_CPU_RDY; - writew(val, i2c_dev->base + REG_CR); + val = readw(i2c_dev->base + WMTI2C_REG_CR); + val &= ~WMTI2C_CR_TX_END; + val |= WMTI2C_CR_CPU_RDY; + writew(val, i2c_dev->base + WMTI2C_REG_CR); } reinit_completion(&i2c_dev->complete); - tcr_val |= (TCR_MASTER_WRITE | (pmsg->addr & TCR_SLAVE_ADDR_MASK)); + tcr_val |= (WMTI2C_TCR_MASTER_WRITE | (pmsg->addr & WMTI2C_TCR_SLAVE_ADDR_MASK)); - writew(tcr_val, i2c_dev->base + REG_TCR); + writew(tcr_val, i2c_dev->base + WMTI2C_REG_TCR); if (pmsg->flags & I2C_M_NOSTART) { - val = readw(i2c_dev->base + REG_CR); - val |= CR_CPU_RDY; - writew(val, i2c_dev->base + REG_CR); + val = readw(i2c_dev->base + WMTI2C_REG_CR); + val |= WMTI2C_CR_CPU_RDY; + writew(val, i2c_dev->base + WMTI2C_REG_CR); } while (xfer_len < pmsg->len) { @@ -166,25 +166,25 @@ static int wmt_i2c_write(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg, xfer_len++; - val = readw(i2c_dev->base + REG_CSR); - if ((val & CSR_RCV_ACK_MASK) == CSR_RCV_NOT_ACK) { + val = readw(i2c_dev->base + WMTI2C_REG_CSR); + if ((val & WMTI2C_CSR_RCV_ACK_MASK) == WMTI2C_CSR_RCV_NOT_ACK) { dev_dbg(i2c_dev->dev, "write RCV NACK error\n"); return -EIO; } if (pmsg->len == 0) { - val = CR_TX_END | CR_CPU_RDY | CR_ENABLE; - writew(val, i2c_dev->base + REG_CR); + val = WMTI2C_CR_TX_END | WMTI2C_CR_CPU_RDY | WMTI2C_CR_ENABLE; + writew(val, i2c_dev->base + WMTI2C_REG_CR); break; } if (xfer_len == pmsg->len) { if (last != 1) - writew(CR_ENABLE, i2c_dev->base + REG_CR); + writew(WMTI2C_CR_ENABLE, i2c_dev->base + WMTI2C_REG_CR); } else { writew(pmsg->buf[xfer_len] & 0xFF, i2c_dev->base + - REG_CDR); - writew(CR_CPU_RDY | CR_ENABLE, i2c_dev->base + REG_CR); + WMTI2C_REG_CDR); + writew(WMTI2C_CR_CPU_RDY | WMTI2C_CR_ENABLE, i2c_dev->base + WMTI2C_REG_CR); } } @@ -197,27 +197,27 @@ static int wmt_i2c_read(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg) int ret; u32 xfer_len = 0; - val = readw(i2c_dev->base + REG_CR); - val &= ~(CR_TX_END | CR_TX_NEXT_NO_ACK); + val = readw(i2c_dev->base + WMTI2C_REG_CR); + val &= ~(WMTI2C_CR_TX_END | WMTI2C_CR_TX_NEXT_NO_ACK); if (!(pmsg->flags & I2C_M_NOSTART)) - val |= CR_CPU_RDY; + val |= WMTI2C_CR_CPU_RDY; if (pmsg->len == 1) - val |= CR_TX_NEXT_NO_ACK; + val |= WMTI2C_CR_TX_NEXT_NO_ACK; - writew(val, i2c_dev->base + REG_CR); + writew(val, i2c_dev->base + WMTI2C_REG_CR); reinit_completion(&i2c_dev->complete); - tcr_val |= TCR_MASTER_READ | (pmsg->addr & TCR_SLAVE_ADDR_MASK); + tcr_val |= WMTI2C_TCR_MASTER_READ | (pmsg->addr & WMTI2C_TCR_SLAVE_ADDR_MASK); - writew(tcr_val, i2c_dev->base + REG_TCR); + writew(tcr_val, i2c_dev->base + WMTI2C_REG_TCR); if (pmsg->flags & I2C_M_NOSTART) { - val = readw(i2c_dev->base + REG_CR); - val |= CR_CPU_RDY; - writew(val, i2c_dev->base + REG_CR); + val = readw(i2c_dev->base + WMTI2C_REG_CR); + val |= WMTI2C_CR_CPU_RDY; + writew(val, i2c_dev->base + WMTI2C_REG_CR); } while (xfer_len < pmsg->len) { @@ -225,13 +225,13 @@ static int wmt_i2c_read(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg) if (ret) return ret; - pmsg->buf[xfer_len] = readw(i2c_dev->base + REG_CDR) >> 8; + pmsg->buf[xfer_len] = readw(i2c_dev->base + WMTI2C_REG_CDR) >> 8; xfer_len++; - val = readw(i2c_dev->base + REG_CR) | CR_CPU_RDY; + val = readw(i2c_dev->base + WMTI2C_REG_CR) | WMTI2C_CR_CPU_RDY; if (xfer_len == pmsg->len - 1) - val |= CR_TX_NEXT_NO_ACK; - writew(val, i2c_dev->base + REG_CR); + val |= WMTI2C_CR_TX_NEXT_NO_ACK; + writew(val, i2c_dev->base + WMTI2C_REG_CR); } return 0; @@ -278,8 +278,8 @@ static irqreturn_t wmt_i2c_isr(int irq, void *data) struct wmt_i2c_dev *i2c_dev = data; /* save the status and write-clear it */ - i2c_dev->cmd_status = readw(i2c_dev->base + REG_ISR); - writew(i2c_dev->cmd_status, i2c_dev->base + REG_ISR); + i2c_dev->cmd_status = readw(i2c_dev->base + WMTI2C_REG_ISR); + writew(i2c_dev->cmd_status, i2c_dev->base + WMTI2C_REG_ISR); complete(&i2c_dev->complete); @@ -335,18 +335,18 @@ static int wmt_i2c_reset_hardware(struct wmt_i2c_dev *i2c_dev) return err; } - writew(0, i2c_dev->base + REG_CR); - writew(MCR_APB_166M, i2c_dev->base + REG_MCR); - writew(ISR_WRITE_ALL, i2c_dev->base + REG_ISR); - writew(IMR_ENABLE_ALL, i2c_dev->base + REG_IMR); - writew(CR_ENABLE, i2c_dev->base + REG_CR); - readw(i2c_dev->base + REG_CSR); /* read clear */ - writew(ISR_WRITE_ALL, i2c_dev->base + REG_ISR); + writew(0, i2c_dev->base + WMTI2C_REG_CR); + writew(WMTI2C_MCR_APB_166M, i2c_dev->base + WMTI2C_REG_MCR); + writew(WMTI2C_ISR_WRITE_ALL, i2c_dev->base + WMTI2C_REG_ISR); + writew(WMTI2C_IMR_ENABLE_ALL, i2c_dev->base + WMTI2C_REG_IMR); + writew(WMTI2C_CR_ENABLE, i2c_dev->base + WMTI2C_REG_CR); + readw(i2c_dev->base + WMTI2C_REG_CSR); /* read clear */ + writew(WMTI2C_ISR_WRITE_ALL, i2c_dev->base + WMTI2C_REG_ISR); - if (i2c_dev->tcr == TCR_FAST_MODE) - writew(SCL_TIMEOUT(128) | TR_HS, i2c_dev->base + REG_TR); + if (i2c_dev->tcr == WMTI2C_TCR_FAST_MODE) + writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_HS, i2c_dev->base + WMTI2C_REG_TR); else - writew(SCL_TIMEOUT(128) | TR_STD, i2c_dev->base + REG_TR); + writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_STD, i2c_dev->base + WMTI2C_REG_TR); return 0; } @@ -371,7 +371,7 @@ static int wmt_i2c_probe(struct platform_device *pdev) err = of_property_read_u32(np, "clock-frequency", &clk_rate); if (!err && (clk_rate == I2C_MAX_FAST_MODE_FREQ)) - i2c_dev->tcr = TCR_FAST_MODE; + i2c_dev->tcr = WMTI2C_TCR_FAST_MODE; adap = &i2c_dev->adapter; i2c_set_adapdata(adap, i2c_dev); @@ -395,7 +395,7 @@ static void wmt_i2c_remove(struct platform_device *pdev) struct wmt_i2c_dev *i2c_dev = platform_get_drvdata(pdev); /* Disable interrupts, clock and delete adapter */ - writew(0, i2c_dev->base + REG_IMR); + writew(0, i2c_dev->base + WMTI2C_REG_IMR); clk_disable_unprepare(i2c_dev->clk); i2c_del_adapter(&i2c_dev->adapter); } From patchwork Fri Dec 29 06:30:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Hu X-Patchwork-Id: 758890 Received: from mx2.zhaoxin.com (mx2.zhaoxin.com [203.110.167.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ADE34567D for ; Fri, 29 Dec 2023 06:30:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=zhaoxin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zhaoxin.com X-ASG-Debug-ID: 1703831441-1eb14e0c7d09100002-PT6Irj Received: from ZXSHMBX3.zhaoxin.com (ZXSHMBX3.zhaoxin.com [10.28.252.165]) by mx2.zhaoxin.com with ESMTP id sI97ejTWBtLoPyPt (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Fri, 29 Dec 2023 14:30:42 +0800 (CST) X-Barracuda-Envelope-From: HansHu-oc@zhaoxin.com X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.165 Received: from ZXBJMBX03.zhaoxin.com (10.29.252.7) by ZXSHMBX3.zhaoxin.com (10.28.252.165) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:41 +0800 Received: from ml-HP-ProDesk-680-G4-MT.zhaoxin.com (10.28.66.68) by ZXBJMBX03.zhaoxin.com (10.29.252.7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:41 +0800 X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.165 From: Hans Hu X-Barracuda-RBL-Trusted-Forwarder: 10.29.252.7 To: , CC: , , Subject: [PATCH v6 3/8] i2c: wmt: adjust line length to meet style Date: Fri, 29 Dec 2023 14:30:34 +0800 X-ASG-Orig-Subj: [PATCH v6 3/8] i2c: wmt: adjust line length to meet style Message-ID: X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-i2c@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: zxbjmbx1.zhaoxin.com (10.29.252.163) To ZXBJMBX03.zhaoxin.com (10.29.252.7) X-Barracuda-Connect: ZXSHMBX3.zhaoxin.com[10.28.252.165] X-Barracuda-Start-Time: 1703831441 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://10.28.252.36:4443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at zhaoxin.com X-Barracuda-Scan-Msg-Size: 13761 X-Barracuda-BRTS-Status: 0 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using global scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=9.0 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.118704 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- v4->v5: add previous prototype 'static' for wmt_i2c_init(). Tweaked a few formatting things: rename wmt_i2c_dev to wmt_i2c, i2c_dev to i2c, etc. Signed-off-by: Hans Hu --- drivers/i2c/busses/i2c-wmt.c | 199 ++++++++++++++++++----------------- 1 file changed, 104 insertions(+), 95 deletions(-) diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c index 95d739fde34f..76fba4ffa126 100644 --- a/drivers/i2c/busses/i2c-wmt.c +++ b/drivers/i2c/busses/i2c-wmt.c @@ -76,7 +76,7 @@ #define WMT_I2C_TIMEOUT (msecs_to_jiffies(1000)) -struct wmt_i2c_dev { +struct wmt_i2c { struct i2c_adapter adapter; struct completion complete; struct device *dev; @@ -87,14 +87,16 @@ struct wmt_i2c_dev { u16 cmd_status; }; -static int wmt_i2c_wait_bus_not_busy(struct wmt_i2c_dev *i2c_dev) +static int wmt_i2c_wait_bus_not_busy(struct wmt_i2c *i2c) { unsigned long timeout; + void __iomem *base = i2c->base; timeout = jiffies + WMT_I2C_TIMEOUT; - while (!(readw(i2c_dev->base + WMTI2C_REG_CSR) & WMTI2C_CSR_READY_MASK)) { + while (!(readw(base + WMTI2C_REG_CSR) & WMTI2C_CSR_READY_MASK)) { if (time_after(jiffies, timeout)) { - dev_warn(i2c_dev->dev, "timeout waiting for bus ready\n"); + dev_warn(i2c->dev, + "timeout waiting for bus ready\n"); return -EBUSY; } msleep(20); @@ -103,31 +105,32 @@ static int wmt_i2c_wait_bus_not_busy(struct wmt_i2c_dev *i2c_dev) return 0; } -static int wmt_check_status(struct wmt_i2c_dev *i2c_dev) +static int wmt_check_status(struct wmt_i2c *i2c) { int ret = 0; unsigned long wait_result; - wait_result = wait_for_completion_timeout(&i2c_dev->complete, + wait_result = wait_for_completion_timeout(&i2c->complete, msecs_to_jiffies(500)); if (!wait_result) return -ETIMEDOUT; - if (i2c_dev->cmd_status & WMTI2C_ISR_NACK_ADDR) + if (i2c->cmd_status & WMTI2C_ISR_NACK_ADDR) ret = -EIO; - if (i2c_dev->cmd_status & WMTI2C_ISR_SCL_TIMEOUT) + if (i2c->cmd_status & WMTI2C_ISR_SCL_TIMEOUT) ret = -ETIMEDOUT; return ret; } -static int wmt_i2c_write(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg, +static int wmt_i2c_write(struct wmt_i2c *i2c, struct i2c_msg *pmsg, int last) { - u16 val, tcr_val = i2c_dev->tcr; + u16 val, tcr_val = i2c->tcr; int ret; int xfer_len = 0; + void __iomem *base = i2c->base; if (pmsg->len == 0) { /* @@ -135,69 +138,73 @@ static int wmt_i2c_write(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg, * start at -1 and break out early from the loop */ xfer_len = -1; - writew(0, i2c_dev->base + WMTI2C_REG_CDR); + writew(0, base + WMTI2C_REG_CDR); } else { - writew(pmsg->buf[0] & 0xFF, i2c_dev->base + WMTI2C_REG_CDR); + writew(pmsg->buf[0] & 0xFF, base + WMTI2C_REG_CDR); } if (!(pmsg->flags & I2C_M_NOSTART)) { - val = readw(i2c_dev->base + WMTI2C_REG_CR); + val = readw(base + WMTI2C_REG_CR); val &= ~WMTI2C_CR_TX_END; val |= WMTI2C_CR_CPU_RDY; - writew(val, i2c_dev->base + WMTI2C_REG_CR); + writew(val, base + WMTI2C_REG_CR); } - reinit_completion(&i2c_dev->complete); + reinit_completion(&i2c->complete); - tcr_val |= (WMTI2C_TCR_MASTER_WRITE | (pmsg->addr & WMTI2C_TCR_SLAVE_ADDR_MASK)); + tcr_val |= (WMTI2C_TCR_MASTER_WRITE + | (pmsg->addr & WMTI2C_TCR_SLAVE_ADDR_MASK)); - writew(tcr_val, i2c_dev->base + WMTI2C_REG_TCR); + writew(tcr_val, base + WMTI2C_REG_TCR); if (pmsg->flags & I2C_M_NOSTART) { - val = readw(i2c_dev->base + WMTI2C_REG_CR); + val = readw(base + WMTI2C_REG_CR); val |= WMTI2C_CR_CPU_RDY; - writew(val, i2c_dev->base + WMTI2C_REG_CR); + writew(val, base + WMTI2C_REG_CR); } while (xfer_len < pmsg->len) { - ret = wmt_check_status(i2c_dev); + ret = wmt_check_status(i2c); if (ret) return ret; xfer_len++; - val = readw(i2c_dev->base + WMTI2C_REG_CSR); - if ((val & WMTI2C_CSR_RCV_ACK_MASK) == WMTI2C_CSR_RCV_NOT_ACK) { - dev_dbg(i2c_dev->dev, "write RCV NACK error\n"); + val = readw(base + WMTI2C_REG_CSR); + if (val & WMTI2C_CSR_RCV_NOT_ACK) { + dev_dbg(i2c->dev, "write RCV NACK error\n"); return -EIO; } if (pmsg->len == 0) { - val = WMTI2C_CR_TX_END | WMTI2C_CR_CPU_RDY | WMTI2C_CR_ENABLE; - writew(val, i2c_dev->base + WMTI2C_REG_CR); + val = WMTI2C_CR_TX_END | WMTI2C_CR_CPU_RDY + | WMTI2C_CR_ENABLE; + writew(val, base + WMTI2C_REG_CR); break; } if (xfer_len == pmsg->len) { if (last != 1) - writew(WMTI2C_CR_ENABLE, i2c_dev->base + WMTI2C_REG_CR); + writew(WMTI2C_CR_ENABLE, base + WMTI2C_REG_CR); } else { - writew(pmsg->buf[xfer_len] & 0xFF, i2c_dev->base + - WMTI2C_REG_CDR); - writew(WMTI2C_CR_CPU_RDY | WMTI2C_CR_ENABLE, i2c_dev->base + WMTI2C_REG_CR); + writew(pmsg->buf[xfer_len] & 0xFF, + base + WMTI2C_REG_CDR); + writew(WMTI2C_CR_CPU_RDY | WMTI2C_CR_ENABLE, + base + WMTI2C_REG_CR); } } return 0; } -static int wmt_i2c_read(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg) +static int wmt_i2c_read(struct wmt_i2c *i2c, struct i2c_msg *pmsg) { - u16 val, tcr_val = i2c_dev->tcr; + u16 val, tcr_val = i2c->tcr; int ret; u32 xfer_len = 0; + void __iomem *base = i2c->base; - val = readw(i2c_dev->base + WMTI2C_REG_CR); + val = readw(base + WMTI2C_REG_CR); val &= ~(WMTI2C_CR_TX_END | WMTI2C_CR_TX_NEXT_NO_ACK); if (!(pmsg->flags & I2C_M_NOSTART)) @@ -206,32 +213,33 @@ static int wmt_i2c_read(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg) if (pmsg->len == 1) val |= WMTI2C_CR_TX_NEXT_NO_ACK; - writew(val, i2c_dev->base + WMTI2C_REG_CR); + writew(val, base + WMTI2C_REG_CR); - reinit_completion(&i2c_dev->complete); + reinit_completion(&i2c->complete); - tcr_val |= WMTI2C_TCR_MASTER_READ | (pmsg->addr & WMTI2C_TCR_SLAVE_ADDR_MASK); + tcr_val |= WMTI2C_TCR_MASTER_READ + | (pmsg->addr & WMTI2C_TCR_SLAVE_ADDR_MASK); - writew(tcr_val, i2c_dev->base + WMTI2C_REG_TCR); + writew(tcr_val, base + WMTI2C_REG_TCR); if (pmsg->flags & I2C_M_NOSTART) { - val = readw(i2c_dev->base + WMTI2C_REG_CR); + val = readw(base + WMTI2C_REG_CR); val |= WMTI2C_CR_CPU_RDY; - writew(val, i2c_dev->base + WMTI2C_REG_CR); + writew(val, base + WMTI2C_REG_CR); } while (xfer_len < pmsg->len) { - ret = wmt_check_status(i2c_dev); + ret = wmt_check_status(i2c); if (ret) return ret; - pmsg->buf[xfer_len] = readw(i2c_dev->base + WMTI2C_REG_CDR) >> 8; + pmsg->buf[xfer_len] = readw(base + WMTI2C_REG_CDR) >> 8; xfer_len++; - val = readw(i2c_dev->base + WMTI2C_REG_CR) | WMTI2C_CR_CPU_RDY; + val = readw(base + WMTI2C_REG_CR) | WMTI2C_CR_CPU_RDY; if (xfer_len == pmsg->len - 1) val |= WMTI2C_CR_TX_NEXT_NO_ACK; - writew(val, i2c_dev->base + WMTI2C_REG_CR); + writew(val, base + WMTI2C_REG_CR); } return 0; @@ -244,20 +252,20 @@ static int wmt_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg; int i; int ret = 0; - struct wmt_i2c_dev *i2c_dev = i2c_get_adapdata(adap); + struct wmt_i2c *i2c = i2c_get_adapdata(adap); for (i = 0; ret >= 0 && i < num; i++) { pmsg = &msgs[i]; if (!(pmsg->flags & I2C_M_NOSTART)) { - ret = wmt_i2c_wait_bus_not_busy(i2c_dev); + ret = wmt_i2c_wait_bus_not_busy(i2c); if (ret < 0) return ret; } if (pmsg->flags & I2C_M_RD) - ret = wmt_i2c_read(i2c_dev, pmsg); + ret = wmt_i2c_read(i2c, pmsg); else - ret = wmt_i2c_write(i2c_dev, pmsg, (i + 1) == num); + ret = wmt_i2c_write(i2c, pmsg, (i + 1) == num); } return (ret < 0) ? ret : i; @@ -275,78 +283,79 @@ static const struct i2c_algorithm wmt_i2c_algo = { static irqreturn_t wmt_i2c_isr(int irq, void *data) { - struct wmt_i2c_dev *i2c_dev = data; + struct wmt_i2c *i2c = data; /* save the status and write-clear it */ - i2c_dev->cmd_status = readw(i2c_dev->base + WMTI2C_REG_ISR); - writew(i2c_dev->cmd_status, i2c_dev->base + WMTI2C_REG_ISR); + i2c->cmd_status = readw(i2c->base + WMTI2C_REG_ISR); + writew(i2c->cmd_status, i2c->base + WMTI2C_REG_ISR); - complete(&i2c_dev->complete); + complete(&i2c->complete); return IRQ_HANDLED; } -static int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c_dev **pi2c_dev) +static int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c **pi2c) { int err; - struct wmt_i2c_dev *i2c_dev; + struct wmt_i2c *i2c; struct device_node *np = pdev->dev.of_node; - i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); - if (!i2c_dev) + i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); + if (!i2c) return -ENOMEM; - i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); - if (IS_ERR(i2c_dev->base)) - return PTR_ERR(i2c_dev->base); + i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + if (IS_ERR(i2c->base)) + return PTR_ERR(i2c->base); - i2c_dev->irq = irq_of_parse_and_map(np, 0); - if (!i2c_dev->irq) + i2c->irq = irq_of_parse_and_map(np, 0); + if (!i2c->irq) return -EINVAL; - err = devm_request_irq(&pdev->dev, i2c_dev->irq, wmt_i2c_isr, - 0, pdev->name, i2c_dev); + err = devm_request_irq(&pdev->dev, i2c->irq, wmt_i2c_isr, + 0, pdev->name, i2c); if (err) return dev_err_probe(&pdev->dev, err, - "failed to request irq %i\n", i2c_dev->irq); + "failed to request irq %i\n", i2c->irq); - i2c_dev->dev = &pdev->dev; - init_completion(&i2c_dev->complete); - platform_set_drvdata(pdev, i2c_dev); + i2c->dev = &pdev->dev; + init_completion(&i2c->complete); + platform_set_drvdata(pdev, i2c); - *pi2c_dev = i2c_dev; + *pi2c = i2c; return 0; } -static int wmt_i2c_reset_hardware(struct wmt_i2c_dev *i2c_dev) +static int wmt_i2c_reset_hardware(struct wmt_i2c *i2c) { int err; + void __iomem *base = i2c->base; - err = clk_prepare_enable(i2c_dev->clk); + err = clk_prepare_enable(i2c->clk); if (err) { - dev_err(i2c_dev->dev, "failed to enable clock\n"); + dev_err(i2c->dev, "failed to enable clock\n"); return err; } - err = clk_set_rate(i2c_dev->clk, 20000000); + err = clk_set_rate(i2c->clk, 20000000); if (err) { - dev_err(i2c_dev->dev, "failed to set clock = 20Mhz\n"); - clk_disable_unprepare(i2c_dev->clk); + dev_err(i2c->dev, "failed to set clock = 20Mhz\n"); + clk_disable_unprepare(i2c->clk); return err; } - writew(0, i2c_dev->base + WMTI2C_REG_CR); - writew(WMTI2C_MCR_APB_166M, i2c_dev->base + WMTI2C_REG_MCR); - writew(WMTI2C_ISR_WRITE_ALL, i2c_dev->base + WMTI2C_REG_ISR); - writew(WMTI2C_IMR_ENABLE_ALL, i2c_dev->base + WMTI2C_REG_IMR); - writew(WMTI2C_CR_ENABLE, i2c_dev->base + WMTI2C_REG_CR); - readw(i2c_dev->base + WMTI2C_REG_CSR); /* read clear */ - writew(WMTI2C_ISR_WRITE_ALL, i2c_dev->base + WMTI2C_REG_ISR); + writew(0, base + WMTI2C_REG_CR); + writew(WMTI2C_MCR_APB_166M, base + WMTI2C_REG_MCR); + writew(WMTI2C_ISR_WRITE_ALL, base + WMTI2C_REG_ISR); + writew(WMTI2C_IMR_ENABLE_ALL, base + WMTI2C_REG_IMR); + writew(WMTI2C_CR_ENABLE, base + WMTI2C_REG_CR); + readw(base + WMTI2C_REG_CSR); /* read clear */ + writew(WMTI2C_ISR_WRITE_ALL, base + WMTI2C_REG_ISR); - if (i2c_dev->tcr == WMTI2C_TCR_FAST_MODE) - writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_HS, i2c_dev->base + WMTI2C_REG_TR); + if (i2c->tcr == WMTI2C_TCR_FAST_MODE) + writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_HS, base + WMTI2C_REG_TR); else - writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_STD, i2c_dev->base + WMTI2C_REG_TR); + writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_STD, base + WMTI2C_REG_TR); return 0; } @@ -354,34 +363,34 @@ static int wmt_i2c_reset_hardware(struct wmt_i2c_dev *i2c_dev) static int wmt_i2c_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct wmt_i2c_dev *i2c_dev; + struct wmt_i2c *i2c; struct i2c_adapter *adap; int err; u32 clk_rate; - err = wmt_i2c_init(pdev, &i2c_dev); + err = wmt_i2c_init(pdev, &i2c); if (err) return err; - i2c_dev->clk = of_clk_get(np, 0); - if (IS_ERR(i2c_dev->clk)) { + i2c->clk = of_clk_get(np, 0); + if (IS_ERR(i2c->clk)) { dev_err(&pdev->dev, "unable to request clock\n"); - return PTR_ERR(i2c_dev->clk); + return PTR_ERR(i2c->clk); } err = of_property_read_u32(np, "clock-frequency", &clk_rate); if (!err && (clk_rate == I2C_MAX_FAST_MODE_FREQ)) - i2c_dev->tcr = WMTI2C_TCR_FAST_MODE; + i2c->tcr = WMTI2C_TCR_FAST_MODE; - adap = &i2c_dev->adapter; - i2c_set_adapdata(adap, i2c_dev); + adap = &i2c->adapter; + i2c_set_adapdata(adap, i2c); strscpy(adap->name, "WMT I2C adapter", sizeof(adap->name)); adap->owner = THIS_MODULE; adap->algo = &wmt_i2c_algo; adap->dev.parent = &pdev->dev; adap->dev.of_node = pdev->dev.of_node; - err = wmt_i2c_reset_hardware(i2c_dev); + err = wmt_i2c_reset_hardware(i2c); if (err) { dev_err(&pdev->dev, "error initializing hardware\n"); return err; @@ -392,12 +401,12 @@ static int wmt_i2c_probe(struct platform_device *pdev) static void wmt_i2c_remove(struct platform_device *pdev) { - struct wmt_i2c_dev *i2c_dev = platform_get_drvdata(pdev); + struct wmt_i2c *i2c = platform_get_drvdata(pdev); /* Disable interrupts, clock and delete adapter */ - writew(0, i2c_dev->base + WMTI2C_REG_IMR); - clk_disable_unprepare(i2c_dev->clk); - i2c_del_adapter(&i2c_dev->adapter); + writew(0, i2c->base + WMTI2C_REG_IMR); + clk_disable_unprepare(i2c->clk); + i2c_del_adapter(&i2c->adapter); } static const struct of_device_id wmt_i2c_dt_ids[] = { From patchwork Fri Dec 29 06:30:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Hu X-Patchwork-Id: 759536 Received: from mx2.zhaoxin.com (mx2.zhaoxin.com [203.110.167.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ADE06567C for ; Fri, 29 Dec 2023 06:30:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=zhaoxin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zhaoxin.com X-ASG-Debug-ID: 1703831442-1eb14e0c7c090f0001-PT6Irj Received: from ZXSHMBX2.zhaoxin.com (ZXSHMBX2.zhaoxin.com [10.28.252.164]) by mx2.zhaoxin.com with ESMTP id nGjcqmIsBXH5FbzF (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Fri, 29 Dec 2023 14:30:42 +0800 (CST) X-Barracuda-Envelope-From: HansHu-oc@zhaoxin.com X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.164 Received: from ZXBJMBX03.zhaoxin.com (10.29.252.7) by ZXSHMBX2.zhaoxin.com (10.28.252.164) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:42 +0800 Received: from ml-HP-ProDesk-680-G4-MT.zhaoxin.com (10.28.66.68) by ZXBJMBX03.zhaoxin.com (10.29.252.7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:41 +0800 X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.164 From: Hans Hu X-Barracuda-RBL-Trusted-Forwarder: 10.29.252.7 To: , CC: , , Subject: [PATCH v6 4/8] i2c: wmt: split out common files Date: Fri, 29 Dec 2023 14:30:35 +0800 X-ASG-Orig-Subj: [PATCH v6 4/8] i2c: wmt: split out common files Message-ID: <1871ceb5c3d6804c6a7f7a38327919861985c066.1703830854.git.hanshu-oc@zhaoxin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-i2c@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: zxbjmbx1.zhaoxin.com (10.29.252.163) To ZXBJMBX03.zhaoxin.com (10.29.252.7) X-Barracuda-Connect: ZXSHMBX2.zhaoxin.com[10.28.252.164] X-Barracuda-Start-Time: 1703831442 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://10.28.252.36:4443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at zhaoxin.com X-Barracuda-Scan-Msg-Size: 25021 X-Barracuda-BRTS-Status: 0 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using global scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=9.0 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.118704 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Since the I2C IP of both wmt and zhaoxin come from VIA, the common driver is named as i2c-viai2c-common.c. Old i2c-wmt.c renamed to i2c-wmt-plt.c. The MAINTAINERS information will added in patch 0008. Signed-off-by: Hans Hu --- MAINTAINERS | 2 +- drivers/i2c/busses/Makefile | 2 + drivers/i2c/busses/i2c-viai2c-common.c | 234 ++++++++++++++ drivers/i2c/busses/i2c-viai2c-common.h | 66 ++++ drivers/i2c/busses/i2c-wmt-plt.c | 137 ++++++++ drivers/i2c/busses/i2c-wmt.c | 431 ------------------------- 6 files changed, 440 insertions(+), 432 deletions(-) create mode 100644 drivers/i2c/busses/i2c-viai2c-common.c create mode 100644 drivers/i2c/busses/i2c-viai2c-common.h create mode 100644 drivers/i2c/busses/i2c-wmt-plt.c delete mode 100644 drivers/i2c/busses/i2c-wmt.c diff --git a/MAINTAINERS b/MAINTAINERS index 9104430e148e..c3005c2c9dd2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2988,7 +2988,7 @@ S: Orphan F: Documentation/devicetree/bindings/i2c/i2c-wmt.txt F: arch/arm/mach-vt8500/ F: drivers/clocksource/timer-vt8500.c -F: drivers/i2c/busses/i2c-wmt.c +F: drivers/i2c/busses/i2c-wmt-plt.c F: drivers/mmc/host/wmt-sdmmc.c F: drivers/pwm/pwm-vt8500.c F: drivers/rtc/rtc-vt8500.c diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 3757b9391e60..2ac59c585c08 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -120,7 +120,9 @@ obj-$(CONFIG_I2C_TEGRA_BPMP) += i2c-tegra-bpmp.o obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o obj-$(CONFIG_I2C_UNIPHIER_F) += i2c-uniphier-f.o obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o +i2c-wmt-objs := i2c-wmt-plt.o i2c-viai2c-common.o obj-$(CONFIG_I2C_WMT) += i2c-wmt.o + i2c-octeon-objs := i2c-octeon-core.o i2c-octeon-platdrv.o obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o i2c-thunderx-objs := i2c-octeon-core.o i2c-thunderx-pcidrv.o diff --git a/drivers/i2c/busses/i2c-viai2c-common.c b/drivers/i2c/busses/i2c-viai2c-common.c new file mode 100644 index 000000000000..76058d6853a7 --- /dev/null +++ b/drivers/i2c/busses/i2c-viai2c-common.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include +#include "i2c-viai2c-common.h" + +#define WMT_I2C_TIMEOUT (msecs_to_jiffies(1000)) + +static int wmt_i2c_wait_bus_not_busy(struct wmt_i2c *i2c) +{ + unsigned long timeout; + void __iomem *base = i2c->base; + + timeout = jiffies + WMT_I2C_TIMEOUT; + while (!(readw(base + WMTI2C_REG_CSR) & WMTI2C_CSR_READY_MASK)) { + if (time_after(jiffies, timeout)) { + dev_warn(i2c->dev, + "timeout waiting for bus ready\n"); + return -EBUSY; + } + msleep(20); + } + + return 0; +} + +static int wmt_check_status(struct wmt_i2c *i2c) +{ + int ret = 0; + unsigned long wait_result; + + wait_result = wait_for_completion_timeout(&i2c->complete, + msecs_to_jiffies(500)); + if (!wait_result) + return -ETIMEDOUT; + + if (i2c->cmd_status & WMTI2C_ISR_NACK_ADDR) + ret = -EIO; + + if (i2c->cmd_status & WMTI2C_ISR_SCL_TIMEOUT) + ret = -ETIMEDOUT; + + return ret; +} + +static irqreturn_t wmt_i2c_isr(int irq, void *data) +{ + struct wmt_i2c *i2c = data; + + /* save the status and write-clear it */ + i2c->cmd_status = readw(i2c->base + WMTI2C_REG_ISR); + writew(i2c->cmd_status, i2c->base + WMTI2C_REG_ISR); + + complete(&i2c->complete); + + return IRQ_HANDLED; +} + +static int wmt_i2c_write(struct wmt_i2c *i2c, struct i2c_msg *pmsg, + int last) +{ + u16 val, tcr_val = i2c->tcr; + int ret; + int xfer_len = 0; + void __iomem *base = i2c->base; + + if (pmsg->len == 0) { + /* + * We still need to run through the while (..) once, so + * start at -1 and break out early from the loop + */ + xfer_len = -1; + writew(0, base + WMTI2C_REG_CDR); + } else { + writew(pmsg->buf[0] & 0xFF, base + WMTI2C_REG_CDR); + } + + if (!(pmsg->flags & I2C_M_NOSTART)) { + val = readw(base + WMTI2C_REG_CR); + val &= ~WMTI2C_CR_TX_END; + val |= WMTI2C_CR_CPU_RDY; + writew(val, base + WMTI2C_REG_CR); + } + + reinit_completion(&i2c->complete); + + tcr_val |= (WMTI2C_TCR_MASTER_WRITE + | (pmsg->addr & WMTI2C_TCR_SLAVE_ADDR_MASK)); + + writew(tcr_val, base + WMTI2C_REG_TCR); + + if (pmsg->flags & I2C_M_NOSTART) { + val = readw(base + WMTI2C_REG_CR); + val |= WMTI2C_CR_CPU_RDY; + writew(val, base + WMTI2C_REG_CR); + } + + while (xfer_len < pmsg->len) { + ret = wmt_check_status(i2c); + if (ret) + return ret; + + xfer_len++; + + val = readw(base + WMTI2C_REG_CSR); + if (val & WMTI2C_CSR_RCV_NOT_ACK) { + dev_dbg(i2c->dev, "write RCV NACK error\n"); + return -EIO; + } + + if (pmsg->len == 0) { + val = WMTI2C_CR_TX_END | WMTI2C_CR_CPU_RDY + | WMTI2C_CR_ENABLE; + writew(val, base + WMTI2C_REG_CR); + break; + } + + if (xfer_len == pmsg->len) { + if (last != 1) + writew(WMTI2C_CR_ENABLE, base + WMTI2C_REG_CR); + } else { + writew(pmsg->buf[xfer_len] & 0xFF, + base + WMTI2C_REG_CDR); + writew(WMTI2C_CR_CPU_RDY | WMTI2C_CR_ENABLE, + base + WMTI2C_REG_CR); + } + } + + return 0; +} + +static int wmt_i2c_read(struct wmt_i2c *i2c, struct i2c_msg *pmsg) +{ + u16 val, tcr_val = i2c->tcr; + int ret; + u32 xfer_len = 0; + void __iomem *base = i2c->base; + + val = readw(base + WMTI2C_REG_CR); + val &= ~(WMTI2C_CR_TX_END | WMTI2C_CR_TX_NEXT_NO_ACK); + + if (!(pmsg->flags & I2C_M_NOSTART)) + val |= WMTI2C_CR_CPU_RDY; + + if (pmsg->len == 1) + val |= WMTI2C_CR_TX_NEXT_NO_ACK; + + writew(val, base + WMTI2C_REG_CR); + + reinit_completion(&i2c->complete); + + tcr_val |= WMTI2C_TCR_MASTER_READ + | (pmsg->addr & WMTI2C_TCR_SLAVE_ADDR_MASK); + + writew(tcr_val, base + WMTI2C_REG_TCR); + + if (pmsg->flags & I2C_M_NOSTART) { + val = readw(base + WMTI2C_REG_CR); + val |= WMTI2C_CR_CPU_RDY; + writew(val, base + WMTI2C_REG_CR); + } + + while (xfer_len < pmsg->len) { + ret = wmt_check_status(i2c); + if (ret) + return ret; + + pmsg->buf[xfer_len] = readw(base + WMTI2C_REG_CDR) >> 8; + xfer_len++; + + val = readw(base + WMTI2C_REG_CR) | WMTI2C_CR_CPU_RDY; + if (xfer_len == pmsg->len - 1) + val |= WMTI2C_CR_TX_NEXT_NO_ACK; + writew(val, base + WMTI2C_REG_CR); + } + + return 0; +} + +int wmt_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg msgs[], + int num) +{ + struct i2c_msg *pmsg; + int i; + int ret = 0; + struct wmt_i2c *i2c = i2c_get_adapdata(adap); + + for (i = 0; ret >= 0 && i < num; i++) { + pmsg = &msgs[i]; + if (!(pmsg->flags & I2C_M_NOSTART)) { + ret = wmt_i2c_wait_bus_not_busy(i2c); + if (ret < 0) + return ret; + } + + if (pmsg->flags & I2C_M_RD) + ret = wmt_i2c_read(i2c, pmsg); + else + ret = wmt_i2c_write(i2c, pmsg, (i + 1) == num); + } + + return (ret < 0) ? ret : i; +} + +int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c **pi2c) +{ + int err; + struct wmt_i2c *i2c; + struct device_node *np = pdev->dev.of_node; + + i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + if (IS_ERR(i2c->base)) + return PTR_ERR(i2c->base); + + i2c->irq = irq_of_parse_and_map(np, 0); + if (!i2c->irq) + return -EINVAL; + + err = devm_request_irq(&pdev->dev, i2c->irq, wmt_i2c_isr, + 0, pdev->name, i2c); + if (err) + return dev_err_probe(&pdev->dev, err, + "failed to request irq %i\n", i2c->irq); + + i2c->dev = &pdev->dev; + init_completion(&i2c->complete); + platform_set_drvdata(pdev, i2c); + + *pi2c = i2c; + return 0; +} diff --git a/drivers/i2c/busses/i2c-viai2c-common.h b/drivers/i2c/busses/i2c-viai2c-common.h new file mode 100644 index 000000000000..e57da0dc68a5 --- /dev/null +++ b/drivers/i2c/busses/i2c-viai2c-common.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef __I2C_VIAI2C_COMMON_H_ +#define __I2C_VIAI2C_COMMON_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* REG_CR Bit fields */ +#define WMTI2C_REG_CR 0x00 +#define WMTI2C_CR_TX_NEXT_ACK 0x0000 +#define WMTI2C_CR_ENABLE 0x0001 +#define WMTI2C_CR_TX_NEXT_NO_ACK 0x0002 +#define WMTI2C_CR_TX_END 0x0004 +#define WMTI2C_CR_CPU_RDY 0x0008 + +/* REG_TCR Bit fields */ +#define WMTI2C_REG_TCR 0x02 +#define WMTI2C_TCR_STANDARD_MODE 0x0000 +#define WMTI2C_TCR_MASTER_WRITE 0x0000 +#define WMTI2C_TCR_HS_MODE 0x2000 +#define WMTI2C_TCR_MASTER_READ 0x4000 +#define WMTI2C_TCR_FAST_MODE 0x8000 +#define WMTI2C_TCR_SLAVE_ADDR_MASK 0x007F + +/* REG_CSR Bit fields */ +#define WMTI2C_REG_CSR 0x04 +#define WMTI2C_CSR_RCV_NOT_ACK 0x0001 +#define WMTI2C_CSR_RCV_ACK_MASK 0x0001 +#define WMTI2C_CSR_READY_MASK 0x0002 + +/* REG_ISR Bit fields */ +#define WMTI2C_REG_ISR 0x06 +#define WMTI2C_ISR_NACK_ADDR 0x0001 +#define WMTI2C_ISR_BYTE_END 0x0002 +#define WMTI2C_ISR_SCL_TIMEOUT 0x0004 +#define WMTI2C_ISR_WRITE_ALL 0x0007 + +/* REG_IMR Bit fields */ +#define WMTI2C_REG_IMR 0x08 +#define WMTI2C_IMR_ENABLE_ALL 0x0007 + +#define WMTI2C_REG_CDR 0x0A +#define WMTI2C_REG_TR 0x0C +#define WMTI2C_REG_MCR 0x0E + +struct wmt_i2c { + struct i2c_adapter adapter; + struct completion complete; + struct device *dev; + void __iomem *base; + struct clk *clk; + u16 tcr; + int irq; + u16 cmd_status; +}; + +int wmt_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num); +int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c **pi2c); + +#endif diff --git a/drivers/i2c/busses/i2c-wmt-plt.c b/drivers/i2c/busses/i2c-wmt-plt.c new file mode 100644 index 000000000000..e0ffccf8a40a --- /dev/null +++ b/drivers/i2c/busses/i2c-wmt-plt.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Wondermedia I2C Master Mode Driver + * + * Copyright (C) 2012 Tony Prisk + * + * Derived from GPLv2+ licensed source: + * - Copyright (C) 2008 WonderMedia Technologies, Inc. + */ + +#include +#include +#include +#include "i2c-viai2c-common.h" + +/* REG_TR */ +#define WMTI2C_SCL_TIMEOUT(x) (((x) & 0xFF) << 8) +#define WMTI2C_TR_STD 0x0064 +#define WMTI2C_TR_HS 0x0019 + +/* REG_MCR */ +#define WMTI2C_MCR_APB_96M 7 +#define WMTI2C_MCR_APB_166M 12 + +static u32 wmt_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART; +} + +static const struct i2c_algorithm wmt_i2c_algo = { + .master_xfer = wmt_i2c_xfer, + .functionality = wmt_i2c_func, +}; + +static int wmt_i2c_reset_hardware(struct wmt_i2c *i2c) +{ + int err; + void __iomem *base = i2c->base; + + err = clk_prepare_enable(i2c->clk); + if (err) { + dev_err(i2c->dev, "failed to enable clock\n"); + return err; + } + + err = clk_set_rate(i2c->clk, 20000000); + if (err) { + dev_err(i2c->dev, "failed to set clock = 20Mhz\n"); + clk_disable_unprepare(i2c->clk); + return err; + } + + writew(0, base + WMTI2C_REG_CR); + writew(WMTI2C_MCR_APB_166M, base + WMTI2C_REG_MCR); + writew(WMTI2C_ISR_WRITE_ALL, base + WMTI2C_REG_ISR); + writew(WMTI2C_IMR_ENABLE_ALL, base + WMTI2C_REG_IMR); + writew(WMTI2C_CR_ENABLE, base + WMTI2C_REG_CR); + readw(base + WMTI2C_REG_CSR); /* read clear */ + writew(WMTI2C_ISR_WRITE_ALL, base + WMTI2C_REG_ISR); + + if (i2c->tcr == WMTI2C_TCR_FAST_MODE) + writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_HS, base + WMTI2C_REG_TR); + else + writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_STD, base + WMTI2C_REG_TR); + + return 0; +} + +static int wmt_i2c_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct wmt_i2c *i2c; + struct i2c_adapter *adap; + int err; + u32 clk_rate; + + err = wmt_i2c_init(pdev, &i2c); + if (err) + return err; + + i2c->clk = of_clk_get(np, 0); + if (IS_ERR(i2c->clk)) { + dev_err(&pdev->dev, "unable to request clock\n"); + return PTR_ERR(i2c->clk); + } + + err = of_property_read_u32(np, "clock-frequency", &clk_rate); + if (!err && (clk_rate == I2C_MAX_FAST_MODE_FREQ)) + i2c->tcr = WMTI2C_TCR_FAST_MODE; + + adap = &i2c->adapter; + i2c_set_adapdata(adap, i2c); + strscpy(adap->name, "WMT I2C adapter", sizeof(adap->name)); + adap->owner = THIS_MODULE; + adap->algo = &wmt_i2c_algo; + adap->dev.parent = &pdev->dev; + adap->dev.of_node = pdev->dev.of_node; + + err = wmt_i2c_reset_hardware(i2c); + if (err) { + dev_err(&pdev->dev, "error initializing hardware\n"); + return err; + } + + return i2c_add_adapter(adap); +} + +static void wmt_i2c_remove(struct platform_device *pdev) +{ + struct wmt_i2c *i2c = platform_get_drvdata(pdev); + + /* Disable interrupts, clock and delete adapter */ + writew(0, i2c->base + WMTI2C_REG_IMR); + clk_disable_unprepare(i2c->clk); + i2c_del_adapter(&i2c->adapter); +} + +static const struct of_device_id wmt_i2c_dt_ids[] = { + { .compatible = "wm,wm8505-i2c" }, + { /* Sentinel */ }, +}; + +static struct platform_driver wmt_i2c_driver = { + .probe = wmt_i2c_probe, + .remove_new = wmt_i2c_remove, + .driver = { + .name = "wmt-i2c", + .of_match_table = wmt_i2c_dt_ids, + }, +}; + +module_platform_driver(wmt_i2c_driver); + +MODULE_DESCRIPTION("Wondermedia I2C master-mode bus adapter"); +MODULE_AUTHOR("Tony Prisk "); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(of, wmt_i2c_dt_ids); diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c deleted file mode 100644 index 76fba4ffa126..000000000000 --- a/drivers/i2c/busses/i2c-wmt.c +++ /dev/null @@ -1,431 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Wondermedia I2C Master Mode Driver - * - * Copyright (C) 2012 Tony Prisk - * - * Derived from GPLv2+ licensed source: - * - Copyright (C) 2008 WonderMedia Technologies, Inc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define WMTI2C_REG_CR 0x00 -#define WMTI2C_REG_TCR 0x02 -#define WMTI2C_REG_CSR 0x04 -#define WMTI2C_REG_ISR 0x06 -#define WMTI2C_REG_IMR 0x08 -#define WMTI2C_REG_CDR 0x0A -#define WMTI2C_REG_TR 0x0C -#define WMTI2C_REG_MCR 0x0E -#define WMTI2C_REG_SLAVE_CR 0x10 -#define WMTI2C_REG_SLAVE_SR 0x12 -#define WMTI2C_REG_SLAVE_ISR 0x14 -#define WMTI2C_REG_SLAVE_IMR 0x16 -#define WMTI2C_REG_SLAVE_DR 0x18 -#define WMTI2C_REG_SLAVE_TR 0x1A - -/* REG_CR Bit fields */ -#define WMTI2C_CR_TX_NEXT_ACK 0x0000 -#define WMTI2C_CR_ENABLE 0x0001 -#define WMTI2C_CR_TX_NEXT_NO_ACK 0x0002 -#define WMTI2C_CR_TX_END 0x0004 -#define WMTI2C_CR_CPU_RDY 0x0008 -#define WMTI2C_SLAV_MODE_SEL 0x8000 - -/* REG_TCR Bit fields */ -#define WMTI2C_TCR_STANDARD_MODE 0x0000 -#define WMTI2C_TCR_MASTER_WRITE 0x0000 -#define WMTI2C_TCR_HS_MODE 0x2000 -#define WMTI2C_TCR_MASTER_READ 0x4000 -#define WMTI2C_TCR_FAST_MODE 0x8000 -#define WMTI2C_TCR_SLAVE_ADDR_MASK 0x007F - -/* REG_ISR Bit fields */ -#define WMTI2C_ISR_NACK_ADDR 0x0001 -#define WMTI2C_ISR_BYTE_END 0x0002 -#define WMTI2C_ISR_SCL_TIMEOUT 0x0004 -#define WMTI2C_ISR_WRITE_ALL 0x0007 - -/* REG_IMR Bit fields */ -#define WMTI2C_IMR_ENABLE_ALL 0x0007 - -/* REG_CSR Bit fields */ -#define WMTI2C_CSR_RCV_NOT_ACK 0x0001 -#define WMTI2C_CSR_RCV_ACK_MASK 0x0001 -#define WMTI2C_CSR_READY_MASK 0x0002 - -/* REG_TR */ -#define WMTI2C_SCL_TIMEOUT(x) (((x) & 0xFF) << 8) -#define WMTI2C_TR_STD 0x0064 -#define WMTI2C_TR_HS 0x0019 - -/* REG_MCR */ -#define WMTI2C_MCR_APB_96M 7 -#define WMTI2C_MCR_APB_166M 12 - -#define WMT_I2C_TIMEOUT (msecs_to_jiffies(1000)) - -struct wmt_i2c { - struct i2c_adapter adapter; - struct completion complete; - struct device *dev; - void __iomem *base; - struct clk *clk; - u16 tcr; - int irq; - u16 cmd_status; -}; - -static int wmt_i2c_wait_bus_not_busy(struct wmt_i2c *i2c) -{ - unsigned long timeout; - void __iomem *base = i2c->base; - - timeout = jiffies + WMT_I2C_TIMEOUT; - while (!(readw(base + WMTI2C_REG_CSR) & WMTI2C_CSR_READY_MASK)) { - if (time_after(jiffies, timeout)) { - dev_warn(i2c->dev, - "timeout waiting for bus ready\n"); - return -EBUSY; - } - msleep(20); - } - - return 0; -} - -static int wmt_check_status(struct wmt_i2c *i2c) -{ - int ret = 0; - unsigned long wait_result; - - wait_result = wait_for_completion_timeout(&i2c->complete, - msecs_to_jiffies(500)); - if (!wait_result) - return -ETIMEDOUT; - - if (i2c->cmd_status & WMTI2C_ISR_NACK_ADDR) - ret = -EIO; - - if (i2c->cmd_status & WMTI2C_ISR_SCL_TIMEOUT) - ret = -ETIMEDOUT; - - return ret; -} - -static int wmt_i2c_write(struct wmt_i2c *i2c, struct i2c_msg *pmsg, - int last) -{ - u16 val, tcr_val = i2c->tcr; - int ret; - int xfer_len = 0; - void __iomem *base = i2c->base; - - if (pmsg->len == 0) { - /* - * We still need to run through the while (..) once, so - * start at -1 and break out early from the loop - */ - xfer_len = -1; - writew(0, base + WMTI2C_REG_CDR); - } else { - writew(pmsg->buf[0] & 0xFF, base + WMTI2C_REG_CDR); - } - - if (!(pmsg->flags & I2C_M_NOSTART)) { - val = readw(base + WMTI2C_REG_CR); - val &= ~WMTI2C_CR_TX_END; - val |= WMTI2C_CR_CPU_RDY; - writew(val, base + WMTI2C_REG_CR); - } - - reinit_completion(&i2c->complete); - - tcr_val |= (WMTI2C_TCR_MASTER_WRITE - | (pmsg->addr & WMTI2C_TCR_SLAVE_ADDR_MASK)); - - writew(tcr_val, base + WMTI2C_REG_TCR); - - if (pmsg->flags & I2C_M_NOSTART) { - val = readw(base + WMTI2C_REG_CR); - val |= WMTI2C_CR_CPU_RDY; - writew(val, base + WMTI2C_REG_CR); - } - - while (xfer_len < pmsg->len) { - ret = wmt_check_status(i2c); - if (ret) - return ret; - - xfer_len++; - - val = readw(base + WMTI2C_REG_CSR); - if (val & WMTI2C_CSR_RCV_NOT_ACK) { - dev_dbg(i2c->dev, "write RCV NACK error\n"); - return -EIO; - } - - if (pmsg->len == 0) { - val = WMTI2C_CR_TX_END | WMTI2C_CR_CPU_RDY - | WMTI2C_CR_ENABLE; - writew(val, base + WMTI2C_REG_CR); - break; - } - - if (xfer_len == pmsg->len) { - if (last != 1) - writew(WMTI2C_CR_ENABLE, base + WMTI2C_REG_CR); - } else { - writew(pmsg->buf[xfer_len] & 0xFF, - base + WMTI2C_REG_CDR); - writew(WMTI2C_CR_CPU_RDY | WMTI2C_CR_ENABLE, - base + WMTI2C_REG_CR); - } - } - - return 0; -} - -static int wmt_i2c_read(struct wmt_i2c *i2c, struct i2c_msg *pmsg) -{ - u16 val, tcr_val = i2c->tcr; - int ret; - u32 xfer_len = 0; - void __iomem *base = i2c->base; - - val = readw(base + WMTI2C_REG_CR); - val &= ~(WMTI2C_CR_TX_END | WMTI2C_CR_TX_NEXT_NO_ACK); - - if (!(pmsg->flags & I2C_M_NOSTART)) - val |= WMTI2C_CR_CPU_RDY; - - if (pmsg->len == 1) - val |= WMTI2C_CR_TX_NEXT_NO_ACK; - - writew(val, base + WMTI2C_REG_CR); - - reinit_completion(&i2c->complete); - - tcr_val |= WMTI2C_TCR_MASTER_READ - | (pmsg->addr & WMTI2C_TCR_SLAVE_ADDR_MASK); - - writew(tcr_val, base + WMTI2C_REG_TCR); - - if (pmsg->flags & I2C_M_NOSTART) { - val = readw(base + WMTI2C_REG_CR); - val |= WMTI2C_CR_CPU_RDY; - writew(val, base + WMTI2C_REG_CR); - } - - while (xfer_len < pmsg->len) { - ret = wmt_check_status(i2c); - if (ret) - return ret; - - pmsg->buf[xfer_len] = readw(base + WMTI2C_REG_CDR) >> 8; - xfer_len++; - - val = readw(base + WMTI2C_REG_CR) | WMTI2C_CR_CPU_RDY; - if (xfer_len == pmsg->len - 1) - val |= WMTI2C_CR_TX_NEXT_NO_ACK; - writew(val, base + WMTI2C_REG_CR); - } - - return 0; -} - -static int wmt_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg msgs[], - int num) -{ - struct i2c_msg *pmsg; - int i; - int ret = 0; - struct wmt_i2c *i2c = i2c_get_adapdata(adap); - - for (i = 0; ret >= 0 && i < num; i++) { - pmsg = &msgs[i]; - if (!(pmsg->flags & I2C_M_NOSTART)) { - ret = wmt_i2c_wait_bus_not_busy(i2c); - if (ret < 0) - return ret; - } - - if (pmsg->flags & I2C_M_RD) - ret = wmt_i2c_read(i2c, pmsg); - else - ret = wmt_i2c_write(i2c, pmsg, (i + 1) == num); - } - - return (ret < 0) ? ret : i; -} - -static u32 wmt_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART; -} - -static const struct i2c_algorithm wmt_i2c_algo = { - .master_xfer = wmt_i2c_xfer, - .functionality = wmt_i2c_func, -}; - -static irqreturn_t wmt_i2c_isr(int irq, void *data) -{ - struct wmt_i2c *i2c = data; - - /* save the status and write-clear it */ - i2c->cmd_status = readw(i2c->base + WMTI2C_REG_ISR); - writew(i2c->cmd_status, i2c->base + WMTI2C_REG_ISR); - - complete(&i2c->complete); - - return IRQ_HANDLED; -} - -static int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c **pi2c) -{ - int err; - struct wmt_i2c *i2c; - struct device_node *np = pdev->dev.of_node; - - i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); - if (!i2c) - return -ENOMEM; - - i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); - if (IS_ERR(i2c->base)) - return PTR_ERR(i2c->base); - - i2c->irq = irq_of_parse_and_map(np, 0); - if (!i2c->irq) - return -EINVAL; - - err = devm_request_irq(&pdev->dev, i2c->irq, wmt_i2c_isr, - 0, pdev->name, i2c); - if (err) - return dev_err_probe(&pdev->dev, err, - "failed to request irq %i\n", i2c->irq); - - i2c->dev = &pdev->dev; - init_completion(&i2c->complete); - platform_set_drvdata(pdev, i2c); - - *pi2c = i2c; - return 0; -} - -static int wmt_i2c_reset_hardware(struct wmt_i2c *i2c) -{ - int err; - void __iomem *base = i2c->base; - - err = clk_prepare_enable(i2c->clk); - if (err) { - dev_err(i2c->dev, "failed to enable clock\n"); - return err; - } - - err = clk_set_rate(i2c->clk, 20000000); - if (err) { - dev_err(i2c->dev, "failed to set clock = 20Mhz\n"); - clk_disable_unprepare(i2c->clk); - return err; - } - - writew(0, base + WMTI2C_REG_CR); - writew(WMTI2C_MCR_APB_166M, base + WMTI2C_REG_MCR); - writew(WMTI2C_ISR_WRITE_ALL, base + WMTI2C_REG_ISR); - writew(WMTI2C_IMR_ENABLE_ALL, base + WMTI2C_REG_IMR); - writew(WMTI2C_CR_ENABLE, base + WMTI2C_REG_CR); - readw(base + WMTI2C_REG_CSR); /* read clear */ - writew(WMTI2C_ISR_WRITE_ALL, base + WMTI2C_REG_ISR); - - if (i2c->tcr == WMTI2C_TCR_FAST_MODE) - writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_HS, base + WMTI2C_REG_TR); - else - writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_STD, base + WMTI2C_REG_TR); - - return 0; -} - -static int wmt_i2c_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct wmt_i2c *i2c; - struct i2c_adapter *adap; - int err; - u32 clk_rate; - - err = wmt_i2c_init(pdev, &i2c); - if (err) - return err; - - i2c->clk = of_clk_get(np, 0); - if (IS_ERR(i2c->clk)) { - dev_err(&pdev->dev, "unable to request clock\n"); - return PTR_ERR(i2c->clk); - } - - err = of_property_read_u32(np, "clock-frequency", &clk_rate); - if (!err && (clk_rate == I2C_MAX_FAST_MODE_FREQ)) - i2c->tcr = WMTI2C_TCR_FAST_MODE; - - adap = &i2c->adapter; - i2c_set_adapdata(adap, i2c); - strscpy(adap->name, "WMT I2C adapter", sizeof(adap->name)); - adap->owner = THIS_MODULE; - adap->algo = &wmt_i2c_algo; - adap->dev.parent = &pdev->dev; - adap->dev.of_node = pdev->dev.of_node; - - err = wmt_i2c_reset_hardware(i2c); - if (err) { - dev_err(&pdev->dev, "error initializing hardware\n"); - return err; - } - - return i2c_add_adapter(adap); -} - -static void wmt_i2c_remove(struct platform_device *pdev) -{ - struct wmt_i2c *i2c = platform_get_drvdata(pdev); - - /* Disable interrupts, clock and delete adapter */ - writew(0, i2c->base + WMTI2C_REG_IMR); - clk_disable_unprepare(i2c->clk); - i2c_del_adapter(&i2c->adapter); -} - -static const struct of_device_id wmt_i2c_dt_ids[] = { - { .compatible = "wm,wm8505-i2c" }, - { /* Sentinel */ }, -}; - -static struct platform_driver wmt_i2c_driver = { - .probe = wmt_i2c_probe, - .remove_new = wmt_i2c_remove, - .driver = { - .name = "wmt-i2c", - .of_match_table = wmt_i2c_dt_ids, - }, -}; - -module_platform_driver(wmt_i2c_driver); - -MODULE_DESCRIPTION("Wondermedia I2C master-mode bus adapter"); -MODULE_AUTHOR("Tony Prisk "); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(of, wmt_i2c_dt_ids); From patchwork Fri Dec 29 06:30:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Hu X-Patchwork-Id: 759537 Received: from mx2.zhaoxin.com (mx2.zhaoxin.com [203.110.167.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 446215696 for ; Fri, 29 Dec 2023 06:30:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=zhaoxin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zhaoxin.com X-ASG-Debug-ID: 1703831442-1eb14e0c7c090f0002-PT6Irj Received: from ZXSHMBX2.zhaoxin.com (ZXSHMBX2.zhaoxin.com [10.28.252.164]) by mx2.zhaoxin.com with ESMTP id DgXDocHuxJZj1pMW (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Fri, 29 Dec 2023 14:30:43 +0800 (CST) X-Barracuda-Envelope-From: HansHu-oc@zhaoxin.com X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.164 Received: from ZXBJMBX03.zhaoxin.com (10.29.252.7) by ZXSHMBX2.zhaoxin.com (10.28.252.164) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:42 +0800 Received: from ml-HP-ProDesk-680-G4-MT.zhaoxin.com (10.28.66.68) by ZXBJMBX03.zhaoxin.com (10.29.252.7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:42 +0800 X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.164 From: Hans Hu X-Barracuda-RBL-Trusted-Forwarder: 10.29.252.7 To: , CC: , , Subject: [PATCH v6 5/8] i2c: wmt: rename with prefix VIAI2C_ and viai2c_ Date: Fri, 29 Dec 2023 14:30:36 +0800 X-ASG-Orig-Subj: [PATCH v6 5/8] i2c: wmt: rename with prefix VIAI2C_ and viai2c_ Message-ID: <65b930cefd380ce45e0e1b3967bc7f51737b0948.1703830854.git.hanshu-oc@zhaoxin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-i2c@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: zxbjmbx1.zhaoxin.com (10.29.252.163) To ZXBJMBX03.zhaoxin.com (10.29.252.7) X-Barracuda-Connect: ZXSHMBX2.zhaoxin.com[10.28.252.164] X-Barracuda-Start-Time: 1703831442 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://10.28.252.36:4443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at zhaoxin.com X-Barracuda-Scan-Msg-Size: 14082 X-Barracuda-BRTS-Status: 1 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using global scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=9.0 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.118704 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Since the I2C IP of both wmt and zhaoxin come from VIA. So, rename common register, function and variable's name to VIAI2C_ and viai2c_. Signed-off-by: Hans Hu --- drivers/i2c/busses/i2c-viai2c-common.c | 118 ++++++++++++------------- drivers/i2c/busses/i2c-viai2c-common.h | 60 ++++++------- drivers/i2c/busses/i2c-wmt-plt.c | 30 ++++--- 3 files changed, 105 insertions(+), 103 deletions(-) diff --git a/drivers/i2c/busses/i2c-viai2c-common.c b/drivers/i2c/busses/i2c-viai2c-common.c index 76058d6853a7..60a4d4ccaf12 100644 --- a/drivers/i2c/busses/i2c-viai2c-common.c +++ b/drivers/i2c/busses/i2c-viai2c-common.c @@ -2,15 +2,15 @@ #include #include "i2c-viai2c-common.h" -#define WMT_I2C_TIMEOUT (msecs_to_jiffies(1000)) +#define VIAI2C_TIMEOUT (msecs_to_jiffies(1000)) -static int wmt_i2c_wait_bus_not_busy(struct wmt_i2c *i2c) +static int viai2c_wait_bus_ready(struct viai2c *i2c) { unsigned long timeout; void __iomem *base = i2c->base; - timeout = jiffies + WMT_I2C_TIMEOUT; - while (!(readw(base + WMTI2C_REG_CSR) & WMTI2C_CSR_READY_MASK)) { + timeout = jiffies + VIAI2C_TIMEOUT; + while (!(readw(base + VIAI2C_REG_CSR) & VIAI2C_CSR_READY_MASK)) { if (time_after(jiffies, timeout)) { dev_warn(i2c->dev, "timeout waiting for bus ready\n"); @@ -22,7 +22,7 @@ static int wmt_i2c_wait_bus_not_busy(struct wmt_i2c *i2c) return 0; } -static int wmt_check_status(struct wmt_i2c *i2c) +static int viai2c_wait_status(struct viai2c *i2c) { int ret = 0; unsigned long wait_result; @@ -32,29 +32,29 @@ static int wmt_check_status(struct wmt_i2c *i2c) if (!wait_result) return -ETIMEDOUT; - if (i2c->cmd_status & WMTI2C_ISR_NACK_ADDR) + if (i2c->cmd_status & VIAI2C_ISR_NACK_ADDR) ret = -EIO; - if (i2c->cmd_status & WMTI2C_ISR_SCL_TIMEOUT) + if (i2c->cmd_status & VIAI2C_ISR_SCL_TIMEOUT) ret = -ETIMEDOUT; return ret; } -static irqreturn_t wmt_i2c_isr(int irq, void *data) +static irqreturn_t viai2c_isr(int irq, void *data) { - struct wmt_i2c *i2c = data; + struct viai2c *i2c = data; /* save the status and write-clear it */ - i2c->cmd_status = readw(i2c->base + WMTI2C_REG_ISR); - writew(i2c->cmd_status, i2c->base + WMTI2C_REG_ISR); + i2c->cmd_status = readw(i2c->base + VIAI2C_REG_ISR); + writew(i2c->cmd_status, i2c->base + VIAI2C_REG_ISR); complete(&i2c->complete); return IRQ_HANDLED; } -static int wmt_i2c_write(struct wmt_i2c *i2c, struct i2c_msg *pmsg, +static int viai2c_write(struct viai2c *i2c, struct i2c_msg *pmsg, int last) { u16 val, tcr_val = i2c->tcr; @@ -68,143 +68,143 @@ static int wmt_i2c_write(struct wmt_i2c *i2c, struct i2c_msg *pmsg, * start at -1 and break out early from the loop */ xfer_len = -1; - writew(0, base + WMTI2C_REG_CDR); + writew(0, base + VIAI2C_REG_CDR); } else { - writew(pmsg->buf[0] & 0xFF, base + WMTI2C_REG_CDR); + writew(pmsg->buf[0] & 0xFF, base + VIAI2C_REG_CDR); } if (!(pmsg->flags & I2C_M_NOSTART)) { - val = readw(base + WMTI2C_REG_CR); - val &= ~WMTI2C_CR_TX_END; - val |= WMTI2C_CR_CPU_RDY; - writew(val, base + WMTI2C_REG_CR); + val = readw(base + VIAI2C_REG_CR); + val &= ~VIAI2C_CR_TX_END; + val |= VIAI2C_CR_CPU_RDY; + writew(val, base + VIAI2C_REG_CR); } reinit_completion(&i2c->complete); - tcr_val |= (WMTI2C_TCR_MASTER_WRITE - | (pmsg->addr & WMTI2C_TCR_SLAVE_ADDR_MASK)); + tcr_val |= (VIAI2C_TCR_MASTER_WRITE + | (pmsg->addr & VIAI2C_TCR_SLAVE_ADDR_MASK)); - writew(tcr_val, base + WMTI2C_REG_TCR); + writew(tcr_val, base + VIAI2C_REG_TCR); if (pmsg->flags & I2C_M_NOSTART) { - val = readw(base + WMTI2C_REG_CR); - val |= WMTI2C_CR_CPU_RDY; - writew(val, base + WMTI2C_REG_CR); + val = readw(base + VIAI2C_REG_CR); + val |= VIAI2C_CR_CPU_RDY; + writew(val, base + VIAI2C_REG_CR); } while (xfer_len < pmsg->len) { - ret = wmt_check_status(i2c); + ret = viai2c_wait_status(i2c); if (ret) return ret; xfer_len++; - val = readw(base + WMTI2C_REG_CSR); - if (val & WMTI2C_CSR_RCV_NOT_ACK) { + val = readw(base + VIAI2C_REG_CSR); + if (val & VIAI2C_CSR_RCV_NOT_ACK) { dev_dbg(i2c->dev, "write RCV NACK error\n"); return -EIO; } if (pmsg->len == 0) { - val = WMTI2C_CR_TX_END | WMTI2C_CR_CPU_RDY - | WMTI2C_CR_ENABLE; - writew(val, base + WMTI2C_REG_CR); + val = VIAI2C_CR_TX_END | VIAI2C_CR_CPU_RDY + | VIAI2C_CR_ENABLE; + writew(val, base + VIAI2C_REG_CR); break; } if (xfer_len == pmsg->len) { if (last != 1) - writew(WMTI2C_CR_ENABLE, base + WMTI2C_REG_CR); + writew(VIAI2C_CR_ENABLE, base + VIAI2C_REG_CR); } else { writew(pmsg->buf[xfer_len] & 0xFF, - base + WMTI2C_REG_CDR); - writew(WMTI2C_CR_CPU_RDY | WMTI2C_CR_ENABLE, - base + WMTI2C_REG_CR); + base + VIAI2C_REG_CDR); + writew(VIAI2C_CR_CPU_RDY | VIAI2C_CR_ENABLE, + base + VIAI2C_REG_CR); } } return 0; } -static int wmt_i2c_read(struct wmt_i2c *i2c, struct i2c_msg *pmsg) +static int viai2c_read(struct viai2c *i2c, struct i2c_msg *pmsg) { u16 val, tcr_val = i2c->tcr; int ret; u32 xfer_len = 0; void __iomem *base = i2c->base; - val = readw(base + WMTI2C_REG_CR); - val &= ~(WMTI2C_CR_TX_END | WMTI2C_CR_TX_NEXT_NO_ACK); + val = readw(base + VIAI2C_REG_CR); + val &= ~(VIAI2C_CR_TX_END | VIAI2C_CR_RX_END); if (!(pmsg->flags & I2C_M_NOSTART)) - val |= WMTI2C_CR_CPU_RDY; + val |= VIAI2C_CR_CPU_RDY; if (pmsg->len == 1) - val |= WMTI2C_CR_TX_NEXT_NO_ACK; + val |= VIAI2C_CR_RX_END; - writew(val, base + WMTI2C_REG_CR); + writew(val, base + VIAI2C_REG_CR); reinit_completion(&i2c->complete); - tcr_val |= WMTI2C_TCR_MASTER_READ - | (pmsg->addr & WMTI2C_TCR_SLAVE_ADDR_MASK); + tcr_val |= VIAI2C_TCR_MASTER_READ + | (pmsg->addr & VIAI2C_TCR_SLAVE_ADDR_MASK); - writew(tcr_val, base + WMTI2C_REG_TCR); + writew(tcr_val, base + VIAI2C_REG_TCR); if (pmsg->flags & I2C_M_NOSTART) { - val = readw(base + WMTI2C_REG_CR); - val |= WMTI2C_CR_CPU_RDY; - writew(val, base + WMTI2C_REG_CR); + val = readw(base + VIAI2C_REG_CR); + val |= VIAI2C_CR_CPU_RDY; + writew(val, base + VIAI2C_REG_CR); } while (xfer_len < pmsg->len) { - ret = wmt_check_status(i2c); + ret = viai2c_wait_status(i2c); if (ret) return ret; - pmsg->buf[xfer_len] = readw(base + WMTI2C_REG_CDR) >> 8; + pmsg->buf[xfer_len] = readw(base + VIAI2C_REG_CDR) >> 8; xfer_len++; - val = readw(base + WMTI2C_REG_CR) | WMTI2C_CR_CPU_RDY; + val = readw(base + VIAI2C_REG_CR) | VIAI2C_CR_CPU_RDY; if (xfer_len == pmsg->len - 1) - val |= WMTI2C_CR_TX_NEXT_NO_ACK; - writew(val, base + WMTI2C_REG_CR); + val |= VIAI2C_CR_RX_END; + writew(val, base + VIAI2C_REG_CR); } return 0; } -int wmt_i2c_xfer(struct i2c_adapter *adap, +int viai2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { struct i2c_msg *pmsg; int i; int ret = 0; - struct wmt_i2c *i2c = i2c_get_adapdata(adap); + struct viai2c *i2c = i2c_get_adapdata(adap); for (i = 0; ret >= 0 && i < num; i++) { pmsg = &msgs[i]; if (!(pmsg->flags & I2C_M_NOSTART)) { - ret = wmt_i2c_wait_bus_not_busy(i2c); + ret = viai2c_wait_bus_ready(i2c); if (ret < 0) return ret; } if (pmsg->flags & I2C_M_RD) - ret = wmt_i2c_read(i2c, pmsg); + ret = viai2c_read(i2c, pmsg); else - ret = wmt_i2c_write(i2c, pmsg, (i + 1) == num); + ret = viai2c_write(i2c, pmsg, (i + 1) == num); } return (ret < 0) ? ret : i; } -int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c **pi2c) +int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c) { int err; - struct wmt_i2c *i2c; + struct viai2c *i2c; struct device_node *np = pdev->dev.of_node; i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); @@ -219,7 +219,7 @@ int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c **pi2c) if (!i2c->irq) return -EINVAL; - err = devm_request_irq(&pdev->dev, i2c->irq, wmt_i2c_isr, + err = devm_request_irq(&pdev->dev, i2c->irq, viai2c_isr, 0, pdev->name, i2c); if (err) return dev_err_probe(&pdev->dev, err, diff --git a/drivers/i2c/busses/i2c-viai2c-common.h b/drivers/i2c/busses/i2c-viai2c-common.h index e57da0dc68a5..f171f81e4d0f 100644 --- a/drivers/i2c/busses/i2c-viai2c-common.h +++ b/drivers/i2c/busses/i2c-viai2c-common.h @@ -12,44 +12,44 @@ #include /* REG_CR Bit fields */ -#define WMTI2C_REG_CR 0x00 -#define WMTI2C_CR_TX_NEXT_ACK 0x0000 -#define WMTI2C_CR_ENABLE 0x0001 -#define WMTI2C_CR_TX_NEXT_NO_ACK 0x0002 -#define WMTI2C_CR_TX_END 0x0004 -#define WMTI2C_CR_CPU_RDY 0x0008 +#define VIAI2C_REG_CR 0x00 +#define VIAI2C_CR_ENABLE BIT(0) +#define VIAI2C_CR_RX_END BIT(1) +#define VIAI2C_CR_TX_END BIT(2) +#define VIAI2C_CR_CPU_RDY BIT(3) +#define VIAI2C_CR_END_MASK GENMASK(2, 1) /* REG_TCR Bit fields */ -#define WMTI2C_REG_TCR 0x02 -#define WMTI2C_TCR_STANDARD_MODE 0x0000 -#define WMTI2C_TCR_MASTER_WRITE 0x0000 -#define WMTI2C_TCR_HS_MODE 0x2000 -#define WMTI2C_TCR_MASTER_READ 0x4000 -#define WMTI2C_TCR_FAST_MODE 0x8000 -#define WMTI2C_TCR_SLAVE_ADDR_MASK 0x007F +#define VIAI2C_REG_TCR 0x02 +#define VIAI2C_TCR_MASTER_WRITE 0x0000 +#define VIAI2C_TCR_HS_MODE BIT(13) +#define VIAI2C_TCR_MASTER_READ BIT(14) +#define VIAI2C_TCR_FAST BIT(15) +#define VIAI2C_TCR_SLAVE_ADDR_MASK GENMASK(6, 0) /* REG_CSR Bit fields */ -#define WMTI2C_REG_CSR 0x04 -#define WMTI2C_CSR_RCV_NOT_ACK 0x0001 -#define WMTI2C_CSR_RCV_ACK_MASK 0x0001 -#define WMTI2C_CSR_READY_MASK 0x0002 +#define VIAI2C_REG_CSR 0x04 +#define VIAI2C_CSR_RCV_NOT_ACK BIT(0) +#define VIAI2C_CSR_RCV_ACK_MASK BIT(0) +#define VIAI2C_CSR_READY_MASK BIT(1) /* REG_ISR Bit fields */ -#define WMTI2C_REG_ISR 0x06 -#define WMTI2C_ISR_NACK_ADDR 0x0001 -#define WMTI2C_ISR_BYTE_END 0x0002 -#define WMTI2C_ISR_SCL_TIMEOUT 0x0004 -#define WMTI2C_ISR_WRITE_ALL 0x0007 +#define VIAI2C_REG_ISR 0x06 +#define VIAI2C_ISR_NACK_ADDR BIT(0) +#define VIAI2C_ISR_BYTE_END BIT(1) +#define VIAI2C_ISR_SCL_TIMEOUT BIT(2) +#define VIAI2C_ISR_MASK_ALL GENMASK(2, 0) /* REG_IMR Bit fields */ -#define WMTI2C_REG_IMR 0x08 -#define WMTI2C_IMR_ENABLE_ALL 0x0007 +#define VIAI2C_REG_IMR 0x08 +#define VIAI2C_IMR_BYTE BIT(1) +#define VIAI2C_IMR_ENABLE_ALL GENMASK(2, 0) -#define WMTI2C_REG_CDR 0x0A -#define WMTI2C_REG_TR 0x0C -#define WMTI2C_REG_MCR 0x0E +#define VIAI2C_REG_CDR 0x0A +#define VIAI2C_REG_TR 0x0C +#define VIAI2C_REG_MCR 0x0E -struct wmt_i2c { +struct viai2c { struct i2c_adapter adapter; struct completion complete; struct device *dev; @@ -60,7 +60,7 @@ struct wmt_i2c { u16 cmd_status; }; -int wmt_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num); -int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c **pi2c); +int viai2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num); +int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c); #endif diff --git a/drivers/i2c/busses/i2c-wmt-plt.c b/drivers/i2c/busses/i2c-wmt-plt.c index e0ffccf8a40a..8f506888cff7 100644 --- a/drivers/i2c/busses/i2c-wmt-plt.c +++ b/drivers/i2c/busses/i2c-wmt-plt.c @@ -22,13 +22,15 @@ #define WMTI2C_MCR_APB_96M 7 #define WMTI2C_MCR_APB_166M 12 +#define wmt_i2c viai2c + static u32 wmt_i2c_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART; } static const struct i2c_algorithm wmt_i2c_algo = { - .master_xfer = wmt_i2c_xfer, + .master_xfer = viai2c_xfer, .functionality = wmt_i2c_func, }; @@ -50,18 +52,18 @@ static int wmt_i2c_reset_hardware(struct wmt_i2c *i2c) return err; } - writew(0, base + WMTI2C_REG_CR); - writew(WMTI2C_MCR_APB_166M, base + WMTI2C_REG_MCR); - writew(WMTI2C_ISR_WRITE_ALL, base + WMTI2C_REG_ISR); - writew(WMTI2C_IMR_ENABLE_ALL, base + WMTI2C_REG_IMR); - writew(WMTI2C_CR_ENABLE, base + WMTI2C_REG_CR); - readw(base + WMTI2C_REG_CSR); /* read clear */ - writew(WMTI2C_ISR_WRITE_ALL, base + WMTI2C_REG_ISR); + writew(0, base + VIAI2C_REG_CR); + writew(WMTI2C_MCR_APB_166M, base + VIAI2C_REG_MCR); + writew(VIAI2C_ISR_MASK_ALL, base + VIAI2C_REG_ISR); + writew(VIAI2C_IMR_ENABLE_ALL, base + VIAI2C_REG_IMR); + writew(VIAI2C_CR_ENABLE, base + VIAI2C_REG_CR); + readw(base + VIAI2C_REG_CSR); /* read clear */ + writew(VIAI2C_ISR_MASK_ALL, base + VIAI2C_REG_ISR); - if (i2c->tcr == WMTI2C_TCR_FAST_MODE) - writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_HS, base + WMTI2C_REG_TR); + if (i2c->tcr == VIAI2C_TCR_FAST) + writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_HS, base + VIAI2C_REG_TR); else - writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_STD, base + WMTI2C_REG_TR); + writew(WMTI2C_SCL_TIMEOUT(128) | WMTI2C_TR_STD, base + VIAI2C_REG_TR); return 0; } @@ -74,7 +76,7 @@ static int wmt_i2c_probe(struct platform_device *pdev) int err; u32 clk_rate; - err = wmt_i2c_init(pdev, &i2c); + err = viai2c_init(pdev, &i2c); if (err) return err; @@ -86,7 +88,7 @@ static int wmt_i2c_probe(struct platform_device *pdev) err = of_property_read_u32(np, "clock-frequency", &clk_rate); if (!err && (clk_rate == I2C_MAX_FAST_MODE_FREQ)) - i2c->tcr = WMTI2C_TCR_FAST_MODE; + i2c->tcr = VIAI2C_TCR_FAST; adap = &i2c->adapter; i2c_set_adapdata(adap, i2c); @@ -110,7 +112,7 @@ static void wmt_i2c_remove(struct platform_device *pdev) struct wmt_i2c *i2c = platform_get_drvdata(pdev); /* Disable interrupts, clock and delete adapter */ - writew(0, i2c->base + WMTI2C_REG_IMR); + writew(0, i2c->base + VIAI2C_REG_IMR); clk_disable_unprepare(i2c->clk); i2c_del_adapter(&i2c->adapter); } From patchwork Fri Dec 29 06:30:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Hu X-Patchwork-Id: 758887 Received: from mx1.zhaoxin.com (MX1.ZHAOXIN.COM [210.0.225.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F104F7488 for ; Fri, 29 Dec 2023 06:30:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=zhaoxin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zhaoxin.com X-ASG-Debug-ID: 1703831441-086e230f290a520003-PT6Irj Received: from ZXSHMBX1.zhaoxin.com (ZXSHMBX1.zhaoxin.com [10.28.252.163]) by mx1.zhaoxin.com with ESMTP id CpusbdcACEjEB3hU (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Fri, 29 Dec 2023 14:30:47 +0800 (CST) X-Barracuda-Envelope-From: HansHu-oc@zhaoxin.com X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.163 Received: from ZXBJMBX03.zhaoxin.com (10.29.252.7) by ZXSHMBX1.zhaoxin.com (10.28.252.163) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:43 +0800 Received: from ml-HP-ProDesk-680-G4-MT.zhaoxin.com (10.28.66.68) by ZXBJMBX03.zhaoxin.com (10.29.252.7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:42 +0800 X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.163 From: Hans Hu X-Barracuda-RBL-Trusted-Forwarder: 10.29.252.7 To: , CC: , , Subject: [PATCH v6 6/8] i2c: wmt: fix a bug when thread blocked Date: Fri, 29 Dec 2023 14:30:37 +0800 X-ASG-Orig-Subj: [PATCH v6 6/8] i2c: wmt: fix a bug when thread blocked Message-ID: X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-i2c@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: zxbjmbx1.zhaoxin.com (10.29.252.163) To ZXBJMBX03.zhaoxin.com (10.29.252.7) X-Barracuda-Connect: ZXSHMBX1.zhaoxin.com[10.28.252.163] X-Barracuda-Start-Time: 1703831446 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://10.28.252.35:4443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at zhaoxin.com X-Barracuda-Scan-Msg-Size: 3075 X-Barracuda-BRTS-Status: 0 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using global scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=9.0 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.118704 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- During each byte access, the host performs clock stretching. In this case, the thread may be interrupted by preemption, resulting in a long stretching time. However, some touchpad can only tolerate host clock stretching of no more than 200 ms. We reduce the impact of this through a retransmission mechanism. Signed-off-by: Hans Hu --- drivers/i2c/busses/i2c-viai2c-common.c | 37 +++++++++++++++++++++----- drivers/i2c/busses/i2c-viai2c-common.h | 2 ++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-viai2c-common.c b/drivers/i2c/busses/i2c-viai2c-common.c index 60a4d4ccaf12..e5eca10efedc 100644 --- a/drivers/i2c/busses/i2c-viai2c-common.c +++ b/drivers/i2c/busses/i2c-viai2c-common.c @@ -2,7 +2,8 @@ #include #include "i2c-viai2c-common.h" -#define VIAI2C_TIMEOUT (msecs_to_jiffies(1000)) +#define VIAI2C_TIMEOUT (msecs_to_jiffies(1000)) +#define VIAI2C_STRETCHING_TIMEOUT 200 static int viai2c_wait_bus_ready(struct viai2c *i2c) { @@ -25,12 +26,35 @@ static int viai2c_wait_bus_ready(struct viai2c *i2c) static int viai2c_wait_status(struct viai2c *i2c) { int ret = 0; - unsigned long wait_result; + unsigned long time_left; + unsigned long delta_ms; + + time_left = wait_for_completion_timeout(&i2c->complete, + VIAI2C_TIMEOUT); + if (!time_left) { + dev_err(i2c->dev, "bus transfer timeout\n"); + return -EIO; + } - wait_result = wait_for_completion_timeout(&i2c->complete, - msecs_to_jiffies(500)); - if (!wait_result) - return -ETIMEDOUT; + /* + * During each byte access, the host performs clock stretching. + * In this case, the thread may be interrupted by preemption, + * resulting in a long stretching time. + * However, some touchpad can only tolerate host clock stretching + * of no more than 200 ms. We reduce the impact of this through + * a retransmission mechanism. + */ + local_irq_disable(); + i2c->to = ktime_get(); + delta_ms = ktime_to_ms(ktime_sub(i2c->to, i2c->ti)); + if (delta_ms > VIAI2C_STRETCHING_TIMEOUT) { + local_irq_enable(); + dev_warn(i2c->dev, "thread blocked more than %ldms\n", + delta_ms); + return -EAGAIN; + } + i2c->ti = i2c->to; + local_irq_enable(); if (i2c->cmd_status & VIAI2C_ISR_NACK_ADDR) ret = -EIO; @@ -184,6 +208,7 @@ int viai2c_xfer(struct i2c_adapter *adap, int ret = 0; struct viai2c *i2c = i2c_get_adapdata(adap); + i2c->to = i2c->ti = ktime_get(); for (i = 0; ret >= 0 && i < num; i++) { pmsg = &msgs[i]; if (!(pmsg->flags & I2C_M_NOSTART)) { diff --git a/drivers/i2c/busses/i2c-viai2c-common.h b/drivers/i2c/busses/i2c-viai2c-common.h index f171f81e4d0f..73a88398d763 100644 --- a/drivers/i2c/busses/i2c-viai2c-common.h +++ b/drivers/i2c/busses/i2c-viai2c-common.h @@ -58,6 +58,8 @@ struct viai2c { u16 tcr; int irq; u16 cmd_status; + ktime_t ti; + ktime_t to; }; int viai2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num); From patchwork Fri Dec 29 06:30:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Hu X-Patchwork-Id: 759535 Received: from mx1.zhaoxin.com (MX1.ZHAOXIN.COM [210.0.225.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 831C963D2 for ; Fri, 29 Dec 2023 06:30:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=zhaoxin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zhaoxin.com X-ASG-Debug-ID: 1703831444-086e230f270a520001-PT6Irj Received: from ZXSHMBX3.zhaoxin.com (ZXSHMBX3.zhaoxin.com [10.28.252.165]) by mx1.zhaoxin.com with ESMTP id xpEEpsPitKrnGtL1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Fri, 29 Dec 2023 14:30:44 +0800 (CST) X-Barracuda-Envelope-From: HansHu-oc@zhaoxin.com X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.165 Received: from ZXBJMBX03.zhaoxin.com (10.29.252.7) by ZXSHMBX3.zhaoxin.com (10.28.252.165) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:43 +0800 Received: from ml-HP-ProDesk-680-G4-MT.zhaoxin.com (10.28.66.68) by ZXBJMBX03.zhaoxin.com (10.29.252.7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:42 +0800 X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.165 From: Hans Hu X-Barracuda-RBL-Trusted-Forwarder: 10.29.252.7 To: , CC: , , Subject: [PATCH v6 7/8] i2c: wmt: add platform type VIAI2C_PLAT_WMT Date: Fri, 29 Dec 2023 14:30:38 +0800 X-ASG-Orig-Subj: [PATCH v6 7/8] i2c: wmt: add platform type VIAI2C_PLAT_WMT Message-ID: X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-i2c@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: zxbjmbx1.zhaoxin.com (10.29.252.163) To ZXBJMBX03.zhaoxin.com (10.29.252.7) X-Barracuda-Connect: ZXSHMBX3.zhaoxin.com[10.28.252.165] X-Barracuda-Start-Time: 1703831444 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://10.28.252.35:4443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at zhaoxin.com X-Barracuda-Scan-Msg-Size: 5306 X-Barracuda-BRTS-Status: 0 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using global scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=9.0 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.118704 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Enumeration variables are added to differentiate between different platforms. Signed-off-by: Hans Hu --- drivers/i2c/busses/i2c-viai2c-common.c | 34 ++++++++++++++++---------- drivers/i2c/busses/i2c-viai2c-common.h | 7 +++++- drivers/i2c/busses/i2c-wmt-plt.c | 2 +- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/drivers/i2c/busses/i2c-viai2c-common.c b/drivers/i2c/busses/i2c-viai2c-common.c index e5eca10efedc..930f4c5c1797 100644 --- a/drivers/i2c/busses/i2c-viai2c-common.c +++ b/drivers/i2c/busses/i2c-viai2c-common.c @@ -78,8 +78,7 @@ static irqreturn_t viai2c_isr(int irq, void *data) return IRQ_HANDLED; } -static int viai2c_write(struct viai2c *i2c, struct i2c_msg *pmsg, - int last) +static int viai2c_write(struct viai2c *i2c, struct i2c_msg *pmsg, bool last) { u16 val, tcr_val = i2c->tcr; int ret; @@ -97,7 +96,7 @@ static int viai2c_write(struct viai2c *i2c, struct i2c_msg *pmsg, writew(pmsg->buf[0] & 0xFF, base + VIAI2C_REG_CDR); } - if (!(pmsg->flags & I2C_M_NOSTART)) { + if (i2c->platform == VIAI2C_PLAT_WMT && !(pmsg->flags & I2C_M_NOSTART)) { val = readw(base + VIAI2C_REG_CR); val &= ~VIAI2C_CR_TX_END; val |= VIAI2C_CR_CPU_RDY; @@ -111,7 +110,7 @@ static int viai2c_write(struct viai2c *i2c, struct i2c_msg *pmsg, writew(tcr_val, base + VIAI2C_REG_TCR); - if (pmsg->flags & I2C_M_NOSTART) { + if (i2c->platform == VIAI2C_PLAT_WMT && pmsg->flags & I2C_M_NOSTART) { val = readw(base + VIAI2C_REG_CR); val |= VIAI2C_CR_CPU_RDY; writew(val, base + VIAI2C_REG_CR); @@ -138,7 +137,7 @@ static int viai2c_write(struct viai2c *i2c, struct i2c_msg *pmsg, } if (xfer_len == pmsg->len) { - if (last != 1) + if (i2c->platform == VIAI2C_PLAT_WMT && !last) writew(VIAI2C_CR_ENABLE, base + VIAI2C_REG_CR); } else { writew(pmsg->buf[xfer_len] & 0xFF, @@ -161,7 +160,7 @@ static int viai2c_read(struct viai2c *i2c, struct i2c_msg *pmsg) val = readw(base + VIAI2C_REG_CR); val &= ~(VIAI2C_CR_TX_END | VIAI2C_CR_RX_END); - if (!(pmsg->flags & I2C_M_NOSTART)) + if (i2c->platform == VIAI2C_PLAT_WMT && !(pmsg->flags & I2C_M_NOSTART)) val |= VIAI2C_CR_CPU_RDY; if (pmsg->len == 1) @@ -176,7 +175,7 @@ static int viai2c_read(struct viai2c *i2c, struct i2c_msg *pmsg) writew(tcr_val, base + VIAI2C_REG_TCR); - if (pmsg->flags & I2C_M_NOSTART) { + if (i2c->platform == VIAI2C_PLAT_WMT && (pmsg->flags & I2C_M_NOSTART)) { val = readw(base + VIAI2C_REG_CR); val |= VIAI2C_CR_CPU_RDY; writew(val, base + VIAI2C_REG_CR); @@ -211,7 +210,8 @@ int viai2c_xfer(struct i2c_adapter *adap, i2c->to = i2c->ti = ktime_get(); for (i = 0; ret >= 0 && i < num; i++) { pmsg = &msgs[i]; - if (!(pmsg->flags & I2C_M_NOSTART)) { + if ((i2c->platform == VIAI2C_PLAT_WMT) + && !(pmsg->flags & I2C_M_NOSTART)) { ret = viai2c_wait_bus_ready(i2c); if (ret < 0) return ret; @@ -226,9 +226,10 @@ int viai2c_xfer(struct i2c_adapter *adap, return (ret < 0) ? ret : i; } -int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c) +int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c, int plat) { int err; + int irq_flags; struct viai2c *i2c; struct device_node *np = pdev->dev.of_node; @@ -240,12 +241,19 @@ int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c) if (IS_ERR(i2c->base)) return PTR_ERR(i2c->base); - i2c->irq = irq_of_parse_and_map(np, 0); - if (!i2c->irq) - return -EINVAL; + if (plat == VIAI2C_PLAT_WMT) { + irq_flags = 0; + i2c->irq = irq_of_parse_and_map(np, 0); + if (!i2c->irq) + return -EINVAL; + } else + return dev_err_probe(&pdev->dev, -EINVAL, + "wrong platform type\n"); + + i2c->platform = plat; err = devm_request_irq(&pdev->dev, i2c->irq, viai2c_isr, - 0, pdev->name, i2c); + irq_flags, pdev->name, i2c); if (err) return dev_err_probe(&pdev->dev, err, "failed to request irq %i\n", i2c->irq); diff --git a/drivers/i2c/busses/i2c-viai2c-common.h b/drivers/i2c/busses/i2c-viai2c-common.h index 73a88398d763..6d210e562c9a 100644 --- a/drivers/i2c/busses/i2c-viai2c-common.h +++ b/drivers/i2c/busses/i2c-viai2c-common.h @@ -49,6 +49,10 @@ #define VIAI2C_REG_TR 0x0C #define VIAI2C_REG_MCR 0x0E +enum { + VIAI2C_PLAT_WMT = 1, +}; + struct viai2c { struct i2c_adapter adapter; struct completion complete; @@ -60,9 +64,10 @@ struct viai2c { u16 cmd_status; ktime_t ti; ktime_t to; + int platform; }; int viai2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num); -int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c); +int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c, int plat); #endif diff --git a/drivers/i2c/busses/i2c-wmt-plt.c b/drivers/i2c/busses/i2c-wmt-plt.c index 8f506888cff7..6afb830eeb40 100644 --- a/drivers/i2c/busses/i2c-wmt-plt.c +++ b/drivers/i2c/busses/i2c-wmt-plt.c @@ -76,7 +76,7 @@ static int wmt_i2c_probe(struct platform_device *pdev) int err; u32 clk_rate; - err = viai2c_init(pdev, &i2c); + err = viai2c_init(pdev, &i2c, VIAI2C_PLAT_WMT); if (err) return err; From patchwork Fri Dec 29 06:30:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Hu X-Patchwork-Id: 759534 Received: from mx1.zhaoxin.com (MX1.ZHAOXIN.COM [210.0.225.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 64BC96FC4 for ; Fri, 29 Dec 2023 06:30:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=zhaoxin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zhaoxin.com X-ASG-Debug-ID: 1703831444-086e230f270a520002-PT6Irj Received: from ZXSHMBX3.zhaoxin.com (ZXSHMBX3.zhaoxin.com [10.28.252.165]) by mx1.zhaoxin.com with ESMTP id RxF53RvuJDMdnjF7 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Fri, 29 Dec 2023 14:30:46 +0800 (CST) X-Barracuda-Envelope-From: HansHu-oc@zhaoxin.com X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.165 Received: from ZXBJMBX03.zhaoxin.com (10.29.252.7) by ZXSHMBX3.zhaoxin.com (10.28.252.165) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:44 +0800 Received: from ml-HP-ProDesk-680-G4-MT.zhaoxin.com (10.28.66.68) by ZXBJMBX03.zhaoxin.com (10.29.252.7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 29 Dec 2023 14:30:43 +0800 X-Barracuda-RBL-Trusted-Forwarder: 10.28.252.165 From: Hans Hu X-Barracuda-RBL-Trusted-Forwarder: 10.29.252.7 To: , CC: , , Subject: [PATCH v6 8/8] i2c: add zhaoxin i2c controller driver Date: Fri, 29 Dec 2023 14:30:39 +0800 X-ASG-Orig-Subj: [PATCH v6 8/8] i2c: add zhaoxin i2c controller driver Message-ID: X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-i2c@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: zxbjmbx1.zhaoxin.com (10.29.252.163) To ZXBJMBX03.zhaoxin.com (10.29.252.7) X-Barracuda-Connect: ZXSHMBX3.zhaoxin.com[10.28.252.165] X-Barracuda-Start-Time: 1703831444 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://10.28.252.35:4443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at zhaoxin.com X-Barracuda-Scan-Msg-Size: 14889 X-Barracuda-BRTS-Status: 1 X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 X-Barracuda-Spam-Score: -2.02 X-Barracuda-Spam-Status: No, SCORE=-2.02 using global scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=9.0 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.118704 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Add Zhaoxin I2C controller driver. It provides the access to the i2c busses, which connects to the touchpad, eeprom, I2S, etc. Zhaoxin I2C controller has two separate busses, so may accommodate up to two I2C adapters. Those adapters are listed in the ACPI namespace with the "IIC1D17" HID, and probed by a platform driver. The driver works with IRQ mode, and supports basic I2C features. Flags I2C_AQ_NO_ZERO_LEN and I2C_AQ_COMB_WRITE_THEN_READ are used to limit the unsupported access. Signed-off-by: Hans Hu --- MAINTAINERS | 8 + drivers/i2c/busses/Kconfig | 10 + drivers/i2c/busses/Makefile | 2 + drivers/i2c/busses/i2c-viai2c-common.c | 21 +- drivers/i2c/busses/i2c-viai2c-common.h | 6 + drivers/i2c/busses/i2c-zhaoxin-plt.c | 298 +++++++++++++++++++++++++ 6 files changed, 340 insertions(+), 5 deletions(-) create mode 100644 drivers/i2c/busses/i2c-zhaoxin-plt.c diff --git a/MAINTAINERS b/MAINTAINERS index c3005c2c9dd2..aa1a7f314b41 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10023,6 +10023,14 @@ L: linux-i2c@vger.kernel.org F: Documentation/i2c/busses/i2c-ismt.rst F: drivers/i2c/busses/i2c-ismt.c +I2C/SMBUS ZHAOXIN DRIVER +M: Hans Hu +L: linux-i2c@vger.kernel.org +S: Maintained +W: https://www.zhaoxin.com +F: drivers/i2c/busses/i2c-viai2c-common.c +F: drivers/i2c/busses/i2c-zhaoxin.c + I2C/SMBUS STUB DRIVER M: Jean Delvare L: linux-i2c@vger.kernel.org diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 28eb48dd5b32..6ccc9f858c90 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -336,6 +336,16 @@ config I2C_VIAPRO if ACPI +config I2C_ZHAOXIN + tristate "Zhaoxin I2C Interface" + depends on PCI || COMPILE_TEST + help + If you say yes to this option, support will be included for the + ZHAOXIN I2C interface + + This driver can also be built as a module. If so, the module + will be called i2c-zhaoxin. + comment "ACPI drivers" config I2C_SCMI diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 2ac59c585c08..1d2d7e9e576e 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -29,6 +29,8 @@ obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o obj-$(CONFIG_I2C_VIA) += i2c-via.o obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o +i2c-zhaoxin-objs := i2c-zhaoxin-plt.o i2c-viai2c-common.o +obj-$(CONFIG_I2C_ZHAOXIN) += i2c-zhaoxin.o # Mac SMBus host controller drivers obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o diff --git a/drivers/i2c/busses/i2c-viai2c-common.c b/drivers/i2c/busses/i2c-viai2c-common.c index 930f4c5c1797..5e31c5efd10e 100644 --- a/drivers/i2c/busses/i2c-viai2c-common.c +++ b/drivers/i2c/busses/i2c-viai2c-common.c @@ -5,7 +5,7 @@ #define VIAI2C_TIMEOUT (msecs_to_jiffies(1000)) #define VIAI2C_STRETCHING_TIMEOUT 200 -static int viai2c_wait_bus_ready(struct viai2c *i2c) +int viai2c_wait_bus_ready(struct viai2c *i2c) { unsigned long timeout; void __iomem *base = i2c->base; @@ -23,7 +23,7 @@ static int viai2c_wait_bus_ready(struct viai2c *i2c) return 0; } -static int viai2c_wait_status(struct viai2c *i2c) +int viai2c_wait_status(struct viai2c *i2c) { int ret = 0; unsigned long time_left; @@ -71,6 +71,9 @@ static irqreturn_t viai2c_isr(int irq, void *data) /* save the status and write-clear it */ i2c->cmd_status = readw(i2c->base + VIAI2C_REG_ISR); + if (!i2c->cmd_status) + return IRQ_NONE; + writew(i2c->cmd_status, i2c->base + VIAI2C_REG_ISR); complete(&i2c->complete); @@ -139,6 +142,8 @@ static int viai2c_write(struct viai2c *i2c, struct i2c_msg *pmsg, bool last) if (xfer_len == pmsg->len) { if (i2c->platform == VIAI2C_PLAT_WMT && !last) writew(VIAI2C_CR_ENABLE, base + VIAI2C_REG_CR); + else if (i2c->platform == VIAI2C_PLAT_ZHAOXIN && last) + writeb(VIAI2C_CR_TX_END, base + VIAI2C_REG_CR); } else { writew(pmsg->buf[xfer_len] & 0xFF, base + VIAI2C_REG_CDR); @@ -150,7 +155,7 @@ static int viai2c_write(struct viai2c *i2c, struct i2c_msg *pmsg, bool last) return 0; } -static int viai2c_read(struct viai2c *i2c, struct i2c_msg *pmsg) +static int viai2c_read(struct viai2c *i2c, struct i2c_msg *pmsg, bool first) { u16 val, tcr_val = i2c->tcr; int ret; @@ -175,7 +180,8 @@ static int viai2c_read(struct viai2c *i2c, struct i2c_msg *pmsg) writew(tcr_val, base + VIAI2C_REG_TCR); - if (i2c->platform == VIAI2C_PLAT_WMT && (pmsg->flags & I2C_M_NOSTART)) { + if ((i2c->platform == VIAI2C_PLAT_WMT && (pmsg->flags & I2C_M_NOSTART)) + || (i2c->platform == VIAI2C_PLAT_ZHAOXIN && !first)) { val = readw(base + VIAI2C_REG_CR); val |= VIAI2C_CR_CPU_RDY; writew(val, base + VIAI2C_REG_CR); @@ -218,7 +224,7 @@ int viai2c_xfer(struct i2c_adapter *adap, } if (pmsg->flags & I2C_M_RD) - ret = viai2c_read(i2c, pmsg); + ret = viai2c_read(i2c, pmsg, i == 0); else ret = viai2c_write(i2c, pmsg, (i + 1) == num); } @@ -246,6 +252,11 @@ int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c, int plat) i2c->irq = irq_of_parse_and_map(np, 0); if (!i2c->irq) return -EINVAL; + } else if (plat == VIAI2C_PLAT_ZHAOXIN) { + irq_flags = IRQF_SHARED; + i2c->irq = platform_get_irq(pdev, 0); + if (i2c->irq < 0) + return i2c->irq; } else return dev_err_probe(&pdev->dev, -EINVAL, "wrong platform type\n"); diff --git a/drivers/i2c/busses/i2c-viai2c-common.h b/drivers/i2c/busses/i2c-viai2c-common.h index 6d210e562c9a..bcff7026e2b8 100644 --- a/drivers/i2c/busses/i2c-viai2c-common.h +++ b/drivers/i2c/busses/i2c-viai2c-common.h @@ -51,6 +51,7 @@ enum { VIAI2C_PLAT_WMT = 1, + VIAI2C_PLAT_ZHAOXIN }; struct viai2c { @@ -65,8 +66,13 @@ struct viai2c { ktime_t ti; ktime_t to; int platform; + u8 hrv; + u16 tr; + u16 mcr; }; +int viai2c_wait_status(struct viai2c *i2c); +int viai2c_wait_bus_ready(struct viai2c *i2c); int viai2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num); int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c, int plat); diff --git a/drivers/i2c/busses/i2c-zhaoxin-plt.c b/drivers/i2c/busses/i2c-zhaoxin-plt.c new file mode 100644 index 000000000000..110a575df201 --- /dev/null +++ b/drivers/i2c/busses/i2c-zhaoxin-plt.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright(c) 2021 Shanghai Zhaoxin Semiconductor Corporation. + * All rights reserved. + */ + +#include +#include +#include "i2c-viai2c-common.h" + +#define ZX_I2C_NAME "i2c_zhaoxin" + +/* + * registers + */ +/* Zhaoxin specific register bit fields */ +/* REG_CR Bit fields */ +#define ZXI2C_CR_MST_RST BIT(7) +#define ZXI2C_CR_FIFO_MODE BIT(14) +/* REG_ISR/IMR Bit fields */ +#define ZXI2C_IRQ_FIFONACK BIT(4) +#define ZXI2C_IRQ_FIFOEND BIT(3) +#define ZXI2C_IRQ_MASK (VIAI2C_ISR_MASK_ALL \ + | ZXI2C_IRQ_FIFOEND \ + | ZXI2C_IRQ_FIFONACK) +/* Zhaoxin specific registers */ +#define ZXI2C_REG_CLK 0x10 +#define ZXI2C_CLK_50M BIT(0) +#define ZXI2C_REG_REV 0x11 +#define ZXI2C_REG_HCR 0x12 +#define ZXI2C_HCR_RST_FIFO GENMASK(1, 0) +#define ZXI2C_REG_HTDR 0x13 +#define ZXI2C_REG_HRDR 0x14 +#define ZXI2C_REG_HTLR 0x15 +#define ZXI2C_REG_HRLR 0x16 +#define ZXI2C_REG_HWCNTR 0x18 +#define ZXI2C_REG_HRCNTR 0x19 + +/* parameters Constants */ +#define ZXI2C_GOLD_FSTP_100K 0xF3 +#define ZXI2C_GOLD_FSTP_400K 0x38 +#define ZXI2C_GOLD_FSTP_1M 0x13 +#define ZXI2C_GOLD_FSTP_3400K 0x37 +#define ZXI2C_HS_MASTER_CODE (0x08 << 8) +#define ZXI2C_FIFO_SIZE 32 + +/* Structure definition */ +#define zxi2c viai2c + +static int zxi2c_fifo_xfer(struct zxi2c *i2c, struct i2c_msg *msg) +{ + u16 xfered_len = 0; + u16 byte_left = msg->len; + u16 tcr_val = i2c->tcr; + void __iomem *base = i2c->base; + bool read = !!(msg->flags & I2C_M_RD); + + i2c->ti = ktime_get(); + while (byte_left) { + u16 i; + u8 tmp; + int error; + u16 xfer_len = min_t(u16, byte_left, ZXI2C_FIFO_SIZE); + + byte_left -= xfer_len; + + /* reset fifo buffer */ + tmp = ioread8(base + ZXI2C_REG_HCR); + iowrite8(tmp | ZXI2C_HCR_RST_FIFO, base + ZXI2C_REG_HCR); + + /* set xfer len */ + if (read) { + iowrite8(xfer_len - 1, base + ZXI2C_REG_HRLR); + } else { + iowrite8(xfer_len - 1, base + ZXI2C_REG_HTLR); + /* set write data */ + for (i = 0; i < xfer_len; i++) + iowrite8(msg->buf[xfered_len + i], + base + ZXI2C_REG_HTDR); + } + + /* prepare to stop transmission */ + if (i2c->hrv && !byte_left) { + tmp = ioread8(i2c->base + VIAI2C_REG_CR); + tmp |= read ? VIAI2C_CR_RX_END : VIAI2C_CR_TX_END; + iowrite8(tmp, base + VIAI2C_REG_CR); + } + + reinit_completion(&i2c->complete); + + if (xfered_len) { + /* continue transmission */ + tmp = ioread8(i2c->base + VIAI2C_REG_CR); + iowrite8(tmp |= VIAI2C_CR_CPU_RDY, + i2c->base + VIAI2C_REG_CR); + } else { + /* start transmission */ + tcr_val |= (read ? VIAI2C_TCR_MASTER_READ : 0); + writew(tcr_val | msg->addr, base + VIAI2C_REG_TCR); + } + + error = viai2c_wait_status(i2c); + if (error) + return error; + + /* get the received data */ + if (read) + for (i = 0; i < xfer_len; i++) + msg->buf[xfered_len + i] = + ioread8(base + ZXI2C_REG_HRDR); + + xfered_len += xfer_len; + } + + return 1; +} + +static int zxi2c_master_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + u8 tmp; + int ret; + struct zxi2c *i2c = (struct zxi2c *)i2c_get_adapdata(adap); + + ret = viai2c_wait_bus_ready(i2c); + if (ret) + return ret; + + tmp = ioread8(i2c->base + VIAI2C_REG_CR); + tmp &= ~(VIAI2C_CR_RX_END | VIAI2C_CR_TX_END); + + if (num == 1 && msgs->len >= 2 && + (i2c->hrv || msgs->len <= ZXI2C_FIFO_SIZE)) { + /* enable fifo mode */ + iowrite16(ZXI2C_CR_FIFO_MODE | tmp, i2c->base + VIAI2C_REG_CR); + /* clear irq status */ + iowrite8(ZXI2C_IRQ_MASK, i2c->base + VIAI2C_REG_ISR); + /* enable fifo irq */ + iowrite8(VIAI2C_ISR_NACK_ADDR | ZXI2C_IRQ_FIFOEND, + i2c->base + VIAI2C_REG_IMR); + + i2c->ti = i2c->to = ktime_get(); + ret = zxi2c_fifo_xfer(i2c, msgs); + } else { + /* enable byte mode */ + iowrite16(tmp, i2c->base + VIAI2C_REG_CR); + /* clear irq status */ + iowrite8(ZXI2C_IRQ_MASK, i2c->base + VIAI2C_REG_ISR); + /* enable byte irq */ + iowrite8(VIAI2C_ISR_NACK_ADDR | VIAI2C_IMR_BYTE, + i2c->base + VIAI2C_REG_IMR); + + ret = viai2c_xfer(adap, msgs, num); + if (ret < 0) + iowrite16(tmp | VIAI2C_CR_END_MASK, + i2c->base + VIAI2C_REG_CR); + /* make sure the state machine is stopped */ + usleep_range(1, 2); + } + /* dis interrupt */ + iowrite8(0, i2c->base + VIAI2C_REG_IMR); + + return ret; +} + +static u32 zxi2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm zxi2c_algorithm = { + .master_xfer = zxi2c_master_xfer, + .functionality = zxi2c_func, +}; + +static const struct i2c_adapter_quirks zxi2c_quirks = { + .flags = I2C_AQ_NO_ZERO_LEN | I2C_AQ_COMB_WRITE_THEN_READ, +}; + +static const u32 zxi2c_speed_params_table[][3] = { + /* speed, ZXI2C_TCR, ZXI2C_FSTP */ + { I2C_MAX_STANDARD_MODE_FREQ, 0, ZXI2C_GOLD_FSTP_100K }, + { I2C_MAX_FAST_MODE_FREQ, VIAI2C_TCR_FAST, ZXI2C_GOLD_FSTP_400K }, + { I2C_MAX_FAST_MODE_PLUS_FREQ, VIAI2C_TCR_FAST, ZXI2C_GOLD_FSTP_1M }, + { I2C_MAX_HIGH_SPEED_MODE_FREQ, VIAI2C_TCR_HS_MODE | VIAI2C_TCR_FAST, + ZXI2C_GOLD_FSTP_3400K }, +}; + +static void zxi2c_set_bus_speed(struct zxi2c *i2c) +{ + iowrite16(i2c->tr, i2c->base + VIAI2C_REG_TR); + iowrite8(ZXI2C_CLK_50M, i2c->base + ZXI2C_REG_CLK); + iowrite16(i2c->mcr, i2c->base + VIAI2C_REG_MCR); +} + +static void zxi2c_get_bus_speed(struct zxi2c *i2c) +{ + u8 i, count; + u8 fstp; + const u32 *params; + u32 acpi_speed = i2c_acpi_find_bus_speed(i2c->dev); + + count = ARRAY_SIZE(zxi2c_speed_params_table); + for (i = 0; i < count; i++) + if (acpi_speed == zxi2c_speed_params_table[i][0]) + break; + /* if not found, use 400k as default */ + i = i < count ? i : 1; + + params = zxi2c_speed_params_table[i]; + fstp = ioread8(i2c->base + VIAI2C_REG_TR); + if (abs(fstp - params[2]) > 0x10) { + /* + * if BIOS setting value far from golden value, + * use golden value and warn user + */ + dev_warn(i2c->dev, "speed:%d, fstp:0x%x, golden:0x%x\n", + params[0], fstp, params[2]); + i2c->tr = params[2] | 0xff00; + } else { + i2c->tr = fstp | 0xff00; + } + + i2c->tcr = params[1]; + i2c->mcr = ioread16(i2c->base + VIAI2C_REG_MCR); + /* for Hs-mode, use 0000 1000 as master code */ + if (params[0] == I2C_MAX_HIGH_SPEED_MODE_FREQ) + i2c->mcr |= ZXI2C_HS_MASTER_CODE; + + dev_info(i2c->dev, "speed mode is %s\n", + i2c_freq_mode_string(params[0])); +} + +static int zxi2c_probe(struct platform_device *pdev) +{ + int error; + struct zxi2c *i2c; + struct pci_dev *pci; + struct i2c_adapter *adap; + + error = viai2c_init(pdev, &i2c, VIAI2C_PLAT_ZHAOXIN); + if (error) + return error; + + zxi2c_get_bus_speed(i2c); + zxi2c_set_bus_speed(i2c); + + i2c->hrv = ioread8(i2c->base + ZXI2C_REG_REV); + + adap = &i2c->adapter; + adap->owner = THIS_MODULE; + adap->algo = &zxi2c_algorithm; + adap->retries = 2; + adap->quirks = &zxi2c_quirks; + adap->dev.parent = &pdev->dev; + ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev)); + pci = to_pci_dev(pdev->dev.parent); + snprintf(adap->name, sizeof(adap->name), "zhaoxin-%s-%s", + dev_name(&pci->dev), dev_name(i2c->dev)); + i2c_set_adapdata(adap, i2c); + + return devm_i2c_add_adapter(&pdev->dev, adap); +} + +static int __maybe_unused zxi2c_resume(struct device *dev) +{ + struct zxi2c *i2c = dev_get_drvdata(dev); + + iowrite8(ZXI2C_CR_MST_RST, i2c->base + VIAI2C_REG_CR); + zxi2c_set_bus_speed(i2c); + + return 0; +} + +static const struct dev_pm_ops zxi2c_pm = { + SET_SYSTEM_SLEEP_PM_OPS(NULL, zxi2c_resume) +}; + +static const struct acpi_device_id zxi2c_acpi_match[] = { + {"IIC1D17", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, zxi2c_acpi_match); + +static struct platform_driver zxi2c_driver = { + .probe = zxi2c_probe, + .driver = { + .name = ZX_I2C_NAME, + .acpi_match_table = zxi2c_acpi_match, + .pm = &zxi2c_pm, + }, +}; + +module_platform_driver(zxi2c_driver); + +MODULE_AUTHOR("HansHu@zhaoxin.com"); +MODULE_DESCRIPTION("Shanghai Zhaoxin IIC driver"); +MODULE_LICENSE("GPL");