phy: ti: gmii-sel: Add support for CPSW5G GMII SEL in J7200
Each of the CPSW5G ports in J7200 support additional modes like QSGMII. Add a new compatible for J7200 to support the additional modes. In TI's J7200, each of the CPSW5G ethernet interfaces can act as a QSGMII or QSGMII-SUB port. The QSGMII interface is responsible for performing auto-negotiation between the MAC and the PHY while the rest of the interfaces are designated as QSGMII-SUB interfaces, indicating that they will not be taking part in the auto-negotiation process. To indicate the interface which will serve as the main QSGMII interface, add a property "ti,qsgmii-main-ports", whose value indicates the port number of the interface which shall serve as the main QSGMII interface. The rest of the interfaces are then assigned QSGMII-SUB mode by default. The property "ti,qsgmii-main-ports" is used to configure the CTRLMMR_ENETx_CTRL register. Depending on the device, it is possible for more than one QSGMII main port to exist. Thus, the property "ti,qsgmii-main-ports" is defined as an array of values in order to reuse the property for other devices. Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com> Link: https://lore.kernel.org/r/20220912085650.83263-4-s-vadapalli@ti.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
bd76037833
commit
af96579dc3
|
@ -22,6 +22,12 @@
|
|||
#define AM33XX_GMII_SEL_MODE_RMII 1
|
||||
#define AM33XX_GMII_SEL_MODE_RGMII 2
|
||||
|
||||
/* J72xx SoC specific definitions for the CONTROL port */
|
||||
#define J72XX_GMII_SEL_MODE_QSGMII 4
|
||||
#define J72XX_GMII_SEL_MODE_QSGMII_SUB 6
|
||||
|
||||
#define PHY_GMII_PORT(n) BIT((n) - 1)
|
||||
|
||||
enum {
|
||||
PHY_GMII_SEL_PORT_MODE = 0,
|
||||
PHY_GMII_SEL_RGMII_ID_MODE,
|
||||
|
@ -43,6 +49,7 @@ struct phy_gmii_sel_soc_data {
|
|||
u32 features;
|
||||
const struct reg_field (*regfields)[PHY_GMII_SEL_LAST];
|
||||
bool use_of_data;
|
||||
u64 extra_modes;
|
||||
};
|
||||
|
||||
struct phy_gmii_sel_priv {
|
||||
|
@ -53,6 +60,7 @@ struct phy_gmii_sel_priv {
|
|||
struct phy_gmii_sel_phy_priv *if_phys;
|
||||
u32 num_ports;
|
||||
u32 reg_offset;
|
||||
u32 qsgmii_main_ports;
|
||||
};
|
||||
|
||||
static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode)
|
||||
|
@ -88,10 +96,17 @@ static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode)
|
|||
gmii_sel_mode = AM33XX_GMII_SEL_MODE_MII;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_QSGMII:
|
||||
if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_QSGMII)))
|
||||
goto unsupported;
|
||||
if (if_phy->priv->qsgmii_main_ports & BIT(if_phy->id - 1))
|
||||
gmii_sel_mode = J72XX_GMII_SEL_MODE_QSGMII;
|
||||
else
|
||||
gmii_sel_mode = J72XX_GMII_SEL_MODE_QSGMII_SUB;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_warn(dev, "port%u: unsupported mode: \"%s\"\n",
|
||||
if_phy->id, phy_modes(submode));
|
||||
return -EINVAL;
|
||||
goto unsupported;
|
||||
}
|
||||
|
||||
if_phy->phy_if_mode = submode;
|
||||
|
@ -123,6 +138,11 @@ static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode)
|
|||
}
|
||||
|
||||
return 0;
|
||||
|
||||
unsupported:
|
||||
dev_warn(dev, "port%u: unsupported mode: \"%s\"\n",
|
||||
if_phy->id, phy_modes(submode));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const
|
||||
|
@ -188,6 +208,13 @@ struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am654 = {
|
|||
.regfields = phy_gmii_sel_fields_am654,
|
||||
};
|
||||
|
||||
static const
|
||||
struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = {
|
||||
.use_of_data = true,
|
||||
.regfields = phy_gmii_sel_fields_am654,
|
||||
.extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII),
|
||||
};
|
||||
|
||||
static const struct of_device_id phy_gmii_sel_id_table[] = {
|
||||
{
|
||||
.compatible = "ti,am3352-phy-gmii-sel",
|
||||
|
@ -209,6 +236,10 @@ static const struct of_device_id phy_gmii_sel_id_table[] = {
|
|||
.compatible = "ti,am654-phy-gmii-sel",
|
||||
.data = &phy_gmii_sel_soc_am654,
|
||||
},
|
||||
{
|
||||
.compatible = "ti,j7200-cpsw5g-phy-gmii-sel",
|
||||
.data = &phy_gmii_sel_cpsw5g_soc_j7200,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, phy_gmii_sel_id_table);
|
||||
|
@ -350,6 +381,7 @@ static int phy_gmii_sel_probe(struct platform_device *pdev)
|
|||
struct device_node *node = dev->of_node;
|
||||
const struct of_device_id *of_id;
|
||||
struct phy_gmii_sel_priv *priv;
|
||||
u32 main_ports = 1;
|
||||
int ret;
|
||||
|
||||
of_id = of_match_node(phy_gmii_sel_id_table, pdev->dev.of_node);
|
||||
|
@ -363,6 +395,15 @@ static int phy_gmii_sel_probe(struct platform_device *pdev)
|
|||
priv->dev = &pdev->dev;
|
||||
priv->soc_data = of_id->data;
|
||||
priv->num_ports = priv->soc_data->num_ports;
|
||||
of_property_read_u32(node, "ti,qsgmii-main-ports", &main_ports);
|
||||
/*
|
||||
* Ensure that main_ports is within bounds. If the property
|
||||
* ti,qsgmii-main-ports is not mentioned, or the value mentioned
|
||||
* is out of bounds, default to 1.
|
||||
*/
|
||||
if (main_ports < 1 || main_ports > 4)
|
||||
main_ports = 1;
|
||||
priv->qsgmii_main_ports = PHY_GMII_PORT(main_ports);
|
||||
|
||||
priv->regmap = syscon_node_to_regmap(node->parent);
|
||||
if (IS_ERR(priv->regmap)) {
|
||||
|
|
Loading…
Reference in New Issue