Commit c3e382ad authored by Jiawen Wu's avatar Jiawen Wu Committed by Paolo Abeni
Browse files

net: txgbe: Add software nodes to support phylink



Register software nodes for GPIO, I2C, SFP and PHYLINK. Define the
device properties.

Signed-off-by: default avatarJiawen Wu <jiawenwu@trustnetic.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Reviewed-by: default avatarPiotr Raczynski <piotr.raczynski@intel.com>
Reviewed-by: default avatarMaciej Fijalkowski <maciej.fijalkowski@intel.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 4a562127
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -814,6 +814,7 @@ enum wx_isb_idx {
struct wx {
	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];

	void *priv;
	u8 __iomem *hw_addr;
	struct pci_dev *pdev;
	struct net_device *netdev;
+1 −0
Original line number Diff line number Diff line
@@ -8,4 +8,5 @@ obj-$(CONFIG_TXGBE) += txgbe.o

txgbe-objs := txgbe_main.o \
              txgbe_hw.o \
              txgbe_phy.o \
              txgbe_ethtool.o
+21 −1
Original line number Diff line number Diff line
@@ -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";
@@ -516,6 +517,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;
@@ -680,10 +682,23 @@ static int txgbe_probe(struct pci_dev *pdev,
			 "0x%08x", etrack_id);
	}

	err = register_netdev(netdev);
	txgbe = devm_kzalloc(&pdev->dev, sizeof(*txgbe), GFP_KERNEL);
	if (!txgbe) {
		err = -ENOMEM;
		goto err_release_hw;
	}

	txgbe->wx = wx;
	wx->priv = txgbe;

	err = txgbe_init_phy(txgbe);
	if (err)
		goto err_release_hw;

	err = register_netdev(netdev);
	if (err)
		goto err_remove_phy;

	pci_set_drvdata(pdev, wx);

	netif_tx_stop_all_queues(netdev);
@@ -711,6 +726,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);
@@ -736,11 +753,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));

+89 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */

#include <linux/gpio/property.h>
#include <linux/i2c.h>
#include <linux/pci.h>

#include "../libwx/wx_type.h"
#include "txgbe_type.h"
#include "txgbe_phy.h"

static int txgbe_swnodes_register(struct txgbe *txgbe)
{
	struct txgbe_nodes *nodes = &txgbe->nodes;
	struct pci_dev *pdev = txgbe->wx->pdev;
	struct software_node *swnodes;
	u32 id;

	id = (pdev->bus->number << 8) | pdev->devfn;

	snprintf(nodes->gpio_name, sizeof(nodes->gpio_name), "txgbe_gpio-%x", id);
	snprintf(nodes->i2c_name, sizeof(nodes->i2c_name), "txgbe_i2c-%x", id);
	snprintf(nodes->sfp_name, sizeof(nodes->sfp_name), "txgbe_sfp-%x", id);
	snprintf(nodes->phylink_name, sizeof(nodes->phylink_name), "txgbe_phylink-%x", id);

	swnodes = nodes->swnodes;

	/* GPIO 0: tx fault
	 * GPIO 1: tx disable
	 * GPIO 2: sfp module absent
	 * GPIO 3: rx signal lost
	 * GPIO 4: rate select, 1G(0) 10G(1)
	 * GPIO 5: rate select, 1G(0) 10G(1)
	 */
	nodes->gpio_props[0] = PROPERTY_ENTRY_STRING("pinctrl-names", "default");
	swnodes[SWNODE_GPIO] = NODE_PROP(nodes->gpio_name, nodes->gpio_props);
	nodes->gpio0_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 0, GPIO_ACTIVE_HIGH);
	nodes->gpio1_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 1, GPIO_ACTIVE_HIGH);
	nodes->gpio2_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 2, GPIO_ACTIVE_LOW);
	nodes->gpio3_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 3, GPIO_ACTIVE_HIGH);
	nodes->gpio4_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 4, GPIO_ACTIVE_HIGH);
	nodes->gpio5_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 5, GPIO_ACTIVE_HIGH);

	nodes->i2c_props[0] = PROPERTY_ENTRY_STRING("compatible", "snps,designware-i2c");
	nodes->i2c_props[1] = PROPERTY_ENTRY_BOOL("wx,i2c-snps-model");
	nodes->i2c_props[2] = PROPERTY_ENTRY_U32("clock-frequency", I2C_MAX_STANDARD_MODE_FREQ);
	swnodes[SWNODE_I2C] = NODE_PROP(nodes->i2c_name, nodes->i2c_props);
	nodes->i2c_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_I2C]);

	nodes->sfp_props[0] = PROPERTY_ENTRY_STRING("compatible", "sff,sfp");
	nodes->sfp_props[1] = PROPERTY_ENTRY_REF_ARRAY("i2c-bus", nodes->i2c_ref);
	nodes->sfp_props[2] = PROPERTY_ENTRY_REF_ARRAY("tx-fault-gpios", nodes->gpio0_ref);
	nodes->sfp_props[3] = PROPERTY_ENTRY_REF_ARRAY("tx-disable-gpios", nodes->gpio1_ref);
	nodes->sfp_props[4] = PROPERTY_ENTRY_REF_ARRAY("mod-def0-gpios", nodes->gpio2_ref);
	nodes->sfp_props[5] = PROPERTY_ENTRY_REF_ARRAY("los-gpios", nodes->gpio3_ref);
	nodes->sfp_props[6] = PROPERTY_ENTRY_REF_ARRAY("rate-select1-gpios", nodes->gpio4_ref);
	nodes->sfp_props[7] = PROPERTY_ENTRY_REF_ARRAY("rate-select0-gpios", nodes->gpio5_ref);
	swnodes[SWNODE_SFP] = NODE_PROP(nodes->sfp_name, nodes->sfp_props);
	nodes->sfp_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_SFP]);

	nodes->phylink_props[0] = PROPERTY_ENTRY_STRING("managed", "in-band-status");
	nodes->phylink_props[1] = PROPERTY_ENTRY_REF_ARRAY("sfp", nodes->sfp_ref);
	swnodes[SWNODE_PHYLINK] = NODE_PROP(nodes->phylink_name, nodes->phylink_props);

	nodes->group[SWNODE_GPIO] = &swnodes[SWNODE_GPIO];
	nodes->group[SWNODE_I2C] = &swnodes[SWNODE_I2C];
	nodes->group[SWNODE_SFP] = &swnodes[SWNODE_SFP];
	nodes->group[SWNODE_PHYLINK] = &swnodes[SWNODE_PHYLINK];

	return software_node_register_node_group(nodes->group);
}

int txgbe_init_phy(struct txgbe *txgbe)
{
	int ret;

	ret = txgbe_swnodes_register(txgbe);
	if (ret) {
		wx_err(txgbe->wx, "failed to register software nodes\n");
		return ret;
	}

	return 0;
}

void txgbe_remove_phy(struct txgbe *txgbe)
{
	software_node_unregister_node_group(txgbe->nodes.group);
}
+10 −0
Original line number Diff line number Diff line
/* 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_ */
Loading