From patchwork Fri Aug 18 16:38:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358148 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 E1A5619BAA for ; Fri, 18 Aug 2023 17:21:33 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6CD173C2F; Fri, 18 Aug 2023 10:21:32 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zb6hvKz9vh3; Fri, 18 Aug 2023 18:39:55 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id qup60zNDrY4u; Fri, 18 Aug 2023 18:39:55 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zb5lwmz9vh0; Fri, 18 Aug 2023 18:39:55 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id BA9278B76E; Fri, 18 Aug 2023 18:39:55 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id iU68_7YXx2LN; Fri, 18 Aug 2023 18:39:55 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 247D28B76D; Fri, 18 Aug 2023 18:39:55 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdnaZ141939 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:49 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdndH141938; Fri, 18 Aug 2023 18:39:49 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 01/28] soc: fsl: cpm1: tsa: Fix __iomem addresses declaration Date: Fri, 18 Aug 2023 18:38:55 +0200 Message-ID: <5cb6fc867f6ac1669f345f087d33146bbbd192e6.1692376360.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376733; l=2795; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=JckFiaw0B32weMpypPXBuy8hhPCeBPl682cS3XyP6to=; b=2eopj1b+FKzM8/8EEDzNbVlSFfQGD2LxW9XBGKK95udg6q3xQJYwdoFmSuXhoegqHhgW5v5pu CKyD+N8oTmsAWwbTjt9lQA3A3xHlvCKW3Og+k0mXCNooFN6+oJ7eXCb X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina Running sparse (make C=1) on tsa.c raises a lot of warning such as: --- 8< --- warning: incorrect type in assignment (different address spaces) expected void *[noderef] si_regs got void [noderef] __iomem * --- 8< --- Indeed, some variable were declared 'type *__iomem var' instead of 'type __iomem *var'. Use the correct declaration to remove these warnings. Fixes: 1d4ba0b81c1c ("soc: fsl: cpm1: Add support for TSA") Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/tsa.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/soc/fsl/qe/tsa.c b/drivers/soc/fsl/qe/tsa.c index 3646153117b3..e0527b9efd05 100644 --- a/drivers/soc/fsl/qe/tsa.c +++ b/drivers/soc/fsl/qe/tsa.c @@ -98,9 +98,9 @@ #define TSA_SIRP 0x10 struct tsa_entries_area { - void *__iomem entries_start; - void *__iomem entries_next; - void *__iomem last_entry; + void __iomem *entries_start; + void __iomem *entries_next; + void __iomem *last_entry; }; struct tsa_tdm { @@ -117,8 +117,8 @@ struct tsa_tdm { struct tsa { struct device *dev; - void *__iomem si_regs; - void *__iomem si_ram; + void __iomem *si_regs; + void __iomem *si_ram; resource_size_t si_ram_sz; spinlock_t lock; int tdms; /* TSA_TDMx ORed */ @@ -135,27 +135,27 @@ static inline struct tsa *tsa_serial_get_tsa(struct tsa_serial *tsa_serial) return container_of(tsa_serial, struct tsa, serials[tsa_serial->id]); } -static inline void tsa_write32(void *__iomem addr, u32 val) +static inline void tsa_write32(void __iomem *addr, u32 val) { iowrite32be(val, addr); } -static inline void tsa_write8(void *__iomem addr, u32 val) +static inline void tsa_write8(void __iomem *addr, u32 val) { iowrite8(val, addr); } -static inline u32 tsa_read32(void *__iomem addr) +static inline u32 tsa_read32(void __iomem *addr) { return ioread32be(addr); } -static inline void tsa_clrbits32(void *__iomem addr, u32 clr) +static inline void tsa_clrbits32(void __iomem *addr, u32 clr) { tsa_write32(addr, tsa_read32(addr) & ~clr); } -static inline void tsa_clrsetbits32(void *__iomem addr, u32 clr, u32 set) +static inline void tsa_clrsetbits32(void __iomem *addr, u32 clr, u32 set) { tsa_write32(addr, (tsa_read32(addr) & ~clr) | set); } @@ -313,7 +313,7 @@ static u32 tsa_serial_id2csel(struct tsa *tsa, u32 serial_id) static int tsa_add_entry(struct tsa *tsa, struct tsa_entries_area *area, u32 count, u32 serial_id) { - void *__iomem addr; + void __iomem *addr; u32 left; u32 val; u32 cnt; From patchwork Fri Aug 18 16:38:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358155 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 05E5418AEF for ; Fri, 18 Aug 2023 17:22:56 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5988B4C37; Fri, 18 Aug 2023 10:22:25 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zc0vxzz9vh4; Fri, 18 Aug 2023 18:39:56 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Bjavs_ntN8Dt; Fri, 18 Aug 2023 18:39:56 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zb5qkjz9vh1; Fri, 18 Aug 2023 18:39:55 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id BACF58B770; Fri, 18 Aug 2023 18:39:55 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id UimrfuHr5_g6; Fri, 18 Aug 2023 18:39:55 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 1D6278B763; Fri, 18 Aug 2023 18:39:55 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdnO5141943 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:49 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdnLq141942; Fri, 18 Aug 2023 18:39:49 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 02/28] soc: fsl: cpm1: qmc: Fix __iomem addresses declaration Date: Fri, 18 Aug 2023 18:38:56 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376733; l=4245; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=VaHcnf0Oe94R1ui0OjR9HSdn/INV9sf104dQNcD0py8=; b=tKGn81RtSSlMcIQajCPXdoiDq1sf2du59SOBWY7dIbH3ybCipHexVrRVZVLiimIUra0+FuSpF mdpnUvVS0uMC836VAMXInMnEgc/vbkmEC+J5OnPqduw4jCMhAfup0ab X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina Running sparse (make C=1) on qmc.c raises a lot of warning such as: ... warning: incorrect type in assignment (different address spaces) expected struct cpm_buf_desc [usertype] *[noderef] __iomem bd got struct cpm_buf_desc [noderef] [usertype] __iomem *txbd_free ... Indeed, some variable were declared 'type *__iomem var' instead of 'type __iomem *var'. Use the correct declaration to remove these warnings. Fixes: 3178d58e0b97 ("soc: fsl: cpm1: Add support for QMC") Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index b3c292c9a14e..7ad0d77f1740 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -175,7 +175,7 @@ struct qmc_chan { struct list_head list; unsigned int id; struct qmc *qmc; - void *__iomem s_param; + void __iomem *s_param; enum qmc_mode mode; u64 tx_ts_mask; u64 rx_ts_mask; @@ -203,9 +203,9 @@ struct qmc_chan { struct qmc { struct device *dev; struct tsa_serial *tsa_serial; - void *__iomem scc_regs; - void *__iomem scc_pram; - void *__iomem dpram; + void __iomem *scc_regs; + void __iomem *scc_pram; + void __iomem *dpram; u16 scc_pram_offset; cbd_t __iomem *bd_table; dma_addr_t bd_dma_addr; @@ -218,37 +218,37 @@ struct qmc { struct qmc_chan *chans[64]; }; -static inline void qmc_write16(void *__iomem addr, u16 val) +static inline void qmc_write16(void __iomem *addr, u16 val) { iowrite16be(val, addr); } -static inline u16 qmc_read16(void *__iomem addr) +static inline u16 qmc_read16(void __iomem *addr) { return ioread16be(addr); } -static inline void qmc_setbits16(void *__iomem addr, u16 set) +static inline void qmc_setbits16(void __iomem *addr, u16 set) { qmc_write16(addr, qmc_read16(addr) | set); } -static inline void qmc_clrbits16(void *__iomem addr, u16 clr) +static inline void qmc_clrbits16(void __iomem *addr, u16 clr) { qmc_write16(addr, qmc_read16(addr) & ~clr); } -static inline void qmc_write32(void *__iomem addr, u32 val) +static inline void qmc_write32(void __iomem *addr, u32 val) { iowrite32be(val, addr); } -static inline u32 qmc_read32(void *__iomem addr) +static inline u32 qmc_read32(void __iomem *addr) { return ioread32be(addr); } -static inline void qmc_setbits32(void *__iomem addr, u32 set) +static inline void qmc_setbits32(void __iomem *addr, u32 set) { qmc_write32(addr, qmc_read32(addr) | set); } @@ -318,7 +318,7 @@ int qmc_chan_write_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, { struct qmc_xfer_desc *xfer_desc; unsigned long flags; - cbd_t *__iomem bd; + cbd_t __iomem *bd; u16 ctrl; int ret; @@ -374,7 +374,7 @@ static void qmc_chan_write_done(struct qmc_chan *chan) void (*complete)(void *context); unsigned long flags; void *context; - cbd_t *__iomem bd; + cbd_t __iomem *bd; u16 ctrl; /* @@ -425,7 +425,7 @@ int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, { struct qmc_xfer_desc *xfer_desc; unsigned long flags; - cbd_t *__iomem bd; + cbd_t __iomem *bd; u16 ctrl; int ret; @@ -488,7 +488,7 @@ static void qmc_chan_read_done(struct qmc_chan *chan) void (*complete)(void *context, size_t size); struct qmc_xfer_desc *xfer_desc; unsigned long flags; - cbd_t *__iomem bd; + cbd_t __iomem *bd; void *context; u16 datalen; u16 ctrl; @@ -663,7 +663,7 @@ static void qmc_chan_reset_rx(struct qmc_chan *chan) { struct qmc_xfer_desc *xfer_desc; unsigned long flags; - cbd_t *__iomem bd; + cbd_t __iomem *bd; u16 ctrl; spin_lock_irqsave(&chan->rx_lock, flags); @@ -694,7 +694,7 @@ static void qmc_chan_reset_tx(struct qmc_chan *chan) { struct qmc_xfer_desc *xfer_desc; unsigned long flags; - cbd_t *__iomem bd; + cbd_t __iomem *bd; u16 ctrl; spin_lock_irqsave(&chan->tx_lock, flags); From patchwork Fri Aug 18 16:38:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358128 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 1B2D4374 for ; Fri, 18 Aug 2023 17:20:12 +0000 (UTC) X-Greylist: delayed 2413 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Fri, 18 Aug 2023 10:20:10 PDT Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 60CBE421E; Fri, 18 Aug 2023 10:20:10 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zt2Tnqz9vhy; Fri, 18 Aug 2023 18:40:10 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6Z2mtYfdpXn8; Fri, 18 Aug 2023 18:40:10 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl2NZVz9vhD; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 490838B763; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id PbjSglRz40z8; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 824878B77B; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGduMT141953 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:56 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdulx141946; Fri, 18 Aug 2023 18:39:56 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 03/28] soc: fsl: cpm1: qmc: Fix rx channel reset Date: Fri, 18 Aug 2023 18:38:57 +0200 Message-ID: <9abc0780ffd0a9044e6898ba215945d23b654e13.1692376360.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376733; l=1148; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=X9kXmBtJCxdri6wIDJc7D4FbiQfqsl2mU0uxDYqz7Xk=; b=vqX5OYOX33oUculF2eTODTe8s/15M/RMXx6M9PfDySyA1I5W2KYOF7tRVyBbWFL7gT1gVm0wT uPilhRKifOJAEzpVTD4vSeXn0iXtChfJW3sft5dyDx4RSvORB4pqfQi X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina The qmc_chan_reset_rx() set the is_rx_stopped flag. This leads to an inconsistent state in the following sequence. qmc_chan_stop() qmc_chan_reset() Indeed, after the qmc_chan_reset() call, the channel must still be stopped. Only a qmc_chan_start() call can move the channel from stopped state to started state. Fix the issue removing the is_rx_stopped flag setting from qmc_chan_reset() Fixes: 3178d58e0b97 ("soc: fsl: cpm1: Add support for QMC") Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 7ad0d77f1740..8dc73cc1a83b 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -685,7 +685,6 @@ static void qmc_chan_reset_rx(struct qmc_chan *chan) qmc_read16(chan->s_param + QMC_SPE_RBASE)); chan->rx_pending = 0; - chan->is_rx_stopped = false; spin_unlock_irqrestore(&chan->rx_lock, flags); } From patchwork Fri Aug 18 16:38:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358131 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 84E9C19BB9 for ; Fri, 18 Aug 2023 17:20:29 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 11F603C2F; Fri, 18 Aug 2023 10:20:26 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zy13R7z9vjC; Fri, 18 Aug 2023 18:40:14 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 4U7RhbHWPQT8; Fri, 18 Aug 2023 18:40:14 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl44p9z9vhW; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 815098B76D; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id cQvcVEpSSBcJ; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 8DC028B77C; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGduno141957 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:56 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdu5A141956; Fri, 18 Aug 2023 18:39:56 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 04/28] soc: fsl: cpm1: qmc: Extend the API to provide Rx status Date: Fri, 18 Aug 2023 18:38:58 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376734; l=5458; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=NLobTtZwmX6+TiWRgTbk0b6G1wgEpGh/t2FaZYMhZLs=; b=31GwyewAkhJBnFz8bfeoy3PPfhugRG03/u3bJHd03c2Rb9ym1AZo3atjcAHYUlxNHwyRwxd4B 796HpaTjo9tCsgzHvVtoi/lQDyl1uU7j9XrNj69Wjvm1qMPCT6eSuat X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina In HDLC mode, some status flags related to the data read transfer can be set by the hardware and need to be known by a QMC consumer for further analysis. Extend the API in order to provide these transfer status flags at the read complete() call. In TRANSPARENT mode, these flags have no meaning. Keep only one read complete() API and update the consumers working in transparent mode. In this case, the newly introduced flags parameter is simply unused. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 29 +++++++++++++++++++++++++---- include/soc/fsl/qe/qmc.h | 15 ++++++++++++++- sound/soc/fsl/fsl_qmc_audio.c | 2 +- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 8dc73cc1a83b..2d2a9d88ba6c 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -166,7 +166,7 @@ struct qmc_xfer_desc { union { void (*tx_complete)(void *context); - void (*rx_complete)(void *context, size_t length); + void (*rx_complete)(void *context, size_t length, unsigned int flags); }; void *context; }; @@ -421,7 +421,8 @@ static void qmc_chan_write_done(struct qmc_chan *chan) } int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, - void (*complete)(void *context, size_t length), void *context) + void (*complete)(void *context, size_t length, unsigned int flags), + void *context) { struct qmc_xfer_desc *xfer_desc; unsigned long flags; @@ -454,6 +455,10 @@ int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, xfer_desc->rx_complete = complete; xfer_desc->context = context; + /* Clear previous status flags */ + ctrl &= ~(QMC_BD_RX_L | QMC_BD_RX_F | QMC_BD_RX_LG | QMC_BD_RX_NO | + QMC_BD_RX_AB | QMC_BD_RX_CR); + /* Activate the descriptor */ ctrl |= (QMC_BD_RX_E | QMC_BD_RX_UB); wmb(); /* Be sure to flush data before descriptor activation */ @@ -485,7 +490,7 @@ EXPORT_SYMBOL(qmc_chan_read_submit); static void qmc_chan_read_done(struct qmc_chan *chan) { - void (*complete)(void *context, size_t size); + void (*complete)(void *context, size_t size, unsigned int flags); struct qmc_xfer_desc *xfer_desc; unsigned long flags; cbd_t __iomem *bd; @@ -527,7 +532,23 @@ static void qmc_chan_read_done(struct qmc_chan *chan) if (complete) { spin_unlock_irqrestore(&chan->rx_lock, flags); - complete(context, datalen); + + /* + * Avoid conversion between internal hardware flags and + * the software API flags. + * -> Be sure that the software API flags are consistent + * with the hardware flags + */ + BUILD_BUG_ON(QMC_RX_FLAG_HDLC_LAST != QMC_BD_RX_L); + BUILD_BUG_ON(QMC_RX_FLAG_HDLC_FIRST != QMC_BD_RX_F); + BUILD_BUG_ON(QMC_RX_FLAG_HDLC_OVF != QMC_BD_RX_LG); + BUILD_BUG_ON(QMC_RX_FLAG_HDLC_UNA != QMC_BD_RX_NO); + BUILD_BUG_ON(QMC_RX_FLAG_HDLC_ABORT != QMC_BD_RX_AB); + BUILD_BUG_ON(QMC_RX_FLAG_HDLC_CRC != QMC_BD_RX_CR); + + complete(context, datalen, + ctrl & (QMC_BD_RX_L | QMC_BD_RX_F | QMC_BD_RX_LG | + QMC_BD_RX_NO | QMC_BD_RX_AB | QMC_BD_RX_CR)); spin_lock_irqsave(&chan->rx_lock, flags); } diff --git a/include/soc/fsl/qe/qmc.h b/include/soc/fsl/qe/qmc.h index 3c61a50d2ae2..6f1d6cebc9fe 100644 --- a/include/soc/fsl/qe/qmc.h +++ b/include/soc/fsl/qe/qmc.h @@ -9,6 +9,7 @@ #ifndef __SOC_FSL_QMC_H__ #define __SOC_FSL_QMC_H__ +#include #include struct device_node; @@ -56,8 +57,20 @@ int qmc_chan_set_param(struct qmc_chan *chan, const struct qmc_chan_param *param int qmc_chan_write_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, void (*complete)(void *context), void *context); +/* Flags available (ORed) for read complete() flags parameter in HDLC mode. + * No flags are available in transparent mode and the read complete() flags + * parameter has no meaning in transparent mode. + */ +#define QMC_RX_FLAG_HDLC_LAST BIT(11) /* Last in frame */ +#define QMC_RX_FLAG_HDLC_FIRST BIT(10) /* First in frame */ +#define QMC_RX_FLAG_HDLC_OVF BIT(5) /* Data overflow */ +#define QMC_RX_FLAG_HDLC_UNA BIT(4) /* Unaligned (ie. bits received not multiple of 8) */ +#define QMC_RX_FLAG_HDLC_ABORT BIT(3) /* Received an abort sequence (seven consecutive ones) */ +#define QMC_RX_FLAG_HDLC_CRC BIT(2) /* CRC error */ + int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, - void (*complete)(void *context, size_t length), + void (*complete)(void *context, size_t length, + unsigned int flags), void *context); #define QMC_CHAN_READ (1<<0) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index 7cbb8e4758cc..5d745aae17a8 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -99,7 +99,7 @@ static void qmc_audio_pcm_write_complete(void *context) snd_pcm_period_elapsed(prtd->substream); } -static void qmc_audio_pcm_read_complete(void *context, size_t length) +static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags) { struct qmc_dai_prtd *prtd = context; int ret; From patchwork Fri Aug 18 16:38:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358156 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 05134525F for ; Fri, 18 Aug 2023 17:24:11 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4CC9F49EA; Fri, 18 Aug 2023 10:23:45 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zq0k5bz9vhr; Fri, 18 Aug 2023 18:40:07 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id e3sU6JfKIHrC; Fri, 18 Aug 2023 18:40:07 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl1B1vz9vhJ; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 1F1E78B763; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id WAQGydDBpqb7; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 6CC5C8B774; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGduIu141961 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:56 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGduB3141960; Fri, 18 Aug 2023 18:39:56 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 05/28] soc: fsl: cpm1: qmc: Remove inline function specifiers Date: Fri, 18 Aug 2023 18:38:59 +0200 Message-ID: <5e4f6d8ae6c6f4e51fdc8d6b8cdbdd42bbdbfcf9.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376734; l=1927; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=kk1Ixhq/BCVZyT9VsSP1IQf1Jw/ahn3zn+6m9m/YV/k=; b=M13QAt9aKgtJFw7MZl2TkKG6g2k3N0uDUJTk2EdWY9JLBRDZmNcT9oDY3wzhySPbXAyFxNXoY x7esQx7fdcsCaW8Ax7sFVrnxgjZrj6JI8RD7HBT011D+N3DB98fNoye X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina The inline function specifier is present on some functions but it is better to let the compiler decide inlining or not these functions. Remove inline specifiers. Fixes: 3178d58e0b97 ("soc: fsl: cpm1: Add support for QMC") Signed-off-by: Herve Codina Suggested-by: Andrew Lunn Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 2d2a9d88ba6c..459e0bbd723d 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -218,37 +218,37 @@ struct qmc { struct qmc_chan *chans[64]; }; -static inline void qmc_write16(void __iomem *addr, u16 val) +static void qmc_write16(void __iomem *addr, u16 val) { iowrite16be(val, addr); } -static inline u16 qmc_read16(void __iomem *addr) +static u16 qmc_read16(void __iomem *addr) { return ioread16be(addr); } -static inline void qmc_setbits16(void __iomem *addr, u16 set) +static void qmc_setbits16(void __iomem *addr, u16 set) { qmc_write16(addr, qmc_read16(addr) | set); } -static inline void qmc_clrbits16(void __iomem *addr, u16 clr) +static void qmc_clrbits16(void __iomem *addr, u16 clr) { qmc_write16(addr, qmc_read16(addr) & ~clr); } -static inline void qmc_write32(void __iomem *addr, u32 val) +static void qmc_write32(void __iomem *addr, u32 val) { iowrite32be(val, addr); } -static inline u32 qmc_read32(void __iomem *addr) +static u32 qmc_read32(void __iomem *addr) { return ioread32be(addr); } -static inline void qmc_setbits32(void __iomem *addr, u32 set) +static void qmc_setbits32(void __iomem *addr, u32 set) { qmc_write32(addr, qmc_read32(addr) | set); } From patchwork Fri Aug 18 16:39:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358137 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 0B7CF198A6 for ; Fri, 18 Aug 2023 17:20:55 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3F9434220; Fri, 18 Aug 2023 10:20:51 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zx101Sz9vj7; Fri, 18 Aug 2023 18:40:13 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Vq0nZ22zTOTC; Fri, 18 Aug 2023 18:40:13 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl3Tzmz9vhS; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 6CFD28B76D; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id FkBysxlO6_lW; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 785AF8B778; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGduZa141965 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:56 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGduW0141964; Fri, 18 Aug 2023 18:39:56 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 06/28] dt-bindings: net: Add support for QMC HDLC Date: Fri, 18 Aug 2023 18:39:00 +0200 Message-ID: <817d1418fa1e9e689375177bee4bdc68ceeab7be.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376734; l=2185; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=Rhuf0RNV4GJcMGFMFtbF5khE6XrVnFMNx4Jm/4p0AlQ=; b=l58NOiJaH/3m2dMO1c4zAyIFYfua+VAE//+mdzcjYAj/fVr74OpMAeaProCJ8fUOhXQdDyPJg z6CfXTIavP+BbLXn6OGqtdM03JBlGJZPnWeD5eXih1eKu3KroYFr3T4 X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Herve Codina The QMC (QUICC mutichannel controller) is a controller present in some PowerQUICC SoC such as MPC885. The QMC HDLC uses the QMC controller to transfer HDLC data. Additionally, a framer can be connected to the QMC HDLC. If present, this framer is the interface between the TDM bus used by the QMC HDLC and the E1/T1 line. The QMC HDLC can use this framer to get information about the E1/T1 line and configure the E1/T1 line. Signed-off-by: Herve Codina Signed-off-by: Christophe Leroy --- .../devicetree/bindings/net/fsl,qmc-hdlc.yaml | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml diff --git a/Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml b/Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml new file mode 100644 index 000000000000..13f3572f0feb --- /dev/null +++ b/Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/fsl,qmc-hdlc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale/NXP QUICC Multichannel Controller (QMC) HDLC + +maintainers: + - Herve Codina + +description: | + The QMC HDLC uses a QMC (QUICC Multichannel Controller) channel to transfer + HDLC data. + +properties: + compatible: + const: fsl,qmc-hdlc + + fsl,qmc-chan: + $ref: /schemas/types.yaml#/definitions/phandle-array + items: + - items: + - description: phandle to QMC node + - description: Channel number + description: + Should be a phandle/number pair. The phandle to QMC node and the QMC + channel to use. + + framer: + $ref: /schemas/types.yaml#/definitions/phandle + description: + phandle to the framer node + +required: + - compatible + - fsl,qmc-chan + +additionalProperties: false + +examples: + - | + hdlc { + compatible = "fsl,qmc-hdlc"; + fsl,qmc-chan = <&qmc 16>; + }; From patchwork Fri Aug 18 16:39:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358129 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 E66CD374 for ; Fri, 18 Aug 2023 17:20:19 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BAB5D422D; Fri, 18 Aug 2023 10:20:14 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zn48npz9vhh; Fri, 18 Aug 2023 18:40:05 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id CTj05KtDi1lF; Fri, 18 Aug 2023 18:40:05 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl0SZFz9vhF; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 04FBB8B786; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id W0rjflobIpTw; Fri, 18 Aug 2023 18:40:02 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 544DD8B763; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdvCo141969 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:57 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdvRm141968; Fri, 18 Aug 2023 18:39:57 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 07/28] net: wan: Add support for QMC HDLC Date: Fri, 18 Aug 2023 18:39:01 +0200 Message-ID: <1f1c9f83995256e536bd059fafc678f40db509fc.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376734; l=13839; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=mRqPvUv6glTTWYDh9voj8egQIX71MFysXs+evtBCtMg=; b=Me85v7WY86Q5ng5ZQrTXl5ZdFUB0F86gbA9HTC1qCn1+zVHCpCXpISZK/dFDlqsRsyAYZQ5s0 sq+jqpJzhxwD87maa8S99S2QtEcCLvfOQ7PZ6vM1aKy5u1vLEruqlFs X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Herve Codina The QMC HDLC driver provides support for HDLC using the QMC (QUICC Multichannel Controller) to transfer the HDLC data. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/net/wan/Kconfig | 12 + drivers/net/wan/Makefile | 1 + drivers/net/wan/fsl_qmc_hdlc.c | 422 +++++++++++++++++++++++++++++++++ 3 files changed, 435 insertions(+) create mode 100644 drivers/net/wan/fsl_qmc_hdlc.c diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index dcb069dde66b..8de99f4b647b 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -195,6 +195,18 @@ config FARSYNC To compile this driver as a module, choose M here: the module will be called farsync. +config FSL_QMC_HDLC + tristate "Freescale QMC HDLC support" + depends on HDLC + depends on CPM_QMC + help + HDLC support using the Freescale QUICC Multichannel Controller (QMC). + + To compile this driver as a module, choose M here: the + module will be called fsl_qmc_hdlc. + + If unsure, say N. + config FSL_UCC_HDLC tristate "Freescale QUICC Engine HDLC support" depends on HDLC diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile index 5bec8fae47f8..f338f4830626 100644 --- a/drivers/net/wan/Makefile +++ b/drivers/net/wan/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_WANXL) += wanxl.o obj-$(CONFIG_PCI200SYN) += pci200syn.o obj-$(CONFIG_PC300TOO) += pc300too.o obj-$(CONFIG_IXP4XX_HSS) += ixp4xx_hss.o +obj-$(CONFIG_FSL_QMC_HDLC) += fsl_qmc_hdlc.o obj-$(CONFIG_FSL_UCC_HDLC) += fsl_ucc_hdlc.o obj-$(CONFIG_SLIC_DS26522) += slic_ds26522.o diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c new file mode 100644 index 000000000000..4f84ac5fc63e --- /dev/null +++ b/drivers/net/wan/fsl_qmc_hdlc.c @@ -0,0 +1,422 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Freescale QMC HDLC Device Driver + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct qmc_hdlc_desc { + struct net_device *netdev; + struct sk_buff *skb; /* NULL if the descriptor is not in use */ + dma_addr_t dma_addr; + size_t dma_size; +}; + +struct qmc_hdlc { + struct device *dev; + struct qmc_chan *qmc_chan; + struct net_device *netdev; + bool is_crc32; + spinlock_t tx_lock; /* Protect tx descriptors */ + struct qmc_hdlc_desc tx_descs[8]; + unsigned int tx_out; + struct qmc_hdlc_desc rx_descs[4]; +}; + +static inline struct qmc_hdlc *netdev_to_qmc_hdlc(struct net_device *netdev) +{ + return dev_to_hdlc(netdev)->priv; +} + +static int qmc_hdlc_recv_queue(struct qmc_hdlc *qmc_hdlc, struct qmc_hdlc_desc *desc, size_t size); + +#define QMC_HDLC_RX_ERROR_FLAGS (QMC_RX_FLAG_HDLC_OVF | \ + QMC_RX_FLAG_HDLC_UNA | \ + QMC_RX_FLAG_HDLC_ABORT | \ + QMC_RX_FLAG_HDLC_CRC) + +static void qmc_hcld_recv_complete(void *context, size_t length, unsigned int flags) +{ + struct qmc_hdlc_desc *desc = context; + struct net_device *netdev = desc->netdev; + struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(desc->netdev); + int ret; + + dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, DMA_FROM_DEVICE); + + if (flags & QMC_HDLC_RX_ERROR_FLAGS) { + netdev->stats.rx_errors++; + if (flags & QMC_RX_FLAG_HDLC_OVF) /* Data overflow */ + netdev->stats.rx_over_errors++; + if (flags & QMC_RX_FLAG_HDLC_UNA) /* bits received not multiple of 8 */ + netdev->stats.rx_frame_errors++; + if (flags & QMC_RX_FLAG_HDLC_ABORT) /* Received an abort sequence */ + netdev->stats.rx_frame_errors++; + if (flags & QMC_RX_FLAG_HDLC_CRC) /* CRC error */ + netdev->stats.rx_crc_errors++; + kfree_skb(desc->skb); + } else { + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += length; + + skb_put(desc->skb, length); + desc->skb->protocol = hdlc_type_trans(desc->skb, netdev); + netif_rx(desc->skb); + } + + /* Re-queue a transfer using the same descriptor */ + ret = qmc_hdlc_recv_queue(qmc_hdlc, desc, desc->dma_size); + if (ret) { + dev_err(qmc_hdlc->dev, "queue recv desc failed (%d)\n", ret); + netdev->stats.rx_errors++; + } +} + +static int qmc_hdlc_recv_queue(struct qmc_hdlc *qmc_hdlc, struct qmc_hdlc_desc *desc, size_t size) +{ + int ret; + + desc->skb = dev_alloc_skb(size); + if (!desc->skb) + return -ENOMEM; + + desc->dma_size = size; + desc->dma_addr = dma_map_single(qmc_hdlc->dev, desc->skb->data, + desc->dma_size, DMA_FROM_DEVICE); + ret = dma_mapping_error(qmc_hdlc->dev, desc->dma_addr); + if (ret) + goto free_skb; + + ret = qmc_chan_read_submit(qmc_hdlc->qmc_chan, desc->dma_addr, desc->dma_size, + qmc_hcld_recv_complete, desc); + if (ret) + goto dma_unmap; + + return 0; + +dma_unmap: + dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, DMA_FROM_DEVICE); +free_skb: + kfree_skb(desc->skb); + desc->skb = NULL; + return ret; +} + +static void qmc_hdlc_xmit_complete(void *context) +{ + struct qmc_hdlc_desc *desc = context; + struct net_device *netdev = desc->netdev; + struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(netdev); + struct sk_buff *skb; + unsigned long flags; + + spin_lock_irqsave(&qmc_hdlc->tx_lock, flags); + dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, DMA_TO_DEVICE); + skb = desc->skb; + desc->skb = NULL; /* Release the descriptor */ + if (netif_queue_stopped(netdev)) + netif_wake_queue(netdev); + spin_unlock_irqrestore(&qmc_hdlc->tx_lock, flags); + + netdev->stats.tx_packets++; + netdev->stats.tx_bytes += skb->len; + + dev_consume_skb_any(skb); +} + +static int qmc_hdlc_xmit_queue(struct qmc_hdlc *qmc_hdlc, struct qmc_hdlc_desc *desc) +{ + int ret; + + desc->dma_addr = dma_map_single(qmc_hdlc->dev, desc->skb->data, + desc->dma_size, DMA_TO_DEVICE); + ret = dma_mapping_error(qmc_hdlc->dev, desc->dma_addr); + if (ret) { + dev_err(qmc_hdlc->dev, "failed to map skb\n"); + return ret; + } + + ret = qmc_chan_write_submit(qmc_hdlc->qmc_chan, desc->dma_addr, desc->dma_size, + qmc_hdlc_xmit_complete, desc); + if (ret) { + dev_err(qmc_hdlc->dev, "qmc chan write returns %d\n", ret); + dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, DMA_TO_DEVICE); + return ret; + } + + return 0; +} + +static netdev_tx_t qmc_hdlc_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(netdev); + struct qmc_hdlc_desc *desc; + unsigned long flags; + int ret; + + spin_lock_irqsave(&qmc_hdlc->tx_lock, flags); + desc = &qmc_hdlc->tx_descs[qmc_hdlc->tx_out]; + if (desc->skb) { + /* Should never happen. + * Previous xmit should have already stopped the queue. + */ + netif_stop_queue(netdev); + spin_unlock_irqrestore(&qmc_hdlc->tx_lock, flags); + return NETDEV_TX_BUSY; + } + spin_unlock_irqrestore(&qmc_hdlc->tx_lock, flags); + + desc->netdev = netdev; + desc->dma_size = skb->len; + desc->skb = skb; + ret = qmc_hdlc_xmit_queue(qmc_hdlc, desc); + if (ret) { + desc->skb = NULL; /* Release the descriptor */ + if (ret == -EBUSY) { + netif_stop_queue(netdev); + return NETDEV_TX_BUSY; + } + dev_kfree_skb(skb); + netdev->stats.tx_dropped++; + return NETDEV_TX_OK; + } + + qmc_hdlc->tx_out = (qmc_hdlc->tx_out + 1) % ARRAY_SIZE(qmc_hdlc->tx_descs); + + spin_lock_irqsave(&qmc_hdlc->tx_lock, flags); + if (qmc_hdlc->tx_descs[qmc_hdlc->tx_out].skb) + netif_stop_queue(netdev); + spin_unlock_irqrestore(&qmc_hdlc->tx_lock, flags); + + return NETDEV_TX_OK; +} + +static int qmc_hdlc_open(struct net_device *netdev) +{ + struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(netdev); + struct qmc_chan_param chan_param; + struct qmc_hdlc_desc *desc; + int ret; + int i; + + ret = hdlc_open(netdev); + if (ret) + return ret; + + chan_param.mode = QMC_HDLC; + /* HDLC_MAX_MRU + 4 for the CRC + * HDLC_MAX_MRU + 4 + 8 for the CRC and some extraspace needed by the QMC + */ + chan_param.hdlc.max_rx_buf_size = HDLC_MAX_MRU + 4 + 8; + chan_param.hdlc.max_rx_frame_size = HDLC_MAX_MRU + 4; + chan_param.hdlc.is_crc32 = qmc_hdlc->is_crc32; + ret = qmc_chan_set_param(qmc_hdlc->qmc_chan, &chan_param); + if (ret) { + dev_err(qmc_hdlc->dev, "failed to set param (%d)\n", ret); + goto hdlc_close; + } + + /* Queue as many recv descriptors as possible */ + for (i = 0; i < ARRAY_SIZE(qmc_hdlc->rx_descs); i++) { + desc = &qmc_hdlc->rx_descs[i]; + + desc->netdev = netdev; + ret = qmc_hdlc_recv_queue(qmc_hdlc, desc, chan_param.hdlc.max_rx_buf_size); + if (ret) { + if (ret == -EBUSY && i != 0) + break; /* We use all the QMC chan capability */ + goto free_desc; + } + } + + ret = qmc_chan_start(qmc_hdlc->qmc_chan, QMC_CHAN_ALL); + if (ret) { + dev_err(qmc_hdlc->dev, "qmc chan start failed (%d)\n", ret); + goto free_desc; + } + + netif_start_queue(netdev); + + return 0; + +free_desc: + qmc_chan_reset(qmc_hdlc->qmc_chan, QMC_CHAN_ALL); + for (i = 0; i < ARRAY_SIZE(qmc_hdlc->rx_descs); i++) { + desc = &qmc_hdlc->rx_descs[i]; + if (!desc->skb) + continue; + dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, + DMA_FROM_DEVICE); + kfree_skb(desc->skb); + desc->skb = NULL; + } +hdlc_close: + hdlc_close(netdev); + return ret; +} + +static int qmc_hdlc_close(struct net_device *netdev) +{ + struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(netdev); + struct qmc_hdlc_desc *desc; + int i; + + netif_stop_queue(netdev); + + qmc_chan_stop(qmc_hdlc->qmc_chan, QMC_CHAN_ALL); + qmc_chan_reset(qmc_hdlc->qmc_chan, QMC_CHAN_ALL); + + for (i = 0; i < ARRAY_SIZE(qmc_hdlc->tx_descs); i++) { + desc = &qmc_hdlc->tx_descs[i]; + if (!desc->skb) + continue; + dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, + DMA_TO_DEVICE); + kfree_skb(desc->skb); + desc->skb = NULL; + } + + for (i = 0; i < ARRAY_SIZE(qmc_hdlc->rx_descs); i++) { + desc = &qmc_hdlc->rx_descs[i]; + if (!desc->skb) + continue; + dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, + DMA_FROM_DEVICE); + kfree_skb(desc->skb); + desc->skb = NULL; + } + + hdlc_close(netdev); + return 0; +} + +static int qmc_hdlc_attach(struct net_device *netdev, unsigned short encoding, + unsigned short parity) +{ + struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(netdev); + + if (encoding != ENCODING_NRZ) + return -EINVAL; + + switch (parity) { + case PARITY_CRC16_PR1_CCITT: + qmc_hdlc->is_crc32 = false; + break; + case PARITY_CRC32_PR1_CCITT: + qmc_hdlc->is_crc32 = true; + break; + default: + dev_err(qmc_hdlc->dev, "unsupported parity %u\n", parity); + return -EINVAL; + } + + return 0; +} + +static const struct net_device_ops qmc_hdlc_netdev_ops = { + .ndo_open = qmc_hdlc_open, + .ndo_stop = qmc_hdlc_close, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_siocwandev = hdlc_ioctl, +}; + +static int qmc_hdlc_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct qmc_hdlc *qmc_hdlc; + struct qmc_chan_info info; + hdlc_device *hdlc; + int ret; + + qmc_hdlc = devm_kzalloc(&pdev->dev, sizeof(*qmc_hdlc), GFP_KERNEL); + if (!qmc_hdlc) + return -ENOMEM; + + qmc_hdlc->dev = &pdev->dev; + spin_lock_init(&qmc_hdlc->tx_lock); + + qmc_hdlc->qmc_chan = devm_qmc_chan_get_byphandle(qmc_hdlc->dev, np, "fsl,qmc-chan"); + if (IS_ERR(qmc_hdlc->qmc_chan)) { + ret = PTR_ERR(qmc_hdlc->qmc_chan); + return dev_err_probe(qmc_hdlc->dev, ret, "get QMC channel failed\n"); + } + + ret = qmc_chan_get_info(qmc_hdlc->qmc_chan, &info); + if (ret) { + dev_err(qmc_hdlc->dev, "get QMC channel info failed %d\n", ret); + return ret; + } + + if (info.mode != QMC_HDLC) { + dev_err(qmc_hdlc->dev, "QMC chan mode %d is not QMC_HDLC\n", + info.mode); + return -EINVAL; + } + + qmc_hdlc->netdev = alloc_hdlcdev(qmc_hdlc); + if (!qmc_hdlc->netdev) { + dev_err(qmc_hdlc->dev, "failed to alloc hdlc dev\n"); + return -ENOMEM; + } + + hdlc = dev_to_hdlc(qmc_hdlc->netdev); + hdlc->attach = qmc_hdlc_attach; + hdlc->xmit = qmc_hdlc_xmit; + SET_NETDEV_DEV(qmc_hdlc->netdev, qmc_hdlc->dev); + qmc_hdlc->netdev->tx_queue_len = ARRAY_SIZE(qmc_hdlc->tx_descs); + qmc_hdlc->netdev->netdev_ops = &qmc_hdlc_netdev_ops; + ret = register_hdlc_device(qmc_hdlc->netdev); + if (ret) { + dev_err(qmc_hdlc->dev, "failed to register hdlc device (%d)\n", ret); + goto free_netdev; + } + + platform_set_drvdata(pdev, qmc_hdlc); + + return 0; + +free_netdev: + free_netdev(qmc_hdlc->netdev); + return ret; +} + +static int qmc_hdlc_remove(struct platform_device *pdev) +{ + struct qmc_hdlc *qmc_hdlc = platform_get_drvdata(pdev); + + unregister_hdlc_device(qmc_hdlc->netdev); + free_netdev(qmc_hdlc->netdev); + + return 0; +} + +static const struct of_device_id qmc_hdlc_id_table[] = { + { .compatible = "fsl,qmc-hdlc" }, + {} /* sentinel */ +}; +MODULE_DEVICE_TABLE(of, qmc_hdlc_driver); + +static struct platform_driver qmc_hdlc_driver = { + .driver = { + .name = "fsl-qmc-hdlc", + .of_match_table = qmc_hdlc_id_table, + }, + .probe = qmc_hdlc_probe, + .remove = qmc_hdlc_remove, +}; +module_platform_driver(qmc_hdlc_driver); + +MODULE_AUTHOR("Herve Codina "); +MODULE_DESCRIPTION("QMC HDLC driver"); +MODULE_LICENSE("GPL"); From patchwork Fri Aug 18 16:39:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358142 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 E6C771BB30 for ; Fri, 18 Aug 2023 17:21:13 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C41E14218; Fri, 18 Aug 2023 10:21:12 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zl1VvJz9vhK; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 4xr2re2nCwpH; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl04lzz9vhD; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id EB9048B781; Fri, 18 Aug 2023 18:40:02 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id VzJn4RpBK86C; Fri, 18 Aug 2023 18:40:02 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 56A258B76C; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdvVf141974 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:57 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdvYc141973; Fri, 18 Aug 2023 18:39:57 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 08/28] MAINTAINERS: Add the Freescale QMC HDLC driver entry Date: Fri, 18 Aug 2023 18:39:02 +0200 Message-ID: <8bdee4c184fd5e69c717de7239b4f880be54c8f5.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376734; l=960; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=bpiHZapqWZt7YkM4wMIROy9IQDsK7WksUXrRIKPnxOw=; b=zoDLqKrE++0C+MfhSrAaOQ7t4ECIZkBe4SHhS3wNsJyLjhEm5XFusJdOKVcEC5coukFjBBw8V sLb7YjZZQcZCgg4/xhjQQEEhHYZMe/M3nfzNzUmwAcsNqR+3v8BNyYY X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina After contributing the driver, add myself as the maintainer for the Freescale QMC HDLC driver. Signed-off-by: Herve Codina Signed-off-by: Christophe Leroy --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0903d87b17cb..e77a7eaef1cb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8305,6 +8305,14 @@ F: Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml F: drivers/soc/fsl/qe/qmc.c F: include/soc/fsl/qe/qmc.h +FREESCALE QUICC ENGINE QMC HDLC DRIVER +M: Herve Codina +L: netdev@vger.kernel.org +L: linuxppc-dev@lists.ozlabs.org +S: Maintained +F: Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml +F: drivers/net/wan/fsl_qmc_hdlc.c + FREESCALE QUICC ENGINE TSA DRIVER M: Herve Codina L: linuxppc-dev@lists.ozlabs.org From patchwork Fri Aug 18 16:39:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358139 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 45BB863A6 for ; Fri, 18 Aug 2023 17:21:01 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5D0EF3C2F; Fri, 18 Aug 2023 10:21:00 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zr19Mhz9vhw; Fri, 18 Aug 2023 18:40:08 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 8sy9kcu9lE8D; Fri, 18 Aug 2023 18:40:08 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl1cfcz9vhM; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 2C8ED8B76C; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id 55B--0WhkOYu; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 7074A8B775; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdv2E141978 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:57 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdvvD141977; Fri, 18 Aug 2023 18:39:57 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 09/28] soc: fsl: cpm1: qmc: Introduce available timeslots masks Date: Fri, 18 Aug 2023 18:39:03 +0200 Message-ID: <778806cad713d7c975a8bf02384ee7b200359a6c.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376734; l=1712; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=3LicTgfMUbXUrQ+y4QfDER9n8SKLy3AuN3dxv7yNc5I=; b=m5WWLYRdD9rdm60QUK8RRcBGmS9OQk3vYQCwizMISmJsYOqZgfvEgDruh2b/4ThMX+GCDMDzt v4RV5yGdyYiBO8o64OQQAe/vTFkpFz0UzwSiC1NLSTAr5q4Kdpnk3zI X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina Available timeslots masks define timeslots available for the related channel. These timeslots are defined by the QMC binding. Timeslots used are initialized to available timeslots but can be a subset of available timeslots. This prepares the dynamic timeslots management (ie. changing timeslots at runtime). Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 459e0bbd723d..1bc2af58e829 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -177,7 +177,9 @@ struct qmc_chan { struct qmc *qmc; void __iomem *s_param; enum qmc_mode mode; + u64 tx_ts_mask_avail; u64 tx_ts_mask; + u64 rx_ts_mask_avail; u64 rx_ts_mask; bool is_reverse_data; @@ -875,7 +877,8 @@ static int qmc_of_parse_chans(struct qmc *qmc, struct device_node *np) of_node_put(chan_np); return ret; } - chan->tx_ts_mask = ts_mask; + chan->tx_ts_mask_avail = ts_mask; + chan->tx_ts_mask = chan->tx_ts_mask_avail; ret = of_property_read_u64(chan_np, "fsl,rx-ts-mask", &ts_mask); if (ret) { @@ -884,7 +887,8 @@ static int qmc_of_parse_chans(struct qmc *qmc, struct device_node *np) of_node_put(chan_np); return ret; } - chan->rx_ts_mask = ts_mask; + chan->rx_ts_mask_avail = ts_mask; + chan->rx_ts_mask = chan->rx_ts_mask_avail; mode = "transparent"; ret = of_property_read_string(chan_np, "fsl,operational-mode", &mode); From patchwork Fri Aug 18 16:39:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358134 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 2849963A2 for ; Fri, 18 Aug 2023 17:20:39 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ECABD3C2F; Fri, 18 Aug 2023 10:20:37 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zz1011z9vjF; Fri, 18 Aug 2023 18:40:15 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id hhlFlM3-7CR9; Fri, 18 Aug 2023 18:40:15 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl44nCz9vhT; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 7BE428B76C; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id 87vsLUCGdixm; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 73FB08B776; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdvOo141982 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:57 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdvWx141981; Fri, 18 Aug 2023 18:39:57 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 10/28] soc: fsl: cpm1: qmc: Rename qmc_setup_tsa* to qmc_init_tsa* Date: Fri, 18 Aug 2023 18:39:04 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376734; l=2610; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=hh5NUCC8hR7L9sikLmlX34sVAqfntoOp1ZPHH9gd+1M=; b=Nz+Ie4I0N6LVLt5NL8fpNAmI8aNSGk/H6qoW26+xsBHuyrwohjQldqvxQ5STWau5pbb0gDNlJ Fc4QgXmuQl1DEkimaNTn9AnWII2MaAmek5jPIMJir7ZmCxMdrh1/u5U X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina qmc_setup_tsa* are called once at initialisation. They initialize the QMC TSA table. In order to introduce setup function later on for dynamic timeslots management, rename the function to avoid later confusion. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 1bc2af58e829..261958e3199f 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -919,7 +919,7 @@ static int qmc_of_parse_chans(struct qmc *qmc, struct device_node *np) return qmc_check_chans(qmc); } -static int qmc_setup_tsa_64rxtx(struct qmc *qmc, const struct tsa_serial_info *info) +static int qmc_init_tsa_64rxtx(struct qmc *qmc, const struct tsa_serial_info *info) { struct qmc_chan *chan; unsigned int i; @@ -961,7 +961,7 @@ static int qmc_setup_tsa_64rxtx(struct qmc *qmc, const struct tsa_serial_info *i return 0; } -static int qmc_setup_tsa_32rx_32tx(struct qmc *qmc, const struct tsa_serial_info *info) +static int qmc_init_tsa_32rx_32tx(struct qmc *qmc, const struct tsa_serial_info *info) { struct qmc_chan *chan; unsigned int i; @@ -1019,7 +1019,7 @@ static int qmc_setup_tsa_32rx_32tx(struct qmc *qmc, const struct tsa_serial_info return 0; } -static int qmc_setup_tsa(struct qmc *qmc) +static int qmc_init_tsa(struct qmc *qmc) { struct tsa_serial_info info; int ret; @@ -1030,12 +1030,12 @@ static int qmc_setup_tsa(struct qmc *qmc) return ret; /* - * Setup one common 64 entries table or two 32 entries (one for Tx and - * one for Tx) according to assigned TS numbers. + * Initialize one common 64 entries table or two 32 entries (one for Tx + * and one for Tx) according to assigned TS numbers. */ return ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) ? - qmc_setup_tsa_64rxtx(qmc, &info) : - qmc_setup_tsa_32rx_32tx(qmc, &info); + qmc_init_tsa_64rxtx(qmc, &info) : + qmc_init_tsa_32rx_32tx(qmc, &info); } static int qmc_setup_chan_trnsync(struct qmc *qmc, struct qmc_chan *chan) @@ -1391,7 +1391,7 @@ static int qmc_probe(struct platform_device *pdev) qmc_write32(qmc->scc_pram + QMC_GBL_C_MASK32, 0xDEBB20E3); qmc_write16(qmc->scc_pram + QMC_GBL_C_MASK16, 0xF0B8); - ret = qmc_setup_tsa(qmc); + ret = qmc_init_tsa(qmc); if (ret) goto err_tsa_serial_disconnect; From patchwork Fri Aug 18 16:39:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358133 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 B39E819BDB for ; Fri, 18 Aug 2023 17:20:35 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 434913AB9; Fri, 18 Aug 2023 10:20:34 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zm1M6pz9vhg; Fri, 18 Aug 2023 18:40:04 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 89Kx67sI9ppz; Fri, 18 Aug 2023 18:40:04 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl0Sbsz9vhG; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 02E4B8B76C; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id 9iYQSi1ifmTA; Fri, 18 Aug 2023 18:40:02 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 63FDF8B770; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdvkM141987 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:57 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdvAW141986; Fri, 18 Aug 2023 18:39:57 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 11/28] soc: fsl: cpm1: qmc: Introduce qmc_chan_setup_tsa* Date: Fri, 18 Aug 2023 18:39:05 +0200 Message-ID: <4e596b428c55f03fc61266b378cebc173534eb11.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376734; l=7081; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=7PGD9fr0thKC9YmjBJOY5hh1E4lpRoBRFjQwX4wPHCs=; b=srH+zLcXBYLz8mlRnvuiTMafDCX1u/WMO0UmnabWjYQKqIwasPjML2OuxF0KH7Q24g2PImrcH sz/ku9P5iqfD8GIDSl8TiPEwtO8ZWby/jg7xW1mp9Q3WZjnogz6HfOZ X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina Introduce the qmc_chan_setup_tsa* functions to setup entries related to the given channel. Use them during QMC channels setup. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 161 ++++++++++++++++++++++++++++++--------- 1 file changed, 125 insertions(+), 36 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 261958e3199f..bddff0b74252 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -240,6 +240,11 @@ static void qmc_clrbits16(void __iomem *addr, u16 clr) qmc_write16(addr, qmc_read16(addr) & ~clr); } +static void qmc_clrsetbits16(void __iomem *addr, u16 clr, u16 set) +{ + qmc_write16(addr, (qmc_read16(addr) & ~clr) | set); +} + static void qmc_write32(void __iomem *addr, u32 val) { iowrite32be(val, addr); @@ -562,6 +567,122 @@ static void qmc_chan_read_done(struct qmc_chan *chan) spin_unlock_irqrestore(&chan->rx_lock, flags); } +static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct tsa_serial_info *info) +{ + unsigned int i; + u16 curr; + u16 val; + + /* + * Use a common Tx/Rx 64 entries table. + * Tx and Rx related stuffs must be identical + */ + if (chan->tx_ts_mask != chan->rx_ts_mask) { + dev_err(chan->qmc->dev, "chan %u uses different Rx and Tx TS\n", chan->id); + return -EINVAL; + } + + val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id); + + /* Check entries based on Rx stuff*/ + for (i = 0; i < info->nb_rx_ts; i++) { + if (!(chan->rx_ts_mask & (((u64)1) << i))) + continue; + + curr = qmc_read16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2)); + if (curr & QMC_TSA_VALID && (curr & ~QMC_TSA_WRAP) != val) { + dev_err(chan->qmc->dev, "chan %u TxRx entry %d already used\n", + chan->id, i); + return -EBUSY; + } + } + + /* Set entries based on Rx stuff*/ + for (i = 0; i < info->nb_rx_ts; i++) { + if (!(chan->rx_ts_mask & (((u64)1) << i))) + continue; + + qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), + ~QMC_TSA_WRAP, val); + } + + return 0; +} + +static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_serial_info *info) +{ + unsigned int i; + u16 curr; + u16 val; + + /* Use a Tx 32 entries table and a Rx 32 entries table */ + + val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id); + + /* Check entries based on Rx stuff */ + for (i = 0; i < info->nb_rx_ts; i++) { + if (!(chan->rx_ts_mask & (((u64)1) << i))) + continue; + + curr = qmc_read16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2)); + if (curr & QMC_TSA_VALID && (curr & ~QMC_TSA_WRAP) != val) { + dev_err(chan->qmc->dev, "chan %u Rx entry %d already used\n", + chan->id, i); + return -EBUSY; + } + } + /* Check entries based on Tx stuff */ + for (i = 0; i < info->nb_tx_ts; i++) { + if (!(chan->tx_ts_mask & (((u64)1) << i))) + continue; + + curr = qmc_read16(chan->qmc->scc_pram + QMC_GBL_TSATTX + (i * 2)); + if (curr & QMC_TSA_VALID && (curr & ~QMC_TSA_WRAP) != val) { + dev_err(chan->qmc->dev, "chan %u Tx entry %d already used\n", + chan->id, i); + return -EBUSY; + } + } + + /* Set entries based on Rx stuff */ + for (i = 0; i < info->nb_rx_ts; i++) { + if (!(chan->rx_ts_mask & (((u64)1) << i))) + continue; + + qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), + ~QMC_TSA_WRAP, val); + } + /* Set entries based on Tx stuff */ + for (i = 0; i < info->nb_tx_ts; i++) { + if (!(chan->tx_ts_mask & (((u64)1) << i))) + continue; + + qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATTX + (i * 2), + ~QMC_TSA_WRAP, val); + } + + return 0; +} + +static int qmc_chan_setup_tsa(struct qmc_chan *chan) +{ + struct tsa_serial_info info; + int ret; + + /* Retrieve info from the TSA related serial */ + ret = tsa_serial_get_info(chan->qmc->tsa_serial, &info); + if (ret) + return ret; + + /* + * Setup one common 64 entries table or two 32 entries (one for Tx + * and one for Tx) according to assigned TS numbers. + */ + return ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) ? + qmc_chan_setup_tsa_64rxtx(chan, &info) : + qmc_chan_setup_tsa_32rx_32tx(chan, &info); +} + static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode) { return cpm_command(chan->id << 2, (qmc_opcode << 4) | 0x0E); @@ -921,7 +1042,6 @@ static int qmc_of_parse_chans(struct qmc *qmc, struct device_node *np) static int qmc_init_tsa_64rxtx(struct qmc *qmc, const struct tsa_serial_info *info) { - struct qmc_chan *chan; unsigned int i; u16 val; @@ -935,18 +1055,6 @@ static int qmc_init_tsa_64rxtx(struct qmc *qmc, const struct tsa_serial_info *in for (i = 0; i < 64; i++) qmc_write16(qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), 0x0000); - /* Set entries based on Rx stuff*/ - list_for_each_entry(chan, &qmc->chan_head, list) { - for (i = 0; i < info->nb_rx_ts; i++) { - if (!(chan->rx_ts_mask & (((u64)1) << i))) - continue; - - val = QMC_TSA_VALID | QMC_TSA_MASK | - QMC_TSA_CHANNEL(chan->id); - qmc_write16(qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), val); - } - } - /* Set Wrap bit on last entry */ qmc_setbits16(qmc->scc_pram + QMC_GBL_TSATRX + ((info->nb_rx_ts - 1) * 2), QMC_TSA_WRAP); @@ -963,7 +1071,6 @@ static int qmc_init_tsa_64rxtx(struct qmc *qmc, const struct tsa_serial_info *in static int qmc_init_tsa_32rx_32tx(struct qmc *qmc, const struct tsa_serial_info *info) { - struct qmc_chan *chan; unsigned int i; u16 val; @@ -978,28 +1085,6 @@ static int qmc_init_tsa_32rx_32tx(struct qmc *qmc, const struct tsa_serial_info qmc_write16(qmc->scc_pram + QMC_GBL_TSATTX + (i * 2), 0x0000); } - /* Set entries based on Rx and Tx stuff*/ - list_for_each_entry(chan, &qmc->chan_head, list) { - /* Rx part */ - for (i = 0; i < info->nb_rx_ts; i++) { - if (!(chan->rx_ts_mask & (((u64)1) << i))) - continue; - - val = QMC_TSA_VALID | QMC_TSA_MASK | - QMC_TSA_CHANNEL(chan->id); - qmc_write16(qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), val); - } - /* Tx part */ - for (i = 0; i < info->nb_tx_ts; i++) { - if (!(chan->tx_ts_mask & (((u64)1) << i))) - continue; - - val = QMC_TSA_VALID | QMC_TSA_MASK | - QMC_TSA_CHANNEL(chan->id); - qmc_write16(qmc->scc_pram + QMC_GBL_TSATTX + (i * 2), val); - } - } - /* Set Wrap bit on last entries */ qmc_setbits16(qmc->scc_pram + QMC_GBL_TSATRX + ((info->nb_rx_ts - 1) * 2), QMC_TSA_WRAP); @@ -1081,6 +1166,10 @@ static int qmc_setup_chan(struct qmc *qmc, struct qmc_chan *chan) chan->qmc = qmc; + ret = qmc_chan_setup_tsa(chan); + if (ret) + return ret; + /* Set channel specific parameter base address */ chan->s_param = qmc->dpram + (chan->id * 64); /* 16 bd per channel (8 rx and 8 tx) */ From patchwork Fri Aug 18 16:39:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358146 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 70DE919BBF for ; Fri, 18 Aug 2023 17:21:27 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5E8F13C2F; Fri, 18 Aug 2023 10:21:26 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zs1by5z9vhM; Fri, 18 Aug 2023 18:40:09 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id lXP2OwoFw5RG; Fri, 18 Aug 2023 18:40:09 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl1qYrz9vhN; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 3397E8B763; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id TDM3vjXENiKH; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 79E568B779; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdvd5141991 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:58 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdvDx141990; Fri, 18 Aug 2023 18:39:57 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 12/28] soc: fsl: cpm1: qmc: Remove no more needed checks from qmc_check_chans() Date: Fri, 18 Aug 2023 18:39:06 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376734; l=2150; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=/2BhkcYFCfVdUJW9iyItt6BfQ3h3Y35LDTdW3A3srlw=; b=CFqlIBlU5AMPuF2hcu/jmjdlTWFhn4WJXBe5RU5oDbnFR1fmzzJ7MkFjSNMKy/bhhMfQs26rg mJOq+SUcC8tA1BBdocSnonDqluqi7jfx8NcGyh8jOB9gb71QuJAoRbk X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina The newly introduced qmc_chan_setup_tsa* functions check that the channel entries are not already used. These checks are also performed by qmc_check_chans() and are no more needed. Remove them from qmc_check_chans(). Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index bddff0b74252..2416408bb7e7 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -884,10 +884,7 @@ EXPORT_SYMBOL(qmc_chan_reset); static int qmc_check_chans(struct qmc *qmc) { struct tsa_serial_info info; - bool is_one_table = false; struct qmc_chan *chan; - u64 tx_ts_mask = 0; - u64 rx_ts_mask = 0; u64 tx_ts_assigned_mask; u64 rx_ts_assigned_mask; int ret; @@ -911,7 +908,6 @@ static int qmc_check_chans(struct qmc *qmc) dev_err(qmc->dev, "Number of TSA Tx/Rx TS assigned are not equal\n"); return -EINVAL; } - is_one_table = true; } tx_ts_assigned_mask = info.nb_tx_ts == 64 ? U64_MAX : (((u64)1) << info.nb_tx_ts) - 1; @@ -922,27 +918,11 @@ static int qmc_check_chans(struct qmc *qmc) dev_err(qmc->dev, "chan %u uses TSA unassigned Tx TS\n", chan->id); return -EINVAL; } - if (tx_ts_mask & chan->tx_ts_mask) { - dev_err(qmc->dev, "chan %u uses an already used Tx TS\n", chan->id); - return -EINVAL; - } if (chan->rx_ts_mask > rx_ts_assigned_mask) { dev_err(qmc->dev, "chan %u uses TSA unassigned Rx TS\n", chan->id); return -EINVAL; } - if (rx_ts_mask & chan->rx_ts_mask) { - dev_err(qmc->dev, "chan %u uses an already used Rx TS\n", chan->id); - return -EINVAL; - } - - if (is_one_table && (chan->tx_ts_mask != chan->rx_ts_mask)) { - dev_err(qmc->dev, "chan %u uses different Rx and Tx TS\n", chan->id); - return -EINVAL; - } - - tx_ts_mask |= chan->tx_ts_mask; - rx_ts_mask |= chan->rx_ts_mask; } return 0; From patchwork Fri Aug 18 16:39:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358140 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 31BB91B7FB for ; Fri, 18 Aug 2023 17:21:05 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1C2184210; Fri, 18 Aug 2023 10:21:04 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS7021YcDz9vjN; Fri, 18 Aug 2023 18:40:18 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 0u5EQwH0IHfw; Fri, 18 Aug 2023 18:40:18 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl4Q41z9vhZ; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 8D1908B770; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id VAf92wOyAjq3; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 8179B8B77A; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdwGP141995 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:58 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdw6p141994; Fri, 18 Aug 2023 18:39:58 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 13/28] soc: fsl: cpm1: qmc: Check available timeslots in qmc_check_chans() Date: Fri, 18 Aug 2023 18:39:07 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376734; l=1620; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=3oCJWknCD0kV9dRpPXFldERVHfu7NKNt3fpqhyftA/U=; b=77KndESlUNFNW5cO4EqUGfYYsJIKJmYxBZvehK626i2v2j/9pacL7BO71YTB4BlMZuHRHbtz3 5E7BGXaSL3vCICkXlZ0Bkjk52XNwarG/F0Q3lf6pLxBwGjktnylJFm7 X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina The timeslots checked in qmc_check_chans() are the timeslots used. With the introduction of the available timeslots, the used timeslots are a subset of the available timeslots. The timeslots checked during the qmc_check_chans() call should be the available ones. Simply update and check the available timeslots instead of the used timeslots in qmc_check_chans(). Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 2416408bb7e7..07fa3c265858 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -914,13 +914,13 @@ static int qmc_check_chans(struct qmc *qmc) rx_ts_assigned_mask = info.nb_rx_ts == 64 ? U64_MAX : (((u64)1) << info.nb_rx_ts) - 1; list_for_each_entry(chan, &qmc->chan_head, list) { - if (chan->tx_ts_mask > tx_ts_assigned_mask) { - dev_err(qmc->dev, "chan %u uses TSA unassigned Tx TS\n", chan->id); + if (chan->tx_ts_mask_avail > tx_ts_assigned_mask) { + dev_err(qmc->dev, "chan %u can use TSA unassigned Tx TS\n", chan->id); return -EINVAL; } - if (chan->rx_ts_mask > rx_ts_assigned_mask) { - dev_err(qmc->dev, "chan %u uses TSA unassigned Rx TS\n", chan->id); + if (chan->rx_ts_mask_avail > rx_ts_assigned_mask) { + dev_err(qmc->dev, "chan %u can use TSA unassigned Rx TS\n", chan->id); return -EINVAL; } } From patchwork Fri Aug 18 16:39:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358145 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 522B01BB30 for ; Fri, 18 Aug 2023 17:21:24 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 539A63AB9; Fri, 18 Aug 2023 10:21:23 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS7011cN8z9vjK; Fri, 18 Aug 2023 18:40:17 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 4HDGofVSMuAd; Fri, 18 Aug 2023 18:40:17 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl4JdHz9vhY; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 89A5C8B76E; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id Dswvfqd2d2cW; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 686868B773; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdw9J141999 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:58 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdwSA141998; Fri, 18 Aug 2023 18:39:58 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 14/28] soc: fsl: cpm1: qmc: Add support for disabling channel TSA entries Date: Fri, 18 Aug 2023 18:39:08 +0200 Message-ID: <4b18bc5b006c1a30337fb2194a2c62793ee128db.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376734; l=3064; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=MvvQxmI7SWDGeYM4+tnD2CE38F/i+/2XM9yFQ5suja4=; b=eCXRNDDxsegY7fXYP5ow+1scCSIZJ5C2rKlqMzMFziYG1sAkvjH9c5uwhLwmgkXCuZgPaF+ej 3iCxCL3fiycBtt8hgMRJfpiIn70SA7l/FeWXM/pfQQ78/Li6R0ax9Y7 X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina In order to allow runtime timeslot route changes, disabling channel TSA entries needs to be supported. Add support for this new feature. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 07fa3c265858..90e6fffddab3 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -567,7 +567,8 @@ static void qmc_chan_read_done(struct qmc_chan *chan) spin_unlock_irqrestore(&chan->rx_lock, flags); } -static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct tsa_serial_info *info) +static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct tsa_serial_info *info, + bool enable) { unsigned int i; u16 curr; @@ -603,13 +604,14 @@ static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct tsa_ser continue; qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), - ~QMC_TSA_WRAP, val); + ~QMC_TSA_WRAP, enable ? val : 0x0000); } return 0; } -static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_serial_info *info) +static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_serial_info *info, + bool enable) { unsigned int i; u16 curr; @@ -650,7 +652,7 @@ static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_ continue; qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), - ~QMC_TSA_WRAP, val); + ~QMC_TSA_WRAP, enable ? val : 0x0000); } /* Set entries based on Tx stuff */ for (i = 0; i < info->nb_tx_ts; i++) { @@ -658,13 +660,13 @@ static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_ continue; qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATTX + (i * 2), - ~QMC_TSA_WRAP, val); + ~QMC_TSA_WRAP, enable ? val : 0x0000); } return 0; } -static int qmc_chan_setup_tsa(struct qmc_chan *chan) +static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool enable) { struct tsa_serial_info info; int ret; @@ -679,8 +681,8 @@ static int qmc_chan_setup_tsa(struct qmc_chan *chan) * and one for Tx) according to assigned TS numbers. */ return ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) ? - qmc_chan_setup_tsa_64rxtx(chan, &info) : - qmc_chan_setup_tsa_32rx_32tx(chan, &info); + qmc_chan_setup_tsa_64rxtx(chan, &info, enable) : + qmc_chan_setup_tsa_32rx_32tx(chan, &info, enable); } static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode) @@ -1146,7 +1148,7 @@ static int qmc_setup_chan(struct qmc *qmc, struct qmc_chan *chan) chan->qmc = qmc; - ret = qmc_chan_setup_tsa(chan); + ret = qmc_chan_setup_tsa(chan, true); if (ret) return ret; From patchwork Fri Aug 18 16:39:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358147 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 8BC81613A for ; Fri, 18 Aug 2023 17:21:30 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4C4604215; Fri, 18 Aug 2023 10:21:29 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS7031SCNz9vjR; Fri, 18 Aug 2023 18:40:19 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id RJpO6BCDLtSG; Fri, 18 Aug 2023 18:40:19 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl5pQwz9vhb; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id BE1EE8B763; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id ZjXNIeoXcU51; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 8EA278B77D; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdwk4142003 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:58 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdwg7142002; Fri, 18 Aug 2023 18:39:58 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 15/28] soc: fsl: cpm1: qmc: Split Tx and Rx TSA entries setup Date: Fri, 18 Aug 2023 18:39:09 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376735; l=3354; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=jK/8j1L6jQ+a76+R36Gva2Uys2IEuWOM319zyb4YE3g=; b=d+pGITHl9ltXzGlRricathGyIaA7WZKylpP9pn742GSqYBN5PLkskBjWn/aABP9xGtIPqMzax hkMPm3nXyEFB/ZQvPXllK3ZX5hi161MCqyRCFlB1myIUSJhErrNUc6S X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina The Tx and Rx entries for a given channel are set in one function. In order to modify Rx entries and Tx entries independently of one other, split this function in one for the Rx part and one for the Tx part. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 49 ++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 90e6fffddab3..1eff1e138460 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -610,14 +610,14 @@ static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct tsa_ser return 0; } -static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_serial_info *info, - bool enable) +static int qmc_chan_setup_tsa_32rx(struct qmc_chan *chan, const struct tsa_serial_info *info, + bool enable) { unsigned int i; u16 curr; u16 val; - /* Use a Tx 32 entries table and a Rx 32 entries table */ + /* Use a Rx 32 entries table */ val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id); @@ -633,6 +633,30 @@ static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_ return -EBUSY; } } + + /* Set entries based on Rx stuff */ + for (i = 0; i < info->nb_rx_ts; i++) { + if (!(chan->rx_ts_mask & (((u64)1) << i))) + continue; + + qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), + ~QMC_TSA_WRAP, enable ? val : 0x0000); + } + + return 0; +} + +static int qmc_chan_setup_tsa_32tx(struct qmc_chan *chan, const struct tsa_serial_info *info, + bool enable) +{ + unsigned int i; + u16 curr; + u16 val; + + /* Use a Tx 32 entries table */ + + val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id); + /* Check entries based on Tx stuff */ for (i = 0; i < info->nb_tx_ts; i++) { if (!(chan->tx_ts_mask & (((u64)1) << i))) @@ -646,14 +670,6 @@ static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_ } } - /* Set entries based on Rx stuff */ - for (i = 0; i < info->nb_rx_ts; i++) { - if (!(chan->rx_ts_mask & (((u64)1) << i))) - continue; - - qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), - ~QMC_TSA_WRAP, enable ? val : 0x0000); - } /* Set entries based on Tx stuff */ for (i = 0; i < info->nb_tx_ts; i++) { if (!(chan->tx_ts_mask & (((u64)1) << i))) @@ -680,9 +696,14 @@ static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool enable) * Setup one common 64 entries table or two 32 entries (one for Tx * and one for Tx) according to assigned TS numbers. */ - return ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) ? - qmc_chan_setup_tsa_64rxtx(chan, &info, enable) : - qmc_chan_setup_tsa_32rx_32tx(chan, &info, enable); + if (info.nb_tx_ts > 32 || info.nb_rx_ts > 32) + return qmc_chan_setup_tsa_64rxtx(chan, &info, enable); + + ret = qmc_chan_setup_tsa_32rx(chan, &info, enable); + if (ret) + return ret; + + return qmc_chan_setup_tsa_32tx(chan, &info, enable); } static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode) From patchwork Fri Aug 18 16:39:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358138 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 AFA321B7DE for ; Fri, 18 Aug 2023 17:20:58 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7B4D34214; Fri, 18 Aug 2023 10:20:56 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zw1Hdfz9vh0; Fri, 18 Aug 2023 18:40:12 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id HLPFjCVnp0mY; Fri, 18 Aug 2023 18:40:12 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl3NNvz9vhR; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 68A9B8B76C; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id Ei7kOfDyK5Cm; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 61D5C8B76E; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdwJu142007 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:58 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdwTH142006; Fri, 18 Aug 2023 18:39:58 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 16/28] soc: fsl: cpm1: qmc: Introduce is_tsa_64rxtx flag Date: Fri, 18 Aug 2023 18:39:10 +0200 Message-ID: <3cb93d685101e3b762e41afee1562c553ae3b6d4.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376735; l=2054; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=5l+2AnuikAJH2hTXLBY5BtwhCbVcyBdM9U4N56URTgk=; b=WAri2p6b1khrclUzL7KH4S4Bpw777rb0RwzUFNzqw3j53iVW1BxsLACFv2P5JinIqDqqh+U+D 8AzevEm+h8FA+o7E++d0856OOUkM6WCmbfzmxM7Nyk5T5Bo9FN3oh1n X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina In order to support runtime timeslot route changes, some operations will be different according the routing table used (common Rx and Tx table or one table for Rx and one for Tx). The is_tsa_64rxtx flag is introduced to avoid extra computation to determine the table format each time we need it. It is set once at initialization. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 1eff1e138460..610be2b8855c 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -216,6 +216,7 @@ struct qmc { u16 __iomem *int_curr; dma_addr_t int_dma_addr; size_t int_size; + bool is_tsa_64rxtx; struct list_head chan_head; struct qmc_chan *chans[64]; }; @@ -696,7 +697,7 @@ static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool enable) * Setup one common 64 entries table or two 32 entries (one for Tx * and one for Tx) according to assigned TS numbers. */ - if (info.nb_tx_ts > 32 || info.nb_rx_ts > 32) + if (chan->qmc->is_tsa_64rxtx) return qmc_chan_setup_tsa_64rxtx(chan, &info, enable); ret = qmc_chan_setup_tsa_32rx(chan, &info, enable); @@ -1053,6 +1054,7 @@ static int qmc_init_tsa_64rxtx(struct qmc *qmc, const struct tsa_serial_info *in * Everything was previously checked, Tx and Rx related stuffs are * identical -> Used Rx related stuff to build the table */ + qmc->is_tsa_64rxtx = true; /* Invalidate all entries */ for (i = 0; i < 64; i++) @@ -1081,6 +1083,7 @@ static int qmc_init_tsa_32rx_32tx(struct qmc *qmc, const struct tsa_serial_info * Use a Tx 32 entries table and a Rx 32 entries table. * Everything was previously checked. */ + qmc->is_tsa_64rxtx = false; /* Invalidate all entries */ for (i = 0; i < 32; i++) { From patchwork Fri Aug 18 16:39:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358143 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 996441BB30 for ; Fri, 18 Aug 2023 17:21:17 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B87E94215; Fri, 18 Aug 2023 10:21:15 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zp1XxTz9vhk; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id iiMP-WHNIwTw; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl0bdpz9vhH; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 03A298B783; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id E3-kcrhfr8pV; Fri, 18 Aug 2023 18:40:02 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 5C7798B76D; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdw5X142011 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:58 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdwGN142010; Fri, 18 Aug 2023 18:39:58 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 17/28] soc: fsl: cpm1: qmc: Handle timeslot entries at channel start() and stop() Date: Fri, 18 Aug 2023 18:39:11 +0200 Message-ID: <78115ca9580e2158072e093f86a2005a65160e46.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376735; l=8287; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=50yiHSSJy8IFGLkAev4NGunV8mdZ+Z0Wklx32bCoAMQ=; b=FIKRGtmVUkKPtN6undn1STSlXhKSRe8gW6PrL2QX5r6KDLgxk8+Yye7p2Ef+HU30qAeFhGDmw orZnI5DAkZxCzbsOS4wLVtxRPIvb7Kqs9kxFeL+Z8biW9Xu7kP4eZOM X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina In order to support runtime timeslot route changes, enable the channel timeslot entries at channel start() and disable them at channel stop(). Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 175 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 163 insertions(+), 12 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 610be2b8855c..00408da14cb4 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -177,6 +177,7 @@ struct qmc_chan { struct qmc *qmc; void __iomem *s_param; enum qmc_mode mode; + spinlock_t ts_lock; /* Protect timeslots */ u64 tx_ts_mask_avail; u64 tx_ts_mask; u64 rx_ts_mask_avail; @@ -265,6 +266,7 @@ static void qmc_setbits32(void __iomem *addr, u32 set) int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info) { struct tsa_serial_info tsa_info; + unsigned long flags; int ret; /* Retrieve info from the TSA related serial */ @@ -272,6 +274,8 @@ int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info) if (ret) return ret; + spin_lock_irqsave(&chan->ts_lock, flags); + info->mode = chan->mode; info->rx_fs_rate = tsa_info.rx_fs_rate; info->rx_bit_rate = tsa_info.rx_bit_rate; @@ -280,6 +284,8 @@ int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info) info->tx_bit_rate = tsa_info.tx_bit_rate; info->nb_rx_ts = hweight64(chan->rx_ts_mask); + spin_unlock_irqrestore(&chan->ts_lock, flags); + return 0; } EXPORT_SYMBOL(qmc_chan_get_info); @@ -683,6 +689,40 @@ static int qmc_chan_setup_tsa_32tx(struct qmc_chan *chan, const struct tsa_seria return 0; } +static int qmc_chan_setup_tsa_tx(struct qmc_chan *chan, bool enable) +{ + struct tsa_serial_info info; + int ret; + + /* Retrieve info from the TSA related serial */ + ret = tsa_serial_get_info(chan->qmc->tsa_serial, &info); + if (ret) + return ret; + + /* Setup entries */ + if (chan->qmc->is_tsa_64rxtx) + return qmc_chan_setup_tsa_64rxtx(chan, &info, enable); + + return qmc_chan_setup_tsa_32tx(chan, &info, enable); +} + +static int qmc_chan_setup_tsa_rx(struct qmc_chan *chan, bool enable) +{ + struct tsa_serial_info info; + int ret; + + /* Retrieve info from the TSA related serial */ + ret = tsa_serial_get_info(chan->qmc->tsa_serial, &info); + if (ret) + return ret; + + /* Setup entries */ + if (chan->qmc->is_tsa_64rxtx) + return qmc_chan_setup_tsa_64rxtx(chan, &info, enable); + + return qmc_chan_setup_tsa_32rx(chan, &info, enable); +} + static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool enable) { struct tsa_serial_info info; @@ -719,6 +759,12 @@ static int qmc_chan_stop_rx(struct qmc_chan *chan) spin_lock_irqsave(&chan->rx_lock, flags); + if (chan->is_rx_stopped) { + /* The channel is already stopped -> simply return ok */ + ret = 0; + goto end; + } + /* Send STOP RECEIVE command */ ret = qmc_chan_command(chan, 0x0); if (ret) { @@ -729,6 +775,15 @@ static int qmc_chan_stop_rx(struct qmc_chan *chan) chan->is_rx_stopped = true; + if (!chan->qmc->is_tsa_64rxtx || chan->is_tx_stopped) { + ret = qmc_chan_setup_tsa_rx(chan, false); + if (ret) { + dev_err(chan->qmc->dev, "chan %u: Disable tsa entries failed (%d)\n", + chan->id, ret); + goto end; + } + } + end: spin_unlock_irqrestore(&chan->rx_lock, flags); return ret; @@ -741,6 +796,12 @@ static int qmc_chan_stop_tx(struct qmc_chan *chan) spin_lock_irqsave(&chan->tx_lock, flags); + if (chan->is_tx_stopped) { + /* The channel is already stopped -> simply return ok */ + ret = 0; + goto end; + } + /* Send STOP TRANSMIT command */ ret = qmc_chan_command(chan, 0x1); if (ret) { @@ -751,37 +812,82 @@ static int qmc_chan_stop_tx(struct qmc_chan *chan) chan->is_tx_stopped = true; + if (!chan->qmc->is_tsa_64rxtx || chan->is_rx_stopped) { + ret = qmc_chan_setup_tsa_tx(chan, false); + if (ret) { + dev_err(chan->qmc->dev, "chan %u: Disable tsa entries failed (%d)\n", + chan->id, ret); + goto end; + } + } + end: spin_unlock_irqrestore(&chan->tx_lock, flags); return ret; } +static int qmc_chan_start_rx(struct qmc_chan *chan); + int qmc_chan_stop(struct qmc_chan *chan, int direction) { - int ret; + bool is_rx_rollback_needed = false; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&chan->ts_lock, flags); if (direction & QMC_CHAN_READ) { + is_rx_rollback_needed = !chan->is_rx_stopped; ret = qmc_chan_stop_rx(chan); if (ret) - return ret; + goto end; } if (direction & QMC_CHAN_WRITE) { ret = qmc_chan_stop_tx(chan); - if (ret) - return ret; + if (ret) { + /* Restart rx if needed */ + if (is_rx_rollback_needed) + qmc_chan_start_rx(chan); + goto end; + } } - return 0; +end: + spin_unlock_irqrestore(&chan->ts_lock, flags); + return ret; } EXPORT_SYMBOL(qmc_chan_stop); -static void qmc_chan_start_rx(struct qmc_chan *chan) +static int qmc_setup_chan_trnsync(struct qmc *qmc, struct qmc_chan *chan); + +static int qmc_chan_start_rx(struct qmc_chan *chan) { unsigned long flags; + int ret; spin_lock_irqsave(&chan->rx_lock, flags); + if (!chan->is_rx_stopped) { + /* The channel is already started -> simply return ok */ + ret = 0; + goto end; + } + + ret = qmc_chan_setup_tsa_rx(chan, true); + if (ret) { + dev_err(chan->qmc->dev, "chan %u: Enable tsa entries failed (%d)\n", + chan->id, ret); + goto end; + } + + ret = qmc_setup_chan_trnsync(chan->qmc, chan); + if (ret) { + dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n", + chan->id, ret); + goto end; + } + /* Restart the receiver */ if (chan->mode == QMC_TRANSPARENT) qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080); @@ -792,15 +898,38 @@ static void qmc_chan_start_rx(struct qmc_chan *chan) chan->is_rx_stopped = false; +end: spin_unlock_irqrestore(&chan->rx_lock, flags); + return ret; } -static void qmc_chan_start_tx(struct qmc_chan *chan) +static int qmc_chan_start_tx(struct qmc_chan *chan) { unsigned long flags; + int ret; spin_lock_irqsave(&chan->tx_lock, flags); + if (!chan->is_tx_stopped) { + /* The channel is already started -> simply return ok */ + ret = 0; + goto end; + } + + ret = qmc_chan_setup_tsa_tx(chan, true); + if (ret) { + dev_err(chan->qmc->dev, "chan %u: Enable tsa entries failed (%d)\n", + chan->id, ret); + goto end; + } + + ret = qmc_setup_chan_trnsync(chan->qmc, chan); + if (ret) { + dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n", + chan->id, ret); + goto end; + } + /* * Enable channel transmitter as it could be disabled if * qmc_chan_reset() was called. @@ -812,18 +941,39 @@ static void qmc_chan_start_tx(struct qmc_chan *chan) chan->is_tx_stopped = false; +end: spin_unlock_irqrestore(&chan->tx_lock, flags); + return ret; } int qmc_chan_start(struct qmc_chan *chan, int direction) { - if (direction & QMC_CHAN_READ) - qmc_chan_start_rx(chan); + bool is_rx_rollback_needed = false; + unsigned long flags; + int ret = 0; - if (direction & QMC_CHAN_WRITE) - qmc_chan_start_tx(chan); + spin_lock_irqsave(&chan->ts_lock, flags); - return 0; + if (direction & QMC_CHAN_READ) { + is_rx_rollback_needed = chan->is_rx_stopped; + ret = qmc_chan_start_rx(chan); + if (ret) + goto end; + } + + if (direction & QMC_CHAN_WRITE) { + ret = qmc_chan_start_tx(chan); + if (ret) { + /* Restop rx if needed */ + if (is_rx_rollback_needed) + qmc_chan_stop_rx(chan); + goto end; + } + } + +end: + spin_unlock_irqrestore(&chan->ts_lock, flags); + return ret; } EXPORT_SYMBOL(qmc_chan_start); @@ -992,6 +1142,7 @@ static int qmc_of_parse_chans(struct qmc *qmc, struct device_node *np) } chan->id = chan_id; + spin_lock_init(&chan->ts_lock); spin_lock_init(&chan->rx_lock); spin_lock_init(&chan->tx_lock); From patchwork Fri Aug 18 16:39:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358152 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 845ED182C3 for ; Fri, 18 Aug 2023 17:21:48 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9359A4236; Fri, 18 Aug 2023 10:21:45 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS7000sFtz9vjJ; Fri, 18 Aug 2023 18:40:16 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 2tLMKMJ80d5b; Fri, 18 Aug 2023 18:40:16 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl44rSz9vhX; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 7BCEF8B763; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id n8iY1WDueSWv; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 9A9448B77E; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdxhi142015 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:59 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdxG6142014; Fri, 18 Aug 2023 18:39:59 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 18/28] soc: fsl: cpm1: qmc: Remove timeslots handling from setup_chan() Date: Fri, 18 Aug 2023 18:39:12 +0200 Message-ID: <50f1e28baee1298cf39c8468b505a51ae6710bda.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376735; l=1901; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=A1rJrsre59ig518myaeGyZpy9HrxV9/ZdRaK15+9tLs=; b=kpMJGD3WpRipjM8MoPvUkI6SF2C1MYxifX8z4JAuWcRsfCqRxpS/a7slMqQewB13rnfdYcmLe 7R+UJR6aIjwDpnxnnsGjxeGXYnpw9IzXq7zunbf+AiwKnnaXkA2Opb+ X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina Timeslots setting is done at channel start() and stop(). There is no more need to do that during setup_chan(). Simply remove timeslot setting from setup_chan(). Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 00408da14cb4..b67e73ad7c1a 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -723,30 +723,6 @@ static int qmc_chan_setup_tsa_rx(struct qmc_chan *chan, bool enable) return qmc_chan_setup_tsa_32rx(chan, &info, enable); } -static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool enable) -{ - struct tsa_serial_info info; - int ret; - - /* Retrieve info from the TSA related serial */ - ret = tsa_serial_get_info(chan->qmc->tsa_serial, &info); - if (ret) - return ret; - - /* - * Setup one common 64 entries table or two 32 entries (one for Tx - * and one for Tx) according to assigned TS numbers. - */ - if (chan->qmc->is_tsa_64rxtx) - return qmc_chan_setup_tsa_64rxtx(chan, &info, enable); - - ret = qmc_chan_setup_tsa_32rx(chan, &info, enable); - if (ret) - return ret; - - return qmc_chan_setup_tsa_32tx(chan, &info, enable); -} - static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode) { return cpm_command(chan->id << 2, (qmc_opcode << 4) | 0x0E); @@ -1323,10 +1299,6 @@ static int qmc_setup_chan(struct qmc *qmc, struct qmc_chan *chan) chan->qmc = qmc; - ret = qmc_chan_setup_tsa(chan, true); - if (ret) - return ret; - /* Set channel specific parameter base address */ chan->s_param = qmc->dpram + (chan->id * 64); /* 16 bd per channel (8 rx and 8 tx) */ From patchwork Fri Aug 18 16:39:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358154 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 A6BC0613A for ; Fri, 18 Aug 2023 17:22:16 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D51CC49CC; Fri, 18 Aug 2023 10:22:00 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS6zv0pwcz9vj0; Fri, 18 Aug 2023 18:40:11 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id axONG-mlx7_u; Fri, 18 Aug 2023 18:40:11 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zl3NNRz9vhP; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 670528B763; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id 02pNESDStCWP; Fri, 18 Aug 2023 18:40:03 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 9B88A8B780; Fri, 18 Aug 2023 18:40:01 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdxXm142019 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:59 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdx5n142018; Fri, 18 Aug 2023 18:39:59 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 19/28] soc: fsl: cpm1: qmc: Introduce functions to change timeslots at runtime Date: Fri, 18 Aug 2023 18:39:13 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376735; l=3289; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=78wehWlqMiFqYxFZMxpjqZHHmzC9lp2SLom1hHjHEc0=; b=EH7Ypvhs7z/Y3OrSfBqFh17QEyqVrp0buZQDOR7eq0JQ1x67x/X1kUy7/Q+pHJwHVuZbuk79e XYTA/MXLFvZDQldKEezNeOYlhhMZAKzOjqczr1Ixz8QYRkMZcU/xiYt X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina Introduce qmc_chan_{get,set}_ts_info() function to allow timeslots modification at runtime. The modification is provided using qmc_chan_set_ts_info() and will be applied on next qmc_chan_start(). qmc_chan_set_ts_info() must be called with the channel rx and/or tx stopped. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 51 ++++++++++++++++++++++++++++++++++++++++ include/soc/fsl/qe/qmc.h | 10 ++++++++ 2 files changed, 61 insertions(+) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index b67e73ad7c1a..2ab21a0023a7 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -290,6 +290,57 @@ int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info) } EXPORT_SYMBOL(qmc_chan_get_info); +int qmc_chan_get_ts_info(struct qmc_chan *chan, struct qmc_chan_ts_info *ts_info) +{ + unsigned long flags; + + spin_lock_irqsave(&chan->ts_lock, flags); + + ts_info->rx_ts_mask_avail = chan->rx_ts_mask_avail; + ts_info->tx_ts_mask_avail = chan->tx_ts_mask_avail; + ts_info->rx_ts_mask = chan->rx_ts_mask; + ts_info->tx_ts_mask = chan->tx_ts_mask; + + spin_unlock_irqrestore(&chan->ts_lock, flags); + + return 0; +} +EXPORT_SYMBOL(qmc_chan_get_ts_info); + +int qmc_chan_set_ts_info(struct qmc_chan *chan, const struct qmc_chan_ts_info *ts_info) +{ + unsigned long flags; + int ret; + + /* Only a subset of available timeslots is allowed */ + if ((ts_info->rx_ts_mask & chan->rx_ts_mask_avail) != ts_info->rx_ts_mask) + return -EINVAL; + if ((ts_info->tx_ts_mask & chan->tx_ts_mask_avail) != ts_info->tx_ts_mask) + return -EINVAL; + + /* In case of common rx/tx table, rx/tx masks must be identical */ + if (chan->qmc->is_tsa_64rxtx) { + if (ts_info->rx_ts_mask != ts_info->tx_ts_mask) + return -EINVAL; + } + + spin_lock_irqsave(&chan->ts_lock, flags); + + if ((chan->tx_ts_mask != ts_info->tx_ts_mask && !chan->is_tx_stopped) || + (chan->rx_ts_mask != ts_info->rx_ts_mask && !chan->is_rx_stopped)) { + dev_err(chan->qmc->dev, "Channel rx and/or tx not stopped\n"); + ret = -EBUSY; + } else { + chan->tx_ts_mask = ts_info->tx_ts_mask; + chan->rx_ts_mask = ts_info->rx_ts_mask; + ret = 0; + } + spin_unlock_irqrestore(&chan->ts_lock, flags); + + return ret; +} +EXPORT_SYMBOL(qmc_chan_set_ts_info); + int qmc_chan_set_param(struct qmc_chan *chan, const struct qmc_chan_param *param) { if (param->mode != chan->mode) diff --git a/include/soc/fsl/qe/qmc.h b/include/soc/fsl/qe/qmc.h index 6f1d6cebc9fe..802c161636bd 100644 --- a/include/soc/fsl/qe/qmc.h +++ b/include/soc/fsl/qe/qmc.h @@ -38,6 +38,16 @@ struct qmc_chan_info { int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info); +struct qmc_chan_ts_info { + u64 rx_ts_mask_avail; + u64 tx_ts_mask_avail; + u64 rx_ts_mask; + u64 tx_ts_mask; +}; + +int qmc_chan_get_ts_info(struct qmc_chan *chan, struct qmc_chan_ts_info *ts_info); +int qmc_chan_set_ts_info(struct qmc_chan *chan, const struct qmc_chan_ts_info *ts_info); + struct qmc_chan_param { enum qmc_mode mode; union { From patchwork Fri Aug 18 16:39:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358150 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 A29B01C2A1 for ; Fri, 18 Aug 2023 17:21:39 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3AF3C3AB9; Fri, 18 Aug 2023 10:21:38 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS70D3SNcz9vk6; Fri, 18 Aug 2023 18:40:28 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id nZ6PxMQtQW9O; Fri, 18 Aug 2023 18:40:28 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zq4GSQz9vhv; Fri, 18 Aug 2023 18:40:07 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 8955F8B763; Fri, 18 Aug 2023 18:40:07 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id NA1yrES0tY_0; Fri, 18 Aug 2023 18:40:07 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id D9B188B774; Fri, 18 Aug 2023 18:40:04 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdxKu142023 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:59 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdxB6142022; Fri, 18 Aug 2023 18:39:59 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 20/28] wan: qmc_hdlc: Add runtime timeslots changes support Date: Fri, 18 Aug 2023 18:39:14 +0200 Message-ID: <1364a0742fc76e7d275273dbbc4c97b008ec70a5.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376735; l=6280; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=eK9eevEQIIuGHSZNag/W1HJUxb7WlRc6XDHKjkWlFLg=; b=eKO9R2JUPU5irzD8QlyKcKFn4LRcBUwa38RPaiyYcCqKOgBrO4tJLxYQEu/JRCkhNLfV3yyAR pnckgyGaV96C/B2j3RvEkBwADfZ5s2bqBCESQlSohZsGSljElzQQJ4y X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Herve Codina QMC channels support runtime timeslots changes but nothing is done at the QMC HDLC driver to handle these changes. Use existing IFACE ioctl in order to configure the timeslots to use. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/net/wan/fsl_qmc_hdlc.c | 169 ++++++++++++++++++++++++++++++++- 1 file changed, 168 insertions(+), 1 deletion(-) diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c index 4f84ac5fc63e..4b8cb5761fd1 100644 --- a/drivers/net/wan/fsl_qmc_hdlc.c +++ b/drivers/net/wan/fsl_qmc_hdlc.c @@ -32,6 +32,7 @@ struct qmc_hdlc { struct qmc_hdlc_desc tx_descs[8]; unsigned int tx_out; struct qmc_hdlc_desc rx_descs[4]; + u32 slot_map; }; static inline struct qmc_hdlc *netdev_to_qmc_hdlc(struct net_device *netdev) @@ -202,6 +203,162 @@ static netdev_tx_t qmc_hdlc_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } +static int qmc_hdlc_xlate_slot_map(struct qmc_hdlc *qmc_hdlc, + u32 slot_map, struct qmc_chan_ts_info *ts_info) +{ + u64 ts_mask_avail; + unsigned int bit; + unsigned int i; + u64 ts_mask; + u64 map = 0; + + /* Tx and Rx masks must be identical */ + if (ts_info->rx_ts_mask_avail != ts_info->tx_ts_mask_avail) { + dev_err(qmc_hdlc->dev, "tx and rx available timeslots mismatch (0x%llx, 0x%llx)\n", + ts_info->rx_ts_mask_avail, ts_info->tx_ts_mask_avail); + return -EINVAL; + } + + ts_mask_avail = ts_info->rx_ts_mask_avail; + ts_mask = 0; + map = slot_map; + bit = 0; + for (i = 0; i < 64; i++) { + if (ts_mask_avail & BIT_ULL(i)) { + if (map & BIT_ULL(bit)) + ts_mask |= BIT_ULL(i); + bit++; + } + } + + if (hweight64(ts_mask) != hweight64(map)) { + dev_err(qmc_hdlc->dev, "Cannot translate timeslots 0x%llx -> (0x%llx,0x%llx)\n", + map, ts_mask_avail, ts_mask); + return -EINVAL; + } + + ts_info->tx_ts_mask = ts_mask; + ts_info->rx_ts_mask = ts_mask; + return 0; +} + +static int qmc_hdlc_xlate_ts_info(struct qmc_hdlc *qmc_hdlc, + const struct qmc_chan_ts_info *ts_info, u32 *slot_map) +{ + u64 ts_mask_avail; + unsigned int bit; + unsigned int i; + u64 ts_mask; + u64 map = 0; + + /* Tx and Rx masks must be identical */ + if (ts_info->rx_ts_mask_avail != ts_info->tx_ts_mask_avail) { + dev_err(qmc_hdlc->dev, "tx and rx available timeslots mismatch (0x%llx, 0x%llx)\n", + ts_info->rx_ts_mask_avail, ts_info->tx_ts_mask_avail); + return -EINVAL; + } + if (ts_info->rx_ts_mask != ts_info->tx_ts_mask) { + dev_err(qmc_hdlc->dev, "tx and rx timeslots mismatch (0x%llx, 0x%llx)\n", + ts_info->rx_ts_mask, ts_info->tx_ts_mask); + return -EINVAL; + } + + ts_mask_avail = ts_info->rx_ts_mask_avail; + ts_mask = ts_info->rx_ts_mask; + map = 0; + bit = 0; + for (i = 0; i < 64; i++) { + if (ts_mask_avail & BIT_ULL(i)) { + if (ts_mask & BIT_ULL(i)) + map |= BIT_ULL(bit); + bit++; + } + } + + if (hweight64(ts_mask) != hweight64(map)) { + dev_err(qmc_hdlc->dev, "Cannot translate timeslots (0x%llx,0x%llx) -> 0x%llx\n", + ts_mask_avail, ts_mask, map); + return -EINVAL; + } + + if (map >= BIT_ULL(32)) { + dev_err(qmc_hdlc->dev, "Slot map out of 32bit (0x%llx,0x%llx) -> 0x%llx\n", + ts_mask_avail, ts_mask, map); + return -EINVAL; + } + + *slot_map = map; + return 0; +} + +static int qmc_hdlc_set_iface(struct qmc_hdlc *qmc_hdlc, int if_iface, const te1_settings *te1) +{ + struct qmc_chan_ts_info ts_info; + int ret; + + ret = qmc_chan_get_ts_info(qmc_hdlc->qmc_chan, &ts_info); + if (ret) { + dev_err(qmc_hdlc->dev, "get QMC channel ts info failed %d\n", ret); + return ret; + } + ret = qmc_hdlc_xlate_slot_map(qmc_hdlc, te1->slot_map, &ts_info); + if (ret) + return ret; + + ret = qmc_chan_set_ts_info(qmc_hdlc->qmc_chan, &ts_info); + if (ret) { + dev_err(qmc_hdlc->dev, "set QMC channel ts info failed %d\n", ret); + return ret; + } + + qmc_hdlc->slot_map = te1->slot_map; + + return 0; +} + +static int qmc_hdlc_ioctl(struct net_device *netdev, struct if_settings *ifs) +{ + struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(netdev); + te1_settings te1; + + switch (ifs->type) { + case IF_GET_IFACE: + ifs->type = IF_IFACE_E1; + if (ifs->size < sizeof(te1)) { + if (!ifs->size) + return 0; /* only type requested */ + + ifs->size = sizeof(te1); /* data size wanted */ + return -ENOBUFS; + } + + memset(&te1, 0, sizeof(te1)); + + /* Update slot_map */ + te1.slot_map = qmc_hdlc->slot_map; + + if (copy_to_user(ifs->ifs_ifsu.te1, &te1, sizeof(te1))) + return -EFAULT; + return 0; + + case IF_IFACE_E1: + case IF_IFACE_T1: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (netdev->flags & IFF_UP) + return -EBUSY; + + if (copy_from_user(&te1, ifs->ifs_ifsu.te1, sizeof(te1))) + return -EFAULT; + + return qmc_hdlc_set_iface(qmc_hdlc, ifs->type, &te1); + + default: + return hdlc_ioctl(netdev, ifs); + } +} + static int qmc_hdlc_open(struct net_device *netdev) { struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(netdev); @@ -328,13 +485,14 @@ static const struct net_device_ops qmc_hdlc_netdev_ops = { .ndo_open = qmc_hdlc_open, .ndo_stop = qmc_hdlc_close, .ndo_start_xmit = hdlc_start_xmit, - .ndo_siocwandev = hdlc_ioctl, + .ndo_siocwandev = qmc_hdlc_ioctl, }; static int qmc_hdlc_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct qmc_hdlc *qmc_hdlc; + struct qmc_chan_ts_info ts_info; struct qmc_chan_info info; hdlc_device *hdlc; int ret; @@ -364,6 +522,15 @@ static int qmc_hdlc_probe(struct platform_device *pdev) return -EINVAL; } + ret = qmc_chan_get_ts_info(qmc_hdlc->qmc_chan, &ts_info); + if (ret) { + dev_err(qmc_hdlc->dev, "get QMC channel ts info failed %d\n", ret); + return ret; + } + ret = qmc_hdlc_xlate_ts_info(qmc_hdlc, &ts_info, &qmc_hdlc->slot_map); + if (ret) + return ret; + qmc_hdlc->netdev = alloc_hdlcdev(qmc_hdlc); if (!qmc_hdlc->netdev) { dev_err(qmc_hdlc->dev, "failed to alloc hdlc dev\n"); From patchwork Fri Aug 18 16:39:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358141 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 D1F1519BAB for ; Fri, 18 Aug 2023 17:21:10 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 10ED03AB9; Fri, 18 Aug 2023 10:21:07 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS70C1pb6z9vk0; Fri, 18 Aug 2023 18:40:27 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id wLBqMdf2JR0B; Fri, 18 Aug 2023 18:40:27 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zq1wmFz9vht; Fri, 18 Aug 2023 18:40:07 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 312008B763; Fri, 18 Aug 2023 18:40:07 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id Gh0B2wMpKaTT; Fri, 18 Aug 2023 18:40:07 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id D8FDD8B773; Fri, 18 Aug 2023 18:40:04 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdxTn142027 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:59 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdxBq142026; Fri, 18 Aug 2023 18:39:59 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 21/28] net: wan: Add framer framework support Date: Fri, 18 Aug 2023 18:39:15 +0200 Message-ID: <5f671caf19be0a9bb7ea7b96a6c86381e243ca4c.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376735; l=40999; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=Y/wU6Xe3B47tqNiF9XOPbrbUyF2zTfP8S7jNCo50jqk=; b=BrXBSZemguFKCUr5vzqAxHlooPBOiYHr6Ez9XNIPWErpvRmETbS+Vckp7gjfjP+y2gX+qus6X zl1O/i98Gr/C6z+Qw9aBTOkcUnhCxMeFy/zMv7UZvBZsWlVW63C8PtK X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Herve Codina A framer is a component in charge of an E1/T1 line interface. Connected usually to a TDM bus, it converts TDM frames to/from E1/T1 frames. It also provides information related to the E1/T1 line. The framer framework provides a set of APIs for the framer drivers (framer provider) to create/destroy a framer and APIs for the framer users (framer consumer) to obtain a reference to the framer, and use the framer. This basic implementation provides a framer abstraction for: - power on/off the framer - get the framer status (line state) - be notified on framer status changes - get/set the framer configuration Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- v4: Fixed wrong names in three EXPORT_SYMBOL() --- drivers/net/wan/Kconfig | 2 + drivers/net/wan/Makefile | 2 + drivers/net/wan/framer/Kconfig | 19 + drivers/net/wan/framer/Makefile | 6 + drivers/net/wan/framer/framer-core.c | 886 +++++++++++++++++++++++++ include/linux/framer/framer-provider.h | 194 ++++++ include/linux/framer/framer.h | 199 ++++++ 7 files changed, 1308 insertions(+) create mode 100644 drivers/net/wan/framer/Kconfig create mode 100644 drivers/net/wan/framer/Makefile create mode 100644 drivers/net/wan/framer/framer-core.c create mode 100644 include/linux/framer/framer-provider.h create mode 100644 include/linux/framer/framer.h diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 8de99f4b647b..31ab2136cdf1 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -95,6 +95,8 @@ config HDLC_X25 comment "X.25/LAPB support is disabled" depends on HDLC && (LAPB!=m || HDLC!=m) && LAPB!=y +source "drivers/net/wan/framer/Kconfig" + config PCI200SYN tristate "Goramo PCI200SYN support" depends on HDLC && PCI diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile index f338f4830626..00e9b7ee1e01 100644 --- a/drivers/net/wan/Makefile +++ b/drivers/net/wan/Makefile @@ -14,6 +14,8 @@ obj-$(CONFIG_HDLC_FR) += hdlc_fr.o obj-$(CONFIG_HDLC_PPP) += hdlc_ppp.o obj-$(CONFIG_HDLC_X25) += hdlc_x25.o +obj-y += framer/ + obj-$(CONFIG_FARSYNC) += farsync.o obj-$(CONFIG_LAPBETHER) += lapbether.o diff --git a/drivers/net/wan/framer/Kconfig b/drivers/net/wan/framer/Kconfig new file mode 100644 index 000000000000..96ef1e7ba8eb --- /dev/null +++ b/drivers/net/wan/framer/Kconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# FRAMER +# + +menu "Framer Subsystem" + +config GENERIC_FRAMER + bool "Framer Core" + help + Generic Framer support. + + This framework is designed to provide a generic interface for framer + devices present in the kernel. This layer will have the generic + API by which framer drivers can create framer using the framer + framework and framer users can obtain reference to the framer. + All the users of this framework should select this config. + +endmenu diff --git a/drivers/net/wan/framer/Makefile b/drivers/net/wan/framer/Makefile new file mode 100644 index 000000000000..78dbd8e563d0 --- /dev/null +++ b/drivers/net/wan/framer/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the framer drivers. +# + +obj-$(CONFIG_GENERIC_FRAMER) += framer-core.o diff --git a/drivers/net/wan/framer/framer-core.c b/drivers/net/wan/framer/framer-core.c new file mode 100644 index 000000000000..1fb23a068010 --- /dev/null +++ b/drivers/net/wan/framer/framer-core.c @@ -0,0 +1,886 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Generic Framer framework. + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct class *framer_class; +static DEFINE_MUTEX(framer_provider_mutex); +static LIST_HEAD(framer_provider_list); +static DEFINE_IDA(framer_ida); + +#define dev_to_framer(a) (container_of((a), struct framer, dev)) + +int framer_pm_runtime_get(struct framer *framer) +{ + int ret; + + if (!pm_runtime_enabled(&framer->dev)) + return -EOPNOTSUPP; + + ret = pm_runtime_get(&framer->dev); + if (ret < 0 && ret != -EINPROGRESS) + pm_runtime_put_noidle(&framer->dev); + + return ret; +} +EXPORT_SYMBOL_GPL(framer_pm_runtime_get); + +int framer_pm_runtime_get_sync(struct framer *framer) +{ + int ret; + + if (!pm_runtime_enabled(&framer->dev)) + return -EOPNOTSUPP; + + ret = pm_runtime_get_sync(&framer->dev); + if (ret < 0) + pm_runtime_put_sync(&framer->dev); + + return ret; +} +EXPORT_SYMBOL_GPL(framer_pm_runtime_get_sync); + +int framer_pm_runtime_put(struct framer *framer) +{ + if (!pm_runtime_enabled(&framer->dev)) + return -EOPNOTSUPP; + + return pm_runtime_put(&framer->dev); +} +EXPORT_SYMBOL_GPL(framer_pm_runtime_put); + +int framer_pm_runtime_put_sync(struct framer *framer) +{ + if (!pm_runtime_enabled(&framer->dev)) + return -EOPNOTSUPP; + + return pm_runtime_put_sync(&framer->dev); +} +EXPORT_SYMBOL_GPL(framer_pm_runtime_put_sync); + +/** + * framer_init - framer internal initialization before framer operation + * @framer: the framer returned by framer_get() + * + * Used to allow framer's driver to perform framer internal initialization, + * such as PLL block powering, clock initialization or anything that's + * is required by the framer to perform the start of operation. + * Must be called before framer_power_on(). + * + * Return: %0 if successful, a negative error code otherwise + */ +int framer_init(struct framer *framer) +{ + bool start_polling = false; + int ret; + + ret = framer_pm_runtime_get_sync(framer); + if (ret < 0 && ret != -EOPNOTSUPP) + return ret; + ret = 0; /* Override possible ret == -EOPNOTSUPP */ + + mutex_lock(&framer->mutex); + if (framer->power_count > framer->init_count) + dev_warn(&framer->dev, "framer_power_on was called before framer init\n"); + + if (framer->init_count == 0) { + if (framer->ops->init) { + ret = framer->ops->init(framer); + if (ret < 0) { + dev_err(&framer->dev, "framer init failed --> %d\n", ret); + goto out; + } + } + if (framer->ops->flags & FRAMER_FLAG_POLL_STATUS) + start_polling = true; + } + ++framer->init_count; + +out: + mutex_unlock(&framer->mutex); + + if (!ret && start_polling) { + ret = framer_get_status(framer, &framer->prev_status); + if (ret < 0) { + dev_warn(&framer->dev, "framer get status failed --> %d\n", ret); + /* Will be retried on polling_work */ + ret = 0; + } + queue_delayed_work(system_power_efficient_wq, &framer->polling_work, 1 * HZ); + } + + framer_pm_runtime_put(framer); + return ret; +} +EXPORT_SYMBOL_GPL(framer_init); + +/** + * framer_exit - Framer internal un-initialization + * @framer: the framer returned by framer_get() + * + * Must be called after framer_power_off(). + */ +int framer_exit(struct framer *framer) +{ + int ret; + + ret = framer_pm_runtime_get_sync(framer); + if (ret < 0 && ret != -EOPNOTSUPP) + return ret; + ret = 0; /* Override possible ret == -EOPNOTSUPP */ + + mutex_lock(&framer->mutex); + --framer->init_count; + if (framer->init_count == 0) { + if (framer->ops->flags & FRAMER_FLAG_POLL_STATUS) { + mutex_unlock(&framer->mutex); + cancel_delayed_work_sync(&framer->polling_work); + mutex_lock(&framer->mutex); + } + + if (framer->ops->exit) + framer->ops->exit(framer); + } + + mutex_unlock(&framer->mutex); + framer_pm_runtime_put(framer); + return ret; +} +EXPORT_SYMBOL_GPL(framer_exit); + +/** + * framer_power_on - Enable the framer and enter proper operation + * @framer: the framer returned by framer_get() + * + * Must be called after framer_init(). + * + * Return: %0 if successful, a negative error code otherwise + */ +int framer_power_on(struct framer *framer) +{ + int ret; + + if (framer->pwr) { + ret = regulator_enable(framer->pwr); + if (ret) + return ret; + } + + ret = framer_pm_runtime_get_sync(framer); + if (ret < 0 && ret != -EOPNOTSUPP) + goto err_pm_sync; + + ret = 0; /* Override possible ret == -EOPNOTSUPP */ + + mutex_lock(&framer->mutex); + if (framer->power_count == 0 && framer->ops->power_on) { + ret = framer->ops->power_on(framer); + if (ret < 0) { + dev_err(&framer->dev, "framer poweron failed --> %d\n", ret); + goto err_pwr_on; + } + } + ++framer->power_count; + mutex_unlock(&framer->mutex); + return 0; + +err_pwr_on: + mutex_unlock(&framer->mutex); + framer_pm_runtime_put_sync(framer); +err_pm_sync: + if (framer->pwr) + regulator_disable(framer->pwr); + return ret; +} +EXPORT_SYMBOL_GPL(framer_power_on); + +/** + * framer_power_off - Disable the framer. + * @framer: the framer returned by framer_get() + * + * Must be called before framer_exit(). + * + * Return: %0 if successful, a negative error code otherwise + */ +int framer_power_off(struct framer *framer) +{ + int ret; + + mutex_lock(&framer->mutex); + if (framer->power_count == 1 && framer->ops->power_off) { + ret = framer->ops->power_off(framer); + if (ret < 0) { + dev_err(&framer->dev, "framer poweroff failed --> %d\n", ret); + mutex_unlock(&framer->mutex); + return ret; + } + } + --framer->power_count; + mutex_unlock(&framer->mutex); + framer_pm_runtime_put(framer); + + if (framer->pwr) + regulator_disable(framer->pwr); + + return 0; +} +EXPORT_SYMBOL_GPL(framer_power_off); + +/** + * framer_get_status() - Gets the framer status + * @framer: the framer returned by framer_get() + * @status: the status to retrieve + * + * Used to get the framer status. framer_init() must have been called + * on the framer. + * + * Return: %0 if successful, a negative error code otherwise + */ +int framer_get_status(struct framer *framer, struct framer_status *status) +{ + int ret; + + if (!framer->ops->get_status) + return -EOPNOTSUPP; + + /* Be sure to have known values (struct padding and future extensions) */ + memset(status, 0, sizeof(*status)); + + mutex_lock(&framer->mutex); + ret = framer->ops->get_status(framer, status); + mutex_unlock(&framer->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(framer_get_status); + +/** + * framer_set_config() - Sets the framer configuration + * @framer: the framer returned by framer_get() + * @config: the configuration to set + * + * Used to set the framer configuration. framer_init() must have been called + * on the framer. + * + * Return: %0 if successful, a negative error code otherwise + */ +int framer_set_config(struct framer *framer, const struct framer_config *config) +{ + int ret; + + if (!framer->ops->set_config) + return -EOPNOTSUPP; + + mutex_lock(&framer->mutex); + ret = framer->ops->set_config(framer, config); + mutex_unlock(&framer->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(framer_set_config); + +/** + * framer_get_config() - Gets the framer configuration + * @framer: the framer returned by framer_get() + * @config: the configuration to retrieve + * + * Used to get the framer configuration. framer_init() must have been called + * on the framer. + * + * Return: %0 if successful, a negative error code otherwise + */ +int framer_get_config(struct framer *framer, struct framer_config *config) +{ + int ret; + + if (!framer->ops->get_config) + return -EOPNOTSUPP; + + mutex_lock(&framer->mutex); + ret = framer->ops->get_config(framer, config); + mutex_unlock(&framer->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(framer_get_config); + +static void framer_polling_work(struct work_struct *work) +{ + struct framer *framer = container_of(work, struct framer, polling_work.work); + struct framer_status status; + int ret; + + ret = framer_get_status(framer, &status); + if (ret) { + dev_err(&framer->dev, "polling, get status failed (%d)\n", ret); + goto end; + } + if (memcmp(&framer->prev_status, &status, sizeof(status))) { + blocking_notifier_call_chain(&framer->notifier_list, + FRAMER_EVENT_STATUS, NULL); + memcpy(&framer->prev_status, &status, sizeof(status)); + } + +end: + /* Re-schedule task in 1 sec */ + queue_delayed_work(system_power_efficient_wq, &framer->polling_work, 1 * HZ); +} + +/** + * framer_notifier_register() - Registers a notifier + * @framer: the framer returned by framer_get() + * @nb: the notifier block to register + * + * Used to register a notifier block on framer events. framer_init() must have + * been called on the framer. + * The available framer events are present in enum framer_events. + * + * Return: %0 if successful, a negative error code otherwise + */ +int framer_notifier_register(struct framer *framer, struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&framer->notifier_list, nb); +} +EXPORT_SYMBOL_GPL(framer_notifier_register); + +/** + * framer_notifier_unregister() - Unregisters a notifier + * @framer: the framer returned by framer_get() + * @nb: the notifier block to unregister + * + * Used to unregister a notifier block. framer_init() must have + * been called on the framer. + * + * Return: %0 if successful, a negative error code otherwise + */ +int framer_notifier_unregister(struct framer *framer, struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&framer->notifier_list, nb); +} +EXPORT_SYMBOL_GPL(framer_notifier_unregister); + +static struct framer_provider *framer_provider_of_lookup(const struct device_node *node) +{ + struct framer_provider *framer_provider; + + list_for_each_entry(framer_provider, &framer_provider_list, list) { + if (device_match_of_node(framer_provider->dev, node)) + return framer_provider; + } + + return ERR_PTR(-EPROBE_DEFER); +} + +static struct framer *framer_of_get_from_provider(struct of_phandle_args *args) +{ + struct framer_provider *framer_provider; + struct framer *framer; + + mutex_lock(&framer_provider_mutex); + framer_provider = framer_provider_of_lookup(args->np); + if (IS_ERR(framer_provider) || !try_module_get(framer_provider->owner)) { + framer = ERR_PTR(-EPROBE_DEFER); + goto end; + } + + framer = framer_provider->of_xlate(framer_provider->dev, args); + + module_put(framer_provider->owner); + +end: + mutex_unlock(&framer_provider_mutex); + + return framer; +} + +static struct framer *framer_of_get_byphandle(struct device_node *np, const char *propname, + int index) +{ + struct of_phandle_args args; + struct framer *framer; + int ret; + + ret = of_parse_phandle_with_args(np, propname, "#framer-cells", index, &args); + if (ret) + return ERR_PTR(-ENODEV); + + if (!of_device_is_available(args.np)) { + framer = ERR_PTR(-ENODEV); + goto out_node_put; + } + + framer = framer_of_get_from_provider(&args); + +out_node_put: + of_node_put(args.np); + + return framer; +} + +static struct framer *framer_of_get_byparent(struct device_node *np, int index) +{ + struct of_phandle_args args; + struct framer *framer; + + args.np = of_get_parent(np); + args.args_count = 1; + args.args[0] = index; + + while (args.np) { + framer = framer_of_get_from_provider(&args); + if (IS_ERR(framer) && PTR_ERR(framer) != -EPROBE_DEFER) { + args.np = of_get_next_parent(args.np); + continue; + } + of_node_put(args.np); + return framer; + } + + return ERR_PTR(-ENODEV); +} + +/** + * framer_get() - lookup and obtain a reference to a framer. + * @dev: device that requests the framer + * @con_id: name of the framer from device's point of view + * + * Returns the framer driver, after getting a refcount to it; or + * -ENODEV if there is no such framer. The caller is responsible for + * calling framer_put() to release that count. + */ +struct framer *framer_get(struct device *dev, const char *con_id) +{ + struct framer *framer = ERR_PTR(-ENODEV); + struct device_link *link; + int ret; + + if (dev->of_node) { + if (con_id) + framer = framer_of_get_byphandle(dev->of_node, con_id, 0); + else + framer = framer_of_get_byparent(dev->of_node, 0); + } + + if (IS_ERR(framer)) + return framer; + + get_device(&framer->dev); + + if (!try_module_get(framer->ops->owner)) { + ret = -EPROBE_DEFER; + goto err_put_device; + } + + link = device_link_add(dev, &framer->dev, DL_FLAG_STATELESS); + if (!link) { + dev_err(dev, "failed to create device_link to %s\n", dev_name(&framer->dev)); + ret = -EPROBE_DEFER; + goto err_module_put; + } + + return framer; + +err_module_put: + module_put(framer->ops->owner); +err_put_device: + put_device(&framer->dev); + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(framer_get); + +/** + * framer_put() - release the framer + * @dev: device that wants to release this framer + * @framer: the framer returned by framer_get() + * + * Releases a refcount the caller received from framer_get(). + */ +void framer_put(struct device *dev, struct framer *framer) +{ + device_link_remove(dev, &framer->dev); + + module_put(framer->ops->owner); + put_device(&framer->dev); +} +EXPORT_SYMBOL_GPL(framer_put); + +static void devm_framer_put(struct device *dev, void *res) +{ + struct framer *framer = *(struct framer **)res; + + framer_put(dev, framer); +} + +/** + * devm_framer_get() - lookup and obtain a reference to a framer. + * @dev: device that requests this framer + * @con_id: name of the framer from device's point of view + * + * Gets the framer using framer_get(), and associates a device with it using + * devres. On driver detach, framer_put() function is invoked on the devres + * data, then, devres data is freed. + */ +struct framer *devm_framer_get(struct device *dev, const char *con_id) +{ + struct framer **ptr, *framer; + + ptr = devres_alloc(devm_framer_put, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + framer = framer_get(dev, con_id); + if (!IS_ERR(framer)) { + *ptr = framer; + devres_add(dev, ptr); + } else { + devres_free(ptr); + return framer; + } + + return framer; +} +EXPORT_SYMBOL_GPL(devm_framer_get); + +/** + * devm_framer_optional_get() - lookup and obtain a reference to an optional + * framer. + * @dev: device that requests this framer + * @con_id: name of the framer from device's point of view + * + * Same as devm_framer_get() except that if the framer does not exist, it is not + * considered an error and -ENODEV will not be returned. Instead the NULL framer + * is returned. + */ +struct framer *devm_framer_optional_get(struct device *dev, const char *con_id) +{ + struct framer *framer = devm_framer_get(dev, con_id); + + if (PTR_ERR(framer) == -ENODEV) + framer = NULL; + + return framer; +} +EXPORT_SYMBOL_GPL(devm_framer_optional_get); + +static void framer_notify_status_work(struct work_struct *work) +{ + struct framer *framer = container_of(work, struct framer, notify_status_work); + + blocking_notifier_call_chain(&framer->notifier_list, FRAMER_EVENT_STATUS, NULL); +} + +void framer_notify_status_change(struct framer *framer) +{ + /* Can be called from atomic context -> just schedule a task to call + * blocking notifiers + */ + queue_work(system_power_efficient_wq, &framer->notify_status_work); +} +EXPORT_SYMBOL_GPL(framer_notify_status_change); + +/** + * framer_create() - create a new framer + * @dev: device that is creating the new framer + * @node: device node of the framer. default to dev->of_node. + * @ops: function pointers for performing framer operations + * + * Called to create a framer using framer framework. + */ +struct framer *framer_create(struct device *dev, struct device_node *node, + const struct framer_ops *ops) +{ + int ret; + int id; + struct framer *framer; + + if (WARN_ON(!dev)) + return ERR_PTR(-EINVAL); + + /* get_status() is mandatory if the provider ask for polling status */ + if (WARN_ON((ops->flags & FRAMER_FLAG_POLL_STATUS) && !ops->get_status)) + return ERR_PTR(-EINVAL); + + framer = kzalloc(sizeof(*framer), GFP_KERNEL); + if (!framer) + return ERR_PTR(-ENOMEM); + + id = ida_simple_get(&framer_ida, 0, 0, GFP_KERNEL); + if (id < 0) { + dev_err(dev, "unable to get id\n"); + ret = id; + goto free_framer; + } + + device_initialize(&framer->dev); + mutex_init(&framer->mutex); + INIT_WORK(&framer->notify_status_work, framer_notify_status_work); + INIT_DELAYED_WORK(&framer->polling_work, framer_polling_work); + BLOCKING_INIT_NOTIFIER_HEAD(&framer->notifier_list); + + framer->dev.class = framer_class; + framer->dev.parent = dev; + framer->dev.of_node = node ? node : dev->of_node; + framer->id = id; + framer->ops = ops; + + ret = dev_set_name(&framer->dev, "framer-%s.%d", dev_name(dev), id); + if (ret) + goto put_dev; + + /* framer-supply */ + framer->pwr = regulator_get_optional(&framer->dev, "framer"); + if (IS_ERR(framer->pwr)) { + ret = PTR_ERR(framer->pwr); + if (ret == -EPROBE_DEFER) + goto put_dev; + + framer->pwr = NULL; + } + + ret = device_add(&framer->dev); + if (ret) + goto put_dev; + + if (pm_runtime_enabled(dev)) { + pm_runtime_enable(&framer->dev); + pm_runtime_no_callbacks(&framer->dev); + } + + return framer; + +put_dev: + put_device(&framer->dev); /* calls framer_release() which frees resources */ + return ERR_PTR(ret); + +free_framer: + kfree(framer); + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(framer_create); + +/** + * framer_destroy() - destroy the framer + * @framer: the framer to be destroyed + * + * Called to destroy the framer. + */ +void framer_destroy(struct framer *framer) +{ + /* polling_work should already be stopped but if framer_exit() was not + * called (bug), here it's the last time to do that ... + */ + cancel_delayed_work_sync(&framer->polling_work); + cancel_work_sync(&framer->notify_status_work); + pm_runtime_disable(&framer->dev); + device_unregister(&framer->dev); /* calls framer_release() which frees resources */ +} +EXPORT_SYMBOL_GPL(framer_destroy); + +static void devm_framer_destroy(struct device *dev, void *res) +{ + struct framer *framer = *(struct framer **)res; + + framer_destroy(framer); +} + +/** + * devm_framer_create() - create a new framer + * @dev: device that is creating the new framer + * @node: device node of the framer + * @ops: function pointers for performing framer operations + * + * Creates a new framer device adding it to the framer class. + * While at that, it also associates the device with the framer using devres. + * On driver detach, release function is invoked on the devres data, + * then, devres data is freed. + */ +struct framer *devm_framer_create(struct device *dev, struct device_node *node, + const struct framer_ops *ops) +{ + struct framer **ptr, *framer; + + ptr = devres_alloc(devm_framer_destroy, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + framer = framer_create(dev, node, ops); + if (!IS_ERR(framer)) { + *ptr = framer; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return framer; +} +EXPORT_SYMBOL_GPL(devm_framer_create); + +/** + * framer_provider_simple_of_xlate() - returns the framer instance from framer provider + * @dev: the framer provider device + * @args: of_phandle_args (not used here) + * + * Intended to be used by framer provider for the common case where #framer-cells is + * 0. For other cases where #framer-cells is greater than '0', the framer provider + * should provide a custom of_xlate function that reads the *args* and returns + * the appropriate framer. + */ +struct framer *framer_provider_simple_of_xlate(struct device *dev, struct of_phandle_args *args) +{ + struct framer *framer; + struct class_dev_iter iter; + + class_dev_iter_init(&iter, framer_class, NULL, NULL); + while ((dev = class_dev_iter_next(&iter))) { + framer = dev_to_framer(dev); + if (args->np != framer->dev.of_node) + continue; + + class_dev_iter_exit(&iter); + return framer; + } + + class_dev_iter_exit(&iter); + return ERR_PTR(-ENODEV); +} +EXPORT_SYMBOL_GPL(framer_provider_simple_of_xlate); + +/** + * __framer_provider_of_register() - create/register framer provider with the framework + * @dev: struct device of the framer provider + * @owner: the module owner containing of_xlate + * @of_xlate: function pointer to obtain framer instance from framer provider + * + * Creates struct framer_provider from dev and of_xlate function pointer. + * This is used in the case of dt boot for finding the framer instance from + * framer provider. + */ +struct framer_provider * +__framer_provider_of_register(struct device *dev, struct module *owner, + struct framer *(*of_xlate)(struct device *dev, + struct of_phandle_args *args)) +{ + struct framer_provider *framer_provider; + + framer_provider = kzalloc(sizeof(*framer_provider), GFP_KERNEL); + if (!framer_provider) + return ERR_PTR(-ENOMEM); + + framer_provider->dev = dev; + framer_provider->owner = owner; + framer_provider->of_xlate = of_xlate; + + of_node_get(framer_provider->dev->of_node); + + mutex_lock(&framer_provider_mutex); + list_add_tail(&framer_provider->list, &framer_provider_list); + mutex_unlock(&framer_provider_mutex); + + return framer_provider; +} +EXPORT_SYMBOL_GPL(__framer_provider_of_register); + +/** + * framer_provider_of_unregister() - unregister framer provider from the framework + * @framer_provider: framer provider returned by framer_provider_of_register() + * + * Removes the framer_provider created using framer_provider_of_register(). + */ +void framer_provider_of_unregister(struct framer_provider *framer_provider) +{ + mutex_lock(&framer_provider_mutex); + list_del(&framer_provider->list); + of_node_put(framer_provider->dev->of_node); + kfree(framer_provider); + mutex_unlock(&framer_provider_mutex); +} +EXPORT_SYMBOL_GPL(framer_provider_of_unregister); + +static void devm_framer_provider_of_unregister(struct device *dev, void *res) +{ + struct framer_provider *framer_provider = *(struct framer_provider **)res; + + framer_provider_of_unregister(framer_provider); +} + +/** + * __devm_framer_provider_of_register() - create/register framer provider with + * the framework + * @dev: struct device of the framer provider + * @owner: the module owner containing of_xlate + * @of_xlate: function pointer to obtain framer instance from framer provider + * + * Creates struct framer_provider from dev and of_xlate function pointer. + * This is used in the case of dt boot for finding the framer instance from + * framer provider. While at that, it also associates the device with the + * framer provider using devres. On driver detach, release function is invoked + * on the devres data, then, devres data is freed. + */ +struct framer_provider * +__devm_framer_provider_of_register(struct device *dev, struct module *owner, + struct framer *(*of_xlate)(struct device *dev, + struct of_phandle_args *args)) +{ + struct framer_provider **ptr, *framer_provider; + + ptr = devres_alloc(devm_framer_provider_of_unregister, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + framer_provider = __framer_provider_of_register(dev, owner, of_xlate); + if (!IS_ERR(framer_provider)) { + *ptr = framer_provider; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return framer_provider; +} +EXPORT_SYMBOL_GPL(__devm_framer_provider_of_register); + +/** + * framer_release() - release the framer + * @dev: the dev member within framer + * + * When the last reference to the device is removed, it is called + * from the embedded kobject as release method. + */ +static void framer_release(struct device *dev) +{ + struct framer *framer; + + framer = dev_to_framer(dev); + regulator_put(framer->pwr); + ida_simple_remove(&framer_ida, framer->id); + kfree(framer); +} + +static int __init framer_core_init(void) +{ + framer_class = class_create("framer"); + if (IS_ERR(framer_class)) { + pr_err("failed to create framer class (%pe)\n", framer_class); + return PTR_ERR(framer_class); + } + + framer_class->dev_release = framer_release; + + return 0; +} +device_initcall(framer_core_init); diff --git a/include/linux/framer/framer-provider.h b/include/linux/framer/framer-provider.h new file mode 100644 index 000000000000..941a343c3ba7 --- /dev/null +++ b/include/linux/framer/framer-provider.h @@ -0,0 +1,194 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Generic framer profider header file + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ + +#ifndef __DRIVERS_PROVIDER_FRAMER_H +#define __DRIVERS_PROVIDER_FRAMER_H + +#include +#include +#include + +#define FRAMER_FLAG_POLL_STATUS BIT(0) + +/** + * struct framer_ops - set of function pointers for performing framer operations + * @init: operation to be performed for initializing the framer + * @exit: operation to be performed while exiting + * @power_on: powering on the framer + * @power_off: powering off the framer + * @flags: OR-ed flags (FRAMER_FLAG_*) to ask for core functionality + * - @FRAMER_FLAG_POLL_STATUS: + * Ask the core to perfom a polling to get the framer status and + * notify consumers on change. + * The framer should call @framer_notify_status_change() when it + * detects a status change. This is usally done using interrutps. + * If the framer cannot detect this change, it can ask the core for + * a status polling. The core will call @get_status() periodically + * and, on change detected, it will notify the consumer. + * the @get_status() + * @owner: the module owner containing the ops + */ +struct framer_ops { + int (*init)(struct framer *framer); + void (*exit)(struct framer *framer); + int (*power_on)(struct framer *framer); + int (*power_off)(struct framer *framer); + + /** + * @get_status: + * + * Optional. + * + * Used to get the framer status. framer_init() must have + * been called on the framer. + * + * Returns: 0 if successful, an negative error code otherwise + */ + int (*get_status)(struct framer *framer, struct framer_status *status); + + /** + * @set_config: + * + * Optional. + * + * Used to set the framer configuration. framer_init() must have + * been called on the framer. + * + * Returns: 0 if successful, an negative error code otherwise + */ + int (*set_config)(struct framer *framer, const struct framer_config *config); + + /** + * @get_config: + * + * Optional. + * + * Used to get the framer configuration. framer_init() must have + * been called on the framer. + * + * Returns: 0 if successful, an negative error code otherwise + */ + int (*get_config)(struct framer *framer, struct framer_config *config); + + u32 flags; + struct module *owner; +}; + +/** + * struct framer_provider - represents the framer provider + * @dev: framer provider device + * @children: can be used to override the default (dev->of_node) child node + * @owner: the module owner having of_xlate + * @list: to maintain a linked list of framer providers + * @of_xlate: function pointer to obtain framer instance from framer pointer + */ +struct framer_provider { + struct device *dev; + struct module *owner; + struct list_head list; + struct framer * (*of_xlate)(struct device *dev, + struct of_phandle_args *args); +}; + +static inline void framer_set_drvdata(struct framer *framer, void *data) +{ + dev_set_drvdata(&framer->dev, data); +} + +static inline void *framer_get_drvdata(struct framer *framer) +{ + return dev_get_drvdata(&framer->dev); +} + +#if IS_ENABLED(CONFIG_GENERIC_FRAMER) + +/* Create and destroy a framer */ +struct framer *framer_create(struct device *dev, struct device_node *node, + const struct framer_ops *ops); +void framer_destroy(struct framer *framer); + +/* devm version */ +struct framer *devm_framer_create(struct device *dev, struct device_node *node, + const struct framer_ops *ops); + +struct framer *framer_provider_simple_of_xlate(struct device *dev, + struct of_phandle_args *args); + +struct framer_provider * +__framer_provider_of_register(struct device *dev, struct module *owner, + struct framer *(*of_xlate)(struct device *dev, + struct of_phandle_args *args)); + +void framer_provider_of_unregister(struct framer_provider *framer_provider); + +struct framer_provider * +__devm_framer_provider_of_register(struct device *dev, struct module *owner, + struct framer *(*of_xlate)(struct device *dev, + struct of_phandle_args *args)); + +void framer_notify_status_change(struct framer *framer); + +#else /* IS_ENABLED(CONFIG_GENERIC_FRAMER) */ + +static inline struct framer *framer_create(struct device *dev, struct device_node *node, + const struct framer_ops *ops) +{ + return ERR_PTR(-ENOSYS); +} + +static inline void framer_destroy(struct framer *framer) +{ +} + +/* devm version */ +static inline struct framer *devm_framer_create(struct device *dev, struct device_node *node, + const struct framer_ops *ops) +{ + return ERR_PTR(-ENOSYS); +} + +static inline struct framer *framer_provider_simple_of_xlate(struct device *dev, + struct of_phandle_args *args) +{ + return ERR_PTR(-ENOSYS); +} + +static inline struct framer_provider * +__framer_provider_of_register(struct device *dev, struct module *owner, + struct framer *(*of_xlate)(struct device *dev, + struct of_phandle_args *args)) +{ + return ERR_PTR(-ENOSYS); +} + +void framer_provider_of_unregister(struct framer_provider *framer_provider) +{ +} + +static inline struct framer_provider * +__devm_framer_provider_of_register(struct device *dev, struct module *owner, + struct framer *(*of_xlate)(struct device *dev, + struct of_phandle_args *args)) +{ + return ERR_PTR(-ENOSYS); +} + +void framer_notify_status_change(struct framer *framer) +{ +} + +#endif /* IS_ENABLED(CONFIG_GENERIC_FRAMER) */ + +#define framer_provider_of_register(dev, xlate) \ + __framer_provider_of_register((dev), THIS_MODULE, (xlate)) + +#define devm_framer_provider_of_register(dev, xlate) \ + __devm_framer_provider_of_register((dev), THIS_MODULE, (xlate)) + +#endif /* __DRIVERS_PROVIDER_FRAMER_H */ diff --git a/include/linux/framer/framer.h b/include/linux/framer/framer.h new file mode 100644 index 000000000000..0bee7135142f --- /dev/null +++ b/include/linux/framer/framer.h @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Generic framer header file + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ + +#ifndef __DRIVERS_FRAMER_H +#define __DRIVERS_FRAMER_H + +#include +#include +#include +#include +#include +#include + +/** + * enum framer_iface - Framer interface + */ +enum framer_iface { + FRAMER_IFACE_E1, /* E1 interface */ + FRAMER_IFACE_T1, /* T1 interface */ +}; + +/** + * enum framer_clock_mode - Framer clock mode + */ +enum framer_clock_type { + FRAMER_CLOCK_EXT, /* External clock */ + FRAMER_CLOCK_INT, /* Internal clock */ +}; + +/** + * struct framer_configuration - Framer configuration + * @line_iface: Framer line interface + * @clock_mode: Framer clock type + * @clock_rate: Framer clock rate + */ +struct framer_config { + enum framer_iface iface; + enum framer_clock_type clock_type; + unsigned long line_clock_rate; +}; + +/** + * struct framer_status - Framer status + * @link_is_on: Framer link state. true, the link is on, false, the link is off. + */ +struct framer_status { + bool link_is_on; +}; + +/** + * framer_event - event available for notification + */ +enum framer_event { + FRAMER_EVENT_STATUS, /* Event notified on framer_status changes */ +}; + +/** + * struct framer - represents the framer device + * @dev: framer device + * @id: id of the framer device + * @ops: function pointers for performing framer operations + * @mutex: mutex to protect framer_ops + * @init_count: used to protect when the framer is used by multiple consumers + * @power_count: used to protect when the framer is used by multiple consumers + * @pwr: power regulator associated with the framer + * @polling_task: polling task used if framer notifier operations are not provided + * @polling_notifier_list: notifier list used by the polling task + * @prev_status: previous read status used by the polling task to detect changes + */ +struct framer { + struct device dev; + int id; + const struct framer_ops *ops; + struct mutex mutex; /* Protect framer */ + int init_count; + int power_count; + struct regulator *pwr; + struct work_struct notify_status_work; + struct blocking_notifier_head notifier_list; + struct delayed_work polling_work; + struct framer_status prev_status; +}; + +#if IS_ENABLED(CONFIG_GENERIC_FRAMER) +int framer_pm_runtime_get(struct framer *framer); +int framer_pm_runtime_get_sync(struct framer *framer); +int framer_pm_runtime_put(struct framer *framer); +int framer_pm_runtime_put_sync(struct framer *framer); +int framer_init(struct framer *framer); +int framer_exit(struct framer *framer); +int framer_power_on(struct framer *framer); +int framer_power_off(struct framer *framer); +int framer_get_status(struct framer *framer, struct framer_status *status); +int framer_get_config(struct framer *framer, struct framer_config *config); +int framer_set_config(struct framer *framer, const struct framer_config *config); +int framer_notifier_register(struct framer *framer, struct notifier_block *nb); +int framer_notifier_unregister(struct framer *framer, struct notifier_block *nb); + +struct framer *framer_get(struct device *dev, const char *con_id); +void framer_put(struct device *dev, struct framer *framer); + +struct framer *devm_framer_get(struct device *dev, const char *con_id); +struct framer *devm_framer_optional_get(struct device *dev, const char *con_id); +#else +static inline int framer_pm_runtime_get(struct framer *framer) +{ + return -ENOSYS; +} + +static inline int framer_pm_runtime_get_sync(struct framer *framer) +{ + return -ENOSYS; +} + +static inline int framer_pm_runtime_put(struct framer *framer) +{ + return -ENOSYS; +} + +static inline int framer_pm_runtime_put_sync(struct framer *framer) +{ + return -ENOSYS; +} + +static inline int framer_init(struct framer *framer) +{ + return -ENOSYS; +} + +static inline int framer_exit(struct framer *framer) +{ + return -ENOSYS; +} + +static inline int framer_power_on(struct framer *framer) +{ + return -ENOSYS; +} + +static inline int framer_power_off(struct framer *framer) +{ + return -ENOSYS; +} + +static inline int framer_get_status(struct framer *framer, struct framer_status *status) +{ + return -ENOSYS; +} + +static inline int framer_get_config(struct framer *framer, struct framer_config *config) +{ + return -ENOSYS; +} + +static inline int framer_set_config(struct framer *framer, const struct framer_config *config) +{ + return -ENOSYS; +} + +static inline int framer_notifier_register(struct framer *framer, + struct notifier_block *nb) +{ + return -ENOSYS; +} + +static inline int framer_notifier_unregister(struct framer *framer, + struct notifier_block *nb) +{ + return -ENOSYS; +} + +struct framer *framer_get(struct device *dev, const char *con_id) +{ + return ERR_PTR(-ENOSYS); +} + +void framer_put(struct device *dev, struct framer *framer) +{ +} + +static inline struct framer *devm_framer_get(struct device *dev, const char *con_id) +{ + return ERR_PTR(-ENOSYS); +} + +static inline struct framer *devm_framer_optional_get(struct device *dev, const char *con_id) +{ + return NULL; +} + +#endif + +#endif /* __DRIVERS_FRAMER_H */ From patchwork Fri Aug 18 16:39:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358132 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 B9BF8648 for ; Fri, 18 Aug 2023 17:20:32 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3D8D8421C; Fri, 18 Aug 2023 10:20:31 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS70715djz9vh8; Fri, 18 Aug 2023 18:40:23 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id vw7WEx3gluED; Fri, 18 Aug 2023 18:40:23 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zp6QMwz9vhn; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id D3FF08B763; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id aJ8Foudrmvpf; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id D48408B770; Fri, 18 Aug 2023 18:40:04 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGdxk6142031 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:39:59 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGdxHi142030; Fri, 18 Aug 2023 18:39:59 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 22/28] dt-bindings: net: Add the Lantiq PEF2256 E1/T1/J1 framer Date: Fri, 18 Aug 2023 18:39:16 +0200 Message-ID: <7c67d590b13a889466f53edf94192bca3bf6ceec.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376735; l=7698; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=YqyJgFwDkMtyydaXfdndsE6FWbduJz/zUoz/auJeyZM=; b=i0rJpTDTgxxCIgPg+BaVGddlx9j+XvU+EZDrNOTLWg5NAi+RfnesvI1l9GQcdoI5pJ9+5bcfd FYQ02wEOvBuBiXp4+hD7nHtbVFjApSWeyajERVHe+GN2ZvuHo/FAkBZ X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Herve Codina The Lantiq PEF2256 is a framer and line interface component designed to fulfill all required interfacing between an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus. Signed-off-by: Herve Codina Signed-off-by: Christophe Leroy --- .../bindings/net/lantiq,pef2256.yaml | 219 ++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/lantiq,pef2256.yaml diff --git a/Documentation/devicetree/bindings/net/lantiq,pef2256.yaml b/Documentation/devicetree/bindings/net/lantiq,pef2256.yaml new file mode 100644 index 000000000000..72f6777afa3a --- /dev/null +++ b/Documentation/devicetree/bindings/net/lantiq,pef2256.yaml @@ -0,0 +1,219 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/lantiq,pef2256.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Lantiq PEF2256 + +maintainers: + - Herve Codina + +description: + The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and + line interface component designed to fulfill all required interfacing between + an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus. + +properties: + compatible: + items: + - const: lantiq,pef2256 + + reg: + maxItems: 1 + + clocks: + items: + - description: Master clock + - description: System Clock Receive + - description: System Clock Transmit + + clock-names: + items: + - const: mclk + - const: sclkr + - const: sclkx + + interrupts: + maxItems: 1 + + reset-gpios: + description: + GPIO used to reset the device. + maxItems: 1 + + '#framer-cells': + const: 0 + + pinctrl: + $ref: /schemas/pinctrl/pinctrl.yaml# + additionalProperties: false + + patternProperties: + '-pins$': + type: object + $ref: /schemas/pinctrl/pincfg-node.yaml# + additionalProperties: false + + properties: + pins: + enum: [ RPA, RPB, RPC, RPD, XPA, XPB, XPC, XPD ] + + function: + enum: [ SYPR, RFM, RFMB, RSIGM, RSIG, DLR, FREEZE, RFSP, LOS, + SYPX, XFMS, XSIG, TCLK, XMFB, XSIGM, DLX, XCLK, XLT, + GPI, GPOH, GPOL ] + + required: + - pins + - function + + lantiq,data-rate-bps: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [2048000, 4096000, 8192000, 16384000] + default: 2048000 + description: + Data rate (bit per seconds) on the system highway. + + lantiq,clock-falling-edge: + $ref: /schemas/types.yaml#/definitions/flag + description: + Data is sent on falling edge of the clock (and received on the rising + edge). If 'clock-falling-edge' is not present, data is sent on the + rising edge (and received on the falling edge). + + lantiq,channel-phase: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3, 4, 5, 6, 7] + default: 0 + description: + The pef2256 delivers a full frame (32 8bit time-slots in E1 and 24 8bit + time-slots 8 8bit signaling in E1/J1) every 125us. This lead to a data + rate of 2048000 bit/s. When lantiq,data-rate-bps is more than 2048000 + bit/s, the data (all 32 8bit) present in the frame are interleave with + unused time-slots. The lantiq,channel-phase property allows to set the + correct alignment of the interleave mechanism. + For instance, suppose lantiq,data-rate-bps = 8192000 (ie 4*2048000), and + lantiq,channel-phase = 2, the interleave schema with unused time-slots + (nu) and used time-slots (XX) for TSi is + nu nu XX nu nu nu XX nu nu nu XX nu + <-- TSi --> <- TSi+1 -> <- TSi+2 -> + With lantiq,data-rate-bps = 8192000, and lantiq,channel-phase = 1, the + interleave schema is + nu XX nu nu nu XX nu nu nu XX nu nu + <-- TSi --> <- TSi+1 -> <- TSi+2 -> + With lantiq,data-rate-bps = 4096000 (ie 2*2048000), and + lantiq,channel-phase = 1, the interleave schema is + nu XX nu XX nu XX + <-- TSi --> <- TSi+1 -> <- TSi+2 -> + +patternProperties: + '^codec(-([0-9]|[1-2][0-9]|3[0-1]))?$': + type: object + $ref: /schemas/sound/dai-common.yaml + unevaluatedProperties: false + description: + Codec provided by the pef2256. This codec allows to use some of the PCM + system highway time-slots as audio channels to transport audio data over + the E1/T1/J1 lines. + The time-slots used by the codec must be set and so, the properties + 'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and + 'dai-tdm-slot-rx-mask' must be present in the sound card node for + sub-nodes that involve the codec. The codec uses 8bit time-slots. + 'dai-tdm-tdm-slot-with' must be set to 8. + The tx and rx masks define the pef2256 time-slots assigned to the codec. + + properties: + compatible: + const: lantiq,pef2256-codec + + '#sound-dai-cells': + const: 0 + + required: + - compatible + - '#sound-dai-cells' + +required: + - compatible + - reg + - clocks + - clock-names + - interrupts + - '#framer-cells' + +additionalProperties: false + +examples: + - | + #include + #include + + pef2256: framer@2000000 { + compatible = "lantiq,pef2256"; + reg = <0x2000000 0x100>; + interrupts = <8 IRQ_TYPE_LEVEL_LOW>; + interrupt-parent = <&intc>; + clocks = <&clk_mclk>, <&clk_sclkr>, <&clk_sclkx>; + clock-names = "mclk", "sclkr", "sclkx"; + reset-gpios = <&gpio 11 GPIO_ACTIVE_LOW>; + lantiq,data-rate-bps = <4096000>; + #framer-cells = <0>; + + pinctrl { + pef2256_rpa_sypr: rpa-pins { + pins = "RPA"; + function = "SYPR"; + }; + pef2256_xpa_sypx: xpa-pins { + pins = "XPA"; + function = "SYPX"; + }; + }; + + pef2256_codec0: codec-0 { + compatible = "lantiq,pef2256-codec"; + #sound-dai-cells = <0>; + sound-name-prefix = "PEF2256_0"; + }; + + pef2256_codec1: codec-1 { + compatible = "lantiq,pef2256-codec"; + #sound-dai-cells = <0>; + sound-name-prefix = "PEF2256_1"; + }; + }; + + sound { + compatible = "simple-audio-card"; + #address-cells = <1>; + #size-cells = <0>; + simple-audio-card,dai-link@0 { /* CPU DAI1 - pef2256 codec 1 */ + reg = <0>; + cpu { + sound-dai = <&cpu_dai1>; + }; + codec { + sound-dai = <&pef2256_codec0>; + dai-tdm-slot-num = <4>; + dai-tdm-slot-width = <8>; + /* TS 1, 2, 3, 4 */ + dai-tdm-slot-tx-mask = <0 1 1 1 1>; + dai-tdm-slot-rx-mask = <0 1 1 1 1>; + }; + }; + simple-audio-card,dai-link@1 { /* CPU DAI2 - pef2256 codec 2 */ + reg = <1>; + cpu { + sound-dai = <&cpu_dai2>; + }; + codec { + sound-dai = <&pef2256_codec1>; + dai-tdm-slot-num = <4>; + dai-tdm-slot-width = <8>; + /* TS 5, 6, 7, 8 */ + dai-tdm-slot-tx-mask = <0 0 0 0 0 1 1 1 1>; + dai-tdm-slot-rx-mask = <0 0 0 0 0 1 1 1 1>; + }; + }; + }; From patchwork Fri Aug 18 16:39:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358130 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 E0BCE612C for ; Fri, 18 Aug 2023 17:20:25 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2D2173C2F; Fri, 18 Aug 2023 10:20:21 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS7060ztwz9vjf; Fri, 18 Aug 2023 18:40:22 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Ppn1n9uuWSiV; Fri, 18 Aug 2023 18:40:22 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zp2ryfz9vhl; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 581038B778; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id NVmsYWnylAQZ; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id DA81D8B775; Fri, 18 Aug 2023 18:40:04 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGe0qF142035 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:40:00 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGe0xK142034; Fri, 18 Aug 2023 18:40:00 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 23/28] mfd: core: Ensure disabled devices are skiped without aborting Date: Fri, 18 Aug 2023 18:39:17 +0200 Message-ID: <528425d6472176bb1d02d79596b51f8c28a551cc.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376735; l=2101; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=hAkFOA9R8r8JmUyKnLgaEreJkNGYzPTwTAaZA8K8KA4=; b=YeZOkU1flwAP6HFasxcc+kTmXgQb5aqLnFHmBhQGqdqq+bhR8cxXtiH2m0yGrTbC5qzh5/Ok6 SXKqp7mwxKtD2wGLbjITvC+WW+jVpAlvefMfI7R+cLvZ1Yv0L2m6/wO X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina The loop searching for a matching device based on its compatible string is aborted when a matching disabled device is found. This abort prevents to add devices as soon as one disabled device is found. Continue searching for an other device instead of aborting on the first disabled one fixes the issue. Fixes: 22380b65dc70 ("mfd: mfd-core: Ensure disabled devices are ignored without error") Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/mfd/mfd-core.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 0ed7c0d7784e..2b85509a90fc 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -146,6 +146,7 @@ static int mfd_add_device(struct device *parent, int id, struct platform_device *pdev; struct device_node *np = NULL; struct mfd_of_node_entry *of_entry, *tmp; + bool disabled = false; int ret = -ENOMEM; int platform_id; int r; @@ -183,11 +184,10 @@ static int mfd_add_device(struct device *parent, int id, if (IS_ENABLED(CONFIG_OF) && parent->of_node && cell->of_compatible) { for_each_child_of_node(parent->of_node, np) { if (of_device_is_compatible(np, cell->of_compatible)) { - /* Ignore 'disabled' devices error free */ + /* Skip 'disabled' devices */ if (!of_device_is_available(np)) { - of_node_put(np); - ret = 0; - goto fail_alias; + disabled = true; + continue; } ret = mfd_match_of_node_to_dev(pdev, np, cell); @@ -197,10 +197,17 @@ static int mfd_add_device(struct device *parent, int id, if (ret) goto fail_alias; - break; + goto match; } } + if (disabled) { + /* Ignore 'disabled' devices error free */ + ret = 0; + goto fail_alias; + } + +match: if (!pdev->dev.of_node) pr_warn("%s: Failed to locate of_node [id: %d]\n", cell->name, platform_id); From patchwork Fri Aug 18 16:39:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358136 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 9215218C24 for ; Fri, 18 Aug 2023 17:20:49 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 481724217; Fri, 18 Aug 2023 10:20:44 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS70B1LHpz9vjs; Fri, 18 Aug 2023 18:40:26 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id bWXxe8wsY9rt; Fri, 18 Aug 2023 18:40:26 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zq1BWNz9vhs; Fri, 18 Aug 2023 18:40:07 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 18ECF8B76C; Fri, 18 Aug 2023 18:40:07 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id uNNsLfzZ8BuV; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id CD5D38B76D; Fri, 18 Aug 2023 18:40:04 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGe0HT142039 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:40:00 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGe02H142038; Fri, 18 Aug 2023 18:40:00 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 24/28] net: wan: framer: Add support for the Lantiq PEF2256 framer Date: Fri, 18 Aug 2023 18:39:18 +0200 Message-ID: <9aa13d3e45f8ccc3b60e4a906346b3485f431890.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376736; l=40300; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=m9/ogsUy2VSsplg8Lq4rCkecGmyItX69wP77DWz0ehc=; b=McAh5Km3iY51d4XRRS2sgeLBb38Zr6EhrnTzEQNZJjQ5gcmpKKlSIMM6JlSMIR0BVJsshu/C+ pMGUCp0InimBA0zP0SE/ElwJvY2VipIpZbZRRBw0RGbcpac/HvysbNe X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Herve Codina The Lantiq PEF2256 is a framer and line interface component designed to fulfill all required interfacing between an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/net/wan/framer/Kconfig | 16 + drivers/net/wan/framer/Makefile | 1 + drivers/net/wan/framer/pef2256/Makefile | 8 + drivers/net/wan/framer/pef2256/pef2256-regs.h | 250 +++++ drivers/net/wan/framer/pef2256/pef2256.c | 880 ++++++++++++++++++ include/linux/framer/pef2256.h | 31 + 6 files changed, 1186 insertions(+) create mode 100644 drivers/net/wan/framer/pef2256/Makefile create mode 100644 drivers/net/wan/framer/pef2256/pef2256-regs.h create mode 100644 drivers/net/wan/framer/pef2256/pef2256.c create mode 100644 include/linux/framer/pef2256.h diff --git a/drivers/net/wan/framer/Kconfig b/drivers/net/wan/framer/Kconfig index 96ef1e7ba8eb..ba43d7f162a2 100644 --- a/drivers/net/wan/framer/Kconfig +++ b/drivers/net/wan/framer/Kconfig @@ -16,4 +16,20 @@ config GENERIC_FRAMER framework and framer users can obtain reference to the framer. All the users of this framework should select this config. +config FRAMER_PEF2256 + tristate "Lantiq PEF2256" + depends on OF + select GENERIC_FRAMER + select MFD_CORE + select REGMAP_MMIO + help + Enable support for the Lantiq PEF2256 (FALC56) framer. + The PEF2256 is a framer and line interface between analog E1/T1/J1 + line and a digital PCM bus. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called framer-pef2256. + endmenu diff --git a/drivers/net/wan/framer/Makefile b/drivers/net/wan/framer/Makefile index 78dbd8e563d0..3403f2b14534 100644 --- a/drivers/net/wan/framer/Makefile +++ b/drivers/net/wan/framer/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_GENERIC_FRAMER) += framer-core.o +obj-$(CONFIG_FRAMER_PEF2256) += pef2256/ diff --git a/drivers/net/wan/framer/pef2256/Makefile b/drivers/net/wan/framer/pef2256/Makefile new file mode 100644 index 000000000000..f4d1208dd8a4 --- /dev/null +++ b/drivers/net/wan/framer/pef2256/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the pef2256 driver. +# + +obj-$(CONFIG_FRAMER_PEF2256) += framer-pef2256.o + +framer-pef2256-objs := pef2256.o diff --git a/drivers/net/wan/framer/pef2256/pef2256-regs.h b/drivers/net/wan/framer/pef2256/pef2256-regs.h new file mode 100644 index 000000000000..5d3183c91714 --- /dev/null +++ b/drivers/net/wan/framer/pef2256/pef2256-regs.h @@ -0,0 +1,250 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * PEF2256 registers definition + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ +#ifndef __PEF2256_REGS_H__ +#define __PEF2256_REGS_H__ + +#include "linux/bitfield.h" + +/* Command Register */ +#define PEF2256_CMDR 0x02 +#define PEF2256_CMDR_RRES BIT(6) +#define PEF2256_CMDR_XRES BIT(4) +#define PEF2256_CMDR_SRES BIT(0) + +/* Interrupt Mask Register 0..5 */ +#define PEF2256_IMR0 0x14 +#define PEF2256_IMR1 0x15 +#define PEF2256_IMR2 0x16 +#define PEF2256_IMR3 0x17 +#define PEF2256_IMR4 0x18 +#define PEF2256_IMR5 0x19 + +/* Framer Mode Register 0 */ +#define PEF2256_FMR0 0x1C +#define PEF2256_FMR0_XC_MASK GENMASK(7, 6) +#define PEF2256_FMR0_XC_NRZ FIELD_PREP_CONST(PEF2256_FMR0_XC_MASK, 0x0) +#define PEF2256_FMR0_XC_CMI FIELD_PREP_CONST(PEF2256_FMR0_XC_MASK, 0x1) +#define PEF2256_FMR0_XC_AMI FIELD_PREP_CONST(PEF2256_FMR0_XC_MASK, 0x2) +#define PEF2256_FMR0_XC_HDB3 FIELD_PREP_CONST(PEF2256_FMR0_XC_MASK, 0x3) +#define PEF2256_FMR0_RC_MASK GENMASK(5, 4) +#define PEF2256_FMR0_RC_NRZ FIELD_PREP_CONST(PEF2256_FMR0_RC_MASK, 0x0) +#define PEF2256_FMR0_RC_CMI FIELD_PREP_CONST(PEF2256_FMR0_RC_MASK, 0x1) +#define PEF2256_FMR0_RC_AMI FIELD_PREP_CONST(PEF2256_FMR0_RC_MASK, 0x2) +#define PEF2256_FMR0_RC_HDB3 FIELD_PREP_CONST(PEF2256_FMR0_RC_MASK, 0x3) + +/* Framer Mode Register 1 */ +#define PEF2256_FMR1 0x1D +#define PEF2256_FMR1_XFS BIT(3) +#define PEF2256_FMR1_ECM BIT(2) +/* SSD is defined on 2 bits. The other bit is on SIC1 register */ +#define PEF2256_FMR1_SSD_MASK GENMASK(1, 1) +#define PEF2256_FMR1_SSD_2048 FIELD_PREP_CONST(PEF2256_FMR1_SSD_MASK, 0x0) +#define PEF2256_FMR1_SSD_4096 FIELD_PREP_CONST(PEF2256_FMR1_SSD_MASK, 0x1) +#define PEF2256_FMR1_SSD_8192 FIELD_PREP_CONST(PEF2256_FMR1_SSD_MASK, 0x0) +#define PEF2256_FMR1_SSD_16384 FIELD_PREP_CONST(PEF2256_FMR1_SSD_MASK, 0x1) + +/* Framer Mode Register 2 */ +#define PEF2256_FMR2 0x1E +#define PEF2256_FMR2_RFS_MASK GENMASK(7, 6) +#define PEF2256_FMR2_RFS_DOUBLEFRAME FIELD_PREP_CONST(PEF2256_FMR2_RFS_MASK, 0x0) +#define PEF2256_FMR2_RFS_CRC4_MULTIFRAME FIELD_PREP_CONST(PEF2256_FMR2_RFS_MASK, 0x2) +#define PEF2256_FMR2_RFS_AUTO_MULTIFRAME FIELD_PREP_CONST(PEF2256_FMR2_RFS_MASK, 0x3) +#define PEF2256_FMR2_AXRA BIT(1) + +/* Transmit Service Word */ +#define PEF2256_XSW 0x20 +#define PEF2256_XSW_XSIS BIT(7) +#define PEF2256_XSW_XTM BIT(6) +#define PEF2256_XSW_XY_MASK GENMASK(5, 0) +#define PEF2256_XSW_XY(_v) FIELD_PREP(PEF2256_XSW_XY_MASK, _v) + +/* Transmit Spare Bits */ +#define PEF2256_XSP 0x21 +#define PEF2256_XSP_XSIF BIT(2) + +/* Transmit Control 0..1 */ +#define PEF2256_XC0 0x22 +#define PEF2256_XC1 0x23 + +/* Receive Control 0 */ +#define PEF2256_RC0 0x24 +#define PEF2256_RC0_SWD BIT(7) +#define PEF2256_RC0_ASY4 BIT(6) + +/* Receive Control 1 */ +#define PEF2256_RC1 0x25 + +/* Transmit Pulse Mask 0..1 */ +#define PEF2256_XPM0 0x26 +#define PEF2256_XPM1 0x27 + +/* Transmit Pulse Mask 2 */ +#define PEF2256_XPM2 0x28 +#define PEF2256_XPM2_XLT BIT(6) + +/* Transparent Service Word Mask */ +#define PEF2256_TSWM 0x29 + +/* Line Interface Mode 0 */ +#define PEF2256_LIM0 0x36 +#define PEF2256_2X_LIM0_BIT3 BIT(3) /* v2.x, described as a forced '1' bit */ +#define PEF2256_LIM0_MAS BIT(0) + +/* Line Interface Mode 1 */ +#define PEF2256_LIM1 0x37 +#define PEF2256_12_LIM1_RIL_MASK GENMASK(6, 4) +#define PEF2256_12_LIM1_RIL_910 FIELD_PREP_CONST(PEF2256_12_LIM1_RIL_MASK, 0x0) +#define PEF2256_12_LIM1_RIL_740 FIELD_PREP_CONST(PEF2256_12_LIM1_RIL_MASK, 0x1) +#define PEF2256_12_LIM1_RIL_590 FIELD_PREP_CONST(PEF2256_12_LIM1_RIL_MASK, 0x2) +#define PEF2256_12_LIM1_RIL_420 FIELD_PREP_CONST(PEF2256_12_LIM1_RIL_MASK, 0x3) +#define PEF2256_12_LIM1_RIL_320 FIELD_PREP_CONST(PEF2256_12_LIM1_RIL_MASK, 0x4) +#define PEF2256_12_LIM1_RIL_210 FIELD_PREP_CONST(PEF2256_12_LIM1_RIL_MASK, 0x5) +#define PEF2256_12_LIM1_RIL_160 FIELD_PREP_CONST(PEF2256_12_LIM1_RIL_MASK, 0x6) +#define PEF2256_12_LIM1_RIL_100 FIELD_PREP_CONST(PEF2256_12_LIM1_RIL_MASK, 0x7) +#define PEF2256_2X_LIM1_RIL_MASK GENMASK(6, 4) +#define PEF2256_2X_LIM1_RIL_2250 FIELD_PREP_CONST(PEF2256_2X_LIM1_RIL_MASK, 0x0) +#define PEF2256_2X_LIM1_RIL_1100 FIELD_PREP_CONST(PEF2256_2X_LIM1_RIL_MASK, 0x1) +#define PEF2256_2X_LIM1_RIL_600 FIELD_PREP_CONST(PEF2256_2X_LIM1_RIL_MASK, 0x2) +#define PEF2256_2X_LIM1_RIL_350 FIELD_PREP_CONST(PEF2256_2X_LIM1_RIL_MASK, 0x3) +#define PEF2256_2X_LIM1_RIL_210 FIELD_PREP_CONST(PEF2256_2X_LIM1_RIL_MASK, 0x4) +#define PEF2256_2X_LIM1_RIL_140 FIELD_PREP_CONST(PEF2256_2X_LIM1_RIL_MASK, 0x5) +#define PEF2256_2X_LIM1_RIL_100 FIELD_PREP_CONST(PEF2256_2X_LIM1_RIL_MASK, 0x6) +#define PEF2256_2X_LIM1_RIL_50 FIELD_PREP_CONST(PEF2256_2X_LIM1_RIL_MASK, 0x7) + +/* Pulse Count Detection */ +#define PEF2256_PCD 0x38 + + /* Pulse Count Recovery */ +#define PEF2256_PCR 0x39 + + /* Line Interface Mode 2 */ +#define PEF2256_LIM2 0x3A +#define PEF2256_LIM2_SLT_MASK GENMASK(5, 4) +#define PEF2256_LIM2_SLT_THR55 FIELD_PREP_CONST(PEF2256_LIM2_SLT_MASK, 0x0) +#define PEF2256_LIM2_SLT_THR67 FIELD_PREP_CONST(PEF2256_LIM2_SLT_MASK, 0x1) +#define PEF2256_LIM2_SLT_THR50 FIELD_PREP_CONST(PEF2256_LIM2_SLT_MASK, 0x2) +#define PEF2256_LIM2_SLT_THR45 FIELD_PREP_CONST(PEF2256_LIM2_SLT_MASK, 0x3) +#define PEF2256_LIM2_ELT BIT(2) + +/* System Interface Control 1 */ +#define PEF2256_SIC1 0x3E +#define PEF2256_SIC1_SSC_MASK (BIT(7) | BIT(3)) +#define PEF2256_SIC1_SSC_2048 (0) +#define PEF2256_SIC1_SSC_4096 BIT(3) +#define PEF2256_SIC1_SSC_8192 BIT(7) +#define PEF2256_SIC1_SSC_16384 (BIT(7) | BIT(3)) +/* SSD is defined on 2 bits. The other bit is on FMR1 register */ +#define PEF2256_SIC1_SSD_MASK GENMASK(6, 6) +#define PEF2256_SIC1_SSD_2048 FIELD_PREP_CONST(PEF2256_SIC1_SSD_MASK, 0x0) +#define PEF2256_SIC1_SSD_4096 FIELD_PREP_CONST(PEF2256_SIC1_SSD_MASK, 0x0) +#define PEF2256_SIC1_SSD_8192 FIELD_PREP_CONST(PEF2256_SIC1_SSD_MASK, 0x1) +#define PEF2256_SIC1_SSD_16384 FIELD_PREP_CONST(PEF2256_SIC1_SSD_MASK, 0x1) +#define PEF2256_SIC1_RBS_MASK GENMASK(5, 4) +#define PEF2256_SIC1_RBS_2FRAMES FIELD_PREP_CONST(PEF2256_SIC1_RBS_MASK, 0x0) +#define PEF2256_SIC1_RBS_1FRAME FIELD_PREP_CONST(PEF2256_SIC1_RBS_MASK, 0x1) +#define PEF2256_SIC1_RBS_96BITS FIELD_PREP_CONST(PEF2256_SIC1_RBS_MASK, 0x2) +#define PEF2256_SIC1_RBS_BYPASS FIELD_PREP_CONST(PEF2256_SIC1_RBS_MASK, 0x3) +#define PEF2256_SIC1_XBS_MASK GENMASK(1, 0) +#define PEF2256_SIC1_XBS_BYPASS FIELD_PREP_CONST(PEF2256_SIC1_XBS_MASK, 0x0) +#define PEF2256_SIC1_XBS_1FRAME FIELD_PREP_CONST(PEF2256_SIC1_XBS_MASK, 0x1) +#define PEF2256_SIC1_XBS_2FRAMES FIELD_PREP_CONST(PEF2256_SIC1_XBS_MASK, 0x2) +#define PEF2256_SIC1_XBS_96BITS FIELD_PREP_CONST(PEF2256_SIC1_XBS_MASK, 0x3) + +/* System Interface Control 2 */ +#define PEF2256_SIC2 0x3F +#define PEF2256_SIC2_SICS_MASK GENMASK(3, 1) +#define PEF2256_SIC2_SICS(_v) FIELD_PREP(PEF2256_SIC2_SICS_MASK, _v) + +/* System Interface Control 3 */ +#define PEF2256_SIC3 0x40 +#define PEF2256_SIC3_RTRI BIT(5) +#define PEF2256_SIC3_RESX BIT(3) +#define PEF2256_SIC3_RESR BIT(2) + +/* Clock Mode Register 1 */ +#define PEF2256_CMR1 0x44 +#define PEF2256_CMR1_RS_MASK GENMASK(5, 4) +#define PEF2256_CMR1_RS_DPLL FIELD_PREP_CONST(PEF2256_CMR1_RS_MASK, 0x0) +#define PEF2256_CMR1_RS_DPLL_LOS_HIGH FIELD_PREP_CONST(PEF2256_CMR1_RS_MASK, 0x1) +#define PEF2256_CMR1_RS_DCOR_2048 FIELD_PREP_CONST(PEF2256_CMR1_RS_MASK, 0x2) +#define PEF2256_CMR1_RS_DCOR_8192 FIELD_PREP_CONST(PEF2256_CMR1_RS_MASK, 0x3) +#define PEF2256_CMR1_DCS BIT(3) + +/* Clock Mode Register 2 */ +#define PEF2256_CMR2 0x45 +#define PEF2256_CMR2_DCOXC BIT(5) + +/* Global Configuration Register */ +#define PEF2256_GCR 0x46 +#define PEF2256_GCR_SCI BIT(6) +#define PEF2256_GCR_ECMC BIT(4) + +/* Port Configuration 5 */ +#define PEF2256_PC5 0x84 +#define PEF2256_PC5_CRP BIT(0) + +/* Global Port Configuration 1 */ +#define PEF2256_GPC1 0x85 +#define PEF2256_GPC1_CSFP_MASK GENMASK(7, 5) +#define PEF2256_GPC1_CSFP_SEC_IN_HIGH FIELD_PREP_CONST(PEF2256_GPC1_CSFP_MASK, 0x0) +#define PEF2256_GPC1_CSFP_SEC_OUT_HIGH FIELD_PREP_CONST(PEF2256_GPC1_CSFP_MASK, 0x1) +#define PEF2256_GPC1_CSFP_FSC_OUT_HIGH FIELD_PREP_CONST(PEF2256_GPC1_CSFP_MASK, 0x2) +#define PEF2256_GPC1_CSFP_FSC_OUT_LOW FIELD_PREP_CONST(PEF2256_GPC1_CSFP_MASK, 0x3) + +/* Port Configuration 6 */ +#define PEF2256_PC6 0x86 + +/* Global Counter Mode n=1..8 */ +#define PEF2256_GCM(_n) (0x92 + (_n) - 1) +#define PEF2256_GCM1 0x92 +#define PEF2256_GCM2 0x93 +#define PEF2256_GCM3 0x94 +#define PEF2256_GCM4 0x95 +#define PEF2256_GCM5 0x96 +#define PEF2256_GCM6 0x97 +#define PEF2256_GCM7 0x98 +#define PEF2256_GCM8 0x99 + +/* Version Status Register */ +#define PEF2256_VSTR 0x4A +#define PEF2256_VSTR_VERSION_12 0x00 +#define PEF2256_VSTR_VERSION_21 0x10 +#define PEF2256_VSTR_VERSION_2x 0x05 + +/* Framer Receive Status 0 */ +#define PEF2256_FRS0 0x4C +#define PEF2256_FRS0_LOS BIT(7) +#define PEF2256_FRS0_AIS BIT(6) + +/* Interrupt Status Register 0..5 */ +#define PEF2256_ISR(_n) (0x68 + (_n)) +#define PEF2256_ISR0 0x68 +#define PEF2256_ISR1 0x69 +#define PEF2256_ISR2 0x6A +#define PEF2256_ISR3 0x6B +#define PEF2256_ISR4 0x6C +#define PEF2256_ISR5 0x6D + +/* Global Interrupt Status */ +#define PEF2256_GIS 0x6E +#define PEF2256_GIS_ISR(_n) BIT(_n) + +/* Wafer Identification Register */ +#define PEF2256_WID 0xEC +#define PEF2256_12_WID_MASK GENMASK(1, 0) +#define PEF2256_12_WID_VERSION_12 FIELD_PREP_CONST(PEF2256_12_WID_MASK, 0x3) +#define PEF2256_2X_WID_MASK GENMASK(7, 6) +#define PEF2256_2X_WID_VERSION_21 FIELD_PREP_CONST(PEF2256_2X_WID_MASK, 0x0) +#define PEF2256_2X_WID_VERSION_22 FIELD_PREP_CONST(PEF2256_2X_WID_MASK, 0x1) + +/* IMR2/ISR2 Interrupts common bits */ +#define PEF2256_INT2_AIS BIT(3) +#define PEF2256_INT2_LOS BIT(2) + +#endif /* __PEF2256_REGS_H__ */ diff --git a/drivers/net/wan/framer/pef2256/pef2256.c b/drivers/net/wan/framer/pef2256/pef2256.c new file mode 100644 index 000000000000..0aa7740ab82f --- /dev/null +++ b/drivers/net/wan/framer/pef2256/pef2256.c @@ -0,0 +1,880 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PEF2256 also known as FALC56 driver + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pef2256-regs.h" + +enum pef2256_frame_type { + PEF2256_FRAME_E1_DOUBLEFRAME, + PEF2256_FRAME_E1_CRC4_MULTIFRAME, + PEF2256_FRAME_E1_AUTO_MULTIFRAME, + PEF2256_FRAME_T1J1_4FRAME, + PEF2256_FRAME_T1J1_12FRAME, + PEF2256_FRAME_T1J1_24FRAME, + PEF2256_FRAME_T1J1_72FRAME, +}; + +struct pef2256 { + struct device *dev; + struct regmap *regmap; + enum pef2256_version version; + struct clk *mclk; + struct clk *sclkr; + struct clk *sclkx; + struct gpio_desc *reset_gpio; + unsigned long sysclk_rate; + u32 data_rate; + bool is_tx_falling_edge; + bool is_subordinate; + enum pef2256_frame_type frame_type; + u8 channel_phase; + atomic_t carrier; + struct framer *framer; +}; + +static u8 pef2256_read8(struct pef2256 *pef2256, int offset) +{ + int val; + + regmap_read(pef2256->regmap, offset, &val); + return val; +} + +static void pef2256_write8(struct pef2256 *pef2256, int offset, u8 val) +{ + regmap_write(pef2256->regmap, offset, val); +} + +static void pef2256_clrbits8(struct pef2256 *pef2256, int offset, u8 clr) +{ + regmap_clear_bits(pef2256->regmap, offset, clr); +} + +static void pef2256_setbits8(struct pef2256 *pef2256, int offset, u8 set) +{ + regmap_set_bits(pef2256->regmap, offset, set); +} + +static void pef2256_clrsetbits8(struct pef2256 *pef2256, int offset, u8 clr, u8 set) +{ + regmap_update_bits(pef2256->regmap, offset, clr | set, set); +} + +enum pef2256_version pef2256_get_version(struct pef2256 *pef2256) +{ + enum pef2256_version version = PEF2256_VERSION_UNKNOWN; + u8 vstr, wid; + + vstr = pef2256_read8(pef2256, PEF2256_VSTR); + wid = pef2256_read8(pef2256, PEF2256_WID); + + switch (vstr) { + case PEF2256_VSTR_VERSION_12: + if ((wid & PEF2256_12_WID_MASK) == PEF2256_12_WID_VERSION_12) + version = PEF2256_VERSION_1_2; + break; + case PEF2256_VSTR_VERSION_2x: + switch (wid & PEF2256_2X_WID_MASK) { + case PEF2256_2X_WID_VERSION_21: + version = PEF2256_VERSION_2_1; + break; + case PEF2256_2X_WID_VERSION_22: + version = PEF2256_VERSION_2_2; + break; + } + break; + case PEF2256_VSTR_VERSION_21: + version = PEF2256_VERSION_2_1; + break; + } + + if (version == PEF2256_VERSION_UNKNOWN) + dev_err(pef2256->dev, "Unknown version (0x%02x, 0x%02x)\n", vstr, wid); + + return version; +} +EXPORT_SYMBOL_GPL(pef2256_get_version); + +enum pef2256_gcm_config_item { + PEF2256_GCM_CONFIG_1544000 = 0, + PEF2256_GCM_CONFIG_2048000, + PEF2256_GCM_CONFIG_8192000, + PEF2256_GCM_CONFIG_10000000, + PEF2256_GCM_CONFIG_12352000, + PEF2256_GCM_CONFIG_16384000, +}; + +struct pef2256_gcm_config { + u8 gcm_12[6]; + u8 gcm_2x[8]; +}; + +static const struct pef2256_gcm_config pef2256_gcm_configs[] = { + [PEF2256_GCM_CONFIG_1544000] = { + .gcm_12 = {0xF0, 0x51, 0x00, 0x80, 0x00, 0x15}, + .gcm_2x = {0x00, 0x15, 0x00, 0x08, 0x00, 0x3F, 0x9C, 0xDF}, + }, + [PEF2256_GCM_CONFIG_2048000] = { + .gcm_12 = {0x00, 0x58, 0xD2, 0xC2, 0x00, 0x10}, + .gcm_2x = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x2F, 0xDB, 0xDF}, + }, + [PEF2256_GCM_CONFIG_8192000] = { + .gcm_12 = {0x00, 0x58, 0xD2, 0xC2, 0x03, 0x10}, + .gcm_2x = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x0B, 0xDB, 0xDF}, + }, + [PEF2256_GCM_CONFIG_10000000] = { + .gcm_12 = {0x90, 0x51, 0x81, 0x8F, 0x04, 0x10}, + .gcm_2x = {0x40, 0x1B, 0x3D, 0x0A, 0x00, 0x07, 0xC9, 0xDC}, + }, + [PEF2256_GCM_CONFIG_12352000] = { + .gcm_12 = {0xF0, 0x51, 0x00, 0x80, 0x07, 0x15}, + .gcm_2x = {0x00, 0x19, 0x00, 0x08, 0x01, 0x0A, 0x98, 0xDA}, + }, + [PEF2256_GCM_CONFIG_16384000] = { + .gcm_12 = {0x00, 0x58, 0xD2, 0xC2, 0x07, 0x10}, + .gcm_2x = {0x00, 0x18, 0xFB, 0x0B, 0x01, 0x0B, 0xDB, 0xDF}, + }, +}; + +static int pef2256_setup_gcm(struct pef2256 *pef2256) +{ + enum pef2256_gcm_config_item item; + unsigned long mclk_rate; + const u8 *gcm; + int i, count; + + mclk_rate = clk_get_rate(pef2256->mclk); + switch (mclk_rate) { + case 1544000: + item = PEF2256_GCM_CONFIG_1544000; + break; + case 2048000: + item = PEF2256_GCM_CONFIG_2048000; + break; + case 8192000: + item = PEF2256_GCM_CONFIG_8192000; + break; + case 10000000: + item = PEF2256_GCM_CONFIG_10000000; + break; + case 12352000: + item = PEF2256_GCM_CONFIG_12352000; + break; + case 16384000: + item = PEF2256_GCM_CONFIG_16384000; + break; + default: + dev_err(pef2256->dev, "Unsupported v2.x MCLK rate %lu\n", mclk_rate); + return -EINVAL; + } + + BUILD_BUG_ON(item >= ARRAY_SIZE(pef2256_gcm_configs)); + + if (pef2256->version == PEF2256_VERSION_1_2) { + gcm = pef2256_gcm_configs[item].gcm_12; + count = ARRAY_SIZE(pef2256_gcm_configs[item].gcm_12); + } else { + gcm = pef2256_gcm_configs[item].gcm_2x; + count = ARRAY_SIZE(pef2256_gcm_configs[item].gcm_2x); + } + + for (i = 0; i < count; i++) + pef2256_write8(pef2256, PEF2256_GCM(i + 1), *(gcm + i)); + + return 0; +} + +static int pef2256_setup_e1_line(struct pef2256 *pef2256) +{ + u8 fmr1, fmr2; + + /* RCLK output : DPLL clock, DCO-X enabled, DCO-X internal ref clock */ + pef2256_write8(pef2256, PEF2256_CMR1, 0x00); + + /* SCLKR selected, SCLKX selected, + * receive synchro pulse sourced by SYPR, + * transmit synchro pulse sourced by SYPX, + * DCO-X center frequency enabled + */ + pef2256_write8(pef2256, PEF2256_CMR2, PEF2256_CMR2_DCOXC); + + if (pef2256->is_subordinate) { + /* select RCLK source = 2M, disable switching from RCLK to SYNC */ + pef2256_clrsetbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_RS_MASK, + PEF2256_CMR1_RS_DCOR_2048 | PEF2256_CMR1_DCS); + } + + /* slave mode, local loop off, mode short-haul + * In v2.x, bit3 is a forced 1 bit in the datasheet -> Need to be set. + */ + if (pef2256->version == PEF2256_VERSION_1_2) + pef2256_write8(pef2256, PEF2256_LIM0, 0x00); + else + pef2256_write8(pef2256, PEF2256_LIM0, PEF2256_2X_LIM0_BIT3); + + /* "master" mode */ + if (!pef2256->is_subordinate) + pef2256_setbits8(pef2256, PEF2256_LIM0, PEF2256_LIM0_MAS); + + /* analog interface selected, remote loop off */ + pef2256_write8(pef2256, PEF2256_LIM1, 0x00); + + /* receive input threshold = 0,21V */ + if (pef2256->version == PEF2256_VERSION_1_2) + pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_12_LIM1_RIL_MASK, + PEF2256_12_LIM1_RIL_210); + else + pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_2X_LIM1_RIL_MASK, + PEF2256_2X_LIM1_RIL_210); + + /* transmit pulse mask, default value from datasheet + * transmit line in normal operation + */ + if (pef2256->version == PEF2256_VERSION_1_2) + pef2256_write8(pef2256, PEF2256_XPM0, 0x7B); + else + pef2256_write8(pef2256, PEF2256_XPM0, 0x9C); + pef2256_write8(pef2256, PEF2256_XPM1, 0x03); + pef2256_write8(pef2256, PEF2256_XPM2, 0x00); + + /* HDB3 coding, no alarm simulation */ + pef2256_write8(pef2256, PEF2256_FMR0, PEF2256_FMR0_XC_HDB3 | PEF2256_FMR0_RC_HDB3); + + /* E1, frame format, 2 Mbit/s system data rate, no AIS + * transmission to remote end or system interface, payload loop + * off, transmit remote alarm on + */ + fmr1 = 0x00; + fmr2 = PEF2256_FMR2_AXRA; + switch (pef2256->frame_type) { + case PEF2256_FRAME_E1_DOUBLEFRAME: + fmr2 |= PEF2256_FMR2_RFS_DOUBLEFRAME; + break; + case PEF2256_FRAME_E1_CRC4_MULTIFRAME: + fmr1 |= PEF2256_FMR1_XFS; + fmr2 |= PEF2256_FMR2_RFS_CRC4_MULTIFRAME; + break; + case PEF2256_FRAME_E1_AUTO_MULTIFRAME: + fmr1 |= PEF2256_FMR1_XFS; + fmr2 |= PEF2256_FMR2_RFS_AUTO_MULTIFRAME; + break; + default: + dev_err(pef2256->dev, "Unsupported frame type %d\n", pef2256->frame_type); + return -EINVAL; + } + pef2256_clrsetbits8(pef2256, PEF2256_FMR1, PEF2256_FMR1_XFS, fmr1); + pef2256_write8(pef2256, PEF2256_FMR2, fmr2); + + if (!pef2256->is_subordinate) { + /* SEC input, active high */ + pef2256_write8(pef2256, PEF2256_GPC1, PEF2256_GPC1_CSFP_SEC_IN_HIGH); + } else { + /* FSC output, active high */ + pef2256_write8(pef2256, PEF2256_GPC1, PEF2256_GPC1_CSFP_FSC_OUT_HIGH); + } + + /* SCLKR, SCLKX, RCLK configured to inputs, + * XFMS active low, CLK1 and CLK2 pin configuration + */ + pef2256_write8(pef2256, PEF2256_PC5, 0x00); + pef2256_write8(pef2256, PEF2256_PC6, 0x00); + + /* port RCLK is output */ + pef2256_setbits8(pef2256, PEF2256_PC5, PEF2256_PC5_CRP); + + return 0; +} + +static void pef2256_setup_e1_los(struct pef2256 *pef2256) +{ + /* detection of LOS alarm = 176 pulses (ie (10 + 1) * 16) */ + pef2256_write8(pef2256, PEF2256_PCD, 10); + /* recovery of LOS alarm = 22 pulses (ie 21 + 1) */ + pef2256_write8(pef2256, PEF2256_PCR, 21); + /* E1 default for the receive slicer threshold */ + pef2256_write8(pef2256, PEF2256_LIM2, PEF2256_LIM2_SLT_THR50); + if (pef2256->is_subordinate) { + /* Loop-timed */ + pef2256_setbits8(pef2256, PEF2256_LIM2, PEF2256_LIM2_ELT); + } +} + +static int pef2256_setup_e1_system(struct pef2256 *pef2256) +{ + u8 sic1, fmr1; + + /* 2.048 MHz system clocking rate, receive buffer 2 frames, transmit + * buffer bypass, data sampled and transmitted on the falling edge of + * SCLKR/X, automatic freeze signaling, data is active in the first + * channel phase + */ + pef2256_write8(pef2256, PEF2256_SIC1, 0x00); + pef2256_write8(pef2256, PEF2256_SIC2, 0x00); + pef2256_write8(pef2256, PEF2256_SIC3, 0x00); + + if (pef2256->is_subordinate) { + /* transmit buffer size = 2 frames, transparent mode */ + pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_XBS_MASK, + PEF2256_SIC1_XBS_2FRAMES); + } + + if (pef2256->version != PEF2256_VERSION_1_2) { + /* during inactive channel phase switch RDO/RSIG into tri-state */ + pef2256_setbits8(pef2256, PEF2256_SIC3, PEF2256_SIC3_RTRI); + } + + if (pef2256->is_tx_falling_edge) { + /* falling edge sync pulse transmit, rising edge sync pulse receive */ + pef2256_clrsetbits8(pef2256, PEF2256_SIC3, PEF2256_SIC3_RESX, PEF2256_SIC3_RESR); + } else { + /* rising edge sync pulse transmit, falling edge sync pulse receive */ + pef2256_clrsetbits8(pef2256, PEF2256_SIC3, PEF2256_SIC3_RESR, PEF2256_SIC3_RESX); + } + + /* transmit offset counter (XCO10..0) = 4 */ + pef2256_write8(pef2256, PEF2256_XC0, 0); + pef2256_write8(pef2256, PEF2256_XC1, 4); + /* receive offset counter (RCO10..0) = 4 */ + pef2256_write8(pef2256, PEF2256_RC0, 0); + pef2256_write8(pef2256, PEF2256_RC1, 4); + + /* system clock rate */ + switch (pef2256->sysclk_rate) { + case 2048000: + sic1 = PEF2256_SIC1_SSC_2048; + break; + case 4096000: + sic1 = PEF2256_SIC1_SSC_4096; + break; + case 8192000: + sic1 = PEF2256_SIC1_SSC_8192; + break; + case 16384000: + sic1 = PEF2256_SIC1_SSC_16384; + break; + default: + dev_err(pef2256->dev, "Unsupported sysclk rate %lu\n", pef2256->sysclk_rate); + return -EINVAL; + } + pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_SSC_MASK, sic1); + + /* data clock rate */ + switch (pef2256->data_rate) { + case 2048000: + fmr1 = PEF2256_FMR1_SSD_2048; + sic1 = PEF2256_SIC1_SSD_2048; + break; + case 4096000: + fmr1 = PEF2256_FMR1_SSD_4096; + sic1 = PEF2256_SIC1_SSD_4096; + break; + case 8192000: + fmr1 = PEF2256_FMR1_SSD_8192; + sic1 = PEF2256_SIC1_SSD_8192; + break; + case 16384000: + fmr1 = PEF2256_FMR1_SSD_16384; + sic1 = PEF2256_SIC1_SSD_16384; + break; + default: + dev_err(pef2256->dev, "Unsupported data rate %u\n", pef2256->data_rate); + return -EINVAL; + } + pef2256_clrsetbits8(pef2256, PEF2256_FMR1, PEF2256_FMR1_SSD_MASK, fmr1); + pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_SSD_MASK, sic1); + + /* channel phase */ + pef2256_clrsetbits8(pef2256, PEF2256_SIC2, PEF2256_SIC2_SICS_MASK, + PEF2256_SIC2_SICS(pef2256->channel_phase)); + + return 0; +} + +static void pef2256_setup_e1_signaling(struct pef2256 *pef2256) +{ + /* All bits of the transmitted service word are cleared */ + pef2256_write8(pef2256, PEF2256_XSW, PEF2256_XSW_XY(0x1F)); + + /* CAS disabled and clear spare bit values */ + pef2256_write8(pef2256, PEF2256_XSP, 0x00); + + if (pef2256->is_subordinate) { + /* transparent mode */ + pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XTM); + } + + /* Si-Bit, Spare bit For International, FAS word */ + pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XSIS); + pef2256_setbits8(pef2256, PEF2256_XSP, PEF2256_XSP_XSIF); + + /* no transparent mode active */ + pef2256_write8(pef2256, PEF2256_TSWM, 0x00); +} + +static void pef2256_setup_e1_errors(struct pef2256 *pef2256) +{ + /* error counter latched every 1s */ + pef2256_setbits8(pef2256, PEF2256_FMR1, PEF2256_FMR1_ECM); + + /* error counter mode COFA */ + pef2256_setbits8(pef2256, PEF2256_GCR, PEF2256_GCR_ECMC); + + /* errors in service words have no influence */ + pef2256_setbits8(pef2256, PEF2256_RC0, PEF2256_RC0_SWD); + + /* 4 consecutive incorrect FAS causes loss of sync */ + pef2256_setbits8(pef2256, PEF2256_RC0, PEF2256_RC0_ASY4); +} + +static int pef2256_setup_e1(struct pef2256 *pef2256) +{ + int ret; + + /* Setup, Master clocking mode (GCM8..1) */ + ret = pef2256_setup_gcm(pef2256); + if (ret) + return ret; + + /* Select E1 mode */ + pef2256_write8(pef2256, PEF2256_FMR1, 0x00); + + /* internal second timer, power on */ + pef2256_write8(pef2256, PEF2256_GCR, 0x00); + + /* Setup line interface */ + ret = pef2256_setup_e1_line(pef2256); + if (ret) + return ret; + + /* Setup Loss-of-signal detection and recovery */ + pef2256_setup_e1_los(pef2256); + + /* Setup system interface */ + ret = pef2256_setup_e1_system(pef2256); + if (ret) + return ret; + + /* Setup signaling */ + pef2256_setup_e1_signaling(pef2256); + + /* Setup errors counters and condition */ + pef2256_setup_e1_errors(pef2256); + + /* status changed interrupt at both up and down */ + pef2256_setbits8(pef2256, PEF2256_GCR, PEF2256_GCR_SCI); + + /* Clear any ISR2 pending interrupts and unmask needed interrupts */ + pef2256_read8(pef2256, PEF2256_ISR2); + pef2256_clrbits8(pef2256, PEF2256_IMR2, PEF2256_INT2_LOS | PEF2256_INT2_AIS); + + /* reset lines */ + pef2256_write8(pef2256, PEF2256_CMDR, PEF2256_CMDR_RRES | PEF2256_CMDR_XRES); + return 0; +} + +static void pef2256_isr_default_handler(struct pef2256 *pef2256, u8 nbr, u8 isr) +{ + dev_warn_ratelimited(pef2256->dev, "ISR%u: 0x%02x not handled\n", nbr, isr); +} + +static bool pef2256_is_carrier_on(struct pef2256 *pef2256) +{ + u8 frs0; + + frs0 = pef2256_read8(pef2256, PEF2256_FRS0); + return !(frs0 & (PEF2256_FRS0_LOS | PEF2256_FRS0_AIS)); +} + +static void pef2256_isr2_handler(struct pef2256 *pef2256, u8 nbr, u8 isr) +{ + bool carrier; + + if (isr & (PEF2256_INT2_LOS | PEF2256_INT2_AIS)) { + carrier = pef2256_is_carrier_on(pef2256); + if (atomic_xchg(&pef2256->carrier, carrier) != carrier) + framer_notify_status_change(pef2256->framer); + } +} + +static irqreturn_t pef2256_irq_handler(int irq, void *priv) +{ + static void (*pef2256_isr_handler[])(struct pef2256 *, u8, u8) = { + [0] = pef2256_isr_default_handler, + [1] = pef2256_isr_default_handler, + [2] = pef2256_isr2_handler, + [3] = pef2256_isr_default_handler, + [4] = pef2256_isr_default_handler, + [5] = pef2256_isr_default_handler + }; + struct pef2256 *pef2256 = (struct pef2256 *)priv; + u8 gis; + u8 isr; + u8 n; + + gis = pef2256_read8(pef2256, PEF2256_GIS); + + for (n = 0; n < ARRAY_SIZE(pef2256_isr_handler); n++) { + if (gis & PEF2256_GIS_ISR(n)) { + isr = pef2256_read8(pef2256, PEF2256_ISR(n)); + pef2256_isr_handler[n](pef2256, n, isr); + } + } + + return IRQ_HANDLED; +} + +static int pef2256_check_rates(struct pef2256 *pef2256, unsigned long sysclk_rate, + unsigned long data_rate) +{ + unsigned long rate; + + switch (sysclk_rate) { + case 2048000: + case 4096000: + case 8192000: + case 16384000: + break; + default: + dev_err(pef2256->dev, "Unsupported system clock rate %lu\n", sysclk_rate); + return -EINVAL; + } + + for (rate = data_rate; rate <= data_rate * 4; rate *= 2) { + if (rate == sysclk_rate) + return 0; + } + dev_err(pef2256->dev, "Unsupported data rate %lu with system clock rate %lu\n", + data_rate, sysclk_rate); + return -EINVAL; +} + +static int pef2556_of_parse(struct pef2256 *pef2256, struct device_node *np) +{ + int ret; + + pef2256->data_rate = 2048000; + ret = of_property_read_u32(np, "lantiq,data-rate-bps", &pef2256->data_rate); + if (ret && ret != -EINVAL) { + dev_err(pef2256->dev, "%pOF: failed to read lantiq,data-rate-bps\n", np); + return ret; + } + + ret = pef2256_check_rates(pef2256, pef2256->sysclk_rate, pef2256->data_rate); + if (ret) + return ret; + + pef2256->is_tx_falling_edge = of_property_read_bool(np, "lantiq,clock-falling-edge"); + + pef2256->channel_phase = 0; + ret = of_property_read_u8(np, "lantiq,channel-phase", &pef2256->channel_phase); + if (ret && ret != -EINVAL) { + dev_err(pef2256->dev, "%pOF: failed to read lantiq,channel-phase\n", + np); + return ret; + } + if (pef2256->channel_phase >= pef2256->sysclk_rate / pef2256->data_rate) { + dev_err(pef2256->dev, "%pOF: Invalid lantiq,channel-phase %u\n", + np, pef2256->channel_phase); + return -EINVAL; + } + + return 0; +} + +static const struct regmap_config pef2256_regmap_config = { + .reg_bits = 32, + .val_bits = 8, + .max_register = 0xff, +}; + +static const struct mfd_cell pef2256_devs[] = { + { .name = "lantiq-pef2256-pinctrl", }, +}; + +static int pef2256_add_audio_devices(struct pef2256 *pef2256) +{ + const char *compatible = "lantiq,pef2256-codec"; + struct mfd_cell *audio_devs; + struct device_node *np; + unsigned int count = 0; + unsigned int i; + int ret; + + for_each_available_child_of_node(pef2256->dev->of_node, np) { + if (of_device_is_compatible(np, compatible)) + count++; + } + + if (!count) + return 0; + + audio_devs = kcalloc(count, sizeof(*audio_devs), GFP_KERNEL); + if (!audio_devs) + return -ENOMEM; + + for (i = 0; i < count; i++) { + (audio_devs + i)->name = "framer-codec"; + (audio_devs + i)->of_compatible = compatible; + (audio_devs + i)->id = i; + } + + ret = mfd_add_devices(pef2256->dev, 0, audio_devs, count, NULL, 0, NULL); + kfree(audio_devs); + return ret; +} + +static int pef2256_framer_get_status(struct framer *framer, struct framer_status *status) +{ + struct pef2256 *pef2256 = framer_get_drvdata(framer); + + status->link_is_on = !!atomic_read(&pef2256->carrier); + return 0; +} + +static int pef2256_framer_set_config(struct framer *framer, const struct framer_config *config) +{ + struct pef2256 *pef2256 = framer_get_drvdata(framer); + + if (config->iface != FRAMER_IFACE_E1) { + dev_err(pef2256->dev, "Only E1 line is currently supported\n"); + return -EOPNOTSUPP; + } + + switch (config->clock_type) { + case FRAMER_CLOCK_EXT: + pef2256->is_subordinate = true; + break; + case FRAMER_CLOCK_INT: + pef2256->is_subordinate = false; + break; + default: + return -EINVAL; + } + + /* Apply the new settings */ + return pef2256_setup_e1(pef2256); +} + +static int pef2256_framer_get_config(struct framer *framer, struct framer_config *config) +{ + struct pef2256 *pef2256 = framer_get_drvdata(framer); + + config->iface = FRAMER_IFACE_E1; + config->clock_type = pef2256->is_subordinate ? FRAMER_CLOCK_EXT : FRAMER_CLOCK_INT; + config->line_clock_rate = 2048000; + return 0; +} + +static const struct framer_ops pef2256_framer_ops = { + .owner = THIS_MODULE, + .get_status = pef2256_framer_get_status, + .get_config = pef2256_framer_get_config, + .set_config = pef2256_framer_set_config, +}; + +static int pef2256_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + unsigned long sclkr_rate, sclkx_rate; + struct framer_provider *framer_provider; + struct pef2256 *pef2256; + const char *version_txt; + void __iomem *iomem; + int ret; + int irq; + + pef2256 = devm_kzalloc(&pdev->dev, sizeof(*pef2256), GFP_KERNEL); + if (!pef2256) + return -ENOMEM; + + pef2256->dev = &pdev->dev; + atomic_set(&pef2256->carrier, 0); + + pef2256->is_subordinate = true; + pef2256->frame_type = PEF2256_FRAME_E1_DOUBLEFRAME; + + iomem = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(iomem)) + return PTR_ERR(iomem); + + pef2256->regmap = devm_regmap_init_mmio(&pdev->dev, iomem, + &pef2256_regmap_config); + if (IS_ERR(pef2256->regmap)) { + dev_err(&pdev->dev, "Failed to initialise Regmap (%ld)\n", + PTR_ERR(pef2256->regmap)); + return PTR_ERR(pef2256->regmap); + } + + pef2256->mclk = devm_clk_get_enabled(&pdev->dev, "mclk"); + if (IS_ERR(pef2256->mclk)) + return PTR_ERR(pef2256->mclk); + + pef2256->sclkr = devm_clk_get_enabled(&pdev->dev, "sclkr"); + if (IS_ERR(pef2256->sclkr)) + return PTR_ERR(pef2256->sclkr); + + pef2256->sclkx = devm_clk_get_enabled(&pdev->dev, "sclkx"); + if (IS_ERR(pef2256->sclkx)) + return PTR_ERR(pef2256->sclkx); + + /* Both SCLKR (receive) and SCLKX (transmit) must have the same rate, + * stored as sysclk_rate. + * The exact value will be checked at pef2256_check_rates() + */ + sclkr_rate = clk_get_rate(pef2256->sclkr); + sclkx_rate = clk_get_rate(pef2256->sclkx); + if (sclkr_rate != sclkx_rate) { + dev_err(pef2256->dev, "clk rate mismatch. sclkr %lu Hz, sclkx %lu Hz\n", + sclkr_rate, sclkx_rate); + return -EINVAL; + } + pef2256->sysclk_rate = sclkr_rate; + + /* Reset the component. The MCLK clock must be active during reset */ + pef2256->reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(pef2256->reset_gpio)) + return PTR_ERR(pef2256->reset_gpio); + if (pef2256->reset_gpio) { + gpiod_set_value_cansleep(pef2256->reset_gpio, 1); + usleep_range(10, 20); + gpiod_set_value_cansleep(pef2256->reset_gpio, 0); + usleep_range(10, 20); + } + + pef2256->version = pef2256_get_version(pef2256); + switch (pef2256->version) { + case PEF2256_VERSION_1_2: + version_txt = "1.2"; + break; + case PEF2256_VERSION_2_1: + version_txt = "2.1"; + break; + case PEF2256_VERSION_2_2: + version_txt = "2.2"; + break; + default: + return -ENODEV; + } + dev_info(pef2256->dev, "Version %s detected\n", version_txt); + + ret = pef2556_of_parse(pef2256, np); + if (ret) + return ret; + + /* Create the framer. It can be used on interrupts */ + pef2256->framer = devm_framer_create(pef2256->dev, NULL, &pef2256_framer_ops); + if (IS_ERR(pef2256->framer)) + return PTR_ERR(pef2256->framer); + + framer_set_drvdata(pef2256->framer, pef2256); + + /* Disable interrupts */ + pef2256_write8(pef2256, PEF2256_IMR0, 0xff); + pef2256_write8(pef2256, PEF2256_IMR1, 0xff); + pef2256_write8(pef2256, PEF2256_IMR2, 0xff); + pef2256_write8(pef2256, PEF2256_IMR3, 0xff); + pef2256_write8(pef2256, PEF2256_IMR4, 0xff); + pef2256_write8(pef2256, PEF2256_IMR5, 0xff); + + /* Clear any pending interrupts */ + pef2256_read8(pef2256, PEF2256_ISR0); + pef2256_read8(pef2256, PEF2256_ISR1); + pef2256_read8(pef2256, PEF2256_ISR2); + pef2256_read8(pef2256, PEF2256_ISR3); + pef2256_read8(pef2256, PEF2256_ISR4); + pef2256_read8(pef2256, PEF2256_ISR5); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + ret = devm_request_irq(pef2256->dev, irq, pef2256_irq_handler, 0, "pef2256", pef2256); + if (ret < 0) + return ret; + + platform_set_drvdata(pdev, pef2256); + + ret = mfd_add_devices(pef2256->dev, 0, pef2256_devs, + ARRAY_SIZE(pef2256_devs), NULL, 0, NULL); + if (ret) { + dev_err(pef2256->dev, "add devices failed (%d)\n", ret); + return ret; + } + + ret = pef2256_setup_e1(pef2256); + if (ret) + return ret; + + framer_provider = devm_framer_provider_of_register(pef2256->dev, + framer_provider_simple_of_xlate); + if (IS_ERR(framer_provider)) + return PTR_ERR(framer_provider); + + /* Add audio devices */ + ret = pef2256_add_audio_devices(pef2256); + if (ret < 0) { + dev_err(pef2256->dev, "add audio devices failed (%d)\n", ret); + return ret; + } + + return 0; +} + +static int pef2256_remove(struct platform_device *pdev) +{ + struct pef2256 *pef2256 = platform_get_drvdata(pdev); + + /* Disable interrupts */ + pef2256_write8(pef2256, PEF2256_IMR0, 0xff); + pef2256_write8(pef2256, PEF2256_IMR1, 0xff); + pef2256_write8(pef2256, PEF2256_IMR2, 0xff); + pef2256_write8(pef2256, PEF2256_IMR3, 0xff); + pef2256_write8(pef2256, PEF2256_IMR4, 0xff); + pef2256_write8(pef2256, PEF2256_IMR5, 0xff); + + return 0; +} + +static const struct of_device_id pef2256_id_table[] = { + { .compatible = "lantiq,pef2256" }, + {} /* sentinel */ +}; +MODULE_DEVICE_TABLE(of, pef2256_id_table); + +static struct platform_driver pef2256_driver = { + .driver = { + .name = "lantiq-pef2256", + .of_match_table = pef2256_id_table, + }, + .probe = pef2256_probe, + .remove = pef2256_remove, +}; +module_platform_driver(pef2256_driver); + +struct regmap *pef2256_get_regmap(struct pef2256 *pef2256) +{ + return pef2256->regmap; +} +EXPORT_SYMBOL_GPL(pef2256_get_regmap); + +MODULE_AUTHOR("Herve Codina "); +MODULE_DESCRIPTION("PEF2256 driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/framer/pef2256.h b/include/linux/framer/pef2256.h new file mode 100644 index 000000000000..71d80af58c40 --- /dev/null +++ b/include/linux/framer/pef2256.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * PEF2256 consumer API + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ +#ifndef __PEF2256_H__ +#define __PEF2256_H__ + +#include + +struct pef2256; +struct regmap; + +/* Retrieve the PEF2256 regmap */ +struct regmap *pef2256_get_regmap(struct pef2256 *pef2256); + +/* PEF2256 hardware versions */ +enum pef2256_version { + PEF2256_VERSION_UNKNOWN, + PEF2256_VERSION_1_2, + PEF2256_VERSION_2_1, + PEF2256_VERSION_2_2, +}; + +/* Get the PEF2256 hardware version */ +enum pef2256_version pef2256_get_version(struct pef2256 *pef2256); + +#endif /* __PEF2256_H__ */ From patchwork Fri Aug 18 16:39:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358153 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 D94EC1C9ED for ; Fri, 18 Aug 2023 17:21:58 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5AF9144AA; Fri, 18 Aug 2023 10:21:50 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS7050v1jz9vjZ; Fri, 18 Aug 2023 18:40:21 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id nC9yLcdfB1wy; Fri, 18 Aug 2023 18:40:21 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zp2rVBz9vhH; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 572ED8B76C; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id XtW-dj6ib3E4; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id C7CA88B763; Fri, 18 Aug 2023 18:40:04 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGe0of142043 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:40:00 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGe0Cs142042; Fri, 18 Aug 2023 18:40:00 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 25/28] pinctrl: Add support for the Lantic PEF2256 pinmux Date: Fri, 18 Aug 2023 18:39:19 +0200 Message-ID: <1ddd366f383bc0094dc3ca63d9078d3066629572.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376736; l=18646; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=MJGTPwO8Ol5U84xvnqlhD//BIFmZDonFLJfH1zPkQKI=; b=ERPbabh+rN2F0De5DIDMq/cC2w0nPUS3A/nsmomR6rnQAOPlzKAoWM/9hpGSK2BDmzt7NJywy bjZeAXGSY+1AuLk0F4W3oFasmZ2kUgwnYNKn7FwXhPt0krtZHXCv4xh X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina The Lantiq PEF2256 is a framer and line interface component designed to fulfill all required interfacing between an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus. This kind of component can be found in old telecommunication system. It was used to digital transmission of many simultaneous telephone calls by time-division multiplexing. Also using HDLC protocol, WAN networks can be reached through the framer. This pinmux support handles the pin muxing part (pins RP(A..D) and pins XP(A..D)) of the PEF2256. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/pinctrl/Kconfig | 14 ++ drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-pef2256-regs.h | 65 ++++++ drivers/pinctrl/pinctrl-pef2256.c | 308 +++++++++++++++++++++++++ 4 files changed, 388 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-pef2256-regs.h create mode 100644 drivers/pinctrl/pinctrl-pef2256.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 57d57af1f624..a3aa96b59c97 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -377,6 +377,20 @@ config PINCTRL_PALMAS open drain configuration for the Palmas series devices like TPS65913, TPS80036 etc. +config PINCTRL_PEF2256 + tristate "Lantiq PEF2256 (FALC56) pin controller driver" + depends on OF && FRAMER_PEF2256 + select PINMUX + select GENERIC_PINCONF + help + This option enables the pin controller support for the Lantiq PEF2256 + framer, also known as FALC56. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called pinctrl-pef2256. + config PINCTRL_PIC32 bool "Microchip PIC32 pin controller driver" depends on OF diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 482b391b5deb..8f211f7671a8 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_PINCTRL_MLXBF3) += pinctrl-mlxbf3.o obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o obj-$(CONFIG_PINCTRL_OXNAS) += pinctrl-oxnas.o obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o +obj-$(CONFIG_PINCTRL_PEF2256) += pinctrl-pef2256.o obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o diff --git a/drivers/pinctrl/pinctrl-pef2256-regs.h b/drivers/pinctrl/pinctrl-pef2256-regs.h new file mode 100644 index 000000000000..cacc492a1623 --- /dev/null +++ b/drivers/pinctrl/pinctrl-pef2256-regs.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * PEF2256 pinctrl registers definition + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ +#ifndef __PEF2256_PINCTRL_REGS_H__ +#define __PEF2256_PINCTRL_REGS_H__ + +#include + +/* Port Configuration 1..4 */ +#define PEF2256_PC1 0x80 +#define PEF2256_PC2 0x81 +#define PEF2256_PC3 0x82 +#define PEF2256_PC4 0x83 +#define PEF2256_12_PC_RPC_MASK GENMASK(6, 4) +#define PEF2256_12_PC_RPC_SYPR FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x0) +#define PEF2256_12_PC_RPC_RFM FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x1) +#define PEF2256_12_PC_RPC_RFMB FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x2) +#define PEF2256_12_PC_RPC_RSIGM FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x3) +#define PEF2256_12_PC_RPC_RSIG FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x4) +#define PEF2256_12_PC_RPC_DLR FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x5) +#define PEF2256_12_PC_RPC_FREEZE FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x6) +#define PEF2256_12_PC_RPC_RFSP FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x7) +#define PEF2256_12_PC_XPC_MASK GENMASK(4, 0) +#define PEF2256_12_PC_XPC_SYPX FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x0) +#define PEF2256_12_PC_XPC_XFMS FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x1) +#define PEF2256_12_PC_XPC_XSIG FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x2) +#define PEF2256_12_PC_XPC_TCLK FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x3) +#define PEF2256_12_PC_XPC_XMFB FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x4) +#define PEF2256_12_PC_XPC_XSIGM FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x5) +#define PEF2256_12_PC_XPC_DLX FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x6) +#define PEF2256_12_PC_XPC_XCLK FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x7) +#define PEF2256_12_PC_XPC_XLT FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x8) +#define PEF2256_2X_PC_RPC_MASK GENMASK(7, 4) +#define PEF2256_2X_PC_RPC_SYPR FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x0) +#define PEF2256_2X_PC_RPC_RFM FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x1) +#define PEF2256_2X_PC_RPC_RFMB FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x2) +#define PEF2256_2X_PC_RPC_RSIGM FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x3) +#define PEF2256_2X_PC_RPC_RSIG FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x4) +#define PEF2256_2X_PC_RPC_DLR FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x5) +#define PEF2256_2X_PC_RPC_FREEZE FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x6) +#define PEF2256_2X_PC_RPC_RFSP FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x7) +#define PEF2256_2X_PC_RPC_GPI FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x9) +#define PEF2256_2X_PC_RPC_GPOH FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0xa) +#define PEF2256_2X_PC_RPC_GPOL FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0xb) +#define PEF2256_2X_PC_RPC_LOS FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0xc) +#define PEF2256_2X_PC_XPC_MASK GENMASK(3, 0) +#define PEF2256_2X_PC_XPC_SYPX FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x0) +#define PEF2256_2X_PC_XPC_XFMS FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x1) +#define PEF2256_2X_PC_XPC_XSIG FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x2) +#define PEF2256_2X_PC_XPC_TCLK FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x3) +#define PEF2256_2X_PC_XPC_XMFB FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x4) +#define PEF2256_2X_PC_XPC_XSIGM FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x5) +#define PEF2256_2X_PC_XPC_DLX FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x6) +#define PEF2256_2X_PC_XPC_XCLK FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x7) +#define PEF2256_2X_PC_XPC_XLT FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x8) +#define PEF2256_2X_PC_XPC_GPI FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x9) +#define PEF2256_2X_PC_XPC_GPOH FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0xa) +#define PEF2256_2X_PC_XPC_GPOL FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0xb) + +#endif /* __PEF2256_PINCTRL_REGS_H__ */ diff --git a/drivers/pinctrl/pinctrl-pef2256.c b/drivers/pinctrl/pinctrl-pef2256.c new file mode 100644 index 000000000000..773f701ecf23 --- /dev/null +++ b/drivers/pinctrl/pinctrl-pef2256.c @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PEF2256 also known as FALC56 driver + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pinctrl-pef2256-regs.h" + +struct pef2256_pinreg_desc { + int offset; + u8 mask; +}; + +struct pef2256_function_desc { + const char *name; + const char * const*groups; + unsigned int ngroups; + u8 func_val; +}; + +struct pef2256_pinctrl { + struct device *dev; + struct regmap *regmap; + enum pef2256_version version; + struct pinctrl_desc pctrl_desc; + const struct pef2256_function_desc *functions; + unsigned int nfunctions; +}; + +static int pef2256_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + + /* We map 1 group <-> 1 pin */ + return pef2256->pctrl_desc.npins; +} + +static const char *pef2256_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + + /* We map 1 group <-> 1 pin */ + return pef2256->pctrl_desc.pins[selector].name; +} + +static int pef2256_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector, + const unsigned int **pins, + unsigned int *num_pins) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + + /* We map 1 group <-> 1 pin */ + *pins = &pef2256->pctrl_desc.pins[selector].number; + *num_pins = 1; + + return 0; +} + +static const struct pinctrl_ops pef2256_pctlops = { + .get_groups_count = pef2256_get_groups_count, + .get_group_name = pef2256_get_group_name, + .get_group_pins = pef2256_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, + .dt_free_map = pinconf_generic_dt_free_map, +}; + +static int pef2256_get_functions_count(struct pinctrl_dev *pctldev) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + + return pef2256->nfunctions; +} + +static const char *pef2256_get_function_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + + return pef2256->functions[selector].name; +} + +static int pef2256_get_function_groups(struct pinctrl_dev *pctldev, unsigned int selector, + const char * const **groups, + unsigned * const num_groups) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + + *groups = pef2256->functions[selector].groups; + *num_groups = pef2256->functions[selector].ngroups; + return 0; +} + +static int pef2256_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector, + unsigned int group_selector) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + const struct pef2256_pinreg_desc *pinreg_desc; + u8 func_val; + + /* We map 1 group <-> 1 pin */ + pinreg_desc = pef2256->pctrl_desc.pins[group_selector].drv_data; + func_val = pef2256->functions[func_selector].func_val; + + return regmap_update_bits(pef2256->regmap, pinreg_desc->offset, + pinreg_desc->mask, func_val); +} + +static const struct pinmux_ops pef2256_pmxops = { + .get_functions_count = pef2256_get_functions_count, + .get_function_name = pef2256_get_function_name, + .get_function_groups = pef2256_get_function_groups, + .set_mux = pef2256_set_mux, +}; + +#define PEF2256_PINCTRL_PIN(_number, _name, _offset, _mask) { \ + .number = _number, \ + .name = _name, \ + .drv_data = &(struct pef2256_pinreg_desc) { \ + .offset = _offset, \ + .mask = _mask, \ + }, \ +} + +static const struct pinctrl_pin_desc pef2256_v12_pins[] = { + PEF2256_PINCTRL_PIN(0, "RPA", PEF2256_PC1, PEF2256_12_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(1, "RPB", PEF2256_PC2, PEF2256_12_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(2, "RPC", PEF2256_PC3, PEF2256_12_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(3, "RPD", PEF2256_PC4, PEF2256_12_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(4, "XPA", PEF2256_PC1, PEF2256_12_PC_XPC_MASK), + PEF2256_PINCTRL_PIN(5, "XPB", PEF2256_PC2, PEF2256_12_PC_XPC_MASK), + PEF2256_PINCTRL_PIN(6, "XPC", PEF2256_PC3, PEF2256_12_PC_XPC_MASK), + PEF2256_PINCTRL_PIN(7, "XPD", PEF2256_PC4, PEF2256_12_PC_XPC_MASK), +}; + +static const struct pinctrl_pin_desc pef2256_v2x_pins[] = { + PEF2256_PINCTRL_PIN(0, "RPA", PEF2256_PC1, PEF2256_2X_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(1, "RPB", PEF2256_PC2, PEF2256_2X_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(2, "RPC", PEF2256_PC3, PEF2256_2X_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(3, "RPD", PEF2256_PC4, PEF2256_2X_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(4, "XPA", PEF2256_PC1, PEF2256_2X_PC_XPC_MASK), + PEF2256_PINCTRL_PIN(5, "XPB", PEF2256_PC2, PEF2256_2X_PC_XPC_MASK), + PEF2256_PINCTRL_PIN(6, "XPC", PEF2256_PC3, PEF2256_2X_PC_XPC_MASK), + PEF2256_PINCTRL_PIN(7, "XPD", PEF2256_PC4, PEF2256_2X_PC_XPC_MASK), +}; + +static const char *const pef2256_rp_groups[] = { "RPA", "RPB", "RPC", "RPD" }; +static const char *const pef2256_xp_groups[] = { "XPA", "XPB", "XPC", "XPD" }; +static const char *const pef2256_all_groups[] = { "RPA", "RPB", "RPC", "RPD", + "XPA", "XPB", "XPC", "XPD" }; + +#define PEF2256_FUNCTION(_name, _func_val, _groups) { \ + .name = _name, \ + .groups = _groups, \ + .ngroups = ARRAY_SIZE(_groups), \ + .func_val = _func_val, \ +} + +static const struct pef2256_function_desc pef2256_v2x_functions[] = { + PEF2256_FUNCTION("SYPR", PEF2256_2X_PC_RPC_SYPR, pef2256_rp_groups), + PEF2256_FUNCTION("RFM", PEF2256_2X_PC_RPC_RFM, pef2256_rp_groups), + PEF2256_FUNCTION("RFMB", PEF2256_2X_PC_RPC_RFMB, pef2256_rp_groups), + PEF2256_FUNCTION("RSIGM", PEF2256_2X_PC_RPC_RSIGM, pef2256_rp_groups), + PEF2256_FUNCTION("RSIG", PEF2256_2X_PC_RPC_RSIG, pef2256_rp_groups), + PEF2256_FUNCTION("DLR", PEF2256_2X_PC_RPC_DLR, pef2256_rp_groups), + PEF2256_FUNCTION("FREEZE", PEF2256_2X_PC_RPC_FREEZE, pef2256_rp_groups), + PEF2256_FUNCTION("RFSP", PEF2256_2X_PC_RPC_RFSP, pef2256_rp_groups), + PEF2256_FUNCTION("LOS", PEF2256_2X_PC_RPC_LOS, pef2256_rp_groups), + + PEF2256_FUNCTION("SYPX", PEF2256_2X_PC_XPC_SYPX, pef2256_xp_groups), + PEF2256_FUNCTION("XFMS", PEF2256_2X_PC_XPC_XFMS, pef2256_xp_groups), + PEF2256_FUNCTION("XSIG", PEF2256_2X_PC_XPC_XSIG, pef2256_xp_groups), + PEF2256_FUNCTION("TCLK", PEF2256_2X_PC_XPC_TCLK, pef2256_xp_groups), + PEF2256_FUNCTION("XMFB", PEF2256_2X_PC_XPC_XMFB, pef2256_xp_groups), + PEF2256_FUNCTION("XSIGM", PEF2256_2X_PC_XPC_XSIGM, pef2256_xp_groups), + PEF2256_FUNCTION("DLX", PEF2256_2X_PC_XPC_DLX, pef2256_xp_groups), + PEF2256_FUNCTION("XCLK", PEF2256_2X_PC_XPC_XCLK, pef2256_xp_groups), + PEF2256_FUNCTION("XLT", PEF2256_2X_PC_XPC_XLT, pef2256_xp_groups), + + PEF2256_FUNCTION("GPI", PEF2256_2X_PC_RPC_GPI | PEF2256_2X_PC_XPC_GPI, + pef2256_all_groups), + PEF2256_FUNCTION("GPOH", PEF2256_2X_PC_RPC_GPOH | PEF2256_2X_PC_XPC_GPOH, + pef2256_all_groups), + PEF2256_FUNCTION("GPOL", PEF2256_2X_PC_RPC_GPOL | PEF2256_2X_PC_XPC_GPOL, + pef2256_all_groups), +}; + +static const struct pef2256_function_desc pef2256_v12_functions[] = { + PEF2256_FUNCTION("SYPR", PEF2256_12_PC_RPC_SYPR, pef2256_rp_groups), + PEF2256_FUNCTION("RFM", PEF2256_12_PC_RPC_RFM, pef2256_rp_groups), + PEF2256_FUNCTION("RFMB", PEF2256_12_PC_RPC_RFMB, pef2256_rp_groups), + PEF2256_FUNCTION("RSIGM", PEF2256_12_PC_RPC_RSIGM, pef2256_rp_groups), + PEF2256_FUNCTION("RSIG", PEF2256_12_PC_RPC_RSIG, pef2256_rp_groups), + PEF2256_FUNCTION("DLR", PEF2256_12_PC_RPC_DLR, pef2256_rp_groups), + PEF2256_FUNCTION("FREEZE", PEF2256_12_PC_RPC_FREEZE, pef2256_rp_groups), + PEF2256_FUNCTION("RFSP", PEF2256_12_PC_RPC_RFSP, pef2256_rp_groups), + + PEF2256_FUNCTION("SYPX", PEF2256_12_PC_XPC_SYPX, pef2256_xp_groups), + PEF2256_FUNCTION("XFMS", PEF2256_12_PC_XPC_XFMS, pef2256_xp_groups), + PEF2256_FUNCTION("XSIG", PEF2256_12_PC_XPC_XSIG, pef2256_xp_groups), + PEF2256_FUNCTION("TCLK", PEF2256_12_PC_XPC_TCLK, pef2256_xp_groups), + PEF2256_FUNCTION("XMFB", PEF2256_12_PC_XPC_XMFB, pef2256_xp_groups), + PEF2256_FUNCTION("XSIGM", PEF2256_12_PC_XPC_XSIGM, pef2256_xp_groups), + PEF2256_FUNCTION("DLX", PEF2256_12_PC_XPC_DLX, pef2256_xp_groups), + PEF2256_FUNCTION("XCLK", PEF2256_12_PC_XPC_XCLK, pef2256_xp_groups), + PEF2256_FUNCTION("XLT", PEF2256_12_PC_XPC_XLT, pef2256_xp_groups), +}; + +static int pef2256_register_pinctrl(struct pef2256_pinctrl *pef2256) +{ + struct pinctrl_dev *pctrl; + + pef2256->pctrl_desc.name = dev_name(pef2256->dev); + pef2256->pctrl_desc.owner = THIS_MODULE; + pef2256->pctrl_desc.pctlops = &pef2256_pctlops; + pef2256->pctrl_desc.pmxops = &pef2256_pmxops; + if (pef2256->version == PEF2256_VERSION_1_2) { + pef2256->pctrl_desc.pins = pef2256_v12_pins; + pef2256->pctrl_desc.npins = ARRAY_SIZE(pef2256_v12_pins); + pef2256->functions = pef2256_v12_functions; + pef2256->nfunctions = ARRAY_SIZE(pef2256_v12_functions); + } else { + pef2256->pctrl_desc.pins = pef2256_v2x_pins; + pef2256->pctrl_desc.npins = ARRAY_SIZE(pef2256_v2x_pins); + pef2256->functions = pef2256_v2x_functions; + pef2256->nfunctions = ARRAY_SIZE(pef2256_v2x_functions); + } + + pctrl = devm_pinctrl_register(pef2256->dev, &pef2256->pctrl_desc, pef2256); + if (IS_ERR(pctrl)) { + dev_err(pef2256->dev, "pinctrl driver registration failed\n"); + return PTR_ERR(pctrl); + } + + return 0; +} + +static void pef2256_reset_pinmux(struct pef2256_pinctrl *pef2256) +{ + u8 val; + /* + * Reset values cannot be used. + * They define the SYPR/SYPX pin mux for all the RPx and XPx pins and + * Only one pin can be muxed to SYPR and one pin can be muxed to SYPX. + * Choose here an other reset value. + */ + if (pef2256->version == PEF2256_VERSION_1_2) + val = PEF2256_12_PC_XPC_XCLK | PEF2256_12_PC_RPC_RFSP; + else + val = PEF2256_2X_PC_XPC_GPI | PEF2256_2X_PC_RPC_GPI; + + regmap_write(pef2256->regmap, PEF2256_PC1, val); + regmap_write(pef2256->regmap, PEF2256_PC2, val); + regmap_write(pef2256->regmap, PEF2256_PC3, val); + regmap_write(pef2256->regmap, PEF2256_PC4, val); +} + +static int pef2256_pinctrl_probe(struct platform_device *pdev) +{ + struct pef2256_pinctrl *pef2256_pinctrl; + struct pef2256 *pef2256; + int ret; + + pef2256_pinctrl = devm_kzalloc(&pdev->dev, sizeof(*pef2256_pinctrl), GFP_KERNEL); + if (!pef2256_pinctrl) + return -ENOMEM; + + device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent)); + + pef2256 = dev_get_drvdata(pdev->dev.parent); + + pef2256_pinctrl->dev = &pdev->dev; + pef2256_pinctrl->regmap = pef2256_get_regmap(pef2256); + pef2256_pinctrl->version = pef2256_get_version(pef2256); + + platform_set_drvdata(pdev, pef2256_pinctrl); + + pef2256_reset_pinmux(pef2256_pinctrl); + ret = pef2256_register_pinctrl(pef2256_pinctrl); + if (ret) + return ret; + + return 0; +} + +static struct platform_driver pef2256_pinctrl_driver = { + .driver = { + .name = "lantiq-pef2256-pinctrl", + }, + .probe = pef2256_pinctrl_probe, +}; +module_platform_driver(pef2256_pinctrl_driver); + +MODULE_AUTHOR("Herve Codina "); +MODULE_DESCRIPTION("PEF2256 pin controller driver"); +MODULE_LICENSE("GPL"); From patchwork Fri Aug 18 16:39:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358149 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 BB6E21C2A1 for ; Fri, 18 Aug 2023 17:21:36 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A44B33AB9; Fri, 18 Aug 2023 10:21:35 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS7043g3cz9vjW; Fri, 18 Aug 2023 18:40:20 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id jX2E8Yz_LcNt; Fri, 18 Aug 2023 18:40:20 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zp0jXLz9vhj; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 0FC1F8B778; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id n2Wkn4ajzUFT; Fri, 18 Aug 2023 18:40:05 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id CA60C8B76C; Fri, 18 Aug 2023 18:40:04 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGe0qs142047 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:40:00 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGe0rD142046; Fri, 18 Aug 2023 18:40:00 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 26/28] MAINTAINERS: Add the Lantiq PEF2256 driver entry Date: Fri, 18 Aug 2023 18:39:20 +0200 Message-ID: <753417cb7883179cf563e58062f2bf88d4c0f07c.1692376361.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376736; l=1004; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=l7R2/11nmFX+6PYVUwKCiARIreP8vujBb/Iu+qgqw+o=; b=rCIBSFY0/gc9QXNyrSYSJXQaiieAfwkDslMa7roSO2fwraDQHzzekb+d6739UbZxRVOuWuqJK A8AFJC43zxSBCQryjPJM5kenO96ctX7qyPvofJes9ZB26UtqNjzF+Yb X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina After contributing the driver, add myself as the maintainer for the Lantiq PEF2256 driver. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index e77a7eaef1cb..6db272911776 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11777,6 +11777,15 @@ S: Maintained F: arch/mips/lantiq F: drivers/soc/lantiq +LANTIQ PEF2256 DRIVER +M: Herve Codina +S: Maintained +F: Documentation/devicetree/bindings/net/lantiq,pef2256.yaml +F: drivers/net/wan/framer/pef2256/ +F: drivers/pinctrl/pinctrl-pef2256-regs.h +F: drivers/pinctrl/pinctrl-pef2256.c +F: include/linux/framer/pef2256.h + LASI 53c700 driver for PARISC M: "James E.J. Bottomley" L: linux-scsi@vger.kernel.org From patchwork Fri Aug 18 16:39:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358135 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 809541AA97 for ; Fri, 18 Aug 2023 17:20:42 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 396634216; Fri, 18 Aug 2023 10:20:40 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS7091GSjz9vjp; Fri, 18 Aug 2023 18:40:25 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 79uZvd4UaR-w; Fri, 18 Aug 2023 18:40:25 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zq114pz9vhJ; Fri, 18 Aug 2023 18:40:07 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 1806F8B763; Fri, 18 Aug 2023 18:40:07 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id r-OYOeLLKIfO; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id E09D98B776; Fri, 18 Aug 2023 18:40:04 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGe0CP142051 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:40:00 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGe0Y8142050; Fri, 18 Aug 2023 18:40:00 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 27/28] ASoC: codecs: Add support for the framer codec Date: Fri, 18 Aug 2023 18:39:21 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376736; l=15355; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=O71cjLS5k9OU/3WHIKQEqcQlZBrYzbIS16KsUPZgULE=; b=e1SeH0+hJUk/INUGhPhTFqVyrVxTzE4K9XZm+pgScYQi9tI2IAVJ7kKsnjkp9srspv3ObPTyb 6iG2NFRnhO0A7GQ+QX2J1ZIglbl57rNwIywlx/2QD828lH+P/k6C0wG X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Herve Codina The framer codec interracts with a framer. It allows to use some of the framer timeslots as audio channels to transport audio data over the framer E1/T1/J1 lines. It also reports line carrier detection events through the ALSA jack detection feature. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- sound/soc/codecs/Kconfig | 15 ++ sound/soc/codecs/Makefile | 2 + sound/soc/codecs/framer-codec.c | 413 ++++++++++++++++++++++++++++++++ 3 files changed, 430 insertions(+) create mode 100644 sound/soc/codecs/framer-codec.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index c2de4ee72183..1de6a9816190 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -109,6 +109,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_ES8328_I2C imply SND_SOC_ES7134 imply SND_SOC_ES7241 + imply SND_SOC_FRAMER imply SND_SOC_GTM601 imply SND_SOC_HDAC_HDMI imply SND_SOC_HDAC_HDA @@ -1032,6 +1033,20 @@ config SND_SOC_ES8328_SPI depends on SPI_MASTER select SND_SOC_ES8328 +config SND_SOC_FRAMER + tristate "Framer codec" + depends on GENERIC_FRAMER + help + Enable support for the framer codec. + The framer codec uses the generic framer infrastructure to transport + some audio data over an analog E1/T1/J1 line. + This codec allows to use some of the time slots available on the TDM + bus on which the framer is connected to transport the audio data. + + To compile this driver as a module, choose M here: the module + will be called snd-soc-framer. + + config SND_SOC_GTM601 tristate 'GTM601 UMTS modem audio codec' diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index b48a9a323b84..b40c5f06caaf 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -115,6 +115,7 @@ snd-soc-es8326-objs := es8326.o snd-soc-es8328-objs := es8328.o snd-soc-es8328-i2c-objs := es8328-i2c.o snd-soc-es8328-spi-objs := es8328-spi.o +snd-soc-framer-objs := framer-codec.o snd-soc-gtm601-objs := gtm601.o snd-soc-hdac-hdmi-objs := hdac_hdmi.o snd-soc-hdac-hda-objs := hdac_hda.o @@ -497,6 +498,7 @@ obj-$(CONFIG_SND_SOC_ES8326) += snd-soc-es8326.o obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o +obj-$(CONFIG_SND_SOC_FRAMER) += snd-soc-framer.o obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o obj-$(CONFIG_SND_SOC_HDAC_HDA) += snd-soc-hdac-hda.o diff --git a/sound/soc/codecs/framer-codec.c b/sound/soc/codecs/framer-codec.c new file mode 100644 index 000000000000..e5fcde9ee308 --- /dev/null +++ b/sound/soc/codecs/framer-codec.c @@ -0,0 +1,413 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Framer ALSA SoC driver +// +// Copyright 2023 CS GROUP France +// +// Author: Herve Codina + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FRAMER_NB_CHANNEL 32 +#define FRAMER_JACK_MASK (SND_JACK_LINEIN | SND_JACK_LINEOUT) + +struct framer_codec { + struct framer *framer; + struct device *dev; + struct snd_soc_jack jack; + struct notifier_block nb; + struct work_struct carrier_work; + int max_chan_playback; + int max_chan_capture; +}; + +static int framer_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int width) +{ + struct framer_codec *framer = snd_soc_component_get_drvdata(dai->component); + + switch (width) { + case 0: + /* Not set -> default 8 */ + case 8: + break; + default: + dev_err(dai->dev, "tdm slot width %d not supported\n", width); + return -EINVAL; + } + + framer->max_chan_playback = hweight32(tx_mask); + if (framer->max_chan_playback > FRAMER_NB_CHANNEL) { + dev_err(dai->dev, "too many tx slots defined (mask = 0x%x) supported max %d\n", + tx_mask, FRAMER_NB_CHANNEL); + return -EINVAL; + } + + framer->max_chan_capture = hweight32(rx_mask); + if (framer->max_chan_capture > FRAMER_NB_CHANNEL) { + dev_err(dai->dev, "too many rx slots defined (mask = 0x%x) supported max %d\n", + rx_mask, FRAMER_NB_CHANNEL); + return -EINVAL; + } + + return 0; +} + +/* + * The constraints for format/channel is to match with the number of 8bit + * time-slots available. + */ +static int framer_dai_hw_rule_channels_by_format(struct snd_soc_dai *dai, + struct snd_pcm_hw_params *params, + unsigned int nb_ts) +{ + struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + snd_pcm_format_t format = params_format(params); + struct snd_interval ch = {0}; + int width; + + width = snd_pcm_format_physical_width(format); + if (width == 8 || width == 16 || width == 32 || width == 64) { + ch.max = nb_ts * 8 / width; + } else { + dev_err(dai->dev, "format physical width %d not supported\n", width); + return -EINVAL; + } + + ch.min = ch.max ? 1 : 0; + + return snd_interval_refine(c, &ch); +} + +static int framer_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_soc_dai *dai = rule->private; + struct framer_codec *framer = snd_soc_component_get_drvdata(dai->component); + + return framer_dai_hw_rule_channels_by_format(dai, params, framer->max_chan_playback); +} + +static int framer_dai_hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_soc_dai *dai = rule->private; + struct framer_codec *framer = snd_soc_component_get_drvdata(dai->component); + + return framer_dai_hw_rule_channels_by_format(dai, params, framer->max_chan_capture); +} + +static int framer_dai_hw_rule_format_by_channels(struct snd_soc_dai *dai, + struct snd_pcm_hw_params *params, + unsigned int nb_ts) +{ + struct snd_mask *f_old = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + unsigned int channels = params_channels(params); + unsigned int slot_width; + snd_pcm_format_t format; + struct snd_mask f_new; + + if (!channels || channels > nb_ts) { + dev_err(dai->dev, "channels %u not supported\n", nb_ts); + return -EINVAL; + } + + slot_width = (nb_ts / channels) * 8; + + snd_mask_none(&f_new); + pcm_for_each_format(format) { + if (snd_mask_test_format(f_old, format)) { + if (snd_pcm_format_physical_width(format) <= slot_width) + snd_mask_set_format(&f_new, format); + } + } + + return snd_mask_refine(f_old, &f_new); +} + +static int framer_dai_hw_rule_playback_format_by_channels(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_soc_dai *dai = rule->private; + struct framer_codec *framer = snd_soc_component_get_drvdata(dai->component); + + return framer_dai_hw_rule_format_by_channels(dai, params, framer->max_chan_playback); +} + +static int framer_dai_hw_rule_capture_format_by_channels(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_soc_dai *dai = rule->private; + struct framer_codec *framer = snd_soc_component_get_drvdata(dai->component); + + return framer_dai_hw_rule_format_by_channels(dai, params, framer->max_chan_capture); +} + +static u64 framer_formats(u8 nb_ts) +{ + unsigned int format_width; + unsigned int chan_width; + snd_pcm_format_t format; + u64 formats_mask; + + if (!nb_ts) + return 0; + + formats_mask = 0; + chan_width = nb_ts * 8; + pcm_for_each_format(format) { + /* Support physical width multiple of 8bit */ + format_width = snd_pcm_format_physical_width(format); + if (format_width == 0 || format_width % 8) + continue; + + /* + * And support physical width that can fit N times in the + * channel + */ + if (format_width > chan_width || chan_width % format_width) + continue; + + formats_mask |= pcm_format_to_bits(format); + } + return formats_mask; +} + +static int framer_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct framer_codec *framer = snd_soc_component_get_drvdata(dai->component); + snd_pcm_hw_rule_func_t hw_rule_channels_by_format; + snd_pcm_hw_rule_func_t hw_rule_format_by_channels; + unsigned int frame_bits; + u64 format; + int ret; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + format = framer_formats(framer->max_chan_capture); + hw_rule_channels_by_format = framer_dai_hw_rule_capture_channels_by_format; + hw_rule_format_by_channels = framer_dai_hw_rule_capture_format_by_channels; + frame_bits = framer->max_chan_capture * 8; + } else { + format = framer_formats(framer->max_chan_playback); + hw_rule_channels_by_format = framer_dai_hw_rule_playback_channels_by_format; + hw_rule_format_by_channels = framer_dai_hw_rule_playback_format_by_channels; + frame_bits = framer->max_chan_playback * 8; + } + + ret = snd_pcm_hw_constraint_mask64(substream->runtime, + SNDRV_PCM_HW_PARAM_FORMAT, format); + if (ret) { + dev_err(dai->dev, "Failed to add format constraint (%d)\n", ret); + return ret; + } + + ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + hw_rule_channels_by_format, dai, + SNDRV_PCM_HW_PARAM_FORMAT, -1); + if (ret) { + dev_err(dai->dev, "Failed to add channels rule (%d)\n", ret); + return ret; + } + + ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, + hw_rule_format_by_channels, dai, + SNDRV_PCM_HW_PARAM_CHANNELS, -1); + if (ret) { + dev_err(dai->dev, "Failed to add format rule (%d)\n", ret); + return ret; + } + + ret = snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_FRAME_BITS, + frame_bits); + if (ret < 0) { + dev_err(dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); + return ret; + } + + return 0; +} + +static u64 framer_dai_formats[] = { + SND_SOC_POSSIBLE_DAIFMT_DSP_B, +}; + +static const struct snd_soc_dai_ops framer_dai_ops = { + .startup = framer_dai_startup, + .set_tdm_slot = framer_dai_set_tdm_slot, + .auto_selectable_formats = framer_dai_formats, + .num_auto_selectable_formats = ARRAY_SIZE(framer_dai_formats), +}; + +static struct snd_soc_dai_driver framer_dai_driver = { + .name = "framer", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = FRAMER_NB_CHANNEL, + .rates = SNDRV_PCM_RATE_8000, + .formats = U64_MAX, /* Will be refined on DAI .startup() */ + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = FRAMER_NB_CHANNEL, + .rates = SNDRV_PCM_RATE_8000, + .formats = U64_MAX, /* Will be refined on DAI .startup() */ + }, + .ops = &framer_dai_ops, +}; + +static void framer_carrier_work(struct work_struct *work) +{ + struct framer_codec *framer = container_of(work, struct framer_codec, carrier_work); + struct framer_status framer_status; + int jack_status; + int ret; + + ret = framer_get_status(framer->framer, &framer_status); + if (ret) { + dev_err(framer->dev, "get framer status failed (%d)\n", ret); + return; + } + + jack_status = framer_status.link_is_on ? FRAMER_JACK_MASK : 0; + snd_soc_jack_report(&framer->jack, jack_status, FRAMER_JACK_MASK); +} + +static int framer_carrier_notifier(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct framer_codec *framer = container_of(nb, struct framer_codec, nb); + + switch (action) { + case FRAMER_EVENT_STATUS: + queue_work(system_power_efficient_wq, &framer->carrier_work); + break; + default: + return NOTIFY_DONE; + } + + return NOTIFY_OK; +} + +static int framer_component_probe(struct snd_soc_component *component) +{ + struct framer_codec *framer = snd_soc_component_get_drvdata(component); + struct framer_status status; + char *name; + int ret; + + INIT_WORK(&framer->carrier_work, framer_carrier_work); + + name = "carrier"; + if (component->name_prefix) { + name = kasprintf(GFP_KERNEL, "%s carrier", component->name_prefix); + if (!name) + return -ENOMEM; + } + + ret = snd_soc_card_jack_new(component->card, name, FRAMER_JACK_MASK, &framer->jack); + if (component->name_prefix) + kfree(name); /* A copy is done by snd_soc_card_jack_new */ + if (ret) { + dev_err(component->dev, "Cannot create jack\n"); + return ret; + } + + ret = framer_init(framer->framer); + if (ret) { + dev_err(component->dev, "framer init failed (%d)\n", ret); + return ret; + } + + ret = framer_power_on(framer->framer); + if (ret) { + dev_err(component->dev, "framer power-on failed (%d)\n", ret); + goto framer_exit; + } + + /* Be sure that get_status is supported */ + ret = framer_get_status(framer->framer, &status); + if (ret) { + dev_err(component->dev, "get framer status failed (%d)\n", ret); + goto framer_power_off; + } + + framer->nb.notifier_call = framer_carrier_notifier; + ret = framer_notifier_register(framer->framer, &framer->nb); + if (ret) { + dev_err(component->dev, "Cannot register event notifier\n"); + goto framer_power_off; + } + + /* Queue work to set the initial value */ + queue_work(system_power_efficient_wq, &framer->carrier_work); + + return 0; + +framer_power_off: + framer_power_off(framer->framer); +framer_exit: + framer_exit(framer->framer); + return ret; +} + +static void framer_component_remove(struct snd_soc_component *component) +{ + struct framer_codec *framer = snd_soc_component_get_drvdata(component); + + framer_notifier_unregister(framer->framer, &framer->nb); + cancel_work_sync(&framer->carrier_work); + framer_power_off(framer->framer); + framer_exit(framer->framer); +} + +static const struct snd_soc_component_driver framer_component_driver = { + .probe = framer_component_probe, + .remove = framer_component_remove, + .endianness = 1, +}; + +static int framer_codec_probe(struct platform_device *pdev) +{ + struct framer_codec *framer; + + framer = devm_kzalloc(&pdev->dev, sizeof(*framer), GFP_KERNEL); + if (!framer) + return -ENOMEM; + + framer->dev = &pdev->dev; + + /* Get framer from parents node */ + framer->framer = devm_framer_get(&pdev->dev, NULL); + if (IS_ERR(framer->framer)) + return dev_err_probe(&pdev->dev, PTR_ERR(framer->framer), "get framer failed\n"); + + platform_set_drvdata(pdev, framer); + + return devm_snd_soc_register_component(&pdev->dev, &framer_component_driver, + &framer_dai_driver, 1); +} + +static struct platform_driver framer_codec_driver = { + .driver = { + .name = "framer-codec", + }, + .probe = framer_codec_probe, +}; +module_platform_driver(framer_codec_driver); + +MODULE_AUTHOR("Herve Codina "); +MODULE_DESCRIPTION("FRAMER ALSA SoC driver"); +MODULE_LICENSE("GPL"); From patchwork Fri Aug 18 16:39:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Leroy X-Patchwork-Id: 13358144 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (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 8FA371BB30 for ; Fri, 18 Aug 2023 17:21:21 +0000 (UTC) Received: from pegase1.c-s.fr (unknown [90.115.179.12]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8EDD64210; Fri, 18 Aug 2023 10:21:19 -0700 (PDT) Received: from localhost (mailhub3.si.c-s.fr [192.168.12.233]) by localhost (Postfix) with ESMTP id 4RS7081Zjnz9vjl; Fri, 18 Aug 2023 18:40:24 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ZdBsb51iqtzc; Fri, 18 Aug 2023 18:40:24 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4RS6zp740Kz9vhq; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id E9A808B763; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id U-vlUOJ5AxeO; Fri, 18 Aug 2023 18:40:06 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (PO17626.IDSI0.si.c-s.fr [172.19.54.29]) by messagerie.si.c-s.fr (Postfix) with ESMTP id D14BA8B76E; Fri, 18 Aug 2023 18:40:04 +0200 (CEST) Received: from PO20335.IDSI0.si.c-s.fr (localhost [127.0.0.1]) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.16.1) with ESMTPS id 37IGe1wE142062 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Aug 2023 18:40:01 +0200 Received: (from chleroy@localhost) by PO20335.IDSI0.si.c-s.fr (8.17.1/8.17.1/Submit) id 37IGe1RS142060; Fri, 18 Aug 2023 18:40:01 +0200 X-Authentication-Warning: PO20335.IDSI0.si.c-s.fr: chleroy set sender to christophe.leroy@csgroup.eu using -f From: Christophe Leroy To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Thomas Petazzoni Subject: [PATCH v4 28/28] net: wan: fsl_qmc_hdlc: Add framer support Date: Fri, 18 Aug 2023 18:39:22 +0200 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1692376736; l=9256; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=RvHkc8ehF1HbXgq/GBw8B5vNFJTvQ6oKhwEXtv8NNIw=; b=vp0Qf80njQjfZJHhjiV5Q7qXe01mNvlbvYUWfL6pHZ8p21BXYNG54AkpdCEhp03nMLQ5ebT0i qxJOqGJ65AxCfYn0SsM9VXCIa5OxWdJVVZtP3eYs0OD5ZZXqhtHeHXv X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE,SPF_FAIL, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org From: Herve Codina Add framer support in the fsl_qmc_hdlc driver in order to be able to signal carrier changes to the network stack based on the framer status Also use this framer to provide information related to the E1/T1 line interface on IF_GET_IFACE and configure the line interface according to IF_IFACE_{E1,T1} information. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Signed-off-by: Christophe Leroy --- drivers/net/wan/fsl_qmc_hdlc.c | 239 ++++++++++++++++++++++++++++++++- 1 file changed, 235 insertions(+), 4 deletions(-) diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c index 4b8cb5761fd1..3efed8fedb40 100644 --- a/drivers/net/wan/fsl_qmc_hdlc.c +++ b/drivers/net/wan/fsl_qmc_hdlc.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -27,6 +28,9 @@ struct qmc_hdlc { struct device *dev; struct qmc_chan *qmc_chan; struct net_device *netdev; + struct framer *framer; + spinlock_t carrier_lock; /* Protect carrier detection */ + struct notifier_block nb; bool is_crc32; spinlock_t tx_lock; /* Protect tx descriptors */ struct qmc_hdlc_desc tx_descs[8]; @@ -40,6 +44,195 @@ static inline struct qmc_hdlc *netdev_to_qmc_hdlc(struct net_device *netdev) return dev_to_hdlc(netdev)->priv; } +static int qmc_hdlc_framer_set_carrier(struct qmc_hdlc *qmc_hdlc) +{ + struct framer_status framer_status; + unsigned long flags; + int ret; + + if (!qmc_hdlc->framer) + return 0; + + spin_lock_irqsave(&qmc_hdlc->carrier_lock, flags); + + ret = framer_get_status(qmc_hdlc->framer, &framer_status); + if (ret) { + dev_err(qmc_hdlc->dev, "get framer status failed (%d)\n", ret); + goto end; + } + if (framer_status.link_is_on) + netif_carrier_on(qmc_hdlc->netdev); + else + netif_carrier_off(qmc_hdlc->netdev); + +end: + spin_unlock_irqrestore(&qmc_hdlc->carrier_lock, flags); + return ret; +} + +static int qmc_hdlc_framer_notifier(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct qmc_hdlc *qmc_hdlc = container_of(nb, struct qmc_hdlc, nb); + int ret; + + if (action != FRAMER_EVENT_STATUS) + return NOTIFY_DONE; + + ret = qmc_hdlc_framer_set_carrier(qmc_hdlc); + return ret ? NOTIFY_DONE : NOTIFY_OK; +} + +static int qmc_hdlc_framer_start(struct qmc_hdlc *qmc_hdlc) +{ + struct framer_status framer_status; + int ret; + + if (!qmc_hdlc->framer) + return 0; + + ret = framer_power_on(qmc_hdlc->framer); + if (ret) { + dev_err(qmc_hdlc->dev, "framer power-on failed (%d)\n", ret); + return ret; + } + + /* Be sure that get_status is supported */ + ret = framer_get_status(qmc_hdlc->framer, &framer_status); + if (ret) { + dev_err(qmc_hdlc->dev, "get framer status failed (%d)\n", ret); + goto framer_power_off; + } + + qmc_hdlc->nb.notifier_call = qmc_hdlc_framer_notifier; + ret = framer_notifier_register(qmc_hdlc->framer, &qmc_hdlc->nb); + if (ret) { + dev_err(qmc_hdlc->dev, "framer notifier register failed (%d)\n", ret); + goto framer_power_off; + } + + return 0; + +framer_power_off: + framer_power_off(qmc_hdlc->framer); + return ret; +} + +static void qmc_hdlc_framer_stop(struct qmc_hdlc *qmc_hdlc) +{ + if (!qmc_hdlc->framer) + return; + + framer_notifier_unregister(qmc_hdlc->framer, &qmc_hdlc->nb); + framer_power_off(qmc_hdlc->framer); +} + +static int qmc_hdlc_framer_set_iface(struct qmc_hdlc *qmc_hdlc, int if_iface, + const te1_settings *te1) +{ + struct framer_config config; + int ret; + + if (!qmc_hdlc->framer) + return 0; + + ret = framer_get_config(qmc_hdlc->framer, &config); + if (ret) + return ret; + + switch (if_iface) { + case IF_IFACE_E1: + config.iface = FRAMER_IFACE_E1; + break; + case IF_IFACE_T1: + config.iface = FRAMER_IFACE_T1; + break; + default: + return -EINVAL; + } + + switch (te1->clock_type) { + case CLOCK_DEFAULT: + /* Keep current value */ + break; + case CLOCK_EXT: + config.clock_type = FRAMER_CLOCK_EXT; + break; + case CLOCK_INT: + config.clock_type = FRAMER_CLOCK_INT; + break; + default: + return -EINVAL; + } + config.line_clock_rate = te1->clock_rate; + + return framer_set_config(qmc_hdlc->framer, &config); +} + +static int qmc_hdlc_framer_get_iface(struct qmc_hdlc *qmc_hdlc, int *if_iface, te1_settings *te1) +{ + struct framer_config config; + int ret; + + if (!qmc_hdlc->framer) { + *if_iface = IF_IFACE_E1; + return 0; + } + + ret = framer_get_config(qmc_hdlc->framer, &config); + if (ret) + return ret; + + switch (config.iface) { + case FRAMER_IFACE_E1: + *if_iface = IF_IFACE_E1; + break; + case FRAMER_IFACE_T1: + *if_iface = IF_IFACE_T1; + break; + } + + if (!te1) + return 0; /* Only iface type requested */ + + switch (config.clock_type) { + case FRAMER_CLOCK_EXT: + te1->clock_type = CLOCK_EXT; + break; + case FRAMER_CLOCK_INT: + te1->clock_type = CLOCK_INT; + break; + default: + return -EINVAL; + } + te1->clock_rate = config.line_clock_rate; + return 0; +} + +static int qmc_hdlc_framer_init(struct qmc_hdlc *qmc_hdlc) +{ + int ret; + + if (!qmc_hdlc->framer) + return 0; + + ret = framer_init(qmc_hdlc->framer); + if (ret) { + dev_err(qmc_hdlc->dev, "framer init failed (%d)\n", ret); + return ret; + } + + return 0; +} + +static void qmc_hdlc_framer_exit(struct qmc_hdlc *qmc_hdlc) +{ + if (!qmc_hdlc->framer) + return; + + framer_exit(qmc_hdlc->framer); +} + static int qmc_hdlc_recv_queue(struct qmc_hdlc *qmc_hdlc, struct qmc_hdlc_desc *desc, size_t size); #define QMC_HDLC_RX_ERROR_FLAGS (QMC_RX_FLAG_HDLC_OVF | \ @@ -313,6 +506,12 @@ static int qmc_hdlc_set_iface(struct qmc_hdlc *qmc_hdlc, int if_iface, const te1 qmc_hdlc->slot_map = te1->slot_map; + ret = qmc_hdlc_framer_set_iface(qmc_hdlc, if_iface, te1); + if (ret) { + dev_err(qmc_hdlc->dev, "framer set iface failed %d\n", ret); + return ret; + } + return 0; } @@ -320,11 +519,16 @@ static int qmc_hdlc_ioctl(struct net_device *netdev, struct if_settings *ifs) { struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(netdev); te1_settings te1; + int ret; switch (ifs->type) { case IF_GET_IFACE: - ifs->type = IF_IFACE_E1; if (ifs->size < sizeof(te1)) { + /* Retrieve type only */ + ret = qmc_hdlc_framer_get_iface(qmc_hdlc, &ifs->type, NULL); + if (ret) + return ret; + if (!ifs->size) return 0; /* only type requested */ @@ -334,6 +538,11 @@ static int qmc_hdlc_ioctl(struct net_device *netdev, struct if_settings *ifs) memset(&te1, 0, sizeof(te1)); + /* Retrieve info from framer */ + ret = qmc_hdlc_framer_get_iface(qmc_hdlc, &ifs->type, &te1); + if (ret) + return ret; + /* Update slot_map */ te1.slot_map = qmc_hdlc->slot_map; @@ -367,10 +576,17 @@ static int qmc_hdlc_open(struct net_device *netdev) int ret; int i; - ret = hdlc_open(netdev); + ret = qmc_hdlc_framer_start(qmc_hdlc); if (ret) return ret; + ret = hdlc_open(netdev); + if (ret) + goto framer_stop; + + /* Update carrier */ + qmc_hdlc_framer_set_carrier(qmc_hdlc); + chan_param.mode = QMC_HDLC; /* HDLC_MAX_MRU + 4 for the CRC * HDLC_MAX_MRU + 4 + 8 for the CRC and some extraspace needed by the QMC @@ -420,6 +636,8 @@ static int qmc_hdlc_open(struct net_device *netdev) } hdlc_close: hdlc_close(netdev); +framer_stop: + qmc_hdlc_framer_stop(qmc_hdlc); return ret; } @@ -455,6 +673,7 @@ static int qmc_hdlc_close(struct net_device *netdev) } hdlc_close(netdev); + qmc_hdlc_framer_stop(qmc_hdlc); return 0; } @@ -503,6 +722,7 @@ static int qmc_hdlc_probe(struct platform_device *pdev) qmc_hdlc->dev = &pdev->dev; spin_lock_init(&qmc_hdlc->tx_lock); + spin_lock_init(&qmc_hdlc->carrier_lock); qmc_hdlc->qmc_chan = devm_qmc_chan_get_byphandle(qmc_hdlc->dev, np, "fsl,qmc-chan"); if (IS_ERR(qmc_hdlc->qmc_chan)) { @@ -531,10 +751,19 @@ static int qmc_hdlc_probe(struct platform_device *pdev) if (ret) return ret; + qmc_hdlc->framer = devm_framer_optional_get(qmc_hdlc->dev, "framer"); + if (IS_ERR(qmc_hdlc->framer)) + return PTR_ERR(qmc_hdlc->framer); + + ret = qmc_hdlc_framer_init(qmc_hdlc); + if (ret) + return ret; + qmc_hdlc->netdev = alloc_hdlcdev(qmc_hdlc); if (!qmc_hdlc->netdev) { dev_err(qmc_hdlc->dev, "failed to alloc hdlc dev\n"); - return -ENOMEM; + ret = -ENOMEM; + goto framer_exit; } hdlc = dev_to_hdlc(qmc_hdlc->netdev); @@ -550,11 +779,12 @@ static int qmc_hdlc_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, qmc_hdlc); - return 0; free_netdev: free_netdev(qmc_hdlc->netdev); +framer_exit: + qmc_hdlc_framer_exit(qmc_hdlc); return ret; } @@ -564,6 +794,7 @@ static int qmc_hdlc_remove(struct platform_device *pdev) unregister_hdlc_device(qmc_hdlc->netdev); free_netdev(qmc_hdlc->netdev); + qmc_hdlc_framer_exit(qmc_hdlc); return 0; }