From patchwork Thu Jun 1 03:01:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 13262943 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 0600B1FB2 for ; Thu, 1 Jun 2023 03:10:31 +0000 (UTC) Received: from smtpbgsg1.qq.com (smtpbgsg1.qq.com [54.254.200.92]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4951A132 for ; Wed, 31 May 2023 20:10:05 -0700 (PDT) X-QQ-mid: bizesmtp86t1685588636tp18zgb9 Received: from wxdbg.localdomain.com ( [183.159.96.128]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 01 Jun 2023 11:03:51 +0800 (CST) X-QQ-SSF: 01400000000000J0Z000000A0000000 X-QQ-FEAT: l1AKOOPZQseDl74Xrtn4rIrnIIm5ieYDwoGZUiczcgY4VpN1J/g/e5903KIXc uVcJ45yBlu099MXmukrW3zF2YRV6SxjwK2JoCPJgEBzENXENkAsmAv6Zs4BjDmbxvALc8Co /JGz08FcsrVApp9yFXGPM9THUgexihQHiRkaNZDOCLi2a7mGULvV/08pxEh2c0aol/d7/JW zTTO3ZhEp9HTEs1mSQ/OqB1ffJoA1mMS64XMYrxQzSxSu53Y0IfMWXZBwXywTIEb9vamDbV 4bXHdguLcJygsofYG9PrZy4Kj1XBoYBUSi+dLzj9Kuza4gl14iNubWA0CNUvfzpej2kRzE3 OeVYhNNEIm+U0jCl3HrqrXxR8Vjcd8T95nrSSrn8UBPm4P3/W5Shcof4oUq1TXm3lb3vgo0 SLWvYMpj8puCXP/q9F6nWda8gu9csLHr X-QQ-GoodBg: 2 X-BIZMAIL-ID: 5402096642234420979 From: Jiawen Wu To: netdev@vger.kernel.org, jarkko.nikula@linux.intel.com, andriy.shevchenko@linux.intel.com, mika.westerberg@linux.intel.com, jsd@semihalf.com, Jose.Abreu@synopsys.com, andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu , Piotr Raczynski Subject: [PATCH net-next v10 1/9] net: txgbe: Add software nodes to support phylink Date: Thu, 1 Jun 2023 11:01:32 +0800 Message-Id: <20230601030140.687493-2-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230601030140.687493-1-jiawenwu@trustnetic.com> References: <20230601030140.687493-1-jiawenwu@trustnetic.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvrgz:qybglogicsvrgz5a-1 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham 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 Register software nodes for GPIO, I2C, SFP and PHYLINK. Define the device properties. Signed-off-by: Jiawen Wu Reviewed-by: Andrew Lunn Reviewed-by: Piotr Raczynski --- drivers/net/ethernet/wangxun/libwx/wx_type.h | 1 + drivers/net/ethernet/wangxun/txgbe/Makefile | 1 + .../net/ethernet/wangxun/txgbe/txgbe_main.c | 22 ++++- .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 89 +++++++++++++++++++ .../net/ethernet/wangxun/txgbe/txgbe_phy.h | 10 +++ .../net/ethernet/wangxun/txgbe/txgbe_type.h | 49 ++++++++++ 6 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c create mode 100644 drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index cbe7f184b50e..f59066d7375c 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -611,6 +611,7 @@ enum wx_isb_idx { struct wx { u8 __iomem *hw_addr; + void *priv; struct pci_dev *pdev; struct net_device *netdev; struct wx_bus_info bus; diff --git a/drivers/net/ethernet/wangxun/txgbe/Makefile b/drivers/net/ethernet/wangxun/txgbe/Makefile index 6db14a2cb2d0..7507f762edfe 100644 --- a/drivers/net/ethernet/wangxun/txgbe/Makefile +++ b/drivers/net/ethernet/wangxun/txgbe/Makefile @@ -8,4 +8,5 @@ obj-$(CONFIG_TXGBE) += txgbe.o txgbe-objs := txgbe_main.o \ txgbe_hw.o \ + txgbe_phy.o \ txgbe_ethtool.o diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index 5b8a121fb496..e10296abf5b4 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -15,6 +15,7 @@ #include "../libwx/wx_hw.h" #include "txgbe_type.h" #include "txgbe_hw.h" +#include "txgbe_phy.h" #include "txgbe_ethtool.h" char txgbe_driver_name[] = "txgbe"; @@ -513,6 +514,7 @@ static int txgbe_probe(struct pci_dev *pdev, struct net_device *netdev; int err, expected_gts; struct wx *wx = NULL; + struct txgbe *txgbe; u16 eeprom_verh = 0, eeprom_verl = 0, offset = 0; u16 eeprom_cfg_blkh = 0, eeprom_cfg_blkl = 0; @@ -663,10 +665,23 @@ static int txgbe_probe(struct pci_dev *pdev, "0x%08x", etrack_id); } - err = register_netdev(netdev); + txgbe = devm_kzalloc(&pdev->dev, sizeof(*txgbe), GFP_KERNEL); + if (!txgbe) { + err = -ENOMEM; + goto err_release_hw; + } + + txgbe->wx = wx; + wx->priv = txgbe; + + err = txgbe_init_phy(txgbe); if (err) goto err_release_hw; + err = register_netdev(netdev); + if (err) + goto err_remove_phy; + pci_set_drvdata(pdev, wx); netif_tx_stop_all_queues(netdev); @@ -694,6 +709,8 @@ static int txgbe_probe(struct pci_dev *pdev, return 0; +err_remove_phy: + txgbe_remove_phy(txgbe); err_release_hw: wx_clear_interrupt_scheme(wx); wx_control_hw(wx, false); @@ -719,11 +736,14 @@ static int txgbe_probe(struct pci_dev *pdev, static void txgbe_remove(struct pci_dev *pdev) { struct wx *wx = pci_get_drvdata(pdev); + struct txgbe *txgbe = wx->priv; struct net_device *netdev; netdev = wx->netdev; unregister_netdev(netdev); + txgbe_remove_phy(txgbe); + pci_release_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM)); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c new file mode 100644 index 000000000000..be4b5ad74a3c --- /dev/null +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */ + +#include +#include +#include + +#include "../libwx/wx_type.h" +#include "txgbe_type.h" +#include "txgbe_phy.h" + +static int txgbe_swnodes_register(struct txgbe *txgbe) +{ + struct txgbe_nodes *nodes = &txgbe->nodes; + struct pci_dev *pdev = txgbe->wx->pdev; + struct software_node *swnodes; + u32 id; + + id = (pdev->bus->number << 8) | pdev->devfn; + + snprintf(nodes->gpio_name, sizeof(nodes->gpio_name), "txgbe_gpio-%x", id); + snprintf(nodes->i2c_name, sizeof(nodes->i2c_name), "txgbe_i2c-%x", id); + snprintf(nodes->sfp_name, sizeof(nodes->sfp_name), "txgbe_sfp-%x", id); + snprintf(nodes->phylink_name, sizeof(nodes->phylink_name), "txgbe_phylink-%x", id); + + swnodes = nodes->swnodes; + + /* GPIO 0: tx fault + * GPIO 1: tx disable + * GPIO 2: sfp module absent + * GPIO 3: rx signal lost + * GPIO 4: rate select, 1G(0) 10G(1) + * GPIO 5: rate select, 1G(0) 10G(1) + */ + nodes->gpio_props[0] = PROPERTY_ENTRY_STRING("pinctrl-names", "default"); + swnodes[SWNODE_GPIO] = NODE_PROP(nodes->gpio_name, nodes->gpio_props); + nodes->gpio0_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 0, GPIO_ACTIVE_HIGH); + nodes->gpio1_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 1, GPIO_ACTIVE_HIGH); + nodes->gpio2_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 2, GPIO_ACTIVE_LOW); + nodes->gpio3_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 3, GPIO_ACTIVE_HIGH); + nodes->gpio4_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 4, GPIO_ACTIVE_HIGH); + nodes->gpio5_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 5, GPIO_ACTIVE_HIGH); + + nodes->i2c_props[0] = PROPERTY_ENTRY_STRING("compatible", "snps,designware-i2c"); + nodes->i2c_props[1] = PROPERTY_ENTRY_BOOL("wx,i2c-snps-model"); + nodes->i2c_props[2] = PROPERTY_ENTRY_U32("clock-frequency", I2C_MAX_STANDARD_MODE_FREQ); + swnodes[SWNODE_I2C] = NODE_PROP(nodes->i2c_name, nodes->i2c_props); + nodes->i2c_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_I2C]); + + nodes->sfp_props[0] = PROPERTY_ENTRY_STRING("compatible", "sff,sfp"); + nodes->sfp_props[1] = PROPERTY_ENTRY_REF_ARRAY("i2c-bus", nodes->i2c_ref); + nodes->sfp_props[2] = PROPERTY_ENTRY_REF_ARRAY("tx-fault-gpios", nodes->gpio0_ref); + nodes->sfp_props[3] = PROPERTY_ENTRY_REF_ARRAY("tx-disable-gpios", nodes->gpio1_ref); + nodes->sfp_props[4] = PROPERTY_ENTRY_REF_ARRAY("mod-def0-gpios", nodes->gpio2_ref); + nodes->sfp_props[5] = PROPERTY_ENTRY_REF_ARRAY("los-gpios", nodes->gpio3_ref); + nodes->sfp_props[6] = PROPERTY_ENTRY_REF_ARRAY("rate-select1-gpios", nodes->gpio4_ref); + nodes->sfp_props[7] = PROPERTY_ENTRY_REF_ARRAY("rate-select0-gpios", nodes->gpio5_ref); + swnodes[SWNODE_SFP] = NODE_PROP(nodes->sfp_name, nodes->sfp_props); + nodes->sfp_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_SFP]); + + nodes->phylink_props[0] = PROPERTY_ENTRY_STRING("managed", "in-band-status"); + nodes->phylink_props[1] = PROPERTY_ENTRY_REF_ARRAY("sfp", nodes->sfp_ref); + swnodes[SWNODE_PHYLINK] = NODE_PROP(nodes->phylink_name, nodes->phylink_props); + + nodes->group[SWNODE_GPIO] = &swnodes[SWNODE_GPIO]; + nodes->group[SWNODE_I2C] = &swnodes[SWNODE_I2C]; + nodes->group[SWNODE_SFP] = &swnodes[SWNODE_SFP]; + nodes->group[SWNODE_PHYLINK] = &swnodes[SWNODE_PHYLINK]; + + return software_node_register_node_group(nodes->group); +} + +int txgbe_init_phy(struct txgbe *txgbe) +{ + int ret; + + ret = txgbe_swnodes_register(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to register software nodes\n"); + return ret; + } + + return 0; +} + +void txgbe_remove_phy(struct txgbe *txgbe) +{ + software_node_unregister_node_group(txgbe->nodes.group); +} diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h new file mode 100644 index 000000000000..1ab592124986 --- /dev/null +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */ + +#ifndef _TXGBE_PHY_H_ +#define _TXGBE_PHY_H_ + +int txgbe_init_phy(struct txgbe *txgbe); +void txgbe_remove_phy(struct txgbe *txgbe); + +#endif /* _TXGBE_NODE_H_ */ diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index 63a1c733718d..5bef0f9df523 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -4,6 +4,8 @@ #ifndef _TXGBE_TYPE_H_ #define _TXGBE_TYPE_H_ +#include + /* Device IDs */ #define TXGBE_DEV_ID_SP1000 0x1001 #define TXGBE_DEV_ID_WX1820 0x2001 @@ -99,4 +101,51 @@ extern char txgbe_driver_name[]; +static inline struct txgbe *netdev_to_txgbe(struct net_device *netdev) +{ + struct wx *wx = netdev_priv(netdev); + + return wx->priv; +} + +#define NODE_PROP(_NAME, _PROP) \ + (const struct software_node) { \ + .name = _NAME, \ + .properties = _PROP, \ + } + +enum txgbe_swnodes { + SWNODE_GPIO = 0, + SWNODE_I2C, + SWNODE_SFP, + SWNODE_PHYLINK, + SWNODE_MAX +}; + +struct txgbe_nodes { + char gpio_name[32]; + char i2c_name[32]; + char sfp_name[32]; + char phylink_name[32]; + struct property_entry gpio_props[1]; + struct property_entry i2c_props[3]; + struct property_entry sfp_props[8]; + struct property_entry phylink_props[2]; + struct software_node_ref_args i2c_ref[1]; + struct software_node_ref_args gpio0_ref[1]; + struct software_node_ref_args gpio1_ref[1]; + struct software_node_ref_args gpio2_ref[1]; + struct software_node_ref_args gpio3_ref[1]; + struct software_node_ref_args gpio4_ref[1]; + struct software_node_ref_args gpio5_ref[1]; + struct software_node_ref_args sfp_ref[1]; + struct software_node swnodes[SWNODE_MAX]; + const struct software_node *group[SWNODE_MAX + 1]; +}; + +struct txgbe { + struct wx *wx; + struct txgbe_nodes nodes; +}; + #endif /* _TXGBE_TYPE_H_ */ From patchwork Thu Jun 1 03:01:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 13262945 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 66B141FD2 for ; Thu, 1 Jun 2023 03:10:42 +0000 (UTC) Received: from smtpbg150.qq.com (smtpbg150.qq.com [18.132.163.193]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DDD26193 for ; Wed, 31 May 2023 20:10:26 -0700 (PDT) X-QQ-mid: bizesmtp86t1685588643tsgsveju Received: from wxdbg.localdomain.com ( [183.159.96.128]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 01 Jun 2023 11:03:59 +0800 (CST) X-QQ-SSF: 01400000000000J0Z000000A0000000 X-QQ-FEAT: CR3LFp2JE4nh9Hz0vOzbBth9Ynn/emOQuEStfeJh6pjlgk0cYQR5wB7iDh00P BAmUfAqPS6AMpjdT5Xyh2yzLsvb5bUOmlcnwkAXWZNxvAeG6ZOynUDZ53jAch/T8ddVovgN qzTatjsxOT/TfvsV6PCFFYRFqmCS3+FYeLN0q+iJjt7Ipaj6nYEIT5O/1LlxtMuneOgruzL satLWJSayGYwbbshVqh3CmaYJBWFHHFSLSKvQ2jZ9923xFrze+0c5eZfV1zA+qE9ZfhNRi6 tvpoAINnoCQv81X4bCB0TU9o2gnXClHTo1lqJpGkOGntx2ANfERDnBwuAOI3gLHDL9dfsf+ iE3ZDg6wbJ9UyjZ9ejIIMLrZe80FnjTFv0WLyDwc6s33XDo7CQaIMUzLsrdYwZjHkbhbJ9X JHR0GhHDlAA= X-QQ-GoodBg: 2 X-BIZMAIL-ID: 12014156887312397919 From: Jiawen Wu To: netdev@vger.kernel.org, jarkko.nikula@linux.intel.com, andriy.shevchenko@linux.intel.com, mika.westerberg@linux.intel.com, jsd@semihalf.com, Jose.Abreu@synopsys.com, andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu , Piotr Raczynski Subject: [PATCH net-next v10 2/9] i2c: designware: Add driver support for Wangxun 10Gb NIC Date: Thu, 1 Jun 2023 11:01:33 +0800 Message-Id: <20230601030140.687493-3-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230601030140.687493-1-jiawenwu@trustnetic.com> References: <20230601030140.687493-1-jiawenwu@trustnetic.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvrgz:qybglogicsvrgz5a-1 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham 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 Wangxun 10Gb ethernet chip is connected to Designware I2C, to communicate with SFP. Introduce the property "wx,i2c-snps-model" to match device data for Wangxun in software node case. Since IO resource was mapped on the ethernet driver, add a model quirk to get regmap from parent device. The exists IP limitations are dealt as workarounds: - IP does not support interrupt mode, it works on polling mode. - Additionally set FIFO depth address the chip issue. Signed-off-by: Jiawen Wu Reviewed-by: Piotr Raczynski Reviewed-by: Andy Shevchenko --- drivers/i2c/busses/i2c-designware-common.c | 8 ++ drivers/i2c/busses/i2c-designware-core.h | 4 + drivers/i2c/busses/i2c-designware-master.c | 89 +++++++++++++++++++-- drivers/i2c/busses/i2c-designware-platdrv.c | 15 ++++ 4 files changed, 111 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index 0dc6b1ce663f..cdd8c67d9129 100644 --- a/drivers/i2c/busses/i2c-designware-common.c +++ b/drivers/i2c/busses/i2c-designware-common.c @@ -575,6 +575,14 @@ int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev) unsigned int param; int ret; + /* DW_IC_COMP_PARAM_1 not implement for IP issue */ + if ((dev->flags & MODEL_MASK) == MODEL_WANGXUN_SP) { + dev->tx_fifo_depth = TXGBE_TX_FIFO_DEPTH; + dev->rx_fifo_depth = TXGBE_RX_FIFO_DEPTH; + + return 0; + } + /* * Try to detect the FIFO depth if not set by interface driver, * the depth could be from 2 to 256 from HW spec. diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index c5d87aae39c6..782532c20bd1 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -303,6 +303,7 @@ struct dw_i2c_dev { #define MODEL_MSCC_OCELOT BIT(8) #define MODEL_BAIKAL_BT1 BIT(9) #define MODEL_AMD_NAVI_GPU BIT(10) +#define MODEL_WANGXUN_SP BIT(11) #define MODEL_MASK GENMASK(11, 8) /* @@ -312,6 +313,9 @@ struct dw_i2c_dev { #define AMD_UCSI_INTR_REG 0x474 #define AMD_UCSI_INTR_EN 0xd +#define TXGBE_TX_FIFO_DEPTH 4 +#define TXGBE_RX_FIFO_DEPTH 0 + struct i2c_dw_semaphore_callbacks { int (*probe)(struct dw_i2c_dev *dev); void (*remove)(struct dw_i2c_dev *dev); diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 55ea91a63382..3bfd7a2232db 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -354,6 +354,68 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs, return 0; } +static int i2c_dw_poll_tx_empty(struct dw_i2c_dev *dev) +{ + u32 val; + + return regmap_read_poll_timeout(dev->map, DW_IC_RAW_INTR_STAT, val, + val & DW_IC_INTR_TX_EMPTY, + 100, 1000); +} + +static int i2c_dw_poll_rx_full(struct dw_i2c_dev *dev) +{ + u32 val; + + return regmap_read_poll_timeout(dev->map, DW_IC_RAW_INTR_STAT, val, + val & DW_IC_INTR_RX_FULL, + 100, 1000); +} + +static int txgbe_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num_msgs) +{ + struct dw_i2c_dev *dev = i2c_get_adapdata(adap); + int msg_idx, buf_len, data_idx, ret; + unsigned int val, stop = 0; + u8 *buf; + + dev->msgs = msgs; + dev->msgs_num = num_msgs; + i2c_dw_xfer_init(dev); + regmap_write(dev->map, DW_IC_INTR_MASK, 0); + + for (msg_idx = 0; msg_idx < num_msgs; msg_idx++) { + buf = msgs[msg_idx].buf; + buf_len = msgs[msg_idx].len; + + for (data_idx = 0; data_idx < buf_len; data_idx++) { + if (msg_idx == num_msgs - 1 && data_idx == buf_len - 1) + stop |= BIT(9); + + if (msgs[msg_idx].flags & I2C_M_RD) { + regmap_write(dev->map, DW_IC_DATA_CMD, 0x100 | stop); + + ret = i2c_dw_poll_rx_full(dev); + if (ret) + return ret; + + regmap_read(dev->map, DW_IC_DATA_CMD, &val); + buf[data_idx] = val; + } else { + ret = i2c_dw_poll_tx_empty(dev); + if (ret) + return ret; + + regmap_write(dev->map, DW_IC_DATA_CMD, + buf[data_idx] | stop); + } + } + } + + return num_msgs; +} + /* * Initiate (and continue) low level master read/write transaction. * This function is only called from i2c_dw_isr, and pumping i2c_msg @@ -559,13 +621,19 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) pm_runtime_get_sync(dev->dev); /* - * Initiate I2C message transfer when AMD NAVI GPU card is enabled, + * Initiate I2C message transfer when polling mode is enabled, * As it is polling based transfer mechanism, which does not support * interrupt based functionalities of existing DesignWare driver. */ - if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) { + switch (dev->flags & MODEL_MASK) { + case MODEL_AMD_NAVI_GPU: ret = amd_i2c_dw_xfer_quirk(adap, msgs, num); goto done_nolock; + case MODEL_WANGXUN_SP: + ret = txgbe_i2c_dw_xfer_quirk(adap, msgs, num); + goto done_nolock; + default: + break; } reinit_completion(&dev->cmd_complete); @@ -848,7 +916,7 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev) return 0; } -static int amd_i2c_adap_quirk(struct dw_i2c_dev *dev) +static int i2c_dw_poll_adap_quirk(struct dw_i2c_dev *dev) { struct i2c_adapter *adap = &dev->adapter; int ret; @@ -862,6 +930,17 @@ static int amd_i2c_adap_quirk(struct dw_i2c_dev *dev) return ret; } +static bool i2c_dw_is_model_poll(struct dw_i2c_dev *dev) +{ + switch (dev->flags & MODEL_MASK) { + case MODEL_AMD_NAVI_GPU: + case MODEL_WANGXUN_SP: + return true; + default: + return false; + } +} + int i2c_dw_probe_master(struct dw_i2c_dev *dev) { struct i2c_adapter *adap = &dev->adapter; @@ -917,8 +996,8 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev) adap->dev.parent = dev->dev; i2c_set_adapdata(adap, dev); - if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) - return amd_i2c_adap_quirk(dev); + if (i2c_dw_is_model_poll(dev)) + return i2c_dw_poll_adap_quirk(dev); if (dev->flags & ACCESS_NO_IRQ_SUSPEND) { irq_flags = IRQF_NO_SUSPEND; diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 89ad88c54754..5a476a38b52f 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -168,6 +168,15 @@ static inline int dw_i2c_of_configure(struct platform_device *pdev) } #endif +static int txgbe_i2c_request_regs(struct dw_i2c_dev *dev) +{ + dev->map = dev_get_regmap(dev->dev->parent, NULL); + if (!dev->map) + return -ENODEV; + + return 0; +} + static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev *dev) { pm_runtime_disable(dev->dev); @@ -185,6 +194,9 @@ static int dw_i2c_plat_request_regs(struct dw_i2c_dev *dev) case MODEL_BAIKAL_BT1: ret = bt1_i2c_request_regs(dev); break; + case MODEL_WANGXUN_SP: + ret = txgbe_i2c_request_regs(dev); + break; default: dev->base = devm_platform_ioremap_resource(pdev, 0); ret = PTR_ERR_OR_ZERO(dev->base); @@ -277,6 +289,9 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) return -ENOMEM; dev->flags = (uintptr_t)device_get_match_data(&pdev->dev); + if (device_property_present(&pdev->dev, "wx,i2c-snps-model")) + dev->flags = MODEL_WANGXUN_SP; + dev->dev = &pdev->dev; dev->irq = irq; platform_set_drvdata(pdev, dev); From patchwork Thu Jun 1 03:01:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 13262940 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 9F49146B5 for ; Thu, 1 Jun 2023 03:10:18 +0000 (UTC) Received: from smtpbgjp3.qq.com (smtpbgjp3.qq.com [54.92.39.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3C906E4C for ; Wed, 31 May 2023 20:09:47 -0700 (PDT) X-QQ-mid: bizesmtp86t1685588650t1z0jih8 Received: from wxdbg.localdomain.com ( [183.159.96.128]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 01 Jun 2023 11:04:06 +0800 (CST) X-QQ-SSF: 01400000000000J0Z000000A0000000 X-QQ-FEAT: CR3LFp2JE4k7lzmlCObq5QVh/vz5vf/K9cw9ZpmpnfMPCcKIfyjXMkeV5wbTD qOsGlI2PJB7BQUawANxDeEif3BpIkQDQ+XRSpHzquC7tvkvGbiup6D0iG7pu62s5tnOBxRQ x9GeH70huz676R2hIErpoVUdB9VlQoeaApFVkt19OlDpHouTykkgfKoe3VsQ9vw2QY+eP1F PyZolI0da5hmpLutSDL2HLRpp+Czq32OuSUc4xH572eGF8jYOsHTUZWiISuBSQ7XNRG151L L7wkK7/B3bX5hzzOTVnE6fw8zARpxTWK/m6RxrG/e7f817Il9ezgc0HtFVr3Z9SE03ZaV7G ZEjadR5H0rUtpMdNJ/v3xYutmyLctBf1Z4ymfWtUq8LG7qsdKJN++ysbEbGma46EP8Zcz+q 7CvD7PR08Q4xxPARGZCVQQ== X-QQ-GoodBg: 2 X-BIZMAIL-ID: 3191998063983009471 From: Jiawen Wu To: netdev@vger.kernel.org, jarkko.nikula@linux.intel.com, andriy.shevchenko@linux.intel.com, mika.westerberg@linux.intel.com, jsd@semihalf.com, Jose.Abreu@synopsys.com, andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu Subject: [PATCH net-next v10 3/9] net: txgbe: Register fixed rate clock Date: Thu, 1 Jun 2023 11:01:34 +0800 Message-Id: <20230601030140.687493-4-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230601030140.687493-1-jiawenwu@trustnetic.com> References: <20230601030140.687493-1-jiawenwu@trustnetic.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvrgz:qybglogicsvrgz5a-1 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham 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 In order for I2C to be able to work in standard mode, register a fixed rate clock for each I2C device. Signed-off-by: Jiawen Wu Reviewed-by: Andrew Lunn --- drivers/net/ethernet/wangxun/Kconfig | 1 + .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 41 +++++++++++++++++++ .../net/ethernet/wangxun/txgbe/txgbe_type.h | 2 + 3 files changed, 44 insertions(+) diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig index c9d88673d306..190d42a203b4 100644 --- a/drivers/net/ethernet/wangxun/Kconfig +++ b/drivers/net/ethernet/wangxun/Kconfig @@ -40,6 +40,7 @@ config NGBE config TXGBE tristate "Wangxun(R) 10GbE PCI Express adapters support" depends on PCI + depends on COMMON_CLK select LIBWX help This driver supports Wangxun(R) 10GbE PCI Express family of diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index be4b5ad74a3c..06506cfb8d06 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -2,6 +2,8 @@ /* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */ #include +#include +#include #include #include @@ -70,6 +72,32 @@ static int txgbe_swnodes_register(struct txgbe *txgbe) return software_node_register_node_group(nodes->group); } +static int txgbe_clock_register(struct txgbe *txgbe) +{ + struct pci_dev *pdev = txgbe->wx->pdev; + struct clk_lookup *clock; + char clk_name[32]; + struct clk *clk; + + snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d", + (pdev->bus->number << 8) | pdev->devfn); + + clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + clock = clkdev_create(clk, NULL, clk_name); + if (!clock) { + clk_unregister(clk); + return -ENOMEM; + } + + txgbe->clk = clk; + txgbe->clock = clock; + + return 0; +} + int txgbe_init_phy(struct txgbe *txgbe) { int ret; @@ -80,10 +108,23 @@ int txgbe_init_phy(struct txgbe *txgbe) return ret; } + ret = txgbe_clock_register(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to register clock: %d\n", ret); + goto err_unregister_swnode; + } + return 0; + +err_unregister_swnode: + software_node_unregister_node_group(txgbe->nodes.group); + + return ret; } void txgbe_remove_phy(struct txgbe *txgbe) { + clkdev_drop(txgbe->clock); + clk_unregister(txgbe->clk); software_node_unregister_node_group(txgbe->nodes.group); } diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index 5bef0f9df523..cdbc4b37f832 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -146,6 +146,8 @@ struct txgbe_nodes { struct txgbe { struct wx *wx; struct txgbe_nodes nodes; + struct clk_lookup *clock; + struct clk *clk; }; #endif /* _TXGBE_TYPE_H_ */ From patchwork Thu Jun 1 03:01:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 13262944 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 335035394 for ; Thu, 1 Jun 2023 03:10:33 +0000 (UTC) Received: from smtpbgsg1.qq.com (smtpbgsg1.qq.com [54.254.200.92]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 34B6AE59 for ; Wed, 31 May 2023 20:10:07 -0700 (PDT) X-QQ-mid: bizesmtp86t1685588656tmp6o21f Received: from wxdbg.localdomain.com ( [183.159.96.128]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 01 Jun 2023 11:04:12 +0800 (CST) X-QQ-SSF: 01400000000000J0Z000000A0000000 X-QQ-FEAT: iDzLjIm7mlYxVkhWRCuJ8so7Fnlcyj6Nk+cfswEV8q/++xRKNSgaEi7Z68Xvx eilEsUjKtmx/gIHV3qM5l292rTopM7weKDghgS6hJVJFKothqhDLgrDp3HAoIlcYGoLCA5K 2FA6AXiXncUVY0WR+p2kUAufThBL0E5UxYQYyUEqGYSTkZmP/q7FP0SRgAlUeQ3UBDfTVmz VxyK3oCKzCcl+NKrjsi3aNwv254x+XNEGprvWLPBc+VBJKs8/tq5oXieRCvvGnjbC5G8Ibc tUV7S2piJLCpcekg8YvLPiHFK5u5OKNzWx2f+W2/RUbYzkSlfE4iZT17uZYY3GdQ+gAPTZ6 tbwqI30biXGKeYqiwOkDXY8kS/KWlh95Whc3jkN6RSko56VV6x/gfruF2aQ/RadPL6IiLzr bqHv7xbeBXodwSvtHGErAQ== X-QQ-GoodBg: 2 X-BIZMAIL-ID: 12059851608889778048 From: Jiawen Wu To: netdev@vger.kernel.org, jarkko.nikula@linux.intel.com, andriy.shevchenko@linux.intel.com, mika.westerberg@linux.intel.com, jsd@semihalf.com, Jose.Abreu@synopsys.com, andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu , Piotr Raczynski Subject: [PATCH net-next v10 4/9] net: txgbe: Register I2C platform device Date: Thu, 1 Jun 2023 11:01:35 +0800 Message-Id: <20230601030140.687493-5-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230601030140.687493-1-jiawenwu@trustnetic.com> References: <20230601030140.687493-1-jiawenwu@trustnetic.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvrgz:qybglogicsvrgz5a-1 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham 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 Register the platform device to use Designware I2C bus master driver. Use regmap to read/write I2C device region from given base offset. Signed-off-by: Jiawen Wu Reviewed-by: Andrew Lunn Reviewed-by: Piotr Raczynski Reviewed-by: Andy Shevchenko --- drivers/net/ethernet/wangxun/Kconfig | 3 + .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 70 +++++++++++++++++++ .../net/ethernet/wangxun/txgbe/txgbe_type.h | 4 ++ 3 files changed, 77 insertions(+) diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig index 190d42a203b4..128cc1cb0605 100644 --- a/drivers/net/ethernet/wangxun/Kconfig +++ b/drivers/net/ethernet/wangxun/Kconfig @@ -41,6 +41,9 @@ config TXGBE tristate "Wangxun(R) 10GbE PCI Express adapters support" depends on PCI depends on COMMON_CLK + select REGMAP + select I2C + select I2C_DESIGNWARE_PLATFORM select LIBWX help This driver supports Wangxun(R) 10GbE PCI Express family of diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index 06506cfb8d06..24a729150e08 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include "../libwx/wx_type.h" #include "txgbe_type.h" @@ -98,6 +100,64 @@ static int txgbe_clock_register(struct txgbe *txgbe) return 0; } +static int txgbe_i2c_read(void *context, unsigned int reg, unsigned int *val) +{ + struct wx *wx = context; + + *val = rd32(wx, reg + TXGBE_I2C_BASE); + + return 0; +} + +static int txgbe_i2c_write(void *context, unsigned int reg, unsigned int val) +{ + struct wx *wx = context; + + wr32(wx, reg + TXGBE_I2C_BASE, val); + + return 0; +} + +static const struct regmap_config i2c_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_read = txgbe_i2c_read, + .reg_write = txgbe_i2c_write, + .fast_io = true, +}; + +static int txgbe_i2c_register(struct txgbe *txgbe) +{ + struct platform_device_info info = {}; + struct platform_device *i2c_dev; + struct regmap *i2c_regmap; + struct pci_dev *pdev; + struct wx *wx; + + wx = txgbe->wx; + pdev = wx->pdev; + i2c_regmap = devm_regmap_init(&pdev->dev, NULL, wx, &i2c_regmap_config); + if (IS_ERR(i2c_regmap)) { + wx_err(wx, "failed to init I2C regmap\n"); + return PTR_ERR(i2c_regmap); + } + + info.parent = &pdev->dev; + info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]); + info.name = "i2c_designware"; + info.id = (pdev->bus->number << 8) | pdev->devfn; + + info.res = &DEFINE_RES_IRQ(pdev->irq); + info.num_res = 1; + i2c_dev = platform_device_register_full(&info); + if (IS_ERR(i2c_dev)) + return PTR_ERR(i2c_dev); + + txgbe->i2c_dev = i2c_dev; + + return 0; +} + int txgbe_init_phy(struct txgbe *txgbe) { int ret; @@ -114,8 +174,17 @@ int txgbe_init_phy(struct txgbe *txgbe) goto err_unregister_swnode; } + ret = txgbe_i2c_register(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to init i2c interface: %d\n", ret); + goto err_unregister_clk; + } + return 0; +err_unregister_clk: + clkdev_drop(txgbe->clock); + clk_unregister(txgbe->clk); err_unregister_swnode: software_node_unregister_node_group(txgbe->nodes.group); @@ -124,6 +193,7 @@ int txgbe_init_phy(struct txgbe *txgbe) void txgbe_remove_phy(struct txgbe *txgbe) { + platform_device_unregister(txgbe->i2c_dev); clkdev_drop(txgbe->clock); clk_unregister(txgbe->clk); software_node_unregister_node_group(txgbe->nodes.group); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index cdbc4b37f832..55979abf01f2 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -55,6 +55,9 @@ #define TXGBE_TS_CTL 0x10300 #define TXGBE_TS_CTL_EVAL_MD BIT(31) +/* I2C registers */ +#define TXGBE_I2C_BASE 0x14900 + /* Part Number String Length */ #define TXGBE_PBANUM_LENGTH 32 @@ -146,6 +149,7 @@ struct txgbe_nodes { struct txgbe { struct wx *wx; struct txgbe_nodes nodes; + struct platform_device *i2c_dev; struct clk_lookup *clock; struct clk *clk; }; From patchwork Thu Jun 1 03:01:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 13262946 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 9C66F46AD for ; Thu, 1 Jun 2023 03:10:49 +0000 (UTC) Received: from smtpbg153.qq.com (smtpbg153.qq.com [13.245.218.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C4B381B1 for ; Wed, 31 May 2023 20:10:41 -0700 (PDT) X-QQ-mid: bizesmtp86t1685588661tguhy6eq Received: from wxdbg.localdomain.com ( [183.159.96.128]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 01 Jun 2023 11:04:19 +0800 (CST) X-QQ-SSF: 01400000000000J0Z000000A0000000 X-QQ-FEAT: xqT8U4SkSpjOVMU2Gf95SOBP5nAjNy1lnKtRxPZ4SJ+1Or/+awmixtzK9WFLc yyx20DrKjRkyyr1Rs/y4U69tPAk6kf2OH6MP0yA6EN/wp+Bb+efxjfLE894sYOH4hc5Yfm5 JzJ1r9O76iOG7uUE50usHoOSLHwPn7gE1oTSABdmLz4dPFnVM8VHL0RsLFwLk7ym/jFd3KC ERt8gI/I3TsE0SF8/BHleZTBiEfbNhCAfTVec21KONvLPRJMK4LbVZx8CJHYUdQg5jXPPPy cJb21p4cZA7O8yECA7vjj3DZtzHacUZjD/MYNE+dA4Fgss2+JRKPBZGRb28bgEZpPRpKsto psEfKuLNAIu/yVg9ORKmW6zXhcp6+xAfR4o1DZ4/vzGE65k6mE5qfrY+836OMCqQdnlaNqp lJ3PsOHb/gRzXrUV6hRCTg== X-QQ-GoodBg: 2 X-BIZMAIL-ID: 12066729671065946516 From: Jiawen Wu To: netdev@vger.kernel.org, jarkko.nikula@linux.intel.com, andriy.shevchenko@linux.intel.com, mika.westerberg@linux.intel.com, jsd@semihalf.com, Jose.Abreu@synopsys.com, andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu , Piotr Raczynski Subject: [PATCH net-next v10 5/9] net: txgbe: Add SFP module identify Date: Thu, 1 Jun 2023 11:01:36 +0800 Message-Id: <20230601030140.687493-6-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230601030140.687493-1-jiawenwu@trustnetic.com> References: <20230601030140.687493-1-jiawenwu@trustnetic.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvrgz:qybglogicsvrgz5a-1 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham 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 Register SFP platform device to get modules information. Signed-off-by: Jiawen Wu Reviewed-by: Andrew Lunn Reviewed-by: Piotr Raczynski --- drivers/net/ethernet/wangxun/Kconfig | 3 ++ .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 28 +++++++++++++++++++ .../net/ethernet/wangxun/txgbe/txgbe_type.h | 1 + 3 files changed, 32 insertions(+) diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig index 128cc1cb0605..59f3a3f492cf 100644 --- a/drivers/net/ethernet/wangxun/Kconfig +++ b/drivers/net/ethernet/wangxun/Kconfig @@ -44,6 +44,9 @@ config TXGBE select REGMAP select I2C select I2C_DESIGNWARE_PLATFORM + select PHYLINK + select HWMON if TXGBE=y + select SFP select LIBWX help This driver supports Wangxun(R) 10GbE PCI Express family of diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index 24a729150e08..d95dc131e91b 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -158,6 +158,25 @@ static int txgbe_i2c_register(struct txgbe *txgbe) return 0; } +static int txgbe_sfp_register(struct txgbe *txgbe) +{ + struct pci_dev *pdev = txgbe->wx->pdev; + struct platform_device_info info = {}; + struct platform_device *sfp_dev; + + info.parent = &pdev->dev; + info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_SFP]); + info.name = "sfp"; + info.id = (pdev->bus->number << 8) | pdev->devfn; + sfp_dev = platform_device_register_full(&info); + if (IS_ERR(sfp_dev)) + return PTR_ERR(sfp_dev); + + txgbe->sfp_dev = sfp_dev; + + return 0; +} + int txgbe_init_phy(struct txgbe *txgbe) { int ret; @@ -180,8 +199,16 @@ int txgbe_init_phy(struct txgbe *txgbe) goto err_unregister_clk; } + ret = txgbe_sfp_register(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to register sfp\n"); + goto err_unregister_i2c; + } + return 0; +err_unregister_i2c: + platform_device_unregister(txgbe->i2c_dev); err_unregister_clk: clkdev_drop(txgbe->clock); clk_unregister(txgbe->clk); @@ -193,6 +220,7 @@ int txgbe_init_phy(struct txgbe *txgbe) void txgbe_remove_phy(struct txgbe *txgbe) { + platform_device_unregister(txgbe->sfp_dev); platform_device_unregister(txgbe->i2c_dev); clkdev_drop(txgbe->clock); clk_unregister(txgbe->clk); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index 55979abf01f2..fc91e0fc37a6 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -149,6 +149,7 @@ struct txgbe_nodes { struct txgbe { struct wx *wx; struct txgbe_nodes nodes; + struct platform_device *sfp_dev; struct platform_device *i2c_dev; struct clk_lookup *clock; struct clk *clk; From patchwork Thu Jun 1 03:01:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 13262938 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 70BCE2103 for ; Thu, 1 Jun 2023 03:09:56 +0000 (UTC) Received: from smtpbg156.qq.com (smtpbg156.qq.com [15.184.82.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AFD9A185 for ; Wed, 31 May 2023 20:09:29 -0700 (PDT) X-QQ-mid: bizesmtp86t1685588667ta4lhd4v Received: from wxdbg.localdomain.com ( [183.159.96.128]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 01 Jun 2023 11:04:24 +0800 (CST) X-QQ-SSF: 01400000000000J0Z000000A0000000 X-QQ-FEAT: H7ipuM2k/9qP30VANI5Kooe8M78jq8YngFqyzUhTlRUkI5htd5g0cxhelH65j RuEmd1Q8Ri3IV7sWkvmcRHp28+rNRttKU/+l8pl0qtVvm0zUV4QcDnrix/lx0srmz61WVmb bEggFGFk0ZzviKeojafXfFoPt/ZE/JFtynvKcEQ7m6TomeT0BBgijM/0CQ1wDdoDffjj9Fk hwy38UbAj4rx4SzWF+VY9JG89jHsJVsY9fKJl8IvmubMIFvCijLJ8iOl6mNPuOWxIYO8Xk0 xjjJE4Zwf6PctX6iYatroAe7bFk1taZbsXlICB8UofrX+x0+eQJtu0FiSz6fcrYaUY4O1ER sD8FNGHNhkfVdYNf1KG2kYMiR4PEjmGI6Rm1uLfQgb0E05Z5Ms4Nth/0bEP6H8ei378+x2m s9DGDNLkDZfJ0AuyyPsOcw== X-QQ-GoodBg: 2 X-BIZMAIL-ID: 16444273069455434631 From: Jiawen Wu To: netdev@vger.kernel.org, jarkko.nikula@linux.intel.com, andriy.shevchenko@linux.intel.com, mika.westerberg@linux.intel.com, jsd@semihalf.com, Jose.Abreu@synopsys.com, andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu Subject: [PATCH net-next v10 6/9] net: txgbe: Support GPIO to SFP socket Date: Thu, 1 Jun 2023 11:01:37 +0800 Message-Id: <20230601030140.687493-7-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230601030140.687493-1-jiawenwu@trustnetic.com> References: <20230601030140.687493-1-jiawenwu@trustnetic.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvrgz:qybglogicsvrgz5a-1 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=unavailable 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 Register GPIO chip and handle GPIO IRQ for SFP socket. Signed-off-by: Jiawen Wu Reviewed-by: Andy Shevchenko --- drivers/net/ethernet/wangxun/Kconfig | 2 + drivers/net/ethernet/wangxun/libwx/wx_lib.c | 3 +- drivers/net/ethernet/wangxun/libwx/wx_type.h | 3 + .../net/ethernet/wangxun/txgbe/txgbe_main.c | 20 +- .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 248 ++++++++++++++++++ .../net/ethernet/wangxun/txgbe/txgbe_type.h | 23 ++ 6 files changed, 280 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig index 59f3a3f492cf..3744735fa708 100644 --- a/drivers/net/ethernet/wangxun/Kconfig +++ b/drivers/net/ethernet/wangxun/Kconfig @@ -47,6 +47,8 @@ config TXGBE select PHYLINK select HWMON if TXGBE=y select SFP + select GPIOLIB + select GPIOLIB_IRQCHIP select LIBWX help This driver supports Wangxun(R) 10GbE PCI Express family of diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c index 1e8d8b7b0c62..590215303d45 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c @@ -1348,7 +1348,8 @@ void wx_free_irq(struct wx *wx) free_irq(entry->vector, q_vector); } - free_irq(wx->msix_entries[vector].vector, wx); + if (wx->mac.type == wx_mac_em) + free_irq(wx->msix_entries[vector].vector, wx); } EXPORT_SYMBOL(wx_free_irq); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index f59066d7375c..297c389fa890 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -79,7 +79,9 @@ #define WX_GPIO_INTMASK 0x14834 #define WX_GPIO_INTTYPE_LEVEL 0x14838 #define WX_GPIO_POLARITY 0x1483C +#define WX_GPIO_INTSTATUS 0x14844 #define WX_GPIO_EOI 0x1484C +#define WX_GPIO_EXT 0x14850 /*********************** Transmit DMA registers **************************/ /* transmit global control */ @@ -643,6 +645,7 @@ struct wx { bool wol_enabled; bool ncsi_enabled; bool gpio_ctrl; + raw_spinlock_t gpio_lock; /* Tx fast path data */ int num_tx_queues; diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index e10296abf5b4..ded04e9e136f 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -82,6 +82,8 @@ static int txgbe_enumerate_functions(struct wx *wx) **/ static void txgbe_irq_enable(struct wx *wx, bool queues) { + wr32(wx, WX_PX_MISC_IEN, TXGBE_PX_MISC_IEN_MASK); + /* unmask interrupt */ wx_intr_enable(wx, TXGBE_INTR_MISC(wx)); if (queues) @@ -129,17 +131,6 @@ static irqreturn_t txgbe_intr(int __always_unused irq, void *data) return IRQ_HANDLED; } -static irqreturn_t txgbe_msix_other(int __always_unused irq, void *data) -{ - struct wx *wx = data; - - /* re-enable the original interrupt state */ - if (netif_running(wx->netdev)) - txgbe_irq_enable(wx, false); - - return IRQ_HANDLED; -} - /** * txgbe_request_msix_irqs - Initialize MSI-X interrupts * @wx: board private structure @@ -171,13 +162,6 @@ static int txgbe_request_msix_irqs(struct wx *wx) } } - err = request_irq(wx->msix_entries[vector].vector, - txgbe_msix_other, 0, netdev->name, wx); - if (err) { - wx_err(wx, "request_irq for msix_other failed: %d\n", err); - goto free_queue_irqs; - } - return 0; free_queue_irqs: diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index d95dc131e91b..32fff693e073 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */ +#include +#include #include #include #include @@ -10,6 +12,7 @@ #include #include "../libwx/wx_type.h" +#include "../libwx/wx_hw.h" #include "txgbe_type.h" #include "txgbe_phy.h" @@ -74,6 +77,245 @@ static int txgbe_swnodes_register(struct txgbe *txgbe) return software_node_register_node_group(nodes->group); } +static int txgbe_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct wx *wx = gpiochip_get_data(chip); + int val; + + val = rd32m(wx, WX_GPIO_EXT, BIT(offset)); + + return !!(val & BIT(offset)); +} + +static int txgbe_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) +{ + struct wx *wx = gpiochip_get_data(chip); + u32 val; + + val = rd32(wx, WX_GPIO_DDR); + if (BIT(offset) & val) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; +} + +static int txgbe_gpio_direction_in(struct gpio_chip *chip, unsigned int offset) +{ + struct wx *wx = gpiochip_get_data(chip); + unsigned long flags; + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32m(wx, WX_GPIO_DDR, BIT(offset), 0); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); + + return 0; +} + +static int txgbe_gpio_direction_out(struct gpio_chip *chip, unsigned int offset, + int val) +{ + struct wx *wx = gpiochip_get_data(chip); + unsigned long flags; + u32 set; + + set = val ? BIT(offset) : 0; + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32m(wx, WX_GPIO_DR, BIT(offset), set); + wr32m(wx, WX_GPIO_DDR, BIT(offset), BIT(offset)); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); + + return 0; +} + +static void txgbe_gpio_irq_ack(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + struct wx *wx = gpiochip_get_data(gc); + unsigned long flags; + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32(wx, WX_GPIO_EOI, BIT(hwirq)); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +} + +static void txgbe_gpio_irq_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + struct wx *wx = gpiochip_get_data(gc); + unsigned long flags; + + gpiochip_disable_irq(gc, hwirq); + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), BIT(hwirq)); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +} + +static void txgbe_gpio_irq_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + struct wx *wx = gpiochip_get_data(gc); + unsigned long flags; + + gpiochip_enable_irq(gc, hwirq); + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), 0); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +} + +static void txgbe_toggle_trigger(struct gpio_chip *gc, unsigned int offset) +{ + struct wx *wx = gpiochip_get_data(gc); + u32 pol, val; + + pol = rd32(wx, WX_GPIO_POLARITY); + val = rd32(wx, WX_GPIO_EXT); + + if (val & BIT(offset)) + pol &= ~BIT(offset); + else + pol |= BIT(offset); + + wr32(wx, WX_GPIO_POLARITY, pol); +} + +static int txgbe_gpio_set_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + struct wx *wx = gpiochip_get_data(gc); + u32 level, polarity, mask; + unsigned long flags; + + mask = BIT(hwirq); + + if (type & IRQ_TYPE_LEVEL_MASK) { + level = 0; + irq_set_handler_locked(d, handle_level_irq); + } else { + level = mask; + irq_set_handler_locked(d, handle_edge_irq); + } + + if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) + polarity = mask; + else + polarity = 0; + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + + wr32m(wx, WX_GPIO_INTEN, mask, mask); + wr32m(wx, WX_GPIO_INTTYPE_LEVEL, mask, level); + if (type == IRQ_TYPE_EDGE_BOTH) + txgbe_toggle_trigger(gc, hwirq); + else + wr32m(wx, WX_GPIO_POLARITY, mask, polarity); + + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); + + return 0; +} + +static const struct irq_chip txgbe_gpio_irq_chip = { + .name = "txgbe_gpio_irq", + .irq_ack = txgbe_gpio_irq_ack, + .irq_mask = txgbe_gpio_irq_mask, + .irq_unmask = txgbe_gpio_irq_unmask, + .irq_set_type = txgbe_gpio_set_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static void txgbe_irq_handler(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct wx *wx = irq_desc_get_handler_data(desc); + struct txgbe *txgbe = wx->priv; + irq_hw_number_t hwirq; + unsigned long gpioirq; + struct gpio_chip *gc; + unsigned long flags; + + chained_irq_enter(chip, desc); + + gpioirq = rd32(wx, WX_GPIO_INTSTATUS); + + gc = txgbe->gpio; + for_each_set_bit(hwirq, &gpioirq, gc->ngpio) { + int gpio = irq_find_mapping(gc->irq.domain, hwirq); + u32 irq_type = irq_get_trigger_type(gpio); + + generic_handle_domain_irq(gc->irq.domain, hwirq); + + if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + txgbe_toggle_trigger(gc, hwirq); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); + } + } + + chained_irq_exit(chip, desc); + + /* unmask interrupt */ + wx_intr_enable(wx, TXGBE_INTR_MISC(wx)); +} + +static int txgbe_gpio_init(struct txgbe *txgbe) +{ + struct gpio_irq_chip *girq; + struct gpio_chip *gc; + struct device *dev; + struct wx *wx; + int ret; + + wx = txgbe->wx; + dev = &wx->pdev->dev; + + raw_spin_lock_init(&wx->gpio_lock); + + gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); + if (!gc) + return -ENOMEM; + + gc->label = devm_kasprintf(dev, GFP_KERNEL, "txgbe_gpio-%x", + (wx->pdev->bus->number << 8) | wx->pdev->devfn); + gc->base = -1; + gc->ngpio = 6; + gc->owner = THIS_MODULE; + gc->parent = dev; + gc->fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_GPIO]); + gc->get = txgbe_gpio_get; + gc->get_direction = txgbe_gpio_get_direction; + gc->direction_input = txgbe_gpio_direction_in; + gc->direction_output = txgbe_gpio_direction_out; + + girq = &gc->irq; + gpio_irq_chip_set_chip(girq, &txgbe_gpio_irq_chip); + girq->parent_handler = txgbe_irq_handler; + girq->parent_handler_data = wx; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, girq->num_parents, + sizeof(*girq->parents), GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = wx->msix_entries[wx->num_q_vectors].vector; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + + ret = devm_gpiochip_add_data(dev, gc, wx); + if (ret) + return ret; + + txgbe->gpio = gc; + + return 0; +} + static int txgbe_clock_register(struct txgbe *txgbe) { struct pci_dev *pdev = txgbe->wx->pdev; @@ -187,6 +429,12 @@ int txgbe_init_phy(struct txgbe *txgbe) return ret; } + ret = txgbe_gpio_init(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to init gpio\n"); + goto err_unregister_swnode; + } + ret = txgbe_clock_register(txgbe); if (ret) { wx_err(txgbe->wx, "failed to register clock: %d\n", ret); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index fc91e0fc37a6..6c903e4517c7 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -55,6 +55,28 @@ #define TXGBE_TS_CTL 0x10300 #define TXGBE_TS_CTL_EVAL_MD BIT(31) +/* GPIO register bit */ +#define TXGBE_GPIOBIT_0 BIT(0) /* I:tx fault */ +#define TXGBE_GPIOBIT_1 BIT(1) /* O:tx disabled */ +#define TXGBE_GPIOBIT_2 BIT(2) /* I:sfp module absent */ +#define TXGBE_GPIOBIT_3 BIT(3) /* I:rx signal lost */ +#define TXGBE_GPIOBIT_4 BIT(4) /* O:rate select, 1G(0) 10G(1) */ +#define TXGBE_GPIOBIT_5 BIT(5) /* O:rate select, 1G(0) 10G(1) */ + +/* Extended Interrupt Enable Set */ +#define TXGBE_PX_MISC_ETH_LKDN BIT(8) +#define TXGBE_PX_MISC_DEV_RST BIT(10) +#define TXGBE_PX_MISC_ETH_EVENT BIT(17) +#define TXGBE_PX_MISC_ETH_LK BIT(18) +#define TXGBE_PX_MISC_ETH_AN BIT(19) +#define TXGBE_PX_MISC_INT_ERR BIT(20) +#define TXGBE_PX_MISC_GPIO BIT(26) +#define TXGBE_PX_MISC_IEN_MASK \ + (TXGBE_PX_MISC_ETH_LKDN | TXGBE_PX_MISC_DEV_RST | \ + TXGBE_PX_MISC_ETH_EVENT | TXGBE_PX_MISC_ETH_LK | \ + TXGBE_PX_MISC_ETH_AN | TXGBE_PX_MISC_INT_ERR | \ + TXGBE_PX_MISC_GPIO) + /* I2C registers */ #define TXGBE_I2C_BASE 0x14900 @@ -153,6 +175,7 @@ struct txgbe { struct platform_device *i2c_dev; struct clk_lookup *clock; struct clk *clk; + struct gpio_chip *gpio; }; #endif /* _TXGBE_TYPE_H_ */ From patchwork Thu Jun 1 03:01:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 13262939 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 BEC5D1108 for ; Thu, 1 Jun 2023 03:10:16 +0000 (UTC) Received: from smtpbg151.qq.com (smtpbg151.qq.com [18.169.211.239]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 46EE910CC for ; Wed, 31 May 2023 20:09:44 -0700 (PDT) X-QQ-mid: bizesmtp86t1685588673t7isw8km Received: from wxdbg.localdomain.com ( [183.159.96.128]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 01 Jun 2023 11:04:30 +0800 (CST) X-QQ-SSF: 01400000000000J0Z000000A0000000 X-QQ-FEAT: D2GZf6M6C/jcBfylfpPngpr+7nNVvsQhCgtmPHqrc50nu3q+4MrlCaFKvqB1m DWcu19HP73vT4xL9FeA6TG+4/bjK0tuEwwJUx6J8RWwJL/uC4EmyMMzIv5F1aXmzic7CzR9 4iVdfrlR9JCbLubyHrbnV2M6ykv1VTtIGjN3CUXez6r0jCHR4Om5TxpeV8SKuCW/BwPbsWS 5MMvNrdZHWdS43xF1lZ0HVYCKk5r66g6GIiSZ+n0BBWu9YX4liCFjJw34GVebhg60ZMtsxu 5iyVFxim5//S7ujLpsnNY9XZXnwFskgvcDd+ziwvinQ/ZgpjjmLysWbtX0x5F2pRwKhCA2G kwQlBg7SAxnmFlo9JsNnzCjFc039IdC+6rin9W1VK2/Ar4cmTr8T6B0WLJZxRRqHQXzN5pY eBNjRi4vcAVNUqn0EDn/QA== X-QQ-GoodBg: 2 X-BIZMAIL-ID: 2350022613580202111 From: Jiawen Wu To: netdev@vger.kernel.org, jarkko.nikula@linux.intel.com, andriy.shevchenko@linux.intel.com, mika.westerberg@linux.intel.com, jsd@semihalf.com, Jose.Abreu@synopsys.com, andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu Subject: [PATCH net-next v10 7/9] net: pcs: Add 10GBASE-R mode for Synopsys Designware XPCS Date: Thu, 1 Jun 2023 11:01:38 +0800 Message-Id: <20230601030140.687493-8-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230601030140.687493-1-jiawenwu@trustnetic.com> References: <20230601030140.687493-1-jiawenwu@trustnetic.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvrgz:qybglogicsvrgz5a-1 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=unavailable 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 Add basic support for XPCS using 10GBASE-R interface. This mode will be extended to use interrupt, so set pcs.poll false. And avoid soft reset so that the device using this mode is in the default configuration. Signed-off-by: Jiawen Wu Reviewed-by: Andrew Lunn --- drivers/net/pcs/pcs-xpcs.c | 30 ++++++++++++++++++++++++++++++ include/linux/pcs/pcs-xpcs.h | 1 + 2 files changed, 31 insertions(+) diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 1ba214429e01..b2ef5fdce3b0 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -64,6 +64,16 @@ static const int xpcs_xlgmii_features[] = { __ETHTOOL_LINK_MODE_MASK_NBITS, }; +static const int xpcs_10gbaser_features[] = { + ETHTOOL_LINK_MODE_Pause_BIT, + ETHTOOL_LINK_MODE_Asym_Pause_BIT, + ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, + ETHTOOL_LINK_MODE_10000baseER_Full_BIT, + __ETHTOOL_LINK_MODE_MASK_NBITS, +}; + static const int xpcs_sgmii_features[] = { ETHTOOL_LINK_MODE_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT, @@ -106,6 +116,10 @@ static const phy_interface_t xpcs_xlgmii_interfaces[] = { PHY_INTERFACE_MODE_XLGMII, }; +static const phy_interface_t xpcs_10gbaser_interfaces[] = { + PHY_INTERFACE_MODE_10GBASER, +}; + static const phy_interface_t xpcs_sgmii_interfaces[] = { PHY_INTERFACE_MODE_SGMII, }; @@ -123,6 +137,7 @@ enum { DW_XPCS_USXGMII, DW_XPCS_10GKR, DW_XPCS_XLGMII, + DW_XPCS_10GBASER, DW_XPCS_SGMII, DW_XPCS_1000BASEX, DW_XPCS_2500BASEX, @@ -246,6 +261,7 @@ static int xpcs_soft_reset(struct dw_xpcs *xpcs, switch (compat->an_mode) { case DW_AN_C73: + case DW_10GBASER: dev = MDIO_MMD_PCS; break; case DW_AN_C37_SGMII: @@ -802,6 +818,8 @@ int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface, return -ENODEV; switch (compat->an_mode) { + case DW_10GBASER: + break; case DW_AN_C73: if (test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) { ret = xpcs_config_aneg_c73(xpcs, compat); @@ -998,6 +1016,9 @@ static void xpcs_get_state(struct phylink_pcs *pcs, return; switch (compat->an_mode) { + case DW_10GBASER: + phylink_mii_c45_pcs_get_state(xpcs->mdiodev, state); + break; case DW_AN_C73: ret = xpcs_get_state_c73(xpcs, state, compat); if (ret) { @@ -1153,6 +1174,12 @@ static const struct xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = { .num_interfaces = ARRAY_SIZE(xpcs_xlgmii_interfaces), .an_mode = DW_AN_C73, }, + [DW_XPCS_10GBASER] = { + .supported = xpcs_10gbaser_features, + .interface = xpcs_10gbaser_interfaces, + .num_interfaces = ARRAY_SIZE(xpcs_10gbaser_interfaces), + .an_mode = DW_10GBASER, + }, [DW_XPCS_SGMII] = { .supported = xpcs_sgmii_features, .interface = xpcs_sgmii_interfaces, @@ -1256,6 +1283,9 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, } xpcs->pcs.ops = &xpcs_phylink_ops; + if (compat->an_mode == DW_10GBASER) + return xpcs; + xpcs->pcs.poll = true; ret = xpcs_soft_reset(xpcs, compat); diff --git a/include/linux/pcs/pcs-xpcs.h b/include/linux/pcs/pcs-xpcs.h index a99972a6d046..daea67b6e3c0 100644 --- a/include/linux/pcs/pcs-xpcs.h +++ b/include/linux/pcs/pcs-xpcs.h @@ -18,6 +18,7 @@ #define DW_AN_C37_SGMII 2 #define DW_2500BASEX 3 #define DW_AN_C37_1000BASEX 4 +#define DW_10GBASER 5 struct xpcs_id; From patchwork Thu Jun 1 03:01:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 13262941 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 36C641C30 for ; Thu, 1 Jun 2023 03:10:20 +0000 (UTC) Received: from smtpbgsg2.qq.com (smtpbgsg2.qq.com [54.254.200.128]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DB307E4D for ; Wed, 31 May 2023 20:09:47 -0700 (PDT) X-QQ-mid: bizesmtp86t1685588680tsg2u596 Received: from wxdbg.localdomain.com ( [183.159.96.128]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 01 Jun 2023 11:04:36 +0800 (CST) X-QQ-SSF: 01400000000000J0Z000000A0000000 X-QQ-FEAT: fs34Pe/+C2S7QiamY6WRBdtsTERScfPrA0KRetE46irPej1dKi8LGGH8g52sS xec3nb7+K0QxkrAuH7YodPLZAFraTinhFXGY7CgHfglkxmOdOoPF1jO3BEpoLL7TiPey9Qq 3VoyRBjT2MQFMphUjKxB5MfzEUNrxtr8c+YmT545afISC0zWMR0aNhd+y/ztGSLkDjXJ7qj PMfs5bfHJTtph41vOqMQT9Uf2ARZem83ukCjLDVYv6lv8PLTeimgIj72DpEl1VHFQvKTawm UZhL02+XoendZAJBlDNq1BeaSsQMprFQI55rBB2gm6CBhjYFbDbNL0/MD+3CFF1IebHf+NJ ACcuO/wNEaM9T8PYG/jgAPoKfiMRJKTh6HhLxRG4AhodnX4tIIBktegbEVHBnOrU5pJZHmB hNxrfTNVUI9tyMhWdad4Vw== X-QQ-GoodBg: 2 X-BIZMAIL-ID: 4825029356197467032 From: Jiawen Wu To: netdev@vger.kernel.org, jarkko.nikula@linux.intel.com, andriy.shevchenko@linux.intel.com, mika.westerberg@linux.intel.com, jsd@semihalf.com, Jose.Abreu@synopsys.com, andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu Subject: [PATCH net-next v10 8/9] net: txgbe: Implement phylink pcs Date: Thu, 1 Jun 2023 11:01:39 +0800 Message-Id: <20230601030140.687493-9-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230601030140.687493-1-jiawenwu@trustnetic.com> References: <20230601030140.687493-1-jiawenwu@trustnetic.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvrgz:qybglogicsvrgz5a-1 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham 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 Register MDIO bus for PCS layer to use Synopsys designware XPCS, support 10GBASE-R interface to the controller. Signed-off-by: Jiawen Wu Reviewed-by: Andrew Lunn --- drivers/net/ethernet/wangxun/Kconfig | 1 + .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 89 ++++++++++++++++++- .../net/ethernet/wangxun/txgbe/txgbe_type.h | 5 ++ 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig index 3744735fa708..39596cd13539 100644 --- a/drivers/net/ethernet/wangxun/Kconfig +++ b/drivers/net/ethernet/wangxun/Kconfig @@ -49,6 +49,7 @@ config TXGBE select SFP select GPIOLIB select GPIOLIB_IRQCHIP + select PCS_XPCS select LIBWX help This driver supports Wangxun(R) 10GbE PCI Express family of diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index 32fff693e073..f4ec27d45a2d 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "../libwx/wx_type.h" #include "../libwx/wx_hw.h" @@ -77,6 +78,81 @@ static int txgbe_swnodes_register(struct txgbe *txgbe) return software_node_register_node_group(nodes->group); } +static int txgbe_pcs_read(struct mii_bus *bus, int addr, int devnum, int regnum) +{ + struct wx *wx = bus->priv; + u32 offset, val; + + if (addr) + return -EOPNOTSUPP; + + offset = devnum << 16 | regnum; + + /* Set the LAN port indicator to IDA_ADDR */ + wr32(wx, TXGBE_XPCS_IDA_ADDR, offset); + + /* Read the data from IDA_DATA register */ + val = rd32(wx, TXGBE_XPCS_IDA_DATA); + + return (u16)val; +} + +static int txgbe_pcs_write(struct mii_bus *bus, int addr, int devnum, int regnum, u16 val) +{ + struct wx *wx = bus->priv; + u32 offset; + + if (addr) + return -EOPNOTSUPP; + + offset = devnum << 16 | regnum; + + /* Set the LAN port indicator to IDA_ADDR */ + wr32(wx, TXGBE_XPCS_IDA_ADDR, offset); + + /* Write the data to IDA_DATA register */ + wr32(wx, TXGBE_XPCS_IDA_DATA, val); + + return 0; +} + +static int txgbe_mdio_pcs_init(struct txgbe *txgbe) +{ + struct mii_bus *mii_bus; + struct dw_xpcs *xpcs; + struct pci_dev *pdev; + struct wx *wx; + int ret = 0; + + wx = txgbe->wx; + pdev = wx->pdev; + + mii_bus = devm_mdiobus_alloc(&pdev->dev); + if (!mii_bus) + return -ENOMEM; + + mii_bus->name = "txgbe_pcs_mdio_bus"; + mii_bus->read_c45 = &txgbe_pcs_read; + mii_bus->write_c45 = &txgbe_pcs_write; + mii_bus->parent = &pdev->dev; + mii_bus->phy_mask = ~0; + mii_bus->priv = wx; + snprintf(mii_bus->id, MII_BUS_ID_SIZE, "txgbe_pcs-%x", + (pdev->bus->number << 8) | pdev->devfn); + + ret = devm_mdiobus_register(&pdev->dev, mii_bus); + if (ret) + return ret; + + xpcs = xpcs_create_mdiodev(mii_bus, 0, PHY_INTERFACE_MODE_10GBASER); + if (IS_ERR(xpcs)) + return PTR_ERR(xpcs); + + txgbe->xpcs = xpcs; + + return 0; +} + static int txgbe_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct wx *wx = gpiochip_get_data(chip); @@ -429,16 +505,22 @@ int txgbe_init_phy(struct txgbe *txgbe) return ret; } + ret = txgbe_mdio_pcs_init(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to init mdio pcs: %d\n", ret); + goto err_unregister_swnode; + } + ret = txgbe_gpio_init(txgbe); if (ret) { wx_err(txgbe->wx, "failed to init gpio\n"); - goto err_unregister_swnode; + goto err_destroy_xpcs; } ret = txgbe_clock_register(txgbe); if (ret) { wx_err(txgbe->wx, "failed to register clock: %d\n", ret); - goto err_unregister_swnode; + goto err_destroy_xpcs; } ret = txgbe_i2c_register(txgbe); @@ -460,6 +542,8 @@ int txgbe_init_phy(struct txgbe *txgbe) err_unregister_clk: clkdev_drop(txgbe->clock); clk_unregister(txgbe->clk); +err_destroy_xpcs: + xpcs_destroy(txgbe->xpcs); err_unregister_swnode: software_node_unregister_node_group(txgbe->nodes.group); @@ -472,5 +556,6 @@ void txgbe_remove_phy(struct txgbe *txgbe) platform_device_unregister(txgbe->i2c_dev); clkdev_drop(txgbe->clock); clk_unregister(txgbe->clk); + xpcs_destroy(txgbe->xpcs); software_node_unregister_node_group(txgbe->nodes.group); } diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index 6c903e4517c7..d1f62f62c28c 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -80,6 +80,10 @@ /* I2C registers */ #define TXGBE_I2C_BASE 0x14900 +/************************************** ETH PHY ******************************/ +#define TXGBE_XPCS_IDA_ADDR 0x13000 +#define TXGBE_XPCS_IDA_DATA 0x13004 + /* Part Number String Length */ #define TXGBE_PBANUM_LENGTH 32 @@ -171,6 +175,7 @@ struct txgbe_nodes { struct txgbe { struct wx *wx; struct txgbe_nodes nodes; + struct dw_xpcs *xpcs; struct platform_device *sfp_dev; struct platform_device *i2c_dev; struct clk_lookup *clock; From patchwork Thu Jun 1 03:01:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 13262942 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 5DC7A4C91 for ; Thu, 1 Jun 2023 03:10:22 +0000 (UTC) Received: from smtpbgau1.qq.com (smtpbgau1.qq.com [54.206.16.166]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 90268E52 for ; Wed, 31 May 2023 20:09:48 -0700 (PDT) X-QQ-mid: bizesmtp86t1685588686tkwlmz9f Received: from wxdbg.localdomain.com ( [183.159.96.128]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 01 Jun 2023 11:04:42 +0800 (CST) X-QQ-SSF: 01400000000000J0Z000000A0000000 X-QQ-FEAT: QityeSR92A2OLiW4LP6Sv33H7++QruIBfTkOx16mPbZ9AUPF+Mx8uo+9hn70g irignGaBIu5QTvbRHcHXa22YdhPEVcdG9gc8cqL+M5nZo1tI9O65p3eZMdQ/3pym3vWDR9w yTluur+a2ZOVWp2m2XidX6P0YZyibS61eiGYAiFlqKmis6R5V9ogXnpB2wf633N6grz6A8n uy77J22nqQx9Gq6SS0YEFAoxhx/QUbuPUBTHucHLwEFAayGfojuepRgTqRdxX30ZtZyxIaR kRZXdDYsOgmDc5JeIJVWO24YClT/6hBExPSsoLpXmvPlwVDr1jO96b3fLnRmSosMugHbov/ 1IyLd5lqHHBNpF/1248GOcKuH8tshQgbMPPh6VXFXZgJI+Dy7vKwbmqHVDAmzTn9lbEurjV gop7rbTjFtOJYHoDFQebXU+/aXPs+r7h X-QQ-GoodBg: 2 X-BIZMAIL-ID: 14059225962376236563 From: Jiawen Wu To: netdev@vger.kernel.org, jarkko.nikula@linux.intel.com, andriy.shevchenko@linux.intel.com, mika.westerberg@linux.intel.com, jsd@semihalf.com, Jose.Abreu@synopsys.com, andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu Subject: [PATCH net-next v10 9/9] net: txgbe: Support phylink MAC layer Date: Thu, 1 Jun 2023 11:01:40 +0800 Message-Id: <20230601030140.687493-10-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230601030140.687493-1-jiawenwu@trustnetic.com> References: <20230601030140.687493-1-jiawenwu@trustnetic.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvrgz:qybglogicsvrgz5a-1 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham 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 Add phylink support to Wangxun 10Gb Ethernet controller for the 10GBASE-R interface. Signed-off-by: Jiawen Wu --- .../ethernet/wangxun/txgbe/txgbe_ethtool.c | 28 +++++ .../net/ethernet/wangxun/txgbe/txgbe_main.c | 23 ++-- .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 113 +++++++++++++++++- .../net/ethernet/wangxun/txgbe/txgbe_type.h | 5 + 4 files changed, 154 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c index d914e9a05404..859da112586a 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c @@ -6,11 +6,39 @@ #include #include "../libwx/wx_ethtool.h" +#include "../libwx/wx_type.h" +#include "txgbe_type.h" #include "txgbe_ethtool.h" +static int txgbe_nway_reset(struct net_device *netdev) +{ + struct txgbe *txgbe = netdev_to_txgbe(netdev); + + return phylink_ethtool_nway_reset(txgbe->phylink); +} + +static int txgbe_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) +{ + struct txgbe *txgbe = netdev_to_txgbe(netdev); + + return phylink_ethtool_ksettings_get(txgbe->phylink, cmd); +} + +static int txgbe_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *cmd) +{ + struct txgbe *txgbe = netdev_to_txgbe(netdev); + + return phylink_ethtool_ksettings_set(txgbe->phylink, cmd); +} + static const struct ethtool_ops txgbe_ethtool_ops = { .get_drvinfo = wx_get_drvinfo, + .nway_reset = txgbe_nway_reset, .get_link = ethtool_op_get_link, + .get_link_ksettings = txgbe_get_link_ksettings, + .set_link_ksettings = txgbe_set_link_ksettings, }; void txgbe_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index ded04e9e136f..73764555af1a 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -204,7 +205,8 @@ static int txgbe_request_irq(struct wx *wx) static void txgbe_up_complete(struct wx *wx) { - u32 reg; + struct net_device *netdev = wx->netdev; + struct txgbe *txgbe; wx_control_hw(wx, true); wx_configure_vectors(wx); @@ -213,24 +215,17 @@ static void txgbe_up_complete(struct wx *wx) smp_mb__before_atomic(); wx_napi_enable_all(wx); + txgbe = netdev_to_txgbe(netdev); + phylink_start(txgbe->phylink); + /* clear any pending interrupts, may auto mask */ rd32(wx, WX_PX_IC(0)); rd32(wx, WX_PX_IC(1)); rd32(wx, WX_PX_MISC_IC); txgbe_irq_enable(wx, true); - /* Configure MAC Rx and Tx when link is up */ - reg = rd32(wx, WX_MAC_RX_CFG); - wr32(wx, WX_MAC_RX_CFG, reg); - wr32(wx, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR); - reg = rd32(wx, WX_MAC_WDG_TIMEOUT); - wr32(wx, WX_MAC_WDG_TIMEOUT, reg); - reg = rd32(wx, WX_MAC_TX_CFG); - wr32(wx, WX_MAC_TX_CFG, (reg & ~WX_MAC_TX_CFG_SPEED_MASK) | WX_MAC_TX_CFG_SPEED_10G); - /* enable transmits */ - netif_tx_start_all_queues(wx->netdev); - netif_carrier_on(wx->netdev); + netif_tx_start_all_queues(netdev); } static void txgbe_reset(struct wx *wx) @@ -264,7 +259,6 @@ static void txgbe_disable_device(struct wx *wx) wx_disable_rx_queue(wx, wx->rx_ring[i]); netif_tx_stop_all_queues(netdev); - netif_carrier_off(netdev); netif_tx_disable(netdev); wx_irq_disable(wx); @@ -295,8 +289,11 @@ static void txgbe_disable_device(struct wx *wx) static void txgbe_down(struct wx *wx) { + struct txgbe *txgbe = netdev_to_txgbe(wx->netdev); + txgbe_disable_device(wx); txgbe_reset(wx); + phylink_stop(txgbe->phylink); wx_clean_all_tx_rings(wx); wx_clean_all_rx_rings(wx); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index f4ec27d45a2d..f68c4452f438 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -11,8 +11,10 @@ #include #include #include +#include #include "../libwx/wx_type.h" +#include "../libwx/wx_lib.h" #include "../libwx/wx_hw.h" #include "txgbe_type.h" #include "txgbe_phy.h" @@ -153,6 +155,95 @@ static int txgbe_mdio_pcs_init(struct txgbe *txgbe) return 0; } +static struct phylink_pcs *txgbe_phylink_mac_select(struct phylink_config *config, + phy_interface_t interface) +{ + struct txgbe *txgbe = netdev_to_txgbe(to_net_dev(config->dev)); + + return &txgbe->xpcs->pcs; +} + +static void txgbe_mac_config(struct phylink_config *config, unsigned int mode, + const struct phylink_link_state *state) +{ +} + +static void txgbe_mac_link_down(struct phylink_config *config, + unsigned int mode, phy_interface_t interface) +{ + struct wx *wx = netdev_priv(to_net_dev(config->dev)); + + wr32m(wx, WX_MAC_TX_CFG, WX_MAC_TX_CFG_TE, 0); +} + +static void txgbe_mac_link_up(struct phylink_config *config, + struct phy_device *phy, + unsigned int mode, phy_interface_t interface, + int speed, int duplex, + bool tx_pause, bool rx_pause) +{ + struct wx *wx = netdev_priv(to_net_dev(config->dev)); + u32 txcfg, wdg; + + txcfg = rd32(wx, WX_MAC_TX_CFG); + txcfg &= ~WX_MAC_TX_CFG_SPEED_MASK; + + switch (speed) { + case SPEED_10000: + txcfg |= WX_MAC_TX_CFG_SPEED_10G; + break; + case SPEED_1000: + case SPEED_100: + case SPEED_10: + txcfg |= WX_MAC_TX_CFG_SPEED_1G; + break; + default: + break; + } + + wr32(wx, WX_MAC_TX_CFG, txcfg | WX_MAC_TX_CFG_TE); + + /* Re configure MAC Rx */ + wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, WX_MAC_RX_CFG_RE); + wr32(wx, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR); + wdg = rd32(wx, WX_MAC_WDG_TIMEOUT); + wr32(wx, WX_MAC_WDG_TIMEOUT, wdg); +} + +static const struct phylink_mac_ops txgbe_mac_ops = { + .mac_select_pcs = txgbe_phylink_mac_select, + .mac_config = txgbe_mac_config, + .mac_link_down = txgbe_mac_link_down, + .mac_link_up = txgbe_mac_link_up, +}; + +static int txgbe_phylink_init(struct txgbe *txgbe) +{ + struct phylink_config *config; + struct fwnode_handle *fwnode; + struct wx *wx = txgbe->wx; + phy_interface_t phy_mode; + struct phylink *phylink; + + config = devm_kzalloc(&wx->pdev->dev, sizeof(*config), GFP_KERNEL); + if (!config) + return -ENOMEM; + + config->dev = &wx->netdev->dev; + config->type = PHYLINK_NETDEV; + config->mac_capabilities = MAC_10000FD | MAC_1000FD | MAC_SYM_PAUSE | MAC_ASYM_PAUSE; + phy_mode = PHY_INTERFACE_MODE_10GBASER; + __set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces); + fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_PHYLINK]); + phylink = phylink_create(config, fwnode, phy_mode, &txgbe_mac_ops); + if (IS_ERR(phylink)) + return PTR_ERR(phylink); + + txgbe->phylink = phylink; + + return 0; +} + static int txgbe_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct wx *wx = gpiochip_get_data(chip); @@ -316,6 +407,9 @@ static void txgbe_irq_handler(struct irq_desc *desc) unsigned long gpioirq; struct gpio_chip *gc; unsigned long flags; + u32 eicr; + + eicr = wx_misc_isb(wx, WX_ISB_MISC); chained_irq_enter(chip, desc); @@ -337,6 +431,12 @@ static void txgbe_irq_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); + if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN)) { + u32 reg = rd32(wx, TXGBE_CFG_PORT_ST); + + phylink_mac_change(txgbe->phylink, !!(reg & TXGBE_CFG_PORT_ST_LINK_UP)); + } + /* unmask interrupt */ wx_intr_enable(wx, TXGBE_INTR_MISC(wx)); } @@ -511,16 +611,22 @@ int txgbe_init_phy(struct txgbe *txgbe) goto err_unregister_swnode; } + ret = txgbe_phylink_init(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to init phylink\n"); + goto err_destroy_xpcs; + } + ret = txgbe_gpio_init(txgbe); if (ret) { wx_err(txgbe->wx, "failed to init gpio\n"); - goto err_destroy_xpcs; + goto err_destroy_phylink; } ret = txgbe_clock_register(txgbe); if (ret) { wx_err(txgbe->wx, "failed to register clock: %d\n", ret); - goto err_destroy_xpcs; + goto err_destroy_phylink; } ret = txgbe_i2c_register(txgbe); @@ -542,6 +648,8 @@ int txgbe_init_phy(struct txgbe *txgbe) err_unregister_clk: clkdev_drop(txgbe->clock); clk_unregister(txgbe->clk); +err_destroy_phylink: + phylink_destroy(txgbe->phylink); err_destroy_xpcs: xpcs_destroy(txgbe->xpcs); err_unregister_swnode: @@ -556,6 +664,7 @@ void txgbe_remove_phy(struct txgbe *txgbe) platform_device_unregister(txgbe->i2c_dev); clkdev_drop(txgbe->clock); clk_unregister(txgbe->clk); + phylink_destroy(txgbe->phylink); xpcs_destroy(txgbe->xpcs); software_node_unregister_node_group(txgbe->nodes.group); } diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index d1f62f62c28c..e9e5c5186f74 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -77,6 +77,10 @@ TXGBE_PX_MISC_ETH_AN | TXGBE_PX_MISC_INT_ERR | \ TXGBE_PX_MISC_GPIO) +/* Port cfg registers */ +#define TXGBE_CFG_PORT_ST 0x14404 +#define TXGBE_CFG_PORT_ST_LINK_UP BIT(0) + /* I2C registers */ #define TXGBE_I2C_BASE 0x14900 @@ -176,6 +180,7 @@ struct txgbe { struct wx *wx; struct txgbe_nodes nodes; struct dw_xpcs *xpcs; + struct phylink *phylink; struct platform_device *sfp_dev; struct platform_device *i2c_dev; struct clk_lookup *clock;