From patchwork Thu Mar 30 07:50:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Kerr X-Patchwork-Id: 13194196 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C6335C761AF for ; Thu, 30 Mar 2023 13:47:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=GG6LKcZ/rbSpqx2yrlFjAJfLGhIC5ODIms0nEsBVsC8=; b=ii8i/MNQmlJKtX LO/lhnEZ8z+rJvZZbqIKIPBmsCaW1RgW4ZKld/c0FnPn1NhJlbLLN08X/NPGyjUk0M2m6eA0+MNpe HxIZTTO2HV6O6MVb9uT7Pl1cB2ewx/NxNTIeX5JZryQ3t0YjItzBmfsaP74+a7MoKMp6qhlfAJFF2 7MNv3jumG4R1NSoJGBXZutitqYzR+CYO1sxPgSCdwEICfj1Lhf6DZ5wCV8KOgXUXv9dfUEW6SIzY9 722z8YebvRje8WhF5EV3RXgELmDUOwlDLzw2dJnuyuR+x95vIysK6HEV1P9NKrTqm/Vv42alegGed 44dI7IRTusW4OrOe8qFA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1phscu-003vTy-0V; Thu, 30 Mar 2023 13:47:40 +0000 Received: from pi.codeconstruct.com.au ([203.29.241.158] helo=codeconstruct.com.au) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1phn3a-002yjp-2C for linux-i3c@lists.infradead.org; Thu, 30 Mar 2023 07:50:52 +0000 Received: by codeconstruct.com.au (Postfix, from userid 10000) id 019F020127; Thu, 30 Mar 2023 15:50:48 +0800 (AWST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codeconstruct.com.au; s=2022a; t=1680162649; bh=z/TACczbFu3Yfs10OBzMNiA9zv6dYykbn3vOqc4lSkY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=gkMJZJqWMQD1OWUeykS/HrQ0XEf9mFLzBXEmdZJKZk5jSVgjsFRWDH78iqwqZzNKo hGFEZ/w+3Q2P8yeJ52H0Hrq3/jtdJojyR7ZuvwFd+6jrRzVpBZCZxiQb+Lf8UMmT4w uyxOzn+83izR4TMnKaqSa/3loooxoZE1kFk5Ln4Xy7y/iDycTJmWTa6ht2sQoMtgT9 pi7C5UmcDBqTum33vvl6W97xgHea3K+hOGG+COXQQPIVOmS80xbEfV4mTRWk/fA2R6 pOE5tjwqwJsAuXHxa44Qx+fy7jQUfanBVSUoXVzaYvo7YW+2LuZLMdZ6JRzjiNuSCz 0eVTiDaAiYAjQ== From: Jeremy Kerr To: linux-i3c@lists.infradead.org Cc: Matt Johnston , Vitor Soares , Alexandre Belloni , Jack Chen , Billy Tsai , Dylan Hung , Joel Stanley , Andrew Jeffery Subject: [PATCH 1/5] i3c: dw: Create a generic fifo read function Date: Thu, 30 Mar 2023 15:50:32 +0800 Message-Id: <827204789583dd86addffb47ecaeab9d67cf95d5.1680161823.git.jk@codeconstruct.com.au> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230330_005050_910020_8A33F627 X-CRM114-Status: UNSURE ( 8.40 ) X-CRM114-Notice: Please train this message. X-Mailman-Approved-At: Thu, 30 Mar 2023 06:47:39 -0700 X-BeenThere: linux-i3c@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-i3c" Errors-To: linux-i3c-bounces+linux-i3c=archiver.kernel.org@lists.infradead.org In a future change we'll want to read from the IBI FIFO too, so turn dw_i3c_read_rx_fifo() into a generic read with the FIFO register as a parameter. Signed-off-by: Jeremy Kerr --- drivers/i3c/master/dw-i3c-master.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c index 9fc03108a5db..cb38ef95f21a 100644 --- a/drivers/i3c/master/dw-i3c-master.c +++ b/drivers/i3c/master/dw-i3c-master.c @@ -318,18 +318,24 @@ static void dw_i3c_master_wr_tx_fifo(struct dw_i3c_master *master, } } -static void dw_i3c_master_read_rx_fifo(struct dw_i3c_master *master, - u8 *bytes, int nbytes) +static void dw_i3c_master_read_fifo(struct dw_i3c_master *master, + int reg, u8 *bytes, int nbytes) { - readsl(master->regs + RX_TX_DATA_PORT, bytes, nbytes / 4); + readsl(master->regs + reg, bytes, nbytes / 4); if (nbytes & 3) { u32 tmp; - readsl(master->regs + RX_TX_DATA_PORT, &tmp, 1); + readsl(master->regs + reg, &tmp, 1); memcpy(bytes + (nbytes & ~3), &tmp, nbytes & 3); } } +static void dw_i3c_master_read_rx_fifo(struct dw_i3c_master *master, + u8 *bytes, int nbytes) +{ + return dw_i3c_master_read_fifo(master, RX_TX_DATA_PORT, bytes, nbytes); +} + static struct dw_i3c_xfer * dw_i3c_master_alloc_xfer(struct dw_i3c_master *master, unsigned int ncmds) { From patchwork Thu Mar 30 07:50:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Kerr X-Patchwork-Id: 13194200 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2AD0AC77B60 for ; Thu, 30 Mar 2023 13:47:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=xSeqVMLUEGAEFvM+1M6tbtRbnIvL0F5UkEljrbA9OoU=; b=poafVz8TAFuCKm k2G9LGhHPoh9Xn9o19QYMa+joQ8z1KchEL+3VtDAiqe1vNmHKts5sqHDNavFAvK7tSwGEiUDJxkm/ 2yRgYw+Vpxw2Ozl9lHeGHEY2TlORbXxhF/DbD3V/UvUAMFWliy9SKv2w6yzrEJfAFy/83CKtWZ2S2 mO2UGDJMD3geZQ65gx9sHZUbwtOHEg4nB9rIXiSclI9+aruQbGr4dXPRHkp312ABq2IF1M3NUR7tF aWlcMbyG5+J5laiWbChwyehjeadz8YfLZg7I7+CfEjCZS8mSFmv8/tcNPA7Pe2iwNJdCkpysGA6Lv BRl7rg4xvFD0NkrwnozA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1phscu-003vUF-2C; Thu, 30 Mar 2023 13:47:40 +0000 Received: from pi.codeconstruct.com.au ([203.29.241.158] helo=codeconstruct.com.au) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1phn3b-002yjv-12 for linux-i3c@lists.infradead.org; Thu, 30 Mar 2023 07:50:53 +0000 Received: by codeconstruct.com.au (Postfix, from userid 10000) id AF555201F2; Thu, 30 Mar 2023 15:50:49 +0800 (AWST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codeconstruct.com.au; s=2022a; t=1680162649; bh=ZdaVymXUnq5Ns0W1+hSf0wiOjoc2I6ncYW7UzKHfH74=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Cpvtq2CpKLdVEkDBoqgELl7U4mvXszIFN3Wn9kET/0FbuAQMSyy9FO3chdj4vf4ml akBl6APnvp1EL0uD+v+eUqgA6p+gJSuMdOt4qvPQgPZnkmuRxmNneeNDjp5gCasvW3 KMa10/tDm+jHPG2OljeICFrStVX8GUlkhiHY7NuMFNfwowJZNweTnG5P++bnayw+3O jZOADzXTaTf0AOqyvXZ/Q7KB6dcmOY06F74Y8ZSowllPpQKEMg+vZGdYrBoU3Hp1hN 89CRnlaQIRSdh3wNF9WbSQ3U4LFMDrmGMyoVypgVRHETla/VRM7suLR0ZF9VwpuihR 5WpjyVhxi6cPw== From: Jeremy Kerr To: linux-i3c@lists.infradead.org Cc: Matt Johnston , Vitor Soares , Alexandre Belloni , Jack Chen , Billy Tsai , Dylan Hung , Joel Stanley , Andrew Jeffery Subject: [PATCH 2/5] i3c: dw: Turn DAT array entry into a struct Date: Thu, 30 Mar 2023 15:50:33 +0800 Message-Id: <9dc0d9e2857e851a0cf04819df48e5d31921f83e.1680161823.git.jk@codeconstruct.com.au> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230330_005051_740887_F3AA38C9 X-CRM114-Status: GOOD ( 13.43 ) X-Mailman-Approved-At: Thu, 30 Mar 2023 06:47:39 -0700 X-BeenThere: linux-i3c@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-i3c" Errors-To: linux-i3c-bounces+linux-i3c=archiver.kernel.org@lists.infradead.org In an upcoming change, we will want to store additional data about the devices we have in the data address table. Change the type of the DAT entries into a struct, which currently just has the address data. Signed-off-by: Jeremy Kerr --- drivers/i3c/master/dw-i3c-master.c | 22 +++++++++++----------- drivers/i3c/master/dw-i3c-master.h | 11 ++++++++++- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c index cb38ef95f21a..a086d9c5ff35 100644 --- a/drivers/i3c/master/dw-i3c-master.c +++ b/drivers/i3c/master/dw-i3c-master.c @@ -291,7 +291,7 @@ static int dw_i3c_master_get_addr_pos(struct dw_i3c_master *master, u8 addr) int pos; for (pos = 0; pos < master->maxdevs; pos++) { - if (addr == master->addrs[pos]) + if (addr == master->devs[pos].addr) return pos; } @@ -769,7 +769,7 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m) if (ret < 0) return -ENOSPC; - master->addrs[pos] = ret; + master->devs[pos].addr = ret; p = even_parity(ret); last_addr = ret; ret |= (p << 7); @@ -806,7 +806,7 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m) for (pos = 0; pos < master->maxdevs; pos++) { if (newdevs & BIT(pos)) - i3c_master_add_i3c_dev_locked(m, master->addrs[pos]); + i3c_master_add_i3c_dev_locked(m, master->devs[pos].addr); } dw_i3c_master_free_xfer(xfer); @@ -905,11 +905,11 @@ static int dw_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev, master->regs + DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); - master->addrs[data->index] = 0; + master->devs[data->index].addr = 0; master->free_pos |= BIT(data->index); data->index = pos; - master->addrs[pos] = dev->info.dyn_addr; + master->devs[pos].addr = dev->info.dyn_addr; master->free_pos &= ~BIT(pos); } @@ -917,7 +917,7 @@ static int dw_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev, master->regs + DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); - master->addrs[data->index] = dev->info.dyn_addr; + master->devs[data->index].addr = dev->info.dyn_addr; return 0; } @@ -938,11 +938,11 @@ static int dw_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev) return -ENOMEM; data->index = pos; - master->addrs[pos] = dev->info.dyn_addr ? : dev->info.static_addr; + master->devs[pos].addr = dev->info.dyn_addr ? : dev->info.static_addr; master->free_pos &= ~BIT(pos); i3c_dev_set_master_data(dev, data); - writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->addrs[pos]), + writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->devs[pos].addr), master->regs + DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); @@ -960,7 +960,7 @@ static void dw_i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev) DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); i3c_dev_set_master_data(dev, NULL); - master->addrs[data->index] = 0; + master->devs[data->index].addr = 0; master->free_pos |= BIT(data->index); kfree(data); } @@ -1046,7 +1046,7 @@ static int dw_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev) return -ENOMEM; data->index = pos; - master->addrs[pos] = dev->addr; + master->devs[pos].addr = dev->addr; master->free_pos &= ~BIT(pos); i2c_dev_set_master_data(dev, data); @@ -1069,7 +1069,7 @@ static void dw_i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev) DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); i2c_dev_set_master_data(dev, NULL); - master->addrs[data->index] = 0; + master->devs[data->index].addr = 0; master->free_pos |= BIT(data->index); kfree(data); } diff --git a/drivers/i3c/master/dw-i3c-master.h b/drivers/i3c/master/dw-i3c-master.h index 9f1e48211aa4..dd0b77e2c66a 100644 --- a/drivers/i3c/master/dw-i3c-master.h +++ b/drivers/i3c/master/dw-i3c-master.h @@ -17,6 +17,10 @@ struct dw_i3c_master_caps { u8 datafifodepth; }; +struct dw_i3c_dat_entry { + u8 addr; +}; + struct dw_i3c_master { struct i3c_master_controller base; u16 maxdevs; @@ -33,7 +37,12 @@ struct dw_i3c_master { struct clk *core_clk; char version[5]; char type[5]; - u8 addrs[DW_I3C_MAX_DEVS]; + + /* + * Per-device hardware data, used to manage the device address table + * (DAT) + */ + struct dw_i3c_dat_entry devs[DW_I3C_MAX_DEVS]; /* platform-specific data */ const struct dw_i3c_platform_ops *platform_ops; From patchwork Thu Mar 30 07:50:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Kerr X-Patchwork-Id: 13194201 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 969A7C77B6E for ; Thu, 30 Mar 2023 13:47:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=aeQ4XEOWUmYT1lV5fS2LNpb/rbwUEz1CAZtB87Tgdgk=; b=HYNacfYDJeWbn6 coJhlNFGmCE15bkyK6zGFm9VF6xp0O7V3ImRoN1/5HCbvOmB7/YEVtLt6eE2ggwz7DxhOC+SKlhzg FWNsLP87+U3zAsTnAjsgm06hYg8rbAl1Eb629uh4xQAnYxU2l2gdsQpvNPC/M9qWnc3Dd3jRRmUaH AwxG2I/MYB+nFI4FNooeOCHnG8V5BRcAJHv6M+tMlNmmUXXwJz8DbCF8mmj+w0V6+RmqlhzPzYdV0 Hxb32M/ziP0TvbR0iEnyKuiaCTc9SOr+QN1XeXAkBwcgUoXSHuw28UsA+6iiHkDNeJSayKzonLHhp BBKvyuwtZetM1SwJQiYw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1phscv-003vUf-0o; Thu, 30 Mar 2023 13:47:41 +0000 Received: from pi.codeconstruct.com.au ([203.29.241.158] helo=codeconstruct.com.au) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1phn3b-002yjz-2t for linux-i3c@lists.infradead.org; Thu, 30 Mar 2023 07:50:54 +0000 Received: by codeconstruct.com.au (Postfix, from userid 10000) id 40954202A3; Thu, 30 Mar 2023 15:50:50 +0800 (AWST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codeconstruct.com.au; s=2022a; t=1680162650; bh=Gn/xs8u2oPEHNBLcAXMZNNbhKiMeKG5elXkUUuBrH2c=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=eUYgnZeCXZ+WLuyeSnhYVk2SbULDsRk8+5rdJJ+2eNLquu1Y/gaKLAXSGjj8VkShb qX9h1ymoI88KYSaGd9tel3t+ND2zktsUmhLEuulGOBiD9k1pSapnhg88fIgSUtULE/ i/mU5FTvERx+HliMYKDtBSIjVbAgzQXNvwwIVT0//cXmtwXkNCZfHcBF3E8SwmdlZJ qBZMeIRZUUMG/9H0gfNd9eLVpO6qt5U4Yhh0+f6e7AUF/JtxZvYUgnESakaeb8Limt MywSWv8rO/13Pl+H24VXpvpAVhzY7RtTDq/IKxwTPY0mWHG6Z1L/EpsGaRbltrS8v/ tsHW3KSZW0tOw== From: Jeremy Kerr To: linux-i3c@lists.infradead.org Cc: Matt Johnston , Vitor Soares , Alexandre Belloni , Jack Chen , Billy Tsai , Dylan Hung , Joel Stanley , Andrew Jeffery Subject: [PATCH 3/5] i3c: dw: Add support for in-band interrupts Date: Thu, 30 Mar 2023 15:50:34 +0800 Message-Id: <79daeefd7ccb7c935d0c159149df21a6c9a73ffa.1680161823.git.jk@codeconstruct.com.au> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230330_005052_329638_35E46D4D X-CRM114-Status: GOOD ( 24.58 ) X-Mailman-Approved-At: Thu, 30 Mar 2023 06:47:39 -0700 X-BeenThere: linux-i3c@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-i3c" Errors-To: linux-i3c-bounces+linux-i3c=archiver.kernel.org@lists.infradead.org This change adds support for receiving and dequeueing i3c IBIs. By setting struct dw_i3c_master->ibi_capable before probe, a platform implementation can select the IBI-enabled version of the i3c_master_ops, enabling the global IBI infrastrcture for that controller. Signed-off-by: Jeremy Kerr --- drivers/i3c/master/dw-i3c-master.c | 281 ++++++++++++++++++++++++++++- drivers/i3c/master/dw-i3c-master.h | 11 ++ 2 files changed, 289 insertions(+), 3 deletions(-) diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c index a086d9c5ff35..c49c5fa01a26 100644 --- a/drivers/i3c/master/dw-i3c-master.c +++ b/drivers/i3c/master/dw-i3c-master.c @@ -76,7 +76,22 @@ #define RX_TX_DATA_PORT 0x14 #define IBI_QUEUE_STATUS 0x18 +#define IBI_QUEUE_STATUS_IBI_ID(x) (((x) & GENMASK(15, 8)) >> 8) +#define IBI_QUEUE_STATUS_DATA_LEN(x) ((x) & GENMASK(7, 0)) +#define IBI_QUEUE_IBI_ADDR(x) (IBI_QUEUE_STATUS_IBI_ID(x) >> 1) +#define IBI_QUEUE_IBI_RNW(x) (IBI_QUEUE_STATUS_IBI_ID(x) & BIT(0)) +#define IBI_TYPE_MR(x) \ + ((IBI_QUEUE_IBI_ADDR(x) != I3C_HOT_JOIN_ADDR) && !IBI_QUEUE_IBI_RNW(x)) +#define IBI_TYPE_HJ(x) \ + ((IBI_QUEUE_IBI_ADDR(x) == I3C_HOT_JOIN_ADDR) && !IBI_QUEUE_IBI_RNW(x)) +#define IBI_TYPE_SIRQ(x) \ + ((IBI_QUEUE_IBI_ADDR(x) != I3C_HOT_JOIN_ADDR) && IBI_QUEUE_IBI_RNW(x)) + #define QUEUE_THLD_CTRL 0x1c +#define QUEUE_THLD_CTRL_IBI_STAT_MASK GENMASK(31, 24) +#define QUEUE_THLD_CTRL_IBI_STAT(x) (((x) - 1) << 24) +#define QUEUE_THLD_CTRL_IBI_DATA_MASK GENMASK(20, 16) +#define QUEUE_THLD_CTRL_IBI_DATA(x) ((x) << 16) #define QUEUE_THLD_CTRL_RESP_BUF_MASK GENMASK(15, 8) #define QUEUE_THLD_CTRL_RESP_BUF(x) (((x) - 1) << 8) @@ -186,6 +201,8 @@ #define EXTENDED_CAPABILITY 0xe8 #define SLAVE_CONFIG 0xec +#define DEV_ADDR_TABLE_IBI_MDB BIT(12) +#define DEV_ADDR_TABLE_SIR_REJECT BIT(13) #define DEV_ADDR_TABLE_LEGACY_I2C_DEV BIT(31) #define DEV_ADDR_TABLE_DYNAMIC_ADDR(x) (((x) << 16) & GENMASK(23, 16)) #define DEV_ADDR_TABLE_STATIC_ADDR(x) ((x) & GENMASK(6, 0)) @@ -221,6 +238,7 @@ struct dw_i3c_xfer { struct dw_i3c_i2c_dev_data { u8 index; + struct i3c_generic_ibi_pool *ibi_pool; }; static u8 even_parity(u8 p) @@ -336,6 +354,12 @@ static void dw_i3c_master_read_rx_fifo(struct dw_i3c_master *master, return dw_i3c_master_read_fifo(master, RX_TX_DATA_PORT, bytes, nbytes); } +static void dw_i3c_master_read_ibi_fifo(struct dw_i3c_master *master, + u8 *bytes, int nbytes) +{ + return dw_i3c_master_read_fifo(master, IBI_QUEUE_STATUS, bytes, nbytes); +} + static struct dw_i3c_xfer * dw_i3c_master_alloc_xfer(struct dw_i3c_master *master, unsigned int ncmds) { @@ -605,7 +629,11 @@ static int dw_i3c_master_bus_init(struct i3c_master_controller *m) } thld_ctrl = readl(master->regs + QUEUE_THLD_CTRL); - thld_ctrl &= ~QUEUE_THLD_CTRL_RESP_BUF_MASK; + thld_ctrl &= ~(QUEUE_THLD_CTRL_RESP_BUF_MASK | + QUEUE_THLD_CTRL_IBI_STAT_MASK | + QUEUE_THLD_CTRL_IBI_STAT_MASK); + thld_ctrl |= QUEUE_THLD_CTRL_IBI_STAT(1) | + QUEUE_THLD_CTRL_IBI_DATA(31); writel(thld_ctrl, master->regs + QUEUE_THLD_CTRL); thld_ctrl = readl(master->regs + DATA_BUFFER_THLD_CTRL); @@ -1074,6 +1102,226 @@ static void dw_i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev) kfree(data); } +static int dw_i3c_master_request_ibi(struct i3c_dev_desc *dev, + const struct i3c_ibi_setup *req) +{ + struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); + struct i3c_master_controller *m = i3c_dev_get_master(dev); + struct dw_i3c_master *master = to_dw_i3c_master(m); + unsigned long flags; + + data->ibi_pool = i3c_generic_ibi_alloc_pool(dev, req); + if (IS_ERR(data->ibi_pool)) + return PTR_ERR(data->ibi_pool); + + spin_lock_irqsave(&master->devs_lock, flags); + master->devs[data->index].ibi_dev = dev; + spin_unlock_irqrestore(&master->devs_lock, flags); + + return 0; +} + +static void dw_i3c_master_free_ibi(struct i3c_dev_desc *dev) +{ + struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); + struct i3c_master_controller *m = i3c_dev_get_master(dev); + struct dw_i3c_master *master = to_dw_i3c_master(m); + unsigned long flags; + + spin_lock_irqsave(&master->devs_lock, flags); + master->devs[data->index].ibi_dev = NULL; + spin_unlock_irqrestore(&master->devs_lock, flags); + + i3c_generic_ibi_free_pool(data->ibi_pool); + data->ibi_pool = NULL; +} + +static void dw_i3c_master_set_sir_enabled(struct dw_i3c_master *master, + struct i3c_dev_desc *dev, + u8 idx, bool enable) +{ + unsigned long flags; + u32 dat_entry, reg; + bool global; + + dat_entry = DEV_ADDR_TABLE_LOC(master->datstartaddr, idx); + + spin_lock_irqsave(&master->devs_lock, flags); + reg = readl(master->regs + dat_entry); + if (enable) { + reg &= ~DEV_ADDR_TABLE_SIR_REJECT; + if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD) + reg |= DEV_ADDR_TABLE_IBI_MDB; + } else { + reg |= DEV_ADDR_TABLE_SIR_REJECT; + } + writel(reg, master->regs + dat_entry); + + reg = readl(master->regs + IBI_SIR_REQ_REJECT); + if (enable) { + global = reg == 0xffffffff; + reg &= ~BIT(idx); + } else { + global = reg == 0; + reg |= BIT(idx); + } + writel(reg, master->regs + IBI_SIR_REQ_REJECT); + + if (global) { + reg = readl(master->regs + INTR_STATUS_EN); + reg &= ~INTR_IBI_THLD_STAT; + if (enable) + reg |= INTR_IBI_THLD_STAT; + writel(reg, master->regs + INTR_STATUS_EN); + + reg = readl(master->regs + INTR_SIGNAL_EN); + reg &= ~INTR_IBI_THLD_STAT; + if (enable) + reg |= INTR_IBI_THLD_STAT; + writel(reg, master->regs + INTR_SIGNAL_EN); + } + + spin_unlock_irqrestore(&master->devs_lock, flags); +} + +static int dw_i3c_master_enable_ibi(struct i3c_dev_desc *dev) +{ + struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); + struct i3c_master_controller *m = i3c_dev_get_master(dev); + struct dw_i3c_master *master = to_dw_i3c_master(m); + int rc; + + dw_i3c_master_set_sir_enabled(master, dev, data->index, true); + + rc = i3c_master_enec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR); + + if (rc) + dw_i3c_master_set_sir_enabled(master, dev, data->index, false); + + return rc; +} + +static int dw_i3c_master_disable_ibi(struct i3c_dev_desc *dev) +{ + struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); + struct i3c_master_controller *m = i3c_dev_get_master(dev); + struct dw_i3c_master *master = to_dw_i3c_master(m); + int rc; + + rc = i3c_master_disec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR); + if (rc) + return rc; + + dw_i3c_master_set_sir_enabled(master, dev, data->index, false); + + return 0; +} + +static void dw_i3c_master_recycle_ibi_slot(struct i3c_dev_desc *dev, + struct i3c_ibi_slot *slot) +{ + struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); + + i3c_generic_ibi_recycle_slot(data->ibi_pool, slot); +} + +static void dw_i3c_master_drain_ibi_queue(struct dw_i3c_master *master, + int len) +{ + int i; + + for (i = 0; i < DIV_ROUND_UP(len, 4); i++) + readl(master->regs + IBI_QUEUE_STATUS); +} + +static void dw_i3c_master_handle_ibi_sir(struct dw_i3c_master *master, + u32 status) +{ + struct dw_i3c_i2c_dev_data *data; + struct i3c_ibi_slot *slot; + struct i3c_dev_desc *dev; + unsigned long flags; + u8 addr, len; + int idx; + + addr = IBI_QUEUE_IBI_ADDR(status); + len = IBI_QUEUE_STATUS_DATA_LEN(status); + + spin_lock_irqsave(&master->devs_lock, flags); + idx = dw_i3c_master_get_addr_pos(master, addr); + if (idx < 0) { + dev_dbg_ratelimited(&master->base.dev, + "IBI from unknown addr 0x%x\n", addr); + goto err_drain; + } + + dev = master->devs[idx].ibi_dev; + if (!dev || !dev->ibi) { + dev_dbg_ratelimited(&master->base.dev, + "IBI from non-requested dev idx %d\n", idx); + goto err_drain; + } + + data = i3c_dev_get_master_data(dev); + slot = i3c_generic_ibi_get_free_slot(data->ibi_pool); + if (!slot) { + dev_dbg_ratelimited(&master->base.dev, + "No IBI slots available\n"); + goto err_drain; + } + + if (dev->ibi->max_payload_len < len) { + dev_dbg_ratelimited(&master->base.dev, + "IBI payload len %d greater than max %d\n", + len, dev->ibi->max_payload_len); + goto err_drain; + } + + if (len) { + dw_i3c_master_read_ibi_fifo(master, slot->data, len); + slot->len = len; + } + i3c_master_queue_ibi(dev, slot); + + spin_unlock_irqrestore(&master->devs_lock, flags); + + return; + +err_drain: + dw_i3c_master_drain_ibi_queue(master, len); + + spin_unlock_irqrestore(&master->devs_lock, flags); +} + +/* "ibis": referring to In-Band Interrupts, and not + * https://en.wikipedia.org/wiki/Australian_white_ibis. The latter should + * not be handled. + */ +static void dw_i3c_master_irq_handle_ibis(struct dw_i3c_master *master) +{ + unsigned int i, len, n_ibis; + u32 reg; + + reg = readl(master->regs + QUEUE_STATUS_LEVEL); + n_ibis = QUEUE_STATUS_IBI_STATUS_CNT(reg); + if (!n_ibis) + return; + + for (i = 0; i < n_ibis; i++) { + reg = readl(master->regs + IBI_QUEUE_STATUS); + + if (IBI_TYPE_SIRQ(reg)) { + dw_i3c_master_handle_ibi_sir(master, reg); + } else { + len = IBI_QUEUE_STATUS_DATA_LEN(reg); + dev_info(&master->base.dev, + "unsupported IBI type 0x%lx len %d\n", + IBI_QUEUE_STATUS_IBI_ID(reg), len); + dw_i3c_master_drain_ibi_queue(master, len); + } + } +} + static irqreturn_t dw_i3c_master_irq_handler(int irq, void *dev_id) { struct dw_i3c_master *master = dev_id; @@ -1092,6 +1340,9 @@ static irqreturn_t dw_i3c_master_irq_handler(int irq, void *dev_id) writel(INTR_TRANSFER_ERR_STAT, master->regs + INTR_STATUS); spin_unlock(&master->xferqueue.lock); + if (status & INTR_IBI_THLD_STAT) + dw_i3c_master_irq_handle_ibis(master); + return IRQ_HANDLED; } @@ -1110,6 +1361,26 @@ static const struct i3c_master_controller_ops dw_mipi_i3c_ops = { .i2c_xfers = dw_i3c_master_i2c_xfers, }; +static const struct i3c_master_controller_ops dw_mipi_i3c_ibi_ops = { + .bus_init = dw_i3c_master_bus_init, + .bus_cleanup = dw_i3c_master_bus_cleanup, + .attach_i3c_dev = dw_i3c_master_attach_i3c_dev, + .reattach_i3c_dev = dw_i3c_master_reattach_i3c_dev, + .detach_i3c_dev = dw_i3c_master_detach_i3c_dev, + .do_daa = dw_i3c_master_daa, + .supports_ccc_cmd = dw_i3c_master_supports_ccc_cmd, + .send_ccc_cmd = dw_i3c_master_send_ccc_cmd, + .priv_xfers = dw_i3c_master_priv_xfers, + .attach_i2c_dev = dw_i3c_master_attach_i2c_dev, + .detach_i2c_dev = dw_i3c_master_detach_i2c_dev, + .i2c_xfers = dw_i3c_master_i2c_xfers, + .request_ibi = dw_i3c_master_request_ibi, + .free_ibi = dw_i3c_master_free_ibi, + .enable_ibi = dw_i3c_master_enable_ibi, + .disable_ibi = dw_i3c_master_disable_ibi, + .recycle_ibi_slot = dw_i3c_master_recycle_ibi_slot, +}; + /* default platform ops implementations */ static int dw_i3c_platform_init_nop(struct dw_i3c_master *i3c) { @@ -1123,6 +1394,7 @@ static const struct dw_i3c_platform_ops dw_i3c_platform_ops_default = { int dw_i3c_common_probe(struct dw_i3c_master *master, struct platform_device *pdev) { + const struct i3c_master_controller_ops *ops; int ret, irq; if (!master->platform_ops) @@ -1172,8 +1444,11 @@ int dw_i3c_common_probe(struct dw_i3c_master *master, master->maxdevs = ret >> 16; master->free_pos = GENMASK(master->maxdevs - 1, 0); - ret = i3c_master_register(&master->base, &pdev->dev, - &dw_mipi_i3c_ops, false); + ops = &dw_mipi_i3c_ops; + if (master->ibi_capable) + ops = &dw_mipi_i3c_ibi_ops; + + ret = i3c_master_register(&master->base, &pdev->dev, ops, false); if (ret) goto err_assert_rst; diff --git a/drivers/i3c/master/dw-i3c-master.h b/drivers/i3c/master/dw-i3c-master.h index dd0b77e2c66a..0096942649a3 100644 --- a/drivers/i3c/master/dw-i3c-master.h +++ b/drivers/i3c/master/dw-i3c-master.h @@ -19,6 +19,7 @@ struct dw_i3c_master_caps { struct dw_i3c_dat_entry { u8 addr; + struct i3c_dev_desc *ibi_dev; }; struct dw_i3c_master { @@ -37,12 +38,22 @@ struct dw_i3c_master { struct clk *core_clk; char version[5]; char type[5]; + bool ibi_capable; /* * Per-device hardware data, used to manage the device address table * (DAT) + * + * Locking: the devs array may be referenced in IRQ context while + * processing an IBI. However, IBIs (for a specific device, which + * implies a specific DAT entry) can only happen while interrupts are + * requested for that device, which is serialised against other + * insertions/removals from the array by the global i3c infrastructure. + * So, devs_lock protects against concurrent updates to devs->ibi_dev + * between request_ibi/free_ibi and the IBI irq event. */ struct dw_i3c_dat_entry devs[DW_I3C_MAX_DEVS]; + spinlock_t devs_lock; /* platform-specific data */ const struct dw_i3c_platform_ops *platform_ops; From patchwork Thu Mar 30 07:50:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Kerr X-Patchwork-Id: 13194198 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 55AD4C761A6 for ; Thu, 30 Mar 2023 13:47:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=vGDRK4Oy5oGUSml1IFwW7TB4T3SH5HNXZ/INGx0uvww=; b=RIfBWQrU+Ejcgy kmCGg1ZKFK3/BSeG1K791e0FRIB1QHyrB+VEbJQl98K0m5AMbhGKNrpAB2UtQ7BDIDeFggy+thlua LhhrTpFsNFYoecR0LoNaKGRzxXrPFBXkD5TiP5+ATpKNwIjHte6iFA2aCiKBLDgelczkeJjl3rCiL RxbfK846a6n+SD8MrcgdUr4RRrOvoYC6H9CMqz0p99UvZT2fqAATOtX3pB/fOf2+VXPjTTIZomfFl RyAwvAQ4S+Cn/+ZizZdVFUc8H9qWswy/vRNblVVYbv1KSLm11mj2B1qQj+JNhPiJlNt4y5Fe3wYd3 QsZj76l3y+5Yhukm0MpA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1phscu-003vUP-38; Thu, 30 Mar 2023 13:47:40 +0000 Received: from pi.codeconstruct.com.au ([203.29.241.158] helo=codeconstruct.com.au) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1phn3c-002ykb-19 for linux-i3c@lists.infradead.org; Thu, 30 Mar 2023 07:50:53 +0000 Received: by codeconstruct.com.au (Postfix, from userid 10000) id A63AE202DE; Thu, 30 Mar 2023 15:50:50 +0800 (AWST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codeconstruct.com.au; s=2022a; t=1680162650; bh=8zhD2adCLYYuScBOR5iCaSFKhpfq+F0X69zJxXLarvo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=GIUJ+wJHtwMjSE88F1CyGXDRAtTwrDkSRaapKOTDaMaixddks/cp4darrUkSpc2pu zn4eRfjnrtRB36syxICSeLa3YtmO6hm8/UKu0tQkuECVb8F8aOuE350fdUsEYejlJY 6UvDhnACIpKcMqYSluyaX9AND9Yu/EsG1sb7p+TExNpK8BIv8r9nnZyN4/RLGJ9I11 6XL/GR9TSYIc7mI596FiwT9ow2Ry0MZRzcGTU1YbgFZbDPBp8+beXDBykQClJwbmHA R5TbVVuDoEQUS1hUek3kyqtW1zbpPqSyz2c0UwfCZ0sWmHY7PLTTzFtdRldByXSRHd x2WGtN1w84wCg== From: Jeremy Kerr To: linux-i3c@lists.infradead.org Cc: Matt Johnston , Vitor Soares , Alexandre Belloni , Jack Chen , Billy Tsai , Dylan Hung , Joel Stanley , Andrew Jeffery Subject: [PATCH 4/5] i3c: dw: Add a platform facility for IBI PEC workarounds Date: Thu, 30 Mar 2023 15:50:35 +0800 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230330_005052_585736_BA0343C4 X-CRM114-Status: GOOD ( 15.12 ) X-Mailman-Approved-At: Thu, 30 Mar 2023 06:47:39 -0700 X-BeenThere: linux-i3c@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-i3c" Errors-To: linux-i3c-bounces+linux-i3c=archiver.kernel.org@lists.infradead.org On the AST2600 i3c controller, we'll need to apply a workaround for a hardware issue with IBI payloads. Introduce a platform hook to allow dw i3c platform implementations to modify the DAT entry in IBI enable/disable to allow this workaround in a future change. Signed-off-by: Jeremy Kerr --- drivers/i3c/master/dw-i3c-master.c | 19 +++++++++++++++++++ drivers/i3c/master/dw-i3c-master.h | 10 ++++++++++ 2 files changed, 29 insertions(+) diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c index c49c5fa01a26..df8bf985abda 100644 --- a/drivers/i3c/master/dw-i3c-master.c +++ b/drivers/i3c/master/dw-i3c-master.c @@ -1155,6 +1155,7 @@ static void dw_i3c_master_set_sir_enabled(struct dw_i3c_master *master, } else { reg |= DEV_ADDR_TABLE_SIR_REJECT; } + master->platform_ops->set_dat_ibi(master, dev, enable, ®); writel(reg, master->regs + dat_entry); reg = readl(master->regs + IBI_SIR_REQ_REJECT); @@ -1247,6 +1248,17 @@ static void dw_i3c_master_handle_ibi_sir(struct dw_i3c_master *master, addr = IBI_QUEUE_IBI_ADDR(status); len = IBI_QUEUE_STATUS_DATA_LEN(status); + /* + * We be tempted to check the error status in bit 30; however, due + * to the PEC errata workaround on some platform implementations (see + * ast2600_i3c_set_dat_ibi()), those will almost always have a PEC + * error on IBI payload data, as well as losing the last byte of + * payload. + * + * If we implement error status checking on that bit, we may need + * a new platform op to validate it. + */ + spin_lock_irqsave(&master->devs_lock, flags); idx = dw_i3c_master_get_addr_pos(master, addr); if (idx < 0) { @@ -1387,8 +1399,15 @@ static int dw_i3c_platform_init_nop(struct dw_i3c_master *i3c) return 0; } +static void dw_i3c_platform_set_dat_ibi_nop(struct dw_i3c_master *i3c, + struct i3c_dev_desc *dev, + bool enable, u32 *dat) +{ +} + static const struct dw_i3c_platform_ops dw_i3c_platform_ops_default = { .init = dw_i3c_platform_init_nop, + .set_dat_ibi = dw_i3c_platform_set_dat_ibi_nop, }; int dw_i3c_common_probe(struct dw_i3c_master *master, diff --git a/drivers/i3c/master/dw-i3c-master.h b/drivers/i3c/master/dw-i3c-master.h index 0096942649a3..379300b7c405 100644 --- a/drivers/i3c/master/dw-i3c-master.h +++ b/drivers/i3c/master/dw-i3c-master.h @@ -67,6 +67,16 @@ struct dw_i3c_platform_ops { * perform actual device enabling with the i3c core ready. */ int (*init)(struct dw_i3c_master *i3c); + + /* + * Initialise a DAT entry to enable/disable IBIs. Allows the platform + * to perform any device workarounds on the DAT entry before + * inserting into the hardware table. + * + * Called with the DAT lock held; must not sleep. + */ + void (*set_dat_ibi)(struct dw_i3c_master *i3c, + struct i3c_dev_desc *dev, bool enable, u32 *reg); }; extern int dw_i3c_common_probe(struct dw_i3c_master *master, From patchwork Thu Mar 30 07:50:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Kerr X-Patchwork-Id: 13194199 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 13DE7C77B6F for ; Thu, 30 Mar 2023 13:47:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=K8KPtzuUmn2TnSIpJ7VXiymS0YT/3UF3zHTCbD00IL8=; b=GJkj56SUR2Rxsu gmoC4CZVf8BU4Yqyd9lSX475+ECzUfK/TtHVEAgPULBfd3yS5RcmH08In7OTsjWTiKwccj6/+ZrGz FhG6rxYJPEdS2Oc9UAtRs65USFuD1nnY+VEe23YDW3Sw3oXNNuwsvrikYSn4Bx94BorOcJvdlu/Z1 Lf4WXQiPppeKebX7IT/YS4QBMH98+WWAC6yUxr8oMmYl2cVPRC88EVUinlsFlNNtaikC9L8UgfEIQ 113iWKdgN4fquuyckNpYcQ+7Ih6ME9g+L2LT2xKrAm4WOCXAaN3yzaJMfmymE/igAWyC0wjJo+ktK fsKs/xmdgXSRR0PrrJ1Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1phscv-003vUq-1l; Thu, 30 Mar 2023 13:47:41 +0000 Received: from pi.codeconstruct.com.au ([203.29.241.158] helo=codeconstruct.com.au) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1phn3d-002ylX-2O for linux-i3c@lists.infradead.org; Thu, 30 Mar 2023 07:50:55 +0000 Received: by codeconstruct.com.au (Postfix, from userid 10000) id 10EE6203CB; Thu, 30 Mar 2023 15:50:51 +0800 (AWST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codeconstruct.com.au; s=2022a; t=1680162651; bh=TgWA3dNdjw60/A4TBWePBoZJR96ih9X8EEXzL94FJKM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=dzWg3NEeDk5FeA5lWd6SScOUizSw4NDd5KWrRnsP7OMPamYA6mYBC6CqDqPonJKL2 O0ZtzOu3xFrH3P49ewg4kdQc8CoiQKLr+fTieHho8I8N97wWjy04YNxwE6nORqtkvu zEzThb5ejhF1bOTv2fo5cl4XdeWaZNJiH6OsfB3WhLtMTuobE39rbEA1iSmVsLN/ft SwBZmrIJLZQqSq4ThoKtkxINc4+TYuw2rHS21ZGR3giBKPqUNUAFpDWS5938t80d6u QK2iVaxVk1aLyVrnl3V9gR4imC3ZJTWOuZpbx5EhJzvNfIjond5q8yCRpp6WuA61wW vGKYl57YBiNcQ== From: Jeremy Kerr To: linux-i3c@lists.infradead.org Cc: Matt Johnston , Vitor Soares , Alexandre Belloni , Jack Chen , Billy Tsai , Dylan Hung , Joel Stanley , Andrew Jeffery Subject: [PATCH 5/5] i3c: ast2600: enable IBI support Date: Thu, 30 Mar 2023 15:50:36 +0800 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230330_005053_975724_A6A3A018 X-CRM114-Status: GOOD ( 13.95 ) X-Mailman-Approved-At: Thu, 30 Mar 2023 06:47:39 -0700 X-BeenThere: linux-i3c@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-i3c" Errors-To: linux-i3c-bounces+linux-i3c=archiver.kernel.org@lists.infradead.org The ast2600 i3c hardware is capable of IBIs, but we need a workaround for a hardware issue with the I3C state machine handling IBI payloads of specific lengths when PEC is not enabled. To avoid this, we need to unconditionally enable PECs, at the consquence of losing a byte of data when the device does not send a PEC. Enable IBIs on the ast2600 platform, including an implementation of the PEC workaround, which prints a warning when triggered. Signed-off-by: Jeremy Kerr --- drivers/i3c/master/ast2600-i3c-master.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/i3c/master/ast2600-i3c-master.c b/drivers/i3c/master/ast2600-i3c-master.c index d3d7b7d19f22..52d9474a7651 100644 --- a/drivers/i3c/master/ast2600-i3c-master.c +++ b/drivers/i3c/master/ast2600-i3c-master.c @@ -36,6 +36,8 @@ #define AST2600_DEFAULT_SDA_PULLUP_OHMS 2000 +#define DEV_ADDR_TABLE_IBI_PEC BIT(11) + struct ast2600_i3c_platform_data { struct regmap *global_regs; unsigned int global_idx; @@ -93,8 +95,26 @@ static int ast2600_i3c_init(struct dw_i3c_master *master) return rc; } +static void ast2600_i3c_set_dat_ibi(struct dw_i3c_master *i3c, + struct i3c_dev_desc *dev, + bool enable, u32 *dat) +{ + /* + * The ast2600 i3c controller will lock up on receiving 4n+1-byte IBIs + * if the PEC is disabled. We have no way to restrict the length of + * IBIs sent to the controller, so we need to unconditionally enable + * PEC checking, which means we drop a byte of payload data + */ + if (enable && dev->info.bcr & I3C_BCR_IBI_PAYLOAD) { + dev_warn_once(&i3c->base.dev, + "Enabling PEC workaround. IBI payloads will be truncated\n"); + *dat |= DEV_ADDR_TABLE_IBI_PEC; + } +} + const struct dw_i3c_platform_ops ast2600_i3c_ops = { .init = ast2600_i3c_init, + .set_dat_ibi = ast2600_i3c_set_dat_ibi, }; static int ast2600_i3c_probe(struct platform_device *pdev) @@ -136,6 +156,7 @@ static int ast2600_i3c_probe(struct platform_device *pdev) dw_i3c->platform_ops = &ast2600_i3c_ops; dw_i3c->platform_data = pdata; + dw_i3c->ibi_capable = true; rc = dw_i3c_common_probe(dw_i3c, pdev); return rc;