From patchwork Sat Apr 22 04:56:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 676391 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 76992C77B7F for ; Sat, 22 Apr 2023 04:59:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229640AbjDVE7f (ORCPT ); Sat, 22 Apr 2023 00:59:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49296 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229484AbjDVE7e (ORCPT ); Sat, 22 Apr 2023 00:59:34 -0400 Received: from smtpbgjp3.qq.com (smtpbgjp3.qq.com [54.92.39.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6B8DC1BE4; Fri, 21 Apr 2023 21:59:31 -0700 (PDT) X-QQ-mid: bizesmtp66t1682139528tmfr22p9 Received: from wxdbg.localdomain.com ( [183.129.236.74]) by bizesmtp.qq.com (ESMTP) with id ; Sat, 22 Apr 2023 12:58:47 +0800 (CST) X-QQ-SSF: 01400000000000I0Z000000A0000000 X-QQ-FEAT: k0mQ4ihyJQOBREoBqPp2In2yJiDzKC5YkxtTsL8xe7oBXefVW3U9eOBePuP9C g02QwVzIQY+sK3LhK4n5aafOotComTur4ahGpXQ7lD3fk/8bgV/q89J6c/3+wgFIJaBErD/ cOUh5A7xXZYA20Hjn3ZJYCY/6xlOKY6Cd7LW5qNwbmDyjy6voqnCmtZjtLsRSFtLADslyBj lpk/giIGBuwEvHTIWOGGBGMApDo0pFminA7lWy5MKnm1v508NqlrMxf9ykk/qxvqGRyyGkH pLG59hcihs4CW3DClfefk4HDOCJoDpZynW7k0Wh/dKm2ebyrhyN7GUDY+2OkBaL9bDkAfG7 t16tL/Mmy8XrsKSV6MdU5YPJ1faX3/B85IOxi4iJhoa4UqxdJPkBTITEzZnc94RR7Sjtg/0 BIfRV1UJ6ro= X-QQ-GoodBg: 2 X-BIZMAIL-ID: 1330227918885388072 From: Jiawen Wu To: netdev@vger.kernel.org, andrew@lunn.ch, linux@armlinux.org.uk, jarkko.nikula@linux.intel.com, olteanv@gmail.com, andriy.shevchenko@linux.intel.com, hkallweit1@gmail.com Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu Subject: [PATCH net-next v4 1/8] net: txgbe: Add software nodes to support phylink Date: Sat, 22 Apr 2023 12:56:14 +0800 Message-Id: <20230422045621.360918-2-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230422045621.360918-1-jiawenwu@trustnetic.com> References: <20230422045621.360918-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvr:qybglogicsvr5 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Register software nodes for GPIO, I2C, SFP and PHYLINK. Define the device properties. Signed-off-by: Jiawen Wu --- drivers/net/ethernet/wangxun/libwx/wx_type.h | 1 + drivers/net/ethernet/wangxun/txgbe/Makefile | 1 + .../net/ethernet/wangxun/txgbe/txgbe_main.c | 20 ++++- .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 88 +++++++++++++++++++ .../net/ethernet/wangxun/txgbe/txgbe_phy.h | 10 +++ .../net/ethernet/wangxun/txgbe/txgbe_type.h | 49 +++++++++++ 6 files changed, 168 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 32f952d93009..97bce855bc60 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..dbd4d409d93b 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,21 @@ 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) + return -ENOMEM; + + 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 +707,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 +734,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..39762c7fc851 --- /dev/null +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -0,0 +1,88 @@ +// 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_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..51bbecb28433 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[2]; + 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 Sat Apr 22 04:56:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 676230 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3791CC7EE24 for ; Sat, 22 Apr 2023 04:59:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229669AbjDVE7h (ORCPT ); Sat, 22 Apr 2023 00:59:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49302 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229635AbjDVE7f (ORCPT ); Sat, 22 Apr 2023 00:59:35 -0400 Received: from smtpbguseast3.qq.com (smtpbguseast3.qq.com [54.243.244.52]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 65F9C1BF8; Fri, 21 Apr 2023 21:59:32 -0700 (PDT) X-QQ-mid: bizesmtp66t1682139532tupp27qu Received: from wxdbg.localdomain.com ( [183.129.236.74]) by bizesmtp.qq.com (ESMTP) with id ; Sat, 22 Apr 2023 12:58:51 +0800 (CST) X-QQ-SSF: 01400000000000I0Z000000A0000000 X-QQ-FEAT: k0mQ4ihyJQM3qK5r0WD2W4jzmJigDKdOunHsnhJyPiW36Dt+DBGFkhXf1AR1C I46FlYkNfN7A8URPPVqu/e9/pxr/iO3kSXj8tDCiXOIjPJcBOKtCA5bhSaG/kNtiXurHlkP Qfdmt6j4wkScYZcZeYMDpQYMmH/cefgJQRF4riq5s3BZ0wndoR9tM08AwdS6vAXqxHR89eA Isl0slj917VcDrnj3IJBdi6FXf//uClNqW5SzI8ImNiW1FPtXff4vZhlQNXPa4t646o5HCu tg2zvoZxH4pzoYWlajXNwjEsZrezNWmGQDPG83FcqIM865Wfqy7UatBxyhTA7hK6kJdk2iK KNPBWBAbFTCjcFTFv2L5e1vJ5vq1KbdM/5JFqdfeMmoaFTFI+faXTPHvpvUFOvthOoALYfK +Onga0Pa/LA= X-QQ-GoodBg: 2 X-BIZMAIL-ID: 763361397142706798 From: Jiawen Wu To: netdev@vger.kernel.org, andrew@lunn.ch, linux@armlinux.org.uk, jarkko.nikula@linux.intel.com, olteanv@gmail.com, andriy.shevchenko@linux.intel.com, hkallweit1@gmail.com Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu Subject: [PATCH net-next v4 2/8] i2c: designware: Add driver support for Wangxun 10Gb NIC Date: Sat, 22 Apr 2023 12:56:15 +0800 Message-Id: <20230422045621.360918-3-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230422045621.360918-1-jiawenwu@trustnetic.com> References: <20230422045621.360918-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvr:qybglogicsvr5 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Wangxun 10Gb ethernet chip is connected to Designware I2C, to communicate with SFP. Add platform data to pass IOMEM base address, board flag since resource address was mapped on ethernet driver. Since there is no device tree to get the clock, the parameters hcnt/lcnt are also set by platform data. 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. Cc: Jarkko Nikula Signed-off-by: Jiawen Wu --- drivers/i2c/busses/i2c-designware-common.c | 8 ++ drivers/i2c/busses/i2c-designware-core.h | 1 + drivers/i2c/busses/i2c-designware-master.c | 84 ++++++++++++++++++++- drivers/i2c/busses/i2c-designware-platdrv.c | 36 ++++++++- include/linux/platform_data/i2c-dw.h | 15 ++++ 5 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 include/linux/platform_data/i2c-dw.h diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index 0dc6b1ce663f..a7c2e67ccbf6 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 = 4; + dev->rx_fifo_depth = 0; + + 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 050d8c63ad3c..c686198e12d2 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) /* diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 55ea91a63382..962b791dae39 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 @@ -568,6 +630,11 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) goto done_nolock; } + if ((dev->flags & MODEL_MASK) == MODEL_WANGXUN_SP) { + ret = txgbe_i2c_dw_xfer_quirk(adap, msgs, num); + goto done_nolock; + } + reinit_completion(&dev->cmd_complete); dev->msgs = msgs; dev->msgs_num = num; @@ -848,7 +915,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 poll_i2c_adap_quirk(struct dw_i2c_dev *dev) { struct i2c_adapter *adap = &dev->adapter; int ret; @@ -862,6 +929,17 @@ static int amd_i2c_adap_quirk(struct dw_i2c_dev *dev) return ret; } +static bool i2c_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 +995,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_is_model_poll(dev)) + return poll_i2c_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 74182db03a88..10b2c61b279f 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -179,12 +180,14 @@ static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev *dev) static int dw_i2c_plat_request_regs(struct dw_i2c_dev *dev) { struct platform_device *pdev = to_platform_device(dev->dev); - int ret; + int ret = 0; switch (dev->flags & MODEL_MASK) { case MODEL_BAIKAL_BT1: ret = bt1_i2c_request_regs(dev); break; + case MODEL_WANGXUN_SP: + break; default: dev->base = devm_platform_ioremap_resource(pdev, 0); ret = PTR_ERR_OR_ZERO(dev->base); @@ -194,6 +197,35 @@ static int dw_i2c_plat_request_regs(struct dw_i2c_dev *dev) return ret; } +static void dw_i2c_get_plat_data(struct dw_i2c_dev *dev) +{ + struct platform_device *pdev = to_platform_device(dev->dev); + struct dw_i2c_platform_data *pdata; + + pdata = dev_get_platdata(&pdev->dev); + if (!pdata) + return; + + dev->flags |= pdata->flags; + dev->base = pdata->base; + + if (pdata->ss_hcnt && pdata->ss_lcnt) { + dev->ss_hcnt = pdata->ss_hcnt; + dev->ss_lcnt = pdata->ss_lcnt; + } else { + dev->ss_hcnt = 6; + dev->ss_lcnt = 8; + } + + if (pdata->fs_hcnt && pdata->fs_lcnt) { + dev->fs_hcnt = pdata->fs_hcnt; + dev->fs_lcnt = pdata->fs_lcnt; + } else { + dev->fs_hcnt = 6; + dev->fs_lcnt = 8; + } +} + static const struct dmi_system_id dw_i2c_hwmon_class_dmi[] = { { .ident = "Qtechnology QT5222", @@ -282,6 +314,8 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) dev->irq = irq; platform_set_drvdata(pdev, dev); + dw_i2c_get_plat_data(dev); + ret = dw_i2c_plat_request_regs(dev); if (ret) return ret; diff --git a/include/linux/platform_data/i2c-dw.h b/include/linux/platform_data/i2c-dw.h new file mode 100644 index 000000000000..f4552df08084 --- /dev/null +++ b/include/linux/platform_data/i2c-dw.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _LINUX_I2C_DW_H +#define _LINUX_I2C_DW_H + +struct dw_i2c_platform_data { + void __iomem *base; + unsigned int flags; + unsigned int ss_hcnt; + unsigned int ss_lcnt; + unsigned int fs_hcnt; + unsigned int fs_lcnt; +}; + +#endif /* _LINUX_I2C_DW_H */ From patchwork Sat Apr 22 04:56:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 676232 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 206A8C6FD18 for ; Sat, 22 Apr 2023 04:59:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229632AbjDVE7e (ORCPT ); Sat, 22 Apr 2023 00:59:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49290 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229451AbjDVE7d (ORCPT ); Sat, 22 Apr 2023 00:59:33 -0400 Received: from smtpbgau1.qq.com (smtpbgau1.qq.com [54.206.16.166]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 644AE1BE3; Fri, 21 Apr 2023 21:59:30 -0700 (PDT) X-QQ-mid: bizesmtp66t1682139536tmblnj9b Received: from wxdbg.localdomain.com ( [183.129.236.74]) by bizesmtp.qq.com (ESMTP) with id ; Sat, 22 Apr 2023 12:58:55 +0800 (CST) X-QQ-SSF: 01400000000000I0Z000000A0000000 X-QQ-FEAT: p8PN4UZ3LytHY1c9ZSEY1Y3Um3l5OT33oeXZ9cGR4Q1k7d80LWLzckHRY+BgR x68aHojT4CwV/B2xVu0GaEMh3iUmEevgVEqw2D/Do3Du3aXTP69hAiVs6ruTFMjaabR6eTw mw/UQSVuYJ8yNg0yZLWO3z+2xLxoSoZfnLY/F5orFsa7VjaMjhVoAq6EmphSoEdFzOY9E9O vxKUUOadAkLRbW29tltDfR835uiJzT5m0cW2pMgGpMTtjrB113IdZ+mo+rVi2Mu62gtnQ+r eTOfTZmkDLlf3fXEpj4eE6F7fGizERCgA8PQ+r0plKFluQMKj3tqLaFWa609ahnKcEaQZqd J4EDqux/U8mqelP+oKkq/fpBpfjpwRYb4yPTxwlDH09IYrhQTVt0QCCRvO8l1Shx1Izs6QH j97fJDqthXCd2l03v5s55A== X-QQ-GoodBg: 2 X-BIZMAIL-ID: 17808385363380690387 From: Jiawen Wu To: netdev@vger.kernel.org, andrew@lunn.ch, linux@armlinux.org.uk, jarkko.nikula@linux.intel.com, olteanv@gmail.com, andriy.shevchenko@linux.intel.com, hkallweit1@gmail.com Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu Subject: [PATCH net-next v4 3/8] net: txgbe: Register I2C platform device Date: Sat, 22 Apr 2023 12:56:16 +0800 Message-Id: <20230422045621.360918-4-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230422045621.360918-1-jiawenwu@trustnetic.com> References: <20230422045621.360918-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvr:qybglogicsvr5 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Register the platform device to use Designware I2C bus master driver. Signed-off-by: Jiawen Wu --- drivers/net/ethernet/wangxun/Kconfig | 1 + .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 48 +++++++++++++++++++ .../net/ethernet/wangxun/txgbe/txgbe_type.h | 4 ++ 3 files changed, 53 insertions(+) diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig index c9d88673d306..8acd6a0d84dc 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 + 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 39762c7fc851..d573f77007db 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 @@ -69,6 +71,40 @@ static int txgbe_swnodes_register(struct txgbe *txgbe) return software_node_register_node_group(nodes->group); } +static int txgbe_i2c_register(struct txgbe *txgbe) +{ + struct pci_dev *pdev = txgbe->wx->pdev; + struct dw_i2c_platform_data pdata = {}; + struct platform_device_info info = {}; + struct platform_device *i2c_dev; + struct resource res = {}; + + pdata.base = txgbe->wx->hw_addr + TXGBE_I2C_BASE; + pdata.flags = BIT(11); /* MODEL_WANGXUN_SP */ + pdata.ss_hcnt = 600; + pdata.ss_lcnt = 600; + + 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.data = &pdata; + info.size_data = sizeof(pdata); + + res.start = pdev->irq; + res.end = pdev->irq; + res.flags = IORESOURCE_IRQ; + info.res = &res; + 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; @@ -79,10 +115,22 @@ int txgbe_init_phy(struct txgbe *txgbe) return ret; } + ret = txgbe_i2c_register(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to init i2c interface: %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) { + platform_device_unregister(txgbe->i2c_dev); 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 51bbecb28433..771aefbc7c80 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; }; #endif /* _TXGBE_TYPE_H_ */ From patchwork Sat Apr 22 04:56:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 676390 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 26606C7EE22 for ; Sat, 22 Apr 2023 04:59:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229656AbjDVE7h (ORCPT ); Sat, 22 Apr 2023 00:59:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49300 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229621AbjDVE7e (ORCPT ); Sat, 22 Apr 2023 00:59:34 -0400 Received: from smtpbg151.qq.com (smtpbg151.qq.com [18.169.211.239]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 911171BEF; Fri, 21 Apr 2023 21:59:31 -0700 (PDT) X-QQ-mid: bizesmtp66t1682139540t4rjm7vb Received: from wxdbg.localdomain.com ( [183.129.236.74]) by bizesmtp.qq.com (ESMTP) with id ; Sat, 22 Apr 2023 12:58:59 +0800 (CST) X-QQ-SSF: 01400000000000I0Z000000A0000000 X-QQ-FEAT: QityeSR92A2eB5yq0dju3AG3oC7nzzD208XVA7OS3vUF09xrEpCMuInDue1JJ RJr408AVMzeu+TydL18vI3G01qdtic8mU/CXEd7bCyoXP9/Mh+ScZhkBurWdGSsMW8V8JZA TnmKuQvvyvTUmdm+5eYG3E917fi4SrKu1r2Fx4RU5d/lq1aDCGiRcaRT98DC7dFpXsC7xsp QD/8SPwgJQXLgsaJjUmVyfJshtk9cRPkuibUGHbt1HjPdqhdrfrWyAUbizvF1+ASQuk3ud0 d6VRqvEGUy2mrYz03Z+DDdljE6IsUn9QQCIEi08ET8H0KxfDCKkS4H4ZXl+vfYQDBKvLYhp j/lOHGYUBIvLRs59W3pW4AkJ1tD1vSiA1n3CD22dS2W314JtZNRi7ijKT4PC/4E1nnhVgYD f4w5HJiO3Eg= X-QQ-GoodBg: 2 X-BIZMAIL-ID: 5170876042864715615 From: Jiawen Wu To: netdev@vger.kernel.org, andrew@lunn.ch, linux@armlinux.org.uk, jarkko.nikula@linux.intel.com, olteanv@gmail.com, andriy.shevchenko@linux.intel.com, hkallweit1@gmail.com Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu Subject: [PATCH net-next v4 4/8] net: txgbe: Add SFP module identify Date: Sat, 22 Apr 2023 12:56:17 +0800 Message-Id: <20230422045621.360918-5-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230422045621.360918-1-jiawenwu@trustnetic.com> References: <20230422045621.360918-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvr:qybglogicsvr5 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Register SFP platform device to get modules information. Signed-off-by: Jiawen Wu --- drivers/net/ethernet/wangxun/Kconfig | 1 + .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 28 +++++++++++++++++++ .../net/ethernet/wangxun/txgbe/txgbe_type.h | 1 + 3 files changed, 30 insertions(+) diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig index 8acd6a0d84dc..d2dbaf19e53d 100644 --- a/drivers/net/ethernet/wangxun/Kconfig +++ b/drivers/net/ethernet/wangxun/Kconfig @@ -42,6 +42,7 @@ config TXGBE depends on PCI select I2C_DESIGNWARE_PLATFORM select LIBWX + select SFP help This driver supports Wangxun(R) 10GbE PCI Express family of adapters. diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index d573f77007db..3fbcfd217079 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -105,6 +105,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; @@ -121,8 +140,16 @@ int txgbe_init_phy(struct txgbe *txgbe) goto err_unregister_swnode; } + 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_swnode: software_node_unregister_node_group(txgbe->nodes.group); @@ -131,6 +158,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); 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 771aefbc7c80..aa94c4fce311 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; }; From patchwork Sat Apr 22 04:56:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 676389 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0A3D3C6FD18 for ; Sat, 22 Apr 2023 04:59:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229692AbjDVE7o (ORCPT ); Sat, 22 Apr 2023 00:59:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49412 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229635AbjDVE7m (ORCPT ); Sat, 22 Apr 2023 00:59:42 -0400 Received: from smtpbg151.qq.com (smtpbg151.qq.com [18.169.211.239]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DCDAC1FE3; Fri, 21 Apr 2023 21:59:38 -0700 (PDT) X-QQ-mid: bizesmtp66t1682139544tqmfuiz5 Received: from wxdbg.localdomain.com ( [183.129.236.74]) by bizesmtp.qq.com (ESMTP) with id ; Sat, 22 Apr 2023 12:59:03 +0800 (CST) X-QQ-SSF: 01400000000000I0Z000000A0000000 X-QQ-FEAT: Og2xOdt/sESvhv3X9qHskRky8+m2DkbDHCCW+4pG5In0MtTmA+kKykfFN1OvN bnyd6b3fH6iUpG8/Le53xGXhxmBizAOfGJB2C6nnHKBN2z3u6Gq49hBBG6sKiu/gpPxtpXf hl7sPxLy/gIinL6GxIC3g9QS6RrsNXAu4kzUEF3fsncnogYKAeJArrmv4Xjkkkyu+07bkaC g3vbJ4ZVk8iG+eononuuA/Jz8VD2COmGK88cQJaBi17HLR1wks1Je7c1b84RkxLA/FcvuaS /MncRmWXKtrH7Ob6lKIy4p2bo7an9P2+qj8YxH0727E8bymnOdoOhdLsJVz5MDkIAsF5Tzx W0+DTV+9qHDtNNbT0kbqb/ErmrVVtOFWL++1yjfmXwNNnuH5I6fJvExpnGHrPKaZVVKnfFh eBgzc8zOnxQ= X-QQ-GoodBg: 2 X-BIZMAIL-ID: 5768916221183516156 From: Jiawen Wu To: netdev@vger.kernel.org, andrew@lunn.ch, linux@armlinux.org.uk, jarkko.nikula@linux.intel.com, olteanv@gmail.com, andriy.shevchenko@linux.intel.com, hkallweit1@gmail.com Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu Subject: [PATCH net-next v4 5/8] net: txgbe: Support GPIO to SFP socket Date: Sat, 22 Apr 2023 12:56:18 +0800 Message-Id: <20230422045621.360918-6-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230422045621.360918-1-jiawenwu@trustnetic.com> References: <20230422045621.360918-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvr:qybglogicsvr5 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Register GPIO chip and handle GPIO IRQ for SFP socket. Signed-off-by: Jiawen Wu --- drivers/net/ethernet/wangxun/Kconfig | 2 + drivers/net/ethernet/wangxun/libwx/wx_lib.c | 3 +- drivers/net/ethernet/wangxun/libwx/wx_type.h | 2 + .../net/ethernet/wangxun/txgbe/txgbe_main.c | 20 +- .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 228 ++++++++++++++++++ .../net/ethernet/wangxun/txgbe/txgbe_type.h | 27 +++ 6 files changed, 263 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig index d2dbaf19e53d..9b69c3d53d65 100644 --- a/drivers/net/ethernet/wangxun/Kconfig +++ b/drivers/net/ethernet/wangxun/Kconfig @@ -41,6 +41,8 @@ config TXGBE tristate "Wangxun(R) 10GbE PCI Express adapters support" depends on PCI select I2C_DESIGNWARE_PLATFORM + select GPIOLIB_IRQCHIP + select GPIOLIB select LIBWX select SFP help diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c index eb89a274083e..dff0d573ee33 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 97bce855bc60..d151d6f79022 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 */ diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index dbd4d409d93b..b1ede19f4ff8 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 3fbcfd217079..feafac53f437 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -3,11 +3,15 @@ #include #include +#include +#include +#include #include #include #include #include "../libwx/wx_type.h" +#include "../libwx/wx_hw.h" #include "txgbe_type.h" #include "txgbe_phy.h" @@ -71,6 +75,224 @@ 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); + struct txgbe *txgbe = wx->priv; + int val; + + val = rd32m(wx, WX_GPIO_EXT, BIT(offset)); + + txgbe->gpio_orig &= ~BIT(offset); + txgbe->gpio_orig |= val; + + 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); + + wr32m(wx, WX_GPIO_DDR, BIT(offset), 0); + + return 0; +} + +static int txgbe_gpio_direction_out(struct gpio_chip *chip, unsigned int offset, + int val) +{ + struct wx *wx = gpiochip_get_data(chip); + u32 mask; + + mask = BIT(offset) | BIT(offset - 1); + if (val) + wr32m(wx, WX_GPIO_DR, mask, mask); + else + wr32m(wx, WX_GPIO_DR, mask, 0); + + wr32m(wx, WX_GPIO_DDR, BIT(offset), BIT(offset)); + + 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); + + wr32(wx, WX_GPIO_EOI, BIT(hwirq)); +} + +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); + + gpiochip_disable_irq(gc, hwirq); + + wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), BIT(hwirq)); +} + +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); + + gpiochip_enable_irq(gc, hwirq); + + wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), 0); +} + +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; + + level = rd32(wx, WX_GPIO_INTTYPE_LEVEL); + polarity = rd32(wx, WX_GPIO_POLARITY); + + switch (type) { + case IRQ_TYPE_EDGE_BOTH: + level |= BIT(hwirq); + break; + case IRQ_TYPE_EDGE_RISING: + level |= BIT(hwirq); + polarity |= BIT(hwirq); + break; + case IRQ_TYPE_EDGE_FALLING: + level |= BIT(hwirq); + polarity &= ~BIT(hwirq); + break; + case IRQ_TYPE_LEVEL_HIGH: + level &= ~BIT(hwirq); + polarity |= BIT(hwirq); + break; + case IRQ_TYPE_LEVEL_LOW: + level &= ~BIT(hwirq); + polarity &= ~BIT(hwirq); + break; + } + + if (type & IRQ_TYPE_LEVEL_MASK) + irq_set_handler_locked(d, handle_level_irq); + else if (type & IRQ_TYPE_EDGE_BOTH) + irq_set_handler_locked(d, handle_edge_irq); + + wr32m(wx, WX_GPIO_INTEN, BIT(hwirq), BIT(hwirq)); + wr32(wx, WX_GPIO_INTTYPE_LEVEL, level); + if (type != IRQ_TYPE_EDGE_BOTH) + wr32(wx, WX_GPIO_POLARITY, polarity); + + 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; + u32 gpio; + + chained_irq_enter(chip, desc); + + gpioirq = rd32(wx, WX_GPIO_INTSTATUS); + + /* workaround for hysteretic gpio interrupts */ + gpio = rd32(wx, WX_GPIO_EXT); + if (!gpioirq) + gpioirq = txgbe->gpio_orig ^ gpio; + + gc = txgbe->gpio; + for_each_set_bit(hwirq, &gpioirq, gc->ngpio) + generic_handle_domain_irq(gc->irq.domain, hwirq); + + chained_irq_exit(chip, desc); + + /* unmask interrupt */ + if (netif_running(wx->netdev)) + wx_intr_enable(wx, TXGBE_INTR_MISC(wx)); +} + +static int txgbe_gpio_init(struct txgbe *txgbe) +{ + struct gpio_irq_chip *girq; + struct wx *wx = txgbe->wx; + struct pci_dev *pdev; + struct gpio_chip *gc; + int ret; + + pdev = wx->pdev; + txgbe->gpio_orig = 0; + + gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); + if (!gc) + return -ENOMEM; + + gc->label = devm_kasprintf(&pdev->dev, GFP_KERNEL, "txgbe_gpio-%x", + (pdev->bus->number << 8) | pdev->devfn); + gc->base = -1; + gc->ngpio = 6; + gc->owner = THIS_MODULE; + gc->parent = &pdev->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; + gc->can_sleep = false; + + 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(&pdev->dev, 1, 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(&pdev->dev, gc, wx); + if (ret) + return ret; + + txgbe->gpio = gc; + + return 0; +} + static int txgbe_i2c_register(struct txgbe *txgbe) { struct pci_dev *pdev = txgbe->wx->pdev; @@ -134,6 +356,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_i2c_register(txgbe); if (ret) { wx_err(txgbe->wx, "failed to init i2c interface: %d\n", ret); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index aa94c4fce311..334803e6a5de 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -55,6 +55,31 @@ #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 @@ -151,6 +176,8 @@ struct txgbe { struct txgbe_nodes nodes; struct platform_device *sfp_dev; struct platform_device *i2c_dev; + struct gpio_chip *gpio; + u32 gpio_orig; }; #endif /* _TXGBE_TYPE_H_ */ From patchwork Sat Apr 22 04:56:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 676229 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9738FC6FD18 for ; Sat, 22 Apr 2023 05:00:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229682AbjDVE77 (ORCPT ); Sat, 22 Apr 2023 00:59:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49970 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229681AbjDVE7z (ORCPT ); Sat, 22 Apr 2023 00:59:55 -0400 Received: from smtpbguseast2.qq.com (smtpbguseast2.qq.com [54.204.34.130]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ED3F62702; Fri, 21 Apr 2023 21:59:48 -0700 (PDT) X-QQ-mid: bizesmtp66t1682139548ty0fxbhr Received: from wxdbg.localdomain.com ( [183.129.236.74]) by bizesmtp.qq.com (ESMTP) with id ; Sat, 22 Apr 2023 12:59:07 +0800 (CST) X-QQ-SSF: 01400000000000I0Z000000A0000000 X-QQ-FEAT: D2GZf6M6C/jsTOe4cSk5yhs/GQ2aXQZrd5tONkSBTvDOaf7Z0rP+K/Tgi90uv Y4MeuJi10pqwbjfaXG5pWxjzscuxFZqjxUcwhdhZ60tYLiOeYQjM5LERPf4e1O8edBw0MA4 5uTTYiQvN8NPzEJRpfEfpk3txs6/DTltZWj6exYgDEVGuXqTNdlRRyWk9kM18Uon99RnTEg x2JpwWQD2hknS/e/XP1gpcvTrzflMZPq4+1NF1bHQFLdMtLzA4TaasDvvGxAUJGvjyn5UlM UplfpTOPnWpOAaGEyIXtTI5MyoVs110ehyp5Y927VBH/uHTa/kRgxJkQcj/EqQF4V7Y7xu2 4IKcWYj65Ez3NNjWNcyz+Bb4srNH2bxbnBE9Eoe/7be03RwCGgpPAiIXdDQZccDOLqPlLOp Qpxdr2Zk1uk= X-QQ-GoodBg: 2 X-BIZMAIL-ID: 281790733503861956 From: Jiawen Wu To: netdev@vger.kernel.org, andrew@lunn.ch, linux@armlinux.org.uk, jarkko.nikula@linux.intel.com, olteanv@gmail.com, andriy.shevchenko@linux.intel.com, hkallweit1@gmail.com Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu , Jose Abreu Subject: [PATCH net-next v4 6/8] net: pcs: Add 10GBASE-R mode for Synopsys Designware XPCS Date: Sat, 22 Apr 2023 12:56:19 +0800 Message-Id: <20230422045621.360918-7-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230422045621.360918-1-jiawenwu@trustnetic.com> References: <20230422045621.360918-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvr:qybglogicsvr5 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.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. Cc: Jose Abreu Signed-off-by: Jiawen Wu --- drivers/net/pcs/pcs-xpcs.c | 56 ++++++++++++++++++++++++++++++++++++ include/linux/pcs/pcs-xpcs.h | 1 + 2 files changed, 57 insertions(+) diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 539cd43eae8d..9ddaceda1fe9 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: @@ -872,6 +888,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 (phylink_autoneg_inband(mode)) { ret = xpcs_config_aneg_c73(xpcs, compat); @@ -919,6 +937,27 @@ static int xpcs_config(struct phylink_pcs *pcs, unsigned int mode, return xpcs_do_config(xpcs, interface, mode, advertising); } +static int xpcs_get_state_10gbaser(struct dw_xpcs *xpcs, + struct phylink_link_state *state) +{ + int ret; + + state->link = false; + + ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1); + if (ret < 0) + return ret; + + if (ret & MDIO_STAT1_LSTATUS) { + state->link = true; + state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX; + state->duplex = DUPLEX_FULL; + state->speed = SPEED_10000; + } + + return 0; +} + static int xpcs_get_state_c73(struct dw_xpcs *xpcs, struct phylink_link_state *state, const struct xpcs_compat *compat) @@ -1033,6 +1072,14 @@ static void xpcs_get_state(struct phylink_pcs *pcs, return; switch (compat->an_mode) { + case DW_10GBASER: + ret = xpcs_get_state_10gbaser(xpcs, state); + if (ret) { + pr_err("xpcs_get_state_10gbaser returned %pe\n", + ERR_PTR(ret)); + return; + } + break; case DW_AN_C73: ret = xpcs_get_state_c73(xpcs, state, compat); if (ret) { @@ -1188,6 +1235,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, @@ -1290,6 +1343,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 d2da1e0b4a92..61df0c717a0e 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 Sat Apr 22 04:56:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 676388 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DD550C77B7F for ; Sat, 22 Apr 2023 05:00:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229704AbjDVFAB (ORCPT ); Sat, 22 Apr 2023 01:00:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49916 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229750AbjDVE74 (ORCPT ); Sat, 22 Apr 2023 00:59:56 -0400 Received: from smtpbgau2.qq.com (smtpbgau2.qq.com [54.206.34.216]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1F53E2719; Fri, 21 Apr 2023 21:59:48 -0700 (PDT) X-QQ-mid: bizesmtp66t1682139552t5ncd7ho Received: from wxdbg.localdomain.com ( [183.129.236.74]) by bizesmtp.qq.com (ESMTP) with id ; Sat, 22 Apr 2023 12:59:11 +0800 (CST) X-QQ-SSF: 01400000000000I0Z000000A0000000 X-QQ-FEAT: Kol1Dm0TdrA536EOhfHOWF70Gqa+U9YZqgbvs2XJue4a6Cpr6eJJCZx5uwG/Q xHHM7pit3mehl+J8vW3JzJhP4b2PLMpzV77tNy5IZZ9Ddvc9Sqq7mxx83pGawUW32tWaaIj Y/Z0zpQlTmk5CecGyOpqA7kavKLg0xZlBv2CSSl5XZ1TI0x21ABYzaBFyAroWRdWkEkncQ+ lGj5lVk35lKWiwOiSpXaesXnSWXw1Z6Yni95zC99uVneHzQPoGNsw0VTMZs82bCdduFN0xL F85A8Gymatm3+iUNaujmVTFNBD988DBOu4+up6Xx1EypsFP9nUwgGxwS5JBP3+CRm6Mhtj1 aYjt0YL3vHtVpMHcp9kw1Tr+9FIs80vgOeZ/R8q/Qr5I9tLbG4mVIewk/fBP72jsyU5EYAr 9xU+25rGrG4+yFTjrWjPQg== X-QQ-GoodBg: 2 X-BIZMAIL-ID: 3464235708605712805 From: Jiawen Wu To: netdev@vger.kernel.org, andrew@lunn.ch, linux@armlinux.org.uk, jarkko.nikula@linux.intel.com, olteanv@gmail.com, andriy.shevchenko@linux.intel.com, hkallweit1@gmail.com Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu Subject: [PATCH net-next v4 7/8] net: txgbe: Implement phylink pcs Date: Sat, 22 Apr 2023 12:56:20 +0800 Message-Id: <20230422045621.360918-8-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230422045621.360918-1-jiawenwu@trustnetic.com> References: <20230422045621.360918-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvr:qybglogicsvr5 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.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 --- drivers/net/ethernet/wangxun/Kconfig | 1 + .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 91 ++++++++++++++++++- .../net/ethernet/wangxun/txgbe/txgbe_type.h | 6 ++ 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig index 9b69c3d53d65..dde979b623fa 100644 --- a/drivers/net/ethernet/wangxun/Kconfig +++ b/drivers/net/ethernet/wangxun/Kconfig @@ -43,6 +43,7 @@ config TXGBE select I2C_DESIGNWARE_PLATFORM select GPIOLIB_IRQCHIP select GPIOLIB + select PCS_XPCS select LIBWX select SFP help diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index feafac53f437..3e5be9aa3b04 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include @@ -75,6 +77,82 @@ 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; + + 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; + + 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 mdio_device *mdiodev; + struct wx *wx = txgbe->wx; + struct mii_bus *mii_bus; + struct dw_xpcs *xpcs; + struct pci_dev *pdev; + int ret = 0; + + 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; + + mdiodev = mdio_device_create(mii_bus, 0); + if (IS_ERR(mdiodev)) + return PTR_ERR(mdiodev); + + xpcs = xpcs_create(mdiodev, PHY_INTERFACE_MODE_10GBASER); + if (IS_ERR_OR_NULL(xpcs)) { + mdio_device_free(mdiodev); + return PTR_ERR(xpcs); + } + + txgbe->mdiodev = mdiodev; + txgbe->xpcs = xpcs; + + return 0; +} + static int txgbe_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct wx *wx = gpiochip_get_data(chip); @@ -356,16 +434,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_i2c_register(txgbe); if (ret) { wx_err(txgbe->wx, "failed to init i2c interface: %d\n", ret); - goto err_unregister_swnode; + goto err_destroy_xpcs; } ret = txgbe_sfp_register(txgbe); @@ -378,6 +462,8 @@ int txgbe_init_phy(struct txgbe *txgbe) err_unregister_i2c: platform_device_unregister(txgbe->i2c_dev); +err_destroy_xpcs: + xpcs_destroy(txgbe->xpcs); err_unregister_swnode: software_node_unregister_node_group(txgbe->nodes.group); @@ -388,5 +474,6 @@ void txgbe_remove_phy(struct txgbe *txgbe) { platform_device_unregister(txgbe->sfp_dev); platform_device_unregister(txgbe->i2c_dev); + 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 334803e6a5de..89a635593ae2 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -83,6 +83,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 @@ -174,6 +178,8 @@ struct txgbe_nodes { struct txgbe { struct wx *wx; struct txgbe_nodes nodes; + struct mdio_device *mdiodev; + struct dw_xpcs *xpcs; struct platform_device *sfp_dev; struct platform_device *i2c_dev; struct gpio_chip *gpio; From patchwork Sat Apr 22 04:56:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 676228 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3C6D7C6FD18 for ; Sat, 22 Apr 2023 05:03:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229540AbjDVFDm (ORCPT ); Sat, 22 Apr 2023 01:03:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51092 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229520AbjDVFDl (ORCPT ); Sat, 22 Apr 2023 01:03:41 -0400 Received: from smtpbgeu2.qq.com (smtpbgeu2.qq.com [18.194.254.142]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4203C1BE4; Fri, 21 Apr 2023 22:03:34 -0700 (PDT) X-QQ-mid: bizesmtp66t1682139556t799mksa Received: from wxdbg.localdomain.com ( [183.129.236.74]) by bizesmtp.qq.com (ESMTP) with id ; Sat, 22 Apr 2023 12:59:15 +0800 (CST) X-QQ-SSF: 01400000000000I0Z000000A0000000 X-QQ-FEAT: DQ0OCu3gog3rE8xw6j7RkzI2GTjKNF9tNpDWExj27WUlOKN9BHYuJjyoFMe2o Q/RO1nxGZiGtt7SnJ9N66yGnGtDInEolFMwdALeWE6yoprITNseED3dWWH0WmTDyHc4pc// 9al6hTkZP6LZsul0c/l/aNwQOvdvGfiF4BXe+aCTcjvTuKKy+gwMsq/BrnZsIIw3K+M3Pwv zBHtR3mJqC960INQenQpPVMl6HHqbCnlo2yRgWrRp87dsEmQ9jz69N5cFz0RvK6YTH6nlkj IgjJAYucA8o9zMPwqG7inm1iHkFkwF+J/Taj2pJS8r2KgEsIE9yJRvWp/LzLX2S+IbLaB5a vxQaID3fmrY9ugpZB0jgBlJ2BpjXwb0O4fq6t+UUZ6Sc0lP/+7Y3TYsdkETXpdkrf+wrItS aqOLdzNmmoANue9uA0OhAA== X-QQ-GoodBg: 2 X-BIZMAIL-ID: 14461354643565128443 From: Jiawen Wu To: netdev@vger.kernel.org, andrew@lunn.ch, linux@armlinux.org.uk, jarkko.nikula@linux.intel.com, olteanv@gmail.com, andriy.shevchenko@linux.intel.com, hkallweit1@gmail.com Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, mengyuanlou@net-swift.com, Jiawen Wu Subject: [PATCH net-next v4 8/8] net: txgbe: Support phylink MAC layer Date: Sat, 22 Apr 2023 12:56:21 +0800 Message-Id: <20230422045621.360918-9-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20230422045621.360918-1-jiawenwu@trustnetic.com> References: <20230422045621.360918-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybglogicsvr:qybglogicsvr5 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Add phylink support to Wangxun 10Gb Ethernet controller for the 10GBASE-R interface. Signed-off-by: Jiawen Wu --- drivers/net/ethernet/wangxun/Kconfig | 1 + .../ethernet/wangxun/txgbe/txgbe_ethtool.c | 28 ++++++ .../net/ethernet/wangxun/txgbe/txgbe_main.c | 23 ++--- .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 91 +++++++++++++++++++ .../net/ethernet/wangxun/txgbe/txgbe_type.h | 5 + 5 files changed, 135 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig index dde979b623fa..e303bff0b13a 100644 --- a/drivers/net/ethernet/wangxun/Kconfig +++ b/drivers/net/ethernet/wangxun/Kconfig @@ -43,6 +43,7 @@ config TXGBE select I2C_DESIGNWARE_PLATFORM select GPIOLIB_IRQCHIP select GPIOLIB + select PHYLINK select PCS_XPCS select LIBWX select SFP 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 b1ede19f4ff8..04091355a5d8 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 = netdev_to_txgbe(netdev); wx_control_hw(wx, true); wx_configure_vectors(wx); @@ -213,24 +215,16 @@ static void txgbe_up_complete(struct wx *wx) smp_mb__before_atomic(); wx_napi_enable_all(wx); + 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 +258,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 +288,12 @@ static void txgbe_disable_device(struct wx *wx) static void txgbe_down(struct wx *wx) { + struct net_device *netdev = wx->netdev; + struct txgbe *txgbe = netdev_to_txgbe(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 3e5be9aa3b04..937ee9a703ec 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -8,11 +8,13 @@ #include #include #include +#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); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index 89a635593ae2..95ed19912a34 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -80,6 +80,10 @@ 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 @@ -180,6 +184,7 @@ struct txgbe { struct txgbe_nodes nodes; struct mdio_device *mdiodev; struct dw_xpcs *xpcs; + struct phylink *phylink; struct platform_device *sfp_dev; struct platform_device *i2c_dev; struct gpio_chip *gpio;