1c3e382adSJiawen Wu // SPDX-License-Identifier: GPL-2.0 2c3e382adSJiawen Wu /* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */ 3c3e382adSJiawen Wu 4b83c3731SJiawen Wu #include <linux/gpio/machine.h> 5b83c3731SJiawen Wu #include <linux/gpio/driver.h> 6c3e382adSJiawen Wu #include <linux/gpio/property.h> 7b63f2048SJiawen Wu #include <linux/clk-provider.h> 8b63f2048SJiawen Wu #include <linux/clkdev.h> 9c3e382adSJiawen Wu #include <linux/i2c.h> 10c3e382adSJiawen Wu #include <linux/pci.h> 11c625e725SJiawen Wu #include <linux/platform_device.h> 12c625e725SJiawen Wu #include <linux/regmap.h> 13854cace6SJiawen Wu #include <linux/pcs/pcs-xpcs.h> 1408f08f93SJiawen Wu #include <linux/phylink.h> 15c3e382adSJiawen Wu 16c3e382adSJiawen Wu #include "../libwx/wx_type.h" 1708f08f93SJiawen Wu #include "../libwx/wx_lib.h" 18b83c3731SJiawen Wu #include "../libwx/wx_hw.h" 19c3e382adSJiawen Wu #include "txgbe_type.h" 20c3e382adSJiawen Wu #include "txgbe_phy.h" 21*a4414dd1SJiawen Wu #include "txgbe_hw.h" 22c3e382adSJiawen Wu 23c3e382adSJiawen Wu static int txgbe_swnodes_register(struct txgbe *txgbe) 24c3e382adSJiawen Wu { 25c3e382adSJiawen Wu struct txgbe_nodes *nodes = &txgbe->nodes; 26c3e382adSJiawen Wu struct pci_dev *pdev = txgbe->wx->pdev; 27c3e382adSJiawen Wu struct software_node *swnodes; 28c3e382adSJiawen Wu u32 id; 29c3e382adSJiawen Wu 30d8c21ef7SXiongfeng Wang id = pci_dev_id(pdev); 31c3e382adSJiawen Wu 32c3e382adSJiawen Wu snprintf(nodes->gpio_name, sizeof(nodes->gpio_name), "txgbe_gpio-%x", id); 33c3e382adSJiawen Wu snprintf(nodes->i2c_name, sizeof(nodes->i2c_name), "txgbe_i2c-%x", id); 34c3e382adSJiawen Wu snprintf(nodes->sfp_name, sizeof(nodes->sfp_name), "txgbe_sfp-%x", id); 35c3e382adSJiawen Wu snprintf(nodes->phylink_name, sizeof(nodes->phylink_name), "txgbe_phylink-%x", id); 36c3e382adSJiawen Wu 37c3e382adSJiawen Wu swnodes = nodes->swnodes; 38c3e382adSJiawen Wu 39c3e382adSJiawen Wu /* GPIO 0: tx fault 40c3e382adSJiawen Wu * GPIO 1: tx disable 41c3e382adSJiawen Wu * GPIO 2: sfp module absent 42c3e382adSJiawen Wu * GPIO 3: rx signal lost 43c3e382adSJiawen Wu * GPIO 4: rate select, 1G(0) 10G(1) 44c3e382adSJiawen Wu * GPIO 5: rate select, 1G(0) 10G(1) 45c3e382adSJiawen Wu */ 46c3e382adSJiawen Wu nodes->gpio_props[0] = PROPERTY_ENTRY_STRING("pinctrl-names", "default"); 47c3e382adSJiawen Wu swnodes[SWNODE_GPIO] = NODE_PROP(nodes->gpio_name, nodes->gpio_props); 48c3e382adSJiawen Wu nodes->gpio0_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 0, GPIO_ACTIVE_HIGH); 49c3e382adSJiawen Wu nodes->gpio1_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 1, GPIO_ACTIVE_HIGH); 50c3e382adSJiawen Wu nodes->gpio2_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 2, GPIO_ACTIVE_LOW); 51c3e382adSJiawen Wu nodes->gpio3_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 3, GPIO_ACTIVE_HIGH); 52c3e382adSJiawen Wu nodes->gpio4_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 4, GPIO_ACTIVE_HIGH); 53c3e382adSJiawen Wu nodes->gpio5_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 5, GPIO_ACTIVE_HIGH); 54c3e382adSJiawen Wu 55c3e382adSJiawen Wu nodes->i2c_props[0] = PROPERTY_ENTRY_STRING("compatible", "snps,designware-i2c"); 56c3e382adSJiawen Wu nodes->i2c_props[1] = PROPERTY_ENTRY_BOOL("wx,i2c-snps-model"); 57c3e382adSJiawen Wu nodes->i2c_props[2] = PROPERTY_ENTRY_U32("clock-frequency", I2C_MAX_STANDARD_MODE_FREQ); 58c3e382adSJiawen Wu swnodes[SWNODE_I2C] = NODE_PROP(nodes->i2c_name, nodes->i2c_props); 59c3e382adSJiawen Wu nodes->i2c_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_I2C]); 60c3e382adSJiawen Wu 61c3e382adSJiawen Wu nodes->sfp_props[0] = PROPERTY_ENTRY_STRING("compatible", "sff,sfp"); 62c3e382adSJiawen Wu nodes->sfp_props[1] = PROPERTY_ENTRY_REF_ARRAY("i2c-bus", nodes->i2c_ref); 63c3e382adSJiawen Wu nodes->sfp_props[2] = PROPERTY_ENTRY_REF_ARRAY("tx-fault-gpios", nodes->gpio0_ref); 64c3e382adSJiawen Wu nodes->sfp_props[3] = PROPERTY_ENTRY_REF_ARRAY("tx-disable-gpios", nodes->gpio1_ref); 65c3e382adSJiawen Wu nodes->sfp_props[4] = PROPERTY_ENTRY_REF_ARRAY("mod-def0-gpios", nodes->gpio2_ref); 66c3e382adSJiawen Wu nodes->sfp_props[5] = PROPERTY_ENTRY_REF_ARRAY("los-gpios", nodes->gpio3_ref); 67c3e382adSJiawen Wu nodes->sfp_props[6] = PROPERTY_ENTRY_REF_ARRAY("rate-select1-gpios", nodes->gpio4_ref); 68c3e382adSJiawen Wu nodes->sfp_props[7] = PROPERTY_ENTRY_REF_ARRAY("rate-select0-gpios", nodes->gpio5_ref); 69c3e382adSJiawen Wu swnodes[SWNODE_SFP] = NODE_PROP(nodes->sfp_name, nodes->sfp_props); 70c3e382adSJiawen Wu nodes->sfp_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_SFP]); 71c3e382adSJiawen Wu 72c3e382adSJiawen Wu nodes->phylink_props[0] = PROPERTY_ENTRY_STRING("managed", "in-band-status"); 73c3e382adSJiawen Wu nodes->phylink_props[1] = PROPERTY_ENTRY_REF_ARRAY("sfp", nodes->sfp_ref); 74c3e382adSJiawen Wu swnodes[SWNODE_PHYLINK] = NODE_PROP(nodes->phylink_name, nodes->phylink_props); 75c3e382adSJiawen Wu 76c3e382adSJiawen Wu nodes->group[SWNODE_GPIO] = &swnodes[SWNODE_GPIO]; 77c3e382adSJiawen Wu nodes->group[SWNODE_I2C] = &swnodes[SWNODE_I2C]; 78c3e382adSJiawen Wu nodes->group[SWNODE_SFP] = &swnodes[SWNODE_SFP]; 79c3e382adSJiawen Wu nodes->group[SWNODE_PHYLINK] = &swnodes[SWNODE_PHYLINK]; 80c3e382adSJiawen Wu 81c3e382adSJiawen Wu return software_node_register_node_group(nodes->group); 82c3e382adSJiawen Wu } 83c3e382adSJiawen Wu 84854cace6SJiawen Wu static int txgbe_pcs_read(struct mii_bus *bus, int addr, int devnum, int regnum) 85854cace6SJiawen Wu { 86854cace6SJiawen Wu struct wx *wx = bus->priv; 87854cace6SJiawen Wu u32 offset, val; 88854cace6SJiawen Wu 89854cace6SJiawen Wu if (addr) 90854cace6SJiawen Wu return -EOPNOTSUPP; 91854cace6SJiawen Wu 92854cace6SJiawen Wu offset = devnum << 16 | regnum; 93854cace6SJiawen Wu 94854cace6SJiawen Wu /* Set the LAN port indicator to IDA_ADDR */ 95854cace6SJiawen Wu wr32(wx, TXGBE_XPCS_IDA_ADDR, offset); 96854cace6SJiawen Wu 97854cace6SJiawen Wu /* Read the data from IDA_DATA register */ 98854cace6SJiawen Wu val = rd32(wx, TXGBE_XPCS_IDA_DATA); 99854cace6SJiawen Wu 100854cace6SJiawen Wu return (u16)val; 101854cace6SJiawen Wu } 102854cace6SJiawen Wu 103854cace6SJiawen Wu static int txgbe_pcs_write(struct mii_bus *bus, int addr, int devnum, int regnum, u16 val) 104854cace6SJiawen Wu { 105854cace6SJiawen Wu struct wx *wx = bus->priv; 106854cace6SJiawen Wu u32 offset; 107854cace6SJiawen Wu 108854cace6SJiawen Wu if (addr) 109854cace6SJiawen Wu return -EOPNOTSUPP; 110854cace6SJiawen Wu 111854cace6SJiawen Wu offset = devnum << 16 | regnum; 112854cace6SJiawen Wu 113854cace6SJiawen Wu /* Set the LAN port indicator to IDA_ADDR */ 114854cace6SJiawen Wu wr32(wx, TXGBE_XPCS_IDA_ADDR, offset); 115854cace6SJiawen Wu 116854cace6SJiawen Wu /* Write the data to IDA_DATA register */ 117854cace6SJiawen Wu wr32(wx, TXGBE_XPCS_IDA_DATA, val); 118854cace6SJiawen Wu 119854cace6SJiawen Wu return 0; 120854cace6SJiawen Wu } 121854cace6SJiawen Wu 122854cace6SJiawen Wu static int txgbe_mdio_pcs_init(struct txgbe *txgbe) 123854cace6SJiawen Wu { 124854cace6SJiawen Wu struct mii_bus *mii_bus; 125854cace6SJiawen Wu struct dw_xpcs *xpcs; 126854cace6SJiawen Wu struct pci_dev *pdev; 127854cace6SJiawen Wu struct wx *wx; 128854cace6SJiawen Wu int ret = 0; 129854cace6SJiawen Wu 130854cace6SJiawen Wu wx = txgbe->wx; 131854cace6SJiawen Wu pdev = wx->pdev; 132854cace6SJiawen Wu 133854cace6SJiawen Wu mii_bus = devm_mdiobus_alloc(&pdev->dev); 134854cace6SJiawen Wu if (!mii_bus) 135854cace6SJiawen Wu return -ENOMEM; 136854cace6SJiawen Wu 137854cace6SJiawen Wu mii_bus->name = "txgbe_pcs_mdio_bus"; 138854cace6SJiawen Wu mii_bus->read_c45 = &txgbe_pcs_read; 139854cace6SJiawen Wu mii_bus->write_c45 = &txgbe_pcs_write; 140854cace6SJiawen Wu mii_bus->parent = &pdev->dev; 141854cace6SJiawen Wu mii_bus->phy_mask = ~0; 142854cace6SJiawen Wu mii_bus->priv = wx; 143854cace6SJiawen Wu snprintf(mii_bus->id, MII_BUS_ID_SIZE, "txgbe_pcs-%x", 144d8c21ef7SXiongfeng Wang pci_dev_id(pdev)); 145854cace6SJiawen Wu 146854cace6SJiawen Wu ret = devm_mdiobus_register(&pdev->dev, mii_bus); 147854cace6SJiawen Wu if (ret) 148854cace6SJiawen Wu return ret; 149854cace6SJiawen Wu 150854cace6SJiawen Wu xpcs = xpcs_create_mdiodev(mii_bus, 0, PHY_INTERFACE_MODE_10GBASER); 151854cace6SJiawen Wu if (IS_ERR(xpcs)) 152854cace6SJiawen Wu return PTR_ERR(xpcs); 153854cace6SJiawen Wu 154854cace6SJiawen Wu txgbe->xpcs = xpcs; 155854cace6SJiawen Wu 156854cace6SJiawen Wu return 0; 157854cace6SJiawen Wu } 158854cace6SJiawen Wu 15908f08f93SJiawen Wu static struct phylink_pcs *txgbe_phylink_mac_select(struct phylink_config *config, 16008f08f93SJiawen Wu phy_interface_t interface) 16108f08f93SJiawen Wu { 16208f08f93SJiawen Wu struct txgbe *txgbe = netdev_to_txgbe(to_net_dev(config->dev)); 16308f08f93SJiawen Wu 16408f08f93SJiawen Wu return &txgbe->xpcs->pcs; 16508f08f93SJiawen Wu } 16608f08f93SJiawen Wu 16708f08f93SJiawen Wu static void txgbe_mac_config(struct phylink_config *config, unsigned int mode, 16808f08f93SJiawen Wu const struct phylink_link_state *state) 16908f08f93SJiawen Wu { 17008f08f93SJiawen Wu } 17108f08f93SJiawen Wu 17208f08f93SJiawen Wu static void txgbe_mac_link_down(struct phylink_config *config, 17308f08f93SJiawen Wu unsigned int mode, phy_interface_t interface) 17408f08f93SJiawen Wu { 17508f08f93SJiawen Wu struct wx *wx = netdev_priv(to_net_dev(config->dev)); 17608f08f93SJiawen Wu 17708f08f93SJiawen Wu wr32m(wx, WX_MAC_TX_CFG, WX_MAC_TX_CFG_TE, 0); 17808f08f93SJiawen Wu } 17908f08f93SJiawen Wu 18008f08f93SJiawen Wu static void txgbe_mac_link_up(struct phylink_config *config, 18108f08f93SJiawen Wu struct phy_device *phy, 18208f08f93SJiawen Wu unsigned int mode, phy_interface_t interface, 18308f08f93SJiawen Wu int speed, int duplex, 18408f08f93SJiawen Wu bool tx_pause, bool rx_pause) 18508f08f93SJiawen Wu { 18608f08f93SJiawen Wu struct wx *wx = netdev_priv(to_net_dev(config->dev)); 18708f08f93SJiawen Wu u32 txcfg, wdg; 18808f08f93SJiawen Wu 18908f08f93SJiawen Wu txcfg = rd32(wx, WX_MAC_TX_CFG); 19008f08f93SJiawen Wu txcfg &= ~WX_MAC_TX_CFG_SPEED_MASK; 19108f08f93SJiawen Wu 19208f08f93SJiawen Wu switch (speed) { 19308f08f93SJiawen Wu case SPEED_10000: 19408f08f93SJiawen Wu txcfg |= WX_MAC_TX_CFG_SPEED_10G; 19508f08f93SJiawen Wu break; 19608f08f93SJiawen Wu case SPEED_1000: 19708f08f93SJiawen Wu case SPEED_100: 19808f08f93SJiawen Wu case SPEED_10: 19908f08f93SJiawen Wu txcfg |= WX_MAC_TX_CFG_SPEED_1G; 20008f08f93SJiawen Wu break; 20108f08f93SJiawen Wu default: 20208f08f93SJiawen Wu break; 20308f08f93SJiawen Wu } 20408f08f93SJiawen Wu 20508f08f93SJiawen Wu wr32(wx, WX_MAC_TX_CFG, txcfg | WX_MAC_TX_CFG_TE); 20608f08f93SJiawen Wu 20708f08f93SJiawen Wu /* Re configure MAC Rx */ 20808f08f93SJiawen Wu wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, WX_MAC_RX_CFG_RE); 20908f08f93SJiawen Wu wr32(wx, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR); 21008f08f93SJiawen Wu wdg = rd32(wx, WX_MAC_WDG_TIMEOUT); 21108f08f93SJiawen Wu wr32(wx, WX_MAC_WDG_TIMEOUT, wdg); 21208f08f93SJiawen Wu } 21308f08f93SJiawen Wu 214*a4414dd1SJiawen Wu static int txgbe_mac_prepare(struct phylink_config *config, unsigned int mode, 215*a4414dd1SJiawen Wu phy_interface_t interface) 216*a4414dd1SJiawen Wu { 217*a4414dd1SJiawen Wu struct wx *wx = netdev_priv(to_net_dev(config->dev)); 218*a4414dd1SJiawen Wu 219*a4414dd1SJiawen Wu wr32m(wx, WX_MAC_TX_CFG, WX_MAC_TX_CFG_TE, 0); 220*a4414dd1SJiawen Wu wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, 0); 221*a4414dd1SJiawen Wu 222*a4414dd1SJiawen Wu return txgbe_disable_sec_tx_path(wx); 223*a4414dd1SJiawen Wu } 224*a4414dd1SJiawen Wu 225*a4414dd1SJiawen Wu static int txgbe_mac_finish(struct phylink_config *config, unsigned int mode, 226*a4414dd1SJiawen Wu phy_interface_t interface) 227*a4414dd1SJiawen Wu { 228*a4414dd1SJiawen Wu struct wx *wx = netdev_priv(to_net_dev(config->dev)); 229*a4414dd1SJiawen Wu 230*a4414dd1SJiawen Wu txgbe_enable_sec_tx_path(wx); 231*a4414dd1SJiawen Wu wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, WX_MAC_RX_CFG_RE); 232*a4414dd1SJiawen Wu 233*a4414dd1SJiawen Wu return 0; 234*a4414dd1SJiawen Wu } 235*a4414dd1SJiawen Wu 23608f08f93SJiawen Wu static const struct phylink_mac_ops txgbe_mac_ops = { 23708f08f93SJiawen Wu .mac_select_pcs = txgbe_phylink_mac_select, 238*a4414dd1SJiawen Wu .mac_prepare = txgbe_mac_prepare, 239*a4414dd1SJiawen Wu .mac_finish = txgbe_mac_finish, 24008f08f93SJiawen Wu .mac_config = txgbe_mac_config, 24108f08f93SJiawen Wu .mac_link_down = txgbe_mac_link_down, 24208f08f93SJiawen Wu .mac_link_up = txgbe_mac_link_up, 24308f08f93SJiawen Wu }; 24408f08f93SJiawen Wu 24508f08f93SJiawen Wu static int txgbe_phylink_init(struct txgbe *txgbe) 24608f08f93SJiawen Wu { 24708f08f93SJiawen Wu struct phylink_config *config; 24808f08f93SJiawen Wu struct fwnode_handle *fwnode; 24908f08f93SJiawen Wu struct wx *wx = txgbe->wx; 25008f08f93SJiawen Wu phy_interface_t phy_mode; 25108f08f93SJiawen Wu struct phylink *phylink; 25208f08f93SJiawen Wu 25308f08f93SJiawen Wu config = devm_kzalloc(&wx->pdev->dev, sizeof(*config), GFP_KERNEL); 25408f08f93SJiawen Wu if (!config) 25508f08f93SJiawen Wu return -ENOMEM; 25608f08f93SJiawen Wu 25708f08f93SJiawen Wu config->dev = &wx->netdev->dev; 25808f08f93SJiawen Wu config->type = PHYLINK_NETDEV; 25908f08f93SJiawen Wu config->mac_capabilities = MAC_10000FD | MAC_1000FD | MAC_SYM_PAUSE | MAC_ASYM_PAUSE; 26008f08f93SJiawen Wu phy_mode = PHY_INTERFACE_MODE_10GBASER; 26108f08f93SJiawen Wu __set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces); 262*a4414dd1SJiawen Wu __set_bit(PHY_INTERFACE_MODE_1000BASEX, config->supported_interfaces); 263*a4414dd1SJiawen Wu __set_bit(PHY_INTERFACE_MODE_SGMII, config->supported_interfaces); 26408f08f93SJiawen Wu fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_PHYLINK]); 26508f08f93SJiawen Wu phylink = phylink_create(config, fwnode, phy_mode, &txgbe_mac_ops); 26608f08f93SJiawen Wu if (IS_ERR(phylink)) 26708f08f93SJiawen Wu return PTR_ERR(phylink); 26808f08f93SJiawen Wu 26908f08f93SJiawen Wu txgbe->phylink = phylink; 27008f08f93SJiawen Wu 27108f08f93SJiawen Wu return 0; 27208f08f93SJiawen Wu } 27308f08f93SJiawen Wu 274b83c3731SJiawen Wu static int txgbe_gpio_get(struct gpio_chip *chip, unsigned int offset) 275b83c3731SJiawen Wu { 276b83c3731SJiawen Wu struct wx *wx = gpiochip_get_data(chip); 277b83c3731SJiawen Wu int val; 278b83c3731SJiawen Wu 279b83c3731SJiawen Wu val = rd32m(wx, WX_GPIO_EXT, BIT(offset)); 280b83c3731SJiawen Wu 281b83c3731SJiawen Wu return !!(val & BIT(offset)); 282b83c3731SJiawen Wu } 283b83c3731SJiawen Wu 284b83c3731SJiawen Wu static int txgbe_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) 285b83c3731SJiawen Wu { 286b83c3731SJiawen Wu struct wx *wx = gpiochip_get_data(chip); 287b83c3731SJiawen Wu u32 val; 288b83c3731SJiawen Wu 289b83c3731SJiawen Wu val = rd32(wx, WX_GPIO_DDR); 290b83c3731SJiawen Wu if (BIT(offset) & val) 291b83c3731SJiawen Wu return GPIO_LINE_DIRECTION_OUT; 292b83c3731SJiawen Wu 293b83c3731SJiawen Wu return GPIO_LINE_DIRECTION_IN; 294b83c3731SJiawen Wu } 295b83c3731SJiawen Wu 296b83c3731SJiawen Wu static int txgbe_gpio_direction_in(struct gpio_chip *chip, unsigned int offset) 297b83c3731SJiawen Wu { 298b83c3731SJiawen Wu struct wx *wx = gpiochip_get_data(chip); 299b83c3731SJiawen Wu unsigned long flags; 300b83c3731SJiawen Wu 301b83c3731SJiawen Wu raw_spin_lock_irqsave(&wx->gpio_lock, flags); 302b83c3731SJiawen Wu wr32m(wx, WX_GPIO_DDR, BIT(offset), 0); 303b83c3731SJiawen Wu raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); 304b83c3731SJiawen Wu 305b83c3731SJiawen Wu return 0; 306b83c3731SJiawen Wu } 307b83c3731SJiawen Wu 308b83c3731SJiawen Wu static int txgbe_gpio_direction_out(struct gpio_chip *chip, unsigned int offset, 309b83c3731SJiawen Wu int val) 310b83c3731SJiawen Wu { 311b83c3731SJiawen Wu struct wx *wx = gpiochip_get_data(chip); 312b83c3731SJiawen Wu unsigned long flags; 313b83c3731SJiawen Wu u32 set; 314b83c3731SJiawen Wu 315b83c3731SJiawen Wu set = val ? BIT(offset) : 0; 316b83c3731SJiawen Wu 317b83c3731SJiawen Wu raw_spin_lock_irqsave(&wx->gpio_lock, flags); 318b83c3731SJiawen Wu wr32m(wx, WX_GPIO_DR, BIT(offset), set); 319b83c3731SJiawen Wu wr32m(wx, WX_GPIO_DDR, BIT(offset), BIT(offset)); 320b83c3731SJiawen Wu raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); 321b83c3731SJiawen Wu 322b83c3731SJiawen Wu return 0; 323b83c3731SJiawen Wu } 324b83c3731SJiawen Wu 325b83c3731SJiawen Wu static void txgbe_gpio_irq_ack(struct irq_data *d) 326b83c3731SJiawen Wu { 327b83c3731SJiawen Wu struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 328b83c3731SJiawen Wu irq_hw_number_t hwirq = irqd_to_hwirq(d); 329b83c3731SJiawen Wu struct wx *wx = gpiochip_get_data(gc); 330b83c3731SJiawen Wu unsigned long flags; 331b83c3731SJiawen Wu 332b83c3731SJiawen Wu raw_spin_lock_irqsave(&wx->gpio_lock, flags); 333b83c3731SJiawen Wu wr32(wx, WX_GPIO_EOI, BIT(hwirq)); 334b83c3731SJiawen Wu raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); 335b83c3731SJiawen Wu } 336b83c3731SJiawen Wu 337b83c3731SJiawen Wu static void txgbe_gpio_irq_mask(struct irq_data *d) 338b83c3731SJiawen Wu { 339b83c3731SJiawen Wu struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 340b83c3731SJiawen Wu irq_hw_number_t hwirq = irqd_to_hwirq(d); 341b83c3731SJiawen Wu struct wx *wx = gpiochip_get_data(gc); 342b83c3731SJiawen Wu unsigned long flags; 343b83c3731SJiawen Wu 344b83c3731SJiawen Wu gpiochip_disable_irq(gc, hwirq); 345b83c3731SJiawen Wu 346b83c3731SJiawen Wu raw_spin_lock_irqsave(&wx->gpio_lock, flags); 347b83c3731SJiawen Wu wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), BIT(hwirq)); 348b83c3731SJiawen Wu raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); 349b83c3731SJiawen Wu } 350b83c3731SJiawen Wu 351b83c3731SJiawen Wu static void txgbe_gpio_irq_unmask(struct irq_data *d) 352b83c3731SJiawen Wu { 353b83c3731SJiawen Wu struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 354b83c3731SJiawen Wu irq_hw_number_t hwirq = irqd_to_hwirq(d); 355b83c3731SJiawen Wu struct wx *wx = gpiochip_get_data(gc); 356b83c3731SJiawen Wu unsigned long flags; 357b83c3731SJiawen Wu 358b83c3731SJiawen Wu gpiochip_enable_irq(gc, hwirq); 359b83c3731SJiawen Wu 360b83c3731SJiawen Wu raw_spin_lock_irqsave(&wx->gpio_lock, flags); 361b83c3731SJiawen Wu wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), 0); 362b83c3731SJiawen Wu raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); 363b83c3731SJiawen Wu } 364b83c3731SJiawen Wu 365b83c3731SJiawen Wu static void txgbe_toggle_trigger(struct gpio_chip *gc, unsigned int offset) 366b83c3731SJiawen Wu { 367b83c3731SJiawen Wu struct wx *wx = gpiochip_get_data(gc); 368b83c3731SJiawen Wu u32 pol, val; 369b83c3731SJiawen Wu 370b83c3731SJiawen Wu pol = rd32(wx, WX_GPIO_POLARITY); 371b83c3731SJiawen Wu val = rd32(wx, WX_GPIO_EXT); 372b83c3731SJiawen Wu 373b83c3731SJiawen Wu if (val & BIT(offset)) 374b83c3731SJiawen Wu pol &= ~BIT(offset); 375b83c3731SJiawen Wu else 376b83c3731SJiawen Wu pol |= BIT(offset); 377b83c3731SJiawen Wu 378b83c3731SJiawen Wu wr32(wx, WX_GPIO_POLARITY, pol); 379b83c3731SJiawen Wu } 380b83c3731SJiawen Wu 381b83c3731SJiawen Wu static int txgbe_gpio_set_type(struct irq_data *d, unsigned int type) 382b83c3731SJiawen Wu { 383b83c3731SJiawen Wu struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 384b83c3731SJiawen Wu irq_hw_number_t hwirq = irqd_to_hwirq(d); 385b83c3731SJiawen Wu struct wx *wx = gpiochip_get_data(gc); 386b83c3731SJiawen Wu u32 level, polarity, mask; 387b83c3731SJiawen Wu unsigned long flags; 388b83c3731SJiawen Wu 389b83c3731SJiawen Wu mask = BIT(hwirq); 390b83c3731SJiawen Wu 391b83c3731SJiawen Wu if (type & IRQ_TYPE_LEVEL_MASK) { 392b83c3731SJiawen Wu level = 0; 393b83c3731SJiawen Wu irq_set_handler_locked(d, handle_level_irq); 394b83c3731SJiawen Wu } else { 395b83c3731SJiawen Wu level = mask; 396b83c3731SJiawen Wu irq_set_handler_locked(d, handle_edge_irq); 397b83c3731SJiawen Wu } 398b83c3731SJiawen Wu 399b83c3731SJiawen Wu if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) 400b83c3731SJiawen Wu polarity = mask; 401b83c3731SJiawen Wu else 402b83c3731SJiawen Wu polarity = 0; 403b83c3731SJiawen Wu 404b83c3731SJiawen Wu raw_spin_lock_irqsave(&wx->gpio_lock, flags); 405b83c3731SJiawen Wu 406b83c3731SJiawen Wu wr32m(wx, WX_GPIO_INTEN, mask, mask); 407b83c3731SJiawen Wu wr32m(wx, WX_GPIO_INTTYPE_LEVEL, mask, level); 408b83c3731SJiawen Wu if (type == IRQ_TYPE_EDGE_BOTH) 409b83c3731SJiawen Wu txgbe_toggle_trigger(gc, hwirq); 410b83c3731SJiawen Wu else 411b83c3731SJiawen Wu wr32m(wx, WX_GPIO_POLARITY, mask, polarity); 412b83c3731SJiawen Wu 413b83c3731SJiawen Wu raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); 414b83c3731SJiawen Wu 415b83c3731SJiawen Wu return 0; 416b83c3731SJiawen Wu } 417b83c3731SJiawen Wu 418b83c3731SJiawen Wu static const struct irq_chip txgbe_gpio_irq_chip = { 419b83c3731SJiawen Wu .name = "txgbe_gpio_irq", 420b83c3731SJiawen Wu .irq_ack = txgbe_gpio_irq_ack, 421b83c3731SJiawen Wu .irq_mask = txgbe_gpio_irq_mask, 422b83c3731SJiawen Wu .irq_unmask = txgbe_gpio_irq_unmask, 423b83c3731SJiawen Wu .irq_set_type = txgbe_gpio_set_type, 424b83c3731SJiawen Wu .flags = IRQCHIP_IMMUTABLE, 425b83c3731SJiawen Wu GPIOCHIP_IRQ_RESOURCE_HELPERS, 426b83c3731SJiawen Wu }; 427b83c3731SJiawen Wu 428b83c3731SJiawen Wu static void txgbe_irq_handler(struct irq_desc *desc) 429b83c3731SJiawen Wu { 430b83c3731SJiawen Wu struct irq_chip *chip = irq_desc_get_chip(desc); 431b83c3731SJiawen Wu struct wx *wx = irq_desc_get_handler_data(desc); 432b83c3731SJiawen Wu struct txgbe *txgbe = wx->priv; 433b83c3731SJiawen Wu irq_hw_number_t hwirq; 434b83c3731SJiawen Wu unsigned long gpioirq; 435b83c3731SJiawen Wu struct gpio_chip *gc; 436b83c3731SJiawen Wu unsigned long flags; 43708f08f93SJiawen Wu u32 eicr; 43808f08f93SJiawen Wu 43908f08f93SJiawen Wu eicr = wx_misc_isb(wx, WX_ISB_MISC); 440b83c3731SJiawen Wu 441b83c3731SJiawen Wu chained_irq_enter(chip, desc); 442b83c3731SJiawen Wu 443b83c3731SJiawen Wu gpioirq = rd32(wx, WX_GPIO_INTSTATUS); 444b83c3731SJiawen Wu 445b83c3731SJiawen Wu gc = txgbe->gpio; 446b83c3731SJiawen Wu for_each_set_bit(hwirq, &gpioirq, gc->ngpio) { 447b83c3731SJiawen Wu int gpio = irq_find_mapping(gc->irq.domain, hwirq); 448b83c3731SJiawen Wu u32 irq_type = irq_get_trigger_type(gpio); 449b83c3731SJiawen Wu 450b83c3731SJiawen Wu generic_handle_domain_irq(gc->irq.domain, hwirq); 451b83c3731SJiawen Wu 452b83c3731SJiawen Wu if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { 453b83c3731SJiawen Wu raw_spin_lock_irqsave(&wx->gpio_lock, flags); 454b83c3731SJiawen Wu txgbe_toggle_trigger(gc, hwirq); 455b83c3731SJiawen Wu raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); 456b83c3731SJiawen Wu } 457b83c3731SJiawen Wu } 458b83c3731SJiawen Wu 459b83c3731SJiawen Wu chained_irq_exit(chip, desc); 460b83c3731SJiawen Wu 461*a4414dd1SJiawen Wu if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN | 462*a4414dd1SJiawen Wu TXGBE_PX_MISC_ETH_AN)) { 46308f08f93SJiawen Wu u32 reg = rd32(wx, TXGBE_CFG_PORT_ST); 46408f08f93SJiawen Wu 46508f08f93SJiawen Wu phylink_mac_change(txgbe->phylink, !!(reg & TXGBE_CFG_PORT_ST_LINK_UP)); 46608f08f93SJiawen Wu } 46708f08f93SJiawen Wu 468b83c3731SJiawen Wu /* unmask interrupt */ 469b83c3731SJiawen Wu wx_intr_enable(wx, TXGBE_INTR_MISC(wx)); 470b83c3731SJiawen Wu } 471b83c3731SJiawen Wu 472b83c3731SJiawen Wu static int txgbe_gpio_init(struct txgbe *txgbe) 473b83c3731SJiawen Wu { 474b83c3731SJiawen Wu struct gpio_irq_chip *girq; 475b83c3731SJiawen Wu struct gpio_chip *gc; 476b83c3731SJiawen Wu struct device *dev; 477b83c3731SJiawen Wu struct wx *wx; 478b83c3731SJiawen Wu int ret; 479b83c3731SJiawen Wu 480b83c3731SJiawen Wu wx = txgbe->wx; 481b83c3731SJiawen Wu dev = &wx->pdev->dev; 482b83c3731SJiawen Wu 483b83c3731SJiawen Wu raw_spin_lock_init(&wx->gpio_lock); 484b83c3731SJiawen Wu 485b83c3731SJiawen Wu gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); 486b83c3731SJiawen Wu if (!gc) 487b83c3731SJiawen Wu return -ENOMEM; 488b83c3731SJiawen Wu 489b83c3731SJiawen Wu gc->label = devm_kasprintf(dev, GFP_KERNEL, "txgbe_gpio-%x", 490d8c21ef7SXiongfeng Wang pci_dev_id(wx->pdev)); 491b83c3731SJiawen Wu if (!gc->label) 492b83c3731SJiawen Wu return -ENOMEM; 493b83c3731SJiawen Wu 494b83c3731SJiawen Wu gc->base = -1; 495b83c3731SJiawen Wu gc->ngpio = 6; 496b83c3731SJiawen Wu gc->owner = THIS_MODULE; 497b83c3731SJiawen Wu gc->parent = dev; 498b83c3731SJiawen Wu gc->fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_GPIO]); 499b83c3731SJiawen Wu gc->get = txgbe_gpio_get; 500b83c3731SJiawen Wu gc->get_direction = txgbe_gpio_get_direction; 501b83c3731SJiawen Wu gc->direction_input = txgbe_gpio_direction_in; 502b83c3731SJiawen Wu gc->direction_output = txgbe_gpio_direction_out; 503b83c3731SJiawen Wu 504b83c3731SJiawen Wu girq = &gc->irq; 505b83c3731SJiawen Wu gpio_irq_chip_set_chip(girq, &txgbe_gpio_irq_chip); 506b83c3731SJiawen Wu girq->parent_handler = txgbe_irq_handler; 507b83c3731SJiawen Wu girq->parent_handler_data = wx; 508b83c3731SJiawen Wu girq->num_parents = 1; 509b83c3731SJiawen Wu girq->parents = devm_kcalloc(dev, girq->num_parents, 510b83c3731SJiawen Wu sizeof(*girq->parents), GFP_KERNEL); 511b83c3731SJiawen Wu if (!girq->parents) 512b83c3731SJiawen Wu return -ENOMEM; 513b83c3731SJiawen Wu girq->parents[0] = wx->msix_entries[wx->num_q_vectors].vector; 514b83c3731SJiawen Wu girq->default_type = IRQ_TYPE_NONE; 515b83c3731SJiawen Wu girq->handler = handle_bad_irq; 516b83c3731SJiawen Wu 517b83c3731SJiawen Wu ret = devm_gpiochip_add_data(dev, gc, wx); 518b83c3731SJiawen Wu if (ret) 519b83c3731SJiawen Wu return ret; 520b83c3731SJiawen Wu 521b83c3731SJiawen Wu txgbe->gpio = gc; 522b83c3731SJiawen Wu 523b83c3731SJiawen Wu return 0; 524b83c3731SJiawen Wu } 525b83c3731SJiawen Wu 526b63f2048SJiawen Wu static int txgbe_clock_register(struct txgbe *txgbe) 527b63f2048SJiawen Wu { 528b63f2048SJiawen Wu struct pci_dev *pdev = txgbe->wx->pdev; 529b63f2048SJiawen Wu struct clk_lookup *clock; 530b63f2048SJiawen Wu char clk_name[32]; 531b63f2048SJiawen Wu struct clk *clk; 532b63f2048SJiawen Wu 533b63f2048SJiawen Wu snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d", 534d8c21ef7SXiongfeng Wang pci_dev_id(pdev)); 535b63f2048SJiawen Wu 536b63f2048SJiawen Wu clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000); 537b63f2048SJiawen Wu if (IS_ERR(clk)) 538b63f2048SJiawen Wu return PTR_ERR(clk); 539b63f2048SJiawen Wu 540b63f2048SJiawen Wu clock = clkdev_create(clk, NULL, clk_name); 541b63f2048SJiawen Wu if (!clock) { 542b63f2048SJiawen Wu clk_unregister(clk); 543b63f2048SJiawen Wu return -ENOMEM; 544b63f2048SJiawen Wu } 545b63f2048SJiawen Wu 546b63f2048SJiawen Wu txgbe->clk = clk; 547b63f2048SJiawen Wu txgbe->clock = clock; 548b63f2048SJiawen Wu 549b63f2048SJiawen Wu return 0; 550b63f2048SJiawen Wu } 551b63f2048SJiawen Wu 552c625e725SJiawen Wu static int txgbe_i2c_read(void *context, unsigned int reg, unsigned int *val) 553c625e725SJiawen Wu { 554c625e725SJiawen Wu struct wx *wx = context; 555c625e725SJiawen Wu 556c625e725SJiawen Wu *val = rd32(wx, reg + TXGBE_I2C_BASE); 557c625e725SJiawen Wu 558c625e725SJiawen Wu return 0; 559c625e725SJiawen Wu } 560c625e725SJiawen Wu 561c625e725SJiawen Wu static int txgbe_i2c_write(void *context, unsigned int reg, unsigned int val) 562c625e725SJiawen Wu { 563c625e725SJiawen Wu struct wx *wx = context; 564c625e725SJiawen Wu 565c625e725SJiawen Wu wr32(wx, reg + TXGBE_I2C_BASE, val); 566c625e725SJiawen Wu 567c625e725SJiawen Wu return 0; 568c625e725SJiawen Wu } 569c625e725SJiawen Wu 570c625e725SJiawen Wu static const struct regmap_config i2c_regmap_config = { 571c625e725SJiawen Wu .reg_bits = 32, 572c625e725SJiawen Wu .val_bits = 32, 573c625e725SJiawen Wu .reg_read = txgbe_i2c_read, 574c625e725SJiawen Wu .reg_write = txgbe_i2c_write, 575c625e725SJiawen Wu .fast_io = true, 576c625e725SJiawen Wu }; 577c625e725SJiawen Wu 578c625e725SJiawen Wu static int txgbe_i2c_register(struct txgbe *txgbe) 579c625e725SJiawen Wu { 580c625e725SJiawen Wu struct platform_device_info info = {}; 581c625e725SJiawen Wu struct platform_device *i2c_dev; 582c625e725SJiawen Wu struct regmap *i2c_regmap; 583c625e725SJiawen Wu struct pci_dev *pdev; 584c625e725SJiawen Wu struct wx *wx; 585c625e725SJiawen Wu 586c625e725SJiawen Wu wx = txgbe->wx; 587c625e725SJiawen Wu pdev = wx->pdev; 588c625e725SJiawen Wu i2c_regmap = devm_regmap_init(&pdev->dev, NULL, wx, &i2c_regmap_config); 589c625e725SJiawen Wu if (IS_ERR(i2c_regmap)) { 590c625e725SJiawen Wu wx_err(wx, "failed to init I2C regmap\n"); 591c625e725SJiawen Wu return PTR_ERR(i2c_regmap); 592c625e725SJiawen Wu } 593c625e725SJiawen Wu 594c625e725SJiawen Wu info.parent = &pdev->dev; 595c625e725SJiawen Wu info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]); 596c625e725SJiawen Wu info.name = "i2c_designware"; 597d8c21ef7SXiongfeng Wang info.id = pci_dev_id(pdev); 598c625e725SJiawen Wu 599c625e725SJiawen Wu info.res = &DEFINE_RES_IRQ(pdev->irq); 600c625e725SJiawen Wu info.num_res = 1; 601c625e725SJiawen Wu i2c_dev = platform_device_register_full(&info); 602c625e725SJiawen Wu if (IS_ERR(i2c_dev)) 603c625e725SJiawen Wu return PTR_ERR(i2c_dev); 604c625e725SJiawen Wu 605c625e725SJiawen Wu txgbe->i2c_dev = i2c_dev; 606c625e725SJiawen Wu 607c625e725SJiawen Wu return 0; 608c625e725SJiawen Wu } 609c625e725SJiawen Wu 61004d94236SJiawen Wu static int txgbe_sfp_register(struct txgbe *txgbe) 61104d94236SJiawen Wu { 61204d94236SJiawen Wu struct pci_dev *pdev = txgbe->wx->pdev; 61304d94236SJiawen Wu struct platform_device_info info = {}; 61404d94236SJiawen Wu struct platform_device *sfp_dev; 61504d94236SJiawen Wu 61604d94236SJiawen Wu info.parent = &pdev->dev; 61704d94236SJiawen Wu info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_SFP]); 61804d94236SJiawen Wu info.name = "sfp"; 619d8c21ef7SXiongfeng Wang info.id = pci_dev_id(pdev); 62004d94236SJiawen Wu sfp_dev = platform_device_register_full(&info); 62104d94236SJiawen Wu if (IS_ERR(sfp_dev)) 62204d94236SJiawen Wu return PTR_ERR(sfp_dev); 62304d94236SJiawen Wu 62404d94236SJiawen Wu txgbe->sfp_dev = sfp_dev; 62504d94236SJiawen Wu 62604d94236SJiawen Wu return 0; 62704d94236SJiawen Wu } 62804d94236SJiawen Wu 629c3e382adSJiawen Wu int txgbe_init_phy(struct txgbe *txgbe) 630c3e382adSJiawen Wu { 631c3e382adSJiawen Wu int ret; 632c3e382adSJiawen Wu 633c3e382adSJiawen Wu ret = txgbe_swnodes_register(txgbe); 634c3e382adSJiawen Wu if (ret) { 635c3e382adSJiawen Wu wx_err(txgbe->wx, "failed to register software nodes\n"); 636c3e382adSJiawen Wu return ret; 637c3e382adSJiawen Wu } 638c3e382adSJiawen Wu 639854cace6SJiawen Wu ret = txgbe_mdio_pcs_init(txgbe); 640854cace6SJiawen Wu if (ret) { 641854cace6SJiawen Wu wx_err(txgbe->wx, "failed to init mdio pcs: %d\n", ret); 642854cace6SJiawen Wu goto err_unregister_swnode; 643854cace6SJiawen Wu } 644854cace6SJiawen Wu 64508f08f93SJiawen Wu ret = txgbe_phylink_init(txgbe); 64608f08f93SJiawen Wu if (ret) { 64708f08f93SJiawen Wu wx_err(txgbe->wx, "failed to init phylink\n"); 64808f08f93SJiawen Wu goto err_destroy_xpcs; 64908f08f93SJiawen Wu } 65008f08f93SJiawen Wu 651b83c3731SJiawen Wu ret = txgbe_gpio_init(txgbe); 652b83c3731SJiawen Wu if (ret) { 653b83c3731SJiawen Wu wx_err(txgbe->wx, "failed to init gpio\n"); 65408f08f93SJiawen Wu goto err_destroy_phylink; 655b83c3731SJiawen Wu } 656b83c3731SJiawen Wu 657b63f2048SJiawen Wu ret = txgbe_clock_register(txgbe); 658b63f2048SJiawen Wu if (ret) { 659b63f2048SJiawen Wu wx_err(txgbe->wx, "failed to register clock: %d\n", ret); 66008f08f93SJiawen Wu goto err_destroy_phylink; 661b63f2048SJiawen Wu } 662b63f2048SJiawen Wu 663c625e725SJiawen Wu ret = txgbe_i2c_register(txgbe); 664c625e725SJiawen Wu if (ret) { 665c625e725SJiawen Wu wx_err(txgbe->wx, "failed to init i2c interface: %d\n", ret); 666c625e725SJiawen Wu goto err_unregister_clk; 667c625e725SJiawen Wu } 668c625e725SJiawen Wu 66904d94236SJiawen Wu ret = txgbe_sfp_register(txgbe); 67004d94236SJiawen Wu if (ret) { 67104d94236SJiawen Wu wx_err(txgbe->wx, "failed to register sfp\n"); 67204d94236SJiawen Wu goto err_unregister_i2c; 67304d94236SJiawen Wu } 67404d94236SJiawen Wu 675c3e382adSJiawen Wu return 0; 676b63f2048SJiawen Wu 67704d94236SJiawen Wu err_unregister_i2c: 67804d94236SJiawen Wu platform_device_unregister(txgbe->i2c_dev); 679c625e725SJiawen Wu err_unregister_clk: 680c625e725SJiawen Wu clkdev_drop(txgbe->clock); 681c625e725SJiawen Wu clk_unregister(txgbe->clk); 68208f08f93SJiawen Wu err_destroy_phylink: 68308f08f93SJiawen Wu phylink_destroy(txgbe->phylink); 684854cace6SJiawen Wu err_destroy_xpcs: 685854cace6SJiawen Wu xpcs_destroy(txgbe->xpcs); 686b63f2048SJiawen Wu err_unregister_swnode: 687b63f2048SJiawen Wu software_node_unregister_node_group(txgbe->nodes.group); 688b63f2048SJiawen Wu 689b63f2048SJiawen Wu return ret; 690c3e382adSJiawen Wu } 691c3e382adSJiawen Wu 692c3e382adSJiawen Wu void txgbe_remove_phy(struct txgbe *txgbe) 693c3e382adSJiawen Wu { 69404d94236SJiawen Wu platform_device_unregister(txgbe->sfp_dev); 695c625e725SJiawen Wu platform_device_unregister(txgbe->i2c_dev); 696b63f2048SJiawen Wu clkdev_drop(txgbe->clock); 697b63f2048SJiawen Wu clk_unregister(txgbe->clk); 69808f08f93SJiawen Wu phylink_destroy(txgbe->phylink); 699854cace6SJiawen Wu xpcs_destroy(txgbe->xpcs); 700c3e382adSJiawen Wu software_node_unregister_node_group(txgbe->nodes.group); 701c3e382adSJiawen Wu } 702