diff mbox series

[net-next,v7,7/9] net: stmmac: dwmac-loongson: Add GNET support

Message ID caf9e822c2f628f09e02760cfa81a1bd4af0b8d6.1702990507.git.siyanteng@loongson.cn (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series stmmac: Add Loongson platform support | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 47 this patch: 47
netdev/cc_maintainers warning 10 maintainers not CCed: ahalaney@redhat.com edumazet@google.com linux-stm32@st-md-mailman.stormreply.com horms@kernel.org pabeni@redhat.com kuba@kernel.org bartosz.golaszewski@linaro.org mcoquelin.stm32@gmail.com linux-arm-kernel@lists.infradead.org richardcochran@gmail.com
netdev/build_clang fail Errors and warnings before: 21 this patch: 21
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn fail Errors and warnings before: 48 this patch: 48
netdev/checkpatch warning WARNING: line length of 86 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Yanteng Si Dec. 19, 2023, 2:26 p.m. UTC
Add Loongson GNET (GMAC with PHY) support. Current GNET does not support
half duplex mode, and GNET on LS7A only supports ANE when speed is set to
1000M.

Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 79 +++++++++++++++++++
 .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
 include/linux/stmmac.h                        |  2 +
 3 files changed, 87 insertions(+)

Comments

Serge Semin Dec. 21, 2023, 2:34 a.m. UTC | #1
On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
> Add Loongson GNET (GMAC with PHY) support. Current GNET does not support
> half duplex mode, and GNET on LS7A only supports ANE when speed is set to
> 1000M.
> 
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> ---
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 79 +++++++++++++++++++
>  .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
>  include/linux/stmmac.h                        |  2 +
>  3 files changed, 87 insertions(+)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 2c08d5495214..9e4953c7e4e0 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -168,6 +168,83 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
>  	.config = loongson_gmac_config,
>  };
>  
> +static void loongson_gnet_fix_speed(void *priv, unsigned int speed, unsigned int mode)
> +{
> +	struct net_device *ndev = dev_get_drvdata(priv);
> +	struct stmmac_priv *ptr = netdev_priv(ndev);
> +
> +	/* The controller and PHY don't work well together.
> +	 * We need to use the PS bit to check if the controller's status
> +	 * is correct and reset PHY if necessary.
> +	 */

> +	if (speed == SPEED_1000)
> +		if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
> +			phy_restart_aneg(ndev->phydev);

{} around the outer if please.

> +}
> +
> +static int loongson_gnet_data(struct pci_dev *pdev,
> +			      struct plat_stmmacenet_data *plat)
> +{
> +	loongson_default_data(pdev, plat);
> +
> +	plat->multicast_filter_bins = 256;
> +

> +	plat->mdio_bus_data->phy_mask = 0xfffffffb;

~BIT(2)?

> +
> +	plat->phy_addr = 2;
> +	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
> +
> +	plat->bsp_priv = &pdev->dev;
> +	plat->fix_mac_speed = loongson_gnet_fix_speed;
> +
> +	plat->dma_cfg->pbl = 32;
> +	plat->dma_cfg->pblx8 = true;
> +
> +	plat->clk_ref_rate = 125000000;
> +	plat->clk_ptp_rate = 125000000;
> +
> +	return 0;
> +}
> +
> +static int loongson_gnet_config(struct pci_dev *pdev,
> +				struct plat_stmmacenet_data *plat,
> +				struct stmmac_resources *res,
> +				struct device_node *np)
> +{
> +	int ret;
> +	u32 version = readl(res->addr + GMAC_VERSION);
> +
> +	switch (version & 0xff) {

> +	case DWLGMAC_CORE_1_00:
> +		ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
> +		break;
> +	default:
> +		ret = loongson_dwmac_config_legacy(pdev, plat, res, np);

Hm, do you have two versions of Loongson GNET? What does the second
one contain in the GMAC_VERSION register then? Can't you distinguish
them by the PCI IDs (device, subsystem, revision)?

-Serge(y)

> +		break;
> +	}
> +
> +	switch (pdev->revision) {
> +	case 0x00:
> +		plat->flags |=
> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
> +			FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
> +		break;
> +	case 0x01:
> +		plat->flags |=
> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static struct stmmac_pci_info loongson_gnet_pci_info = {
> +	.setup = loongson_gnet_data,
> +	.config = loongson_gnet_config,
> +};
> +
>  static int loongson_dwmac_probe(struct pci_dev *pdev,
>  				const struct pci_device_id *id)
>  {
> @@ -318,9 +395,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>  			 loongson_dwmac_resume);
>  
>  #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
> +#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
>  
>  static const struct pci_device_id loongson_dwmac_id_table[] = {
>  	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
> +	{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
>  	{}
>  };
>  MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> index 8105ce47c6ad..d6939eb9a0d8 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
>  		return 0;
>  	}
>  
> +	if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000, priv->plat->flags)) {
> +		if (cmd->base.speed == SPEED_1000 &&
> +		    cmd->base.autoneg != AUTONEG_ENABLE)
> +			return -EOPNOTSUPP;
> +	}
> +
>  	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
>  }
>  
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index f07f79d50b06..067030cdb60f 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -222,6 +222,8 @@ struct dwmac4_addrs {
>  #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>  #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>  #define STMMAC_FLAG_HAS_LGMAC			BIT(13)
> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
> +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
>  
>  struct plat_stmmacenet_data {
>  	int bus_id;
> -- 
> 2.31.4
>
Yanteng Si Jan. 1, 2024, 7:27 a.m. UTC | #2
在 2023/12/21 10:34, Serge Semin 写道:
> On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
>> Add Loongson GNET (GMAC with PHY) support. Current GNET does not support
>> half duplex mode, and GNET on LS7A only supports ANE when speed is set to
>> 1000M.
>>
>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>> ---
>>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 79 +++++++++++++++++++
>>   .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
>>   include/linux/stmmac.h                        |  2 +
>>   3 files changed, 87 insertions(+)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> index 2c08d5495214..9e4953c7e4e0 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>> @@ -168,6 +168,83 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
>>   	.config = loongson_gmac_config,
>>   };
>>   
>> +static void loongson_gnet_fix_speed(void *priv, unsigned int speed, unsigned int mode)
>> +{
>> +	struct net_device *ndev = dev_get_drvdata(priv);
>> +	struct stmmac_priv *ptr = netdev_priv(ndev);
>> +
>> +	/* The controller and PHY don't work well together.
>> +	 * We need to use the PS bit to check if the controller's status
>> +	 * is correct and reset PHY if necessary.
>> +	 */
>> +	if (speed == SPEED_1000)
>> +		if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
>> +			phy_restart_aneg(ndev->phydev);
> {} around the outer if please.
OK.
>
>> +}
>> +
>> +static int loongson_gnet_data(struct pci_dev *pdev,
>> +			      struct plat_stmmacenet_data *plat)
>> +{
>> +	loongson_default_data(pdev, plat);
>> +
>> +	plat->multicast_filter_bins = 256;
>> +
>> +	plat->mdio_bus_data->phy_mask = 0xfffffffb;
> ~BIT(2)?
I still need to confirm, please allow me to get back to you later.
>
>> +
>> +	plat->phy_addr = 2;
>> +	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
>> +
>> +	plat->bsp_priv = &pdev->dev;
>> +	plat->fix_mac_speed = loongson_gnet_fix_speed;
>> +
>> +	plat->dma_cfg->pbl = 32;
>> +	plat->dma_cfg->pblx8 = true;
>> +
>> +	plat->clk_ref_rate = 125000000;
>> +	plat->clk_ptp_rate = 125000000;
>> +
>> +	return 0;
>> +}
>> +
>> +static int loongson_gnet_config(struct pci_dev *pdev,
>> +				struct plat_stmmacenet_data *plat,
>> +				struct stmmac_resources *res,
>> +				struct device_node *np)
>> +{
>> +	int ret;
>> +	u32 version = readl(res->addr + GMAC_VERSION);
>> +
>> +	switch (version & 0xff) {
>> +	case DWLGMAC_CORE_1_00:
>> +		ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
>> +		break;
>> +	default:
>> +		ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> Hm, do you have two versions of Loongson GNET? What does the second
Yes.
> one contain in the GMAC_VERSION register then? Can't you distinguish
> them by the PCI IDs (device, subsystem, revision)?

I'm afraid that's not possible.

Because they have the same pci id and revision.


Thanks,

Yanteng

>
> -Serge(y)
>
>> +		break;
>> +	}
>> +
>> +	switch (pdev->revision) {
>> +	case 0x00:
>> +		plat->flags |=
>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
>> +		break;
>> +	case 0x01:
>> +		plat->flags |=
>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static struct stmmac_pci_info loongson_gnet_pci_info = {
>> +	.setup = loongson_gnet_data,
>> +	.config = loongson_gnet_config,
>> +};
>> +
>>   static int loongson_dwmac_probe(struct pci_dev *pdev,
>>   				const struct pci_device_id *id)
>>   {
>> @@ -318,9 +395,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>>   			 loongson_dwmac_resume);
>>   
>>   #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
>> +#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
>>   
>>   static const struct pci_device_id loongson_dwmac_id_table[] = {
>>   	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
>> +	{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
>>   	{}
>>   };
>>   MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>> index 8105ce47c6ad..d6939eb9a0d8 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>> @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
>>   		return 0;
>>   	}
>>   
>> +	if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000, priv->plat->flags)) {
>> +		if (cmd->base.speed == SPEED_1000 &&
>> +		    cmd->base.autoneg != AUTONEG_ENABLE)
>> +			return -EOPNOTSUPP;
>> +	}
>> +
>>   	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
>>   }
>>   
>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>> index f07f79d50b06..067030cdb60f 100644
>> --- a/include/linux/stmmac.h
>> +++ b/include/linux/stmmac.h
>> @@ -222,6 +222,8 @@ struct dwmac4_addrs {
>>   #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>>   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>>   #define STMMAC_FLAG_HAS_LGMAC			BIT(13)
>> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
>> +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
>>   
>>   struct plat_stmmacenet_data {
>>   	int bus_id;
>> -- 
>> 2.31.4
>>
Serge Semin Jan. 2, 2024, 1:22 a.m. UTC | #3
On Mon, Jan 01, 2024 at 03:27:07PM +0800, Yanteng Si wrote:
> 
> 在 2023/12/21 10:34, Serge Semin 写道:
> > On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
> > > Add Loongson GNET (GMAC with PHY) support. Current GNET does not support
> > > half duplex mode, and GNET on LS7A only supports ANE when speed is set to
> > > 1000M.
> > > 
> > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > > ---
> > >   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 79 +++++++++++++++++++
> > >   .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
> > >   include/linux/stmmac.h                        |  2 +
> > >   3 files changed, 87 insertions(+)
> > > 
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > index 2c08d5495214..9e4953c7e4e0 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > @@ -168,6 +168,83 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
> > >   	.config = loongson_gmac_config,
> > >   };
> > > +static void loongson_gnet_fix_speed(void *priv, unsigned int speed, unsigned int mode)
> > > +{
> > > +	struct net_device *ndev = dev_get_drvdata(priv);
> > > +	struct stmmac_priv *ptr = netdev_priv(ndev);
> > > +
> > > +	/* The controller and PHY don't work well together.
> > > +	 * We need to use the PS bit to check if the controller's status
> > > +	 * is correct and reset PHY if necessary.
> > > +	 */
> > > +	if (speed == SPEED_1000)
> > > +		if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
> > > +			phy_restart_aneg(ndev->phydev);
> > {} around the outer if please.
> OK.
> > 
> > > +}
> > > +
> > > +static int loongson_gnet_data(struct pci_dev *pdev,
> > > +			      struct plat_stmmacenet_data *plat)
> > > +{
> > > +	loongson_default_data(pdev, plat);
> > > +
> > > +	plat->multicast_filter_bins = 256;
> > > +
> > > +	plat->mdio_bus_data->phy_mask = 0xfffffffb;
> > ~BIT(2)?
> I still need to confirm, please allow me to get back to you later.
> > 
> > > +
> > > +	plat->phy_addr = 2;
> > > +	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
> > > +
> > > +	plat->bsp_priv = &pdev->dev;
> > > +	plat->fix_mac_speed = loongson_gnet_fix_speed;
> > > +
> > > +	plat->dma_cfg->pbl = 32;
> > > +	plat->dma_cfg->pblx8 = true;
> > > +
> > > +	plat->clk_ref_rate = 125000000;
> > > +	plat->clk_ptp_rate = 125000000;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int loongson_gnet_config(struct pci_dev *pdev,
> > > +				struct plat_stmmacenet_data *plat,
> > > +				struct stmmac_resources *res,
> > > +				struct device_node *np)
> > > +{
> > > +	int ret;
> > > +	u32 version = readl(res->addr + GMAC_VERSION);
> > > +
> > > +	switch (version & 0xff) {
> > > +	case DWLGMAC_CORE_1_00:
> > > +		ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
> > > +		break;
> > > +	default:
> > > +		ret = loongson_dwmac_config_legacy(pdev, plat, res, np);

> > Hm, do you have two versions of Loongson GNET? What does the second
> Yes.
> > one contain in the GMAC_VERSION register then? Can't you distinguish
> > them by the PCI IDs (device, subsystem, revision)?
> 
> I'm afraid that's not possible.
> 
> Because they have the same pci id and revision.

Please provide more details about what platform/devices support you
are adding and what PCI IDs and DW GMAC IP-core version they have.

> 
> 
> Thanks,
> 
> Yanteng
> 
> > 
> > -Serge(y)
> > 
> > > +		break;
> > > +	}
> > > +
> > > +	switch (pdev->revision) {
> > > +	case 0x00:
> > > +		plat->flags |=
> > > +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
> > > +			FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
> > > +		break;
> > > +	case 0x01:
> > > +		plat->flags |=
> > > +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
> > > +		break;
> > > +	default:
> > > +		break;
> > > +	}
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static struct stmmac_pci_info loongson_gnet_pci_info = {
> > > +	.setup = loongson_gnet_data,
> > > +	.config = loongson_gnet_config,
> > > +};
> > > +
> > >   static int loongson_dwmac_probe(struct pci_dev *pdev,
> > >   				const struct pci_device_id *id)
> > >   {
> > > @@ -318,9 +395,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
> > >   			 loongson_dwmac_resume);
> > >   #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
> > > +#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
> > >   static const struct pci_device_id loongson_dwmac_id_table[] = {
> > >   	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
> > > +	{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
> > >   	{}
> > >   };
> > >   MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > index 8105ce47c6ad..d6939eb9a0d8 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
> > >   		return 0;
> > >   	}
> > > +	if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000, priv->plat->flags)) {
> > > +		if (cmd->base.speed == SPEED_1000 &&
> > > +		    cmd->base.autoneg != AUTONEG_ENABLE)
> > > +			return -EOPNOTSUPP;
> > > +	}
> > > +
> > >   	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
> > >   }
> > > diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> > > index f07f79d50b06..067030cdb60f 100644
> > > --- a/include/linux/stmmac.h
> > > +++ b/include/linux/stmmac.h
> > > @@ -222,6 +222,8 @@ struct dwmac4_addrs {
> > >   #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
> > >   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
> > >   #define STMMAC_FLAG_HAS_LGMAC			BIT(13)

> > > +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)

Just noticed. I do not see this flag affecting any part of the code.
Drop it if no actual action is implied by it.

-Serge(y)

> > > +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
> > >   struct plat_stmmacenet_data {
> > >   	int bus_id;
> > > -- 
> > > 2.31.4
> > > 
>
Yanteng Si Jan. 24, 2024, 9:21 a.m. UTC | #4
在 2024/1/1 15:27, Yanteng Si 写道:
>
> 在 2023/12/21 10:34, Serge Semin 写道:
>> On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
>>> Add Loongson GNET (GMAC with PHY) support. Current GNET does not 
>>> support
>>> half duplex mode, and GNET on LS7A only supports ANE when speed is 
>>> set to
>>> 1000M.
>>>
>>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>>> ---
>>>   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 79 
>>> +++++++++++++++++++
>>>   .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
>>>   include/linux/stmmac.h                        |  2 +
>>>   3 files changed, 87 insertions(+)
>>>
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c 
>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> index 2c08d5495214..9e4953c7e4e0 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>> @@ -168,6 +168,83 @@ static struct stmmac_pci_info 
>>> loongson_gmac_pci_info = {
>>>       .config = loongson_gmac_config,
>>>   };
>>>   +static void loongson_gnet_fix_speed(void *priv, unsigned int 
>>> speed, unsigned int mode)
>>> +{
>>> +    struct net_device *ndev = dev_get_drvdata(priv);
>>> +    struct stmmac_priv *ptr = netdev_priv(ndev);
>>> +
>>> +    /* The controller and PHY don't work well together.
>>> +     * We need to use the PS bit to check if the controller's status
>>> +     * is correct and reset PHY if necessary.
>>> +     */
>>> +    if (speed == SPEED_1000)
>>> +        if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
>>> +            phy_restart_aneg(ndev->phydev);
>> {} around the outer if please.
> OK.
>>
>>> +}
>>> +
>>> +static int loongson_gnet_data(struct pci_dev *pdev,
>>> +                  struct plat_stmmacenet_data *plat)
>>> +{
>>> +    loongson_default_data(pdev, plat);
>>> +
>>> +    plat->multicast_filter_bins = 256;
>>> +
>>> +    plat->mdio_bus_data->phy_mask = 0xfffffffb;
>> ~BIT(2)?
> I still need to confirm, please allow me to get back to you later.

Yes, that's fine.


Thanks,

Yanteng


>>
>>> +
>>> +    plat->phy_addr = 2;
>>> +    plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
>>> +
>>> +    plat->bsp_priv = &pdev->dev;
>>> +    plat->fix_mac_speed = loongson_gnet_fix_speed;
>>> +
>>> +    plat->dma_cfg->pbl = 32;
>>> +    plat->dma_cfg->pblx8 = true;
>>> +
>>> +    plat->clk_ref_rate = 125000000;
>>> +    plat->clk_ptp_rate = 125000000;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int loongson_gnet_config(struct pci_dev *pdev,
>>> +                struct plat_stmmacenet_data *plat,
>>> +                struct stmmac_resources *res,
>>> +                struct device_node *np)
>>> +{
>>> +    int ret;
>>> +    u32 version = readl(res->addr + GMAC_VERSION);
>>> +
>>> +    switch (version & 0xff) {
>>> +    case DWLGMAC_CORE_1_00:
>>> +        ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
>>> +        break;
>>> +    default:
>>> +        ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
>> Hm, do you have two versions of Loongson GNET? What does the second
> Yes.
>> one contain in the GMAC_VERSION register then? Can't you distinguish
>> them by the PCI IDs (device, subsystem, revision)?
>
> I'm afraid that's not possible.
>
> Because they have the same pci id and revision.
>
>
> Thanks,
>
> Yanteng
>
>>
>> -Serge(y)
>>
>>> +        break;
>>> +    }
>>> +
>>> +    switch (pdev->revision) {
>>> +    case 0x00:
>>> +        plat->flags |=
>>> +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
>>> +            FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
>>> +        break;
>>> +    case 0x01:
>>> +        plat->flags |=
>>> +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
>>> +        break;
>>> +    default:
>>> +        break;
>>> +    }
>>> +
>>> +    return ret;
>>> +}
>>> +
>>> +static struct stmmac_pci_info loongson_gnet_pci_info = {
>>> +    .setup = loongson_gnet_data,
>>> +    .config = loongson_gnet_config,
>>> +};
>>> +
>>>   static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>                   const struct pci_device_id *id)
>>>   {
>>> @@ -318,9 +395,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, 
>>> loongson_dwmac_suspend,
>>>                loongson_dwmac_resume);
>>>     #define PCI_DEVICE_ID_LOONGSON_GMAC    0x7a03
>>> +#define PCI_DEVICE_ID_LOONGSON_GNET    0x7a13
>>>     static const struct pci_device_id loongson_dwmac_id_table[] = {
>>>       { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
>>> +    { PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
>>>       {}
>>>   };
>>>   MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c 
>>> b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>> index 8105ce47c6ad..d6939eb9a0d8 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>> @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct 
>>> net_device *dev,
>>>           return 0;
>>>       }
>>>   +    if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000, 
>>> priv->plat->flags)) {
>>> +        if (cmd->base.speed == SPEED_1000 &&
>>> +            cmd->base.autoneg != AUTONEG_ENABLE)
>>> +            return -EOPNOTSUPP;
>>> +    }
>>> +
>>>       return phylink_ethtool_ksettings_set(priv->phylink, cmd);
>>>   }
>>>   diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>>> index f07f79d50b06..067030cdb60f 100644
>>> --- a/include/linux/stmmac.h
>>> +++ b/include/linux/stmmac.h
>>> @@ -222,6 +222,8 @@ struct dwmac4_addrs {
>>>   #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING    BIT(11)
>>>   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY    BIT(12)
>>>   #define STMMAC_FLAG_HAS_LGMAC            BIT(13)
>>> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX    BIT(14)
>>> +#define STMMAC_FLAG_DISABLE_FORCE_1000    BIT(15)
>>>     struct plat_stmmacenet_data {
>>>       int bus_id;
>>> -- 
>>> 2.31.4
>>>
Serge Semin Jan. 24, 2024, 1:51 p.m. UTC | #5
On Wed, Jan 24, 2024 at 05:21:03PM +0800, Yanteng Si wrote:
> 
> 在 2024/1/1 15:27, Yanteng Si 写道:
> > 
> > 在 2023/12/21 10:34, Serge Semin 写道:
> > > On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
> > > > Add Loongson GNET (GMAC with PHY) support. Current GNET does not
> > > > support
> > > > half duplex mode, and GNET on LS7A only supports ANE when speed
> > > > is set to
> > > > 1000M.
> > > > 
> > > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > > > ---
> > > >   .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 79
> > > > +++++++++++++++++++
> > > >   .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
> > > >   include/linux/stmmac.h                        |  2 +
> > > >   3 files changed, 87 insertions(+)
> > > > 
> > > > diff --git
> > > > a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > index 2c08d5495214..9e4953c7e4e0 100644
> > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > @@ -168,6 +168,83 @@ static struct stmmac_pci_info
> > > > loongson_gmac_pci_info = {
> > > >       .config = loongson_gmac_config,
> > > >   };
> > > >   +static void loongson_gnet_fix_speed(void *priv, unsigned int
> > > > speed, unsigned int mode)
> > > > +{
> > > > +    struct net_device *ndev = dev_get_drvdata(priv);
> > > > +    struct stmmac_priv *ptr = netdev_priv(ndev);
> > > > +
> > > > +    /* The controller and PHY don't work well together.
> > > > +     * We need to use the PS bit to check if the controller's status
> > > > +     * is correct and reset PHY if necessary.
> > > > +     */
> > > > +    if (speed == SPEED_1000)
> > > > +        if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
> > > > +            phy_restart_aneg(ndev->phydev);
> > > {} around the outer if please.
> > OK.
> > > 
> > > > +}
> > > > +
> > > > +static int loongson_gnet_data(struct pci_dev *pdev,
> > > > +                  struct plat_stmmacenet_data *plat)
> > > > +{
> > > > +    loongson_default_data(pdev, plat);
> > > > +
> > > > +    plat->multicast_filter_bins = 256;
> > > > +

> > > > +    plat->mdio_bus_data->phy_mask = 0xfffffffb;
> > > ~BIT(2)?
> > I still need to confirm, please allow me to get back to you later.
> 
> Yes, that's fine.

Glad this part has been settled.)

-Serge(y)

> 
> 
> Thanks,
> 
> Yanteng
> 
> 
> > > 
> > > > +
> > > > +    plat->phy_addr = 2;
> > > > +    plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
> > > > +
> > > > +    plat->bsp_priv = &pdev->dev;
> > > > +    plat->fix_mac_speed = loongson_gnet_fix_speed;
> > > > +
> > > > +    plat->dma_cfg->pbl = 32;
> > > > +    plat->dma_cfg->pblx8 = true;
> > > > +
> > > > +    plat->clk_ref_rate = 125000000;
> > > > +    plat->clk_ptp_rate = 125000000;
> > > > +
> > > > +    return 0;
> > > > +}
> > > > +
> > > > +static int loongson_gnet_config(struct pci_dev *pdev,
> > > > +                struct plat_stmmacenet_data *plat,
> > > > +                struct stmmac_resources *res,
> > > > +                struct device_node *np)
> > > > +{
> > > > +    int ret;
> > > > +    u32 version = readl(res->addr + GMAC_VERSION);
> > > > +
> > > > +    switch (version & 0xff) {
> > > > +    case DWLGMAC_CORE_1_00:
> > > > +        ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
> > > > +        break;
> > > > +    default:
> > > > +        ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> > > Hm, do you have two versions of Loongson GNET? What does the second
> > Yes.
> > > one contain in the GMAC_VERSION register then? Can't you distinguish
> > > them by the PCI IDs (device, subsystem, revision)?
> > 
> > I'm afraid that's not possible.
> > 
> > Because they have the same pci id and revision.
> > 
> > 
> > Thanks,
> > 
> > Yanteng
> > 
> > > 
> > > -Serge(y)
> > > 
> > > > +        break;
> > > > +    }
> > > > +
> > > > +    switch (pdev->revision) {
> > > > +    case 0x00:
> > > > +        plat->flags |=
> > > > +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
> > > > +            FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
> > > > +        break;
> > > > +    case 0x01:
> > > > +        plat->flags |=
> > > > +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
> > > > +        break;
> > > > +    default:
> > > > +        break;
> > > > +    }
> > > > +
> > > > +    return ret;
> > > > +}
> > > > +
> > > > +static struct stmmac_pci_info loongson_gnet_pci_info = {
> > > > +    .setup = loongson_gnet_data,
> > > > +    .config = loongson_gnet_config,
> > > > +};
> > > > +
> > > >   static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > >                   const struct pci_device_id *id)
> > > >   {
> > > > @@ -318,9 +395,11 @@ static
> > > > SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
> > > >                loongson_dwmac_resume);
> > > >     #define PCI_DEVICE_ID_LOONGSON_GMAC    0x7a03
> > > > +#define PCI_DEVICE_ID_LOONGSON_GNET    0x7a13
> > > >     static const struct pci_device_id loongson_dwmac_id_table[] = {
> > > >       { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
> > > > +    { PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
> > > >       {}
> > > >   };
> > > >   MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
> > > > diff --git
> > > > a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > index 8105ce47c6ad..d6939eb9a0d8 100644
> > > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct
> > > > net_device *dev,
> > > >           return 0;
> > > >       }
> > > >   +    if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000,
> > > > priv->plat->flags)) {
> > > > +        if (cmd->base.speed == SPEED_1000 &&
> > > > +            cmd->base.autoneg != AUTONEG_ENABLE)
> > > > +            return -EOPNOTSUPP;
> > > > +    }
> > > > +
> > > >       return phylink_ethtool_ksettings_set(priv->phylink, cmd);
> > > >   }
> > > >   diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> > > > index f07f79d50b06..067030cdb60f 100644
> > > > --- a/include/linux/stmmac.h
> > > > +++ b/include/linux/stmmac.h
> > > > @@ -222,6 +222,8 @@ struct dwmac4_addrs {
> > > >   #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING    BIT(11)
> > > >   #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY    BIT(12)
> > > >   #define STMMAC_FLAG_HAS_LGMAC            BIT(13)
> > > > +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX    BIT(14)
> > > > +#define STMMAC_FLAG_DISABLE_FORCE_1000    BIT(15)
> > > >     struct plat_stmmacenet_data {
> > > >       int bus_id;
> > > > -- 
> > > > 2.31.4
> > > > 
>
Yanteng Si Jan. 25, 2024, 6:57 a.m. UTC | #6
在 2024/1/2 09:22, Serge Semin 写道:
> On Mon, Jan 01, 2024 at 03:27:07PM +0800, Yanteng Si wrote:
>> 在 2023/12/21 10:34, Serge Semin 写道:
>>> On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
>>>> Add Loongson GNET (GMAC with PHY) support. Current GNET does not support
>>>> half duplex mode, and GNET on LS7A only supports ANE when speed is set to
>>>> 1000M.
>>>>
>>>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>>>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>>>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>>>> ---
>>>>    .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 79 +++++++++++++++++++
>>>>    .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
>>>>    include/linux/stmmac.h                        |  2 +
>>>>    3 files changed, 87 insertions(+)
>>>>
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> index 2c08d5495214..9e4953c7e4e0 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> @@ -168,6 +168,83 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
>>>>    	.config = loongson_gmac_config,
>>>>    };
>>>> +static void loongson_gnet_fix_speed(void *priv, unsigned int speed, unsigned int mode)
>>>> +{
>>>> +	struct net_device *ndev = dev_get_drvdata(priv);
>>>> +	struct stmmac_priv *ptr = netdev_priv(ndev);
>>>> +
>>>> +	/* The controller and PHY don't work well together.
>>>> +	 * We need to use the PS bit to check if the controller's status
>>>> +	 * is correct and reset PHY if necessary.
>>>> +	 */
>>>> +	if (speed == SPEED_1000)
>>>> +		if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
>>>> +			phy_restart_aneg(ndev->phydev);
>>> {} around the outer if please.
>> OK.
>>>> +}
>>>> +
>>>> +static int loongson_gnet_data(struct pci_dev *pdev,
>>>> +			      struct plat_stmmacenet_data *plat)
>>>> +{
>>>> +	loongson_default_data(pdev, plat);
>>>> +
>>>> +	plat->multicast_filter_bins = 256;
>>>> +
>>>> +	plat->mdio_bus_data->phy_mask = 0xfffffffb;
>>> ~BIT(2)?
>> I still need to confirm, please allow me to get back to you later.
>>>> +
>>>> +	plat->phy_addr = 2;
>>>> +	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
>>>> +
>>>> +	plat->bsp_priv = &pdev->dev;
>>>> +	plat->fix_mac_speed = loongson_gnet_fix_speed;
>>>> +
>>>> +	plat->dma_cfg->pbl = 32;
>>>> +	plat->dma_cfg->pblx8 = true;
>>>> +
>>>> +	plat->clk_ref_rate = 125000000;
>>>> +	plat->clk_ptp_rate = 125000000;
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>> +static int loongson_gnet_config(struct pci_dev *pdev,
>>>> +				struct plat_stmmacenet_data *plat,
>>>> +				struct stmmac_resources *res,
>>>> +				struct device_node *np)
>>>> +{
>>>> +	int ret;
>>>> +	u32 version = readl(res->addr + GMAC_VERSION);
>>>> +
>>>> +	switch (version & 0xff) {
>>>> +	case DWLGMAC_CORE_1_00:
>>>> +		ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
>>>> +		break;
>>>> +	default:
>>>> +		ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
>>> Hm, do you have two versions of Loongson GNET? What does the second
>> Yes.
>>> one contain in the GMAC_VERSION register then? Can't you distinguish
>>> them by the PCI IDs (device, subsystem, revision)?
>> I'm afraid that's not possible.
>>
>> Because they have the same pci id and revision.
> Please provide more details about what platform/devices support you
> are adding and what PCI IDs and DW GMAC IP-core version they have.
Okay, I will do my best to make them appear in the next version of the 
commit message.
>
>>
>> Thanks,
>>
>> Yanteng
>>
>>> -Serge(y)
>>>
>>>> +		break;
>>>> +	}
>>>> +
>>>> +	switch (pdev->revision) {
>>>> +	case 0x00:
>>>> +		plat->flags |=
>>>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
>>>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
>>>> +		break;
>>>> +	case 0x01:
>>>> +		plat->flags |=
>>>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
>>>> +		break;
>>>> +	default:
>>>> +		break;
>>>> +	}
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>>> +static struct stmmac_pci_info loongson_gnet_pci_info = {
>>>> +	.setup = loongson_gnet_data,
>>>> +	.config = loongson_gnet_config,
>>>> +};
>>>> +
>>>>    static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>    				const struct pci_device_id *id)
>>>>    {
>>>> @@ -318,9 +395,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>>>>    			 loongson_dwmac_resume);
>>>>    #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
>>>> +#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
>>>>    static const struct pci_device_id loongson_dwmac_id_table[] = {
>>>>    	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
>>>> +	{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
>>>>    	{}
>>>>    };
>>>>    MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>> index 8105ce47c6ad..d6939eb9a0d8 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>> @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
>>>>    		return 0;
>>>>    	}
>>>> +	if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000, priv->plat->flags)) {
>>>> +		if (cmd->base.speed == SPEED_1000 &&
>>>> +		    cmd->base.autoneg != AUTONEG_ENABLE)
>>>> +			return -EOPNOTSUPP;
>>>> +	}
>>>> +
>>>>    	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
>>>>    }
>>>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>>>> index f07f79d50b06..067030cdb60f 100644
>>>> --- a/include/linux/stmmac.h
>>>> +++ b/include/linux/stmmac.h
>>>> @@ -222,6 +222,8 @@ struct dwmac4_addrs {
>>>>    #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>>>>    #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>>>>    #define STMMAC_FLAG_HAS_LGMAC			BIT(13)
>>>> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
> Just noticed. I do not see this flag affecting any part of the code.
> Drop it if no actual action is implied by it.

Sorry, I lost it, it will be added in the next version, otherwise there 
will be an

error on the 7a13 0x37 device.


@@ -1201,7 +1201,8 @@ static int stmmac_init_phy(struct net_device *dev)
  static void stmmac_set_half_duplex(struct stmmac_priv *priv)
  {
         /* Half-Duplex can only work with single tx queue */
-       if (priv->plat->tx_queues_to_use > 1)
+       if (priv->plat->tx_queues_to_use > 1 ||
+               (STMMAC_FLAG_DISABLE_HALF_DUPLEX & priv->plat->flags))
                 priv->phylink_config.mac_capabilities &=
                         ~(MAC_10HD | MAC_100HD | MAC_1000HD);

         else




Thanks,

Yanteng

>
> -Serge(y)
>
>>>> +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
>>>>    struct plat_stmmacenet_data {
>>>>    	int bus_id;
>>>> -- 
>>>> 2.31.4
>>>>
Yanteng Si Jan. 25, 2024, 8:36 a.m. UTC | #7
在 2024/1/24 21:51, Serge Semin 写道:
> On Wed, Jan 24, 2024 at 05:21:03PM +0800, Yanteng Si wrote:
>> 在 2024/1/1 15:27, Yanteng Si 写道:
>>> 在 2023/12/21 10:34, Serge Semin 写道:
>>>> On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
>>>>> Add Loongson GNET (GMAC with PHY) support. Current GNET does not
>>>>> support
>>>>> half duplex mode, and GNET on LS7A only supports ANE when speed
>>>>> is set to
>>>>> 1000M.
>>>>>
>>>>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>>>>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>>>>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>>>>> ---
>>>>>    .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 79
>>>>> +++++++++++++++++++
>>>>>    .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
>>>>>    include/linux/stmmac.h                        |  2 +
>>>>>    3 files changed, 87 insertions(+)
>>>>>
>>>>> diff --git
>>>>> a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> index 2c08d5495214..9e4953c7e4e0 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>>> @@ -168,6 +168,83 @@ static struct stmmac_pci_info
>>>>> loongson_gmac_pci_info = {
>>>>>        .config = loongson_gmac_config,
>>>>>    };
>>>>>    +static void loongson_gnet_fix_speed(void *priv, unsigned int
>>>>> speed, unsigned int mode)
>>>>> +{
>>>>> +    struct net_device *ndev = dev_get_drvdata(priv);
>>>>> +    struct stmmac_priv *ptr = netdev_priv(ndev);
>>>>> +
>>>>> +    /* The controller and PHY don't work well together.
>>>>> +     * We need to use the PS bit to check if the controller's status
>>>>> +     * is correct and reset PHY if necessary.
>>>>> +     */
>>>>> +    if (speed == SPEED_1000)
>>>>> +        if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
>>>>> +            phy_restart_aneg(ndev->phydev);
>>>> {} around the outer if please.
>>> OK.
>>>>> +}
>>>>> +
>>>>> +static int loongson_gnet_data(struct pci_dev *pdev,
>>>>> +                  struct plat_stmmacenet_data *plat)
>>>>> +{
>>>>> +    loongson_default_data(pdev, plat);
>>>>> +
>>>>> +    plat->multicast_filter_bins = 256;
>>>>> +
>>>>> +    plat->mdio_bus_data->phy_mask = 0xfffffffb;
>>>> ~BIT(2)?
>>> I still need to confirm, please allow me to get back to you later.
>> Yes, that's fine.

Oops! A warning will be output:

drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c: In function 
'loongson_gnet_data':
drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:463:41: warning: 
conversion from

'long unsigned int' to 'unsigned int' changes value from 
'18446744073709551611' to '4294967291' [-Woverflow]
   463 |         plat->mdio_bus_data->phy_mask = ~BIT(2);
       |                                         ^

Unfortunately, we don't have an unsigned int macro for BIT(nr).


Thanks,

Yanteng

>
> -Serge(y)
>
>>
>> Thanks,
>>
>> Yanteng
>>
>>
>>>>> +
>>>>> +    plat->phy_addr = 2;
>>>>> +    plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
>>>>> +
>>>>> +    plat->bsp_priv = &pdev->dev;
>>>>> +    plat->fix_mac_speed = loongson_gnet_fix_speed;
>>>>> +
>>>>> +    plat->dma_cfg->pbl = 32;
>>>>> +    plat->dma_cfg->pblx8 = true;
>>>>> +
>>>>> +    plat->clk_ref_rate = 125000000;
>>>>> +    plat->clk_ptp_rate = 125000000;
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +
>>>>> +static int loongson_gnet_config(struct pci_dev *pdev,
>>>>> +                struct plat_stmmacenet_data *plat,
>>>>> +                struct stmmac_resources *res,
>>>>> +                struct device_node *np)
>>>>> +{
>>>>> +    int ret;
>>>>> +    u32 version = readl(res->addr + GMAC_VERSION);
>>>>> +
>>>>> +    switch (version & 0xff) {
>>>>> +    case DWLGMAC_CORE_1_00:
>>>>> +        ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
>>>>> +        break;
>>>>> +    default:
>>>>> +        ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
>>>> Hm, do you have two versions of Loongson GNET? What does the second
>>> Yes.
>>>> one contain in the GMAC_VERSION register then? Can't you distinguish
>>>> them by the PCI IDs (device, subsystem, revision)?
>>> I'm afraid that's not possible.
>>>
>>> Because they have the same pci id and revision.
>>>
>>>
>>> Thanks,
>>>
>>> Yanteng
>>>
>>>> -Serge(y)
>>>>
>>>>> +        break;
>>>>> +    }
>>>>> +
>>>>> +    switch (pdev->revision) {
>>>>> +    case 0x00:
>>>>> +        plat->flags |=
>>>>> +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
>>>>> +            FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
>>>>> +        break;
>>>>> +    case 0x01:
>>>>> +        plat->flags |=
>>>>> +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
>>>>> +        break;
>>>>> +    default:
>>>>> +        break;
>>>>> +    }
>>>>> +
>>>>> +    return ret;
>>>>> +}
>>>>> +
>>>>> +static struct stmmac_pci_info loongson_gnet_pci_info = {
>>>>> +    .setup = loongson_gnet_data,
>>>>> +    .config = loongson_gnet_config,
>>>>> +};
>>>>> +
>>>>>    static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>>                    const struct pci_device_id *id)
>>>>>    {
>>>>> @@ -318,9 +395,11 @@ static
>>>>> SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>>>>>                 loongson_dwmac_resume);
>>>>>      #define PCI_DEVICE_ID_LOONGSON_GMAC    0x7a03
>>>>> +#define PCI_DEVICE_ID_LOONGSON_GNET    0x7a13
>>>>>      static const struct pci_device_id loongson_dwmac_id_table[] = {
>>>>>        { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
>>>>> +    { PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
>>>>>        {}
>>>>>    };
>>>>>    MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
>>>>> diff --git
>>>>> a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>>> b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>>> index 8105ce47c6ad..d6939eb9a0d8 100644
>>>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>>> @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct
>>>>> net_device *dev,
>>>>>            return 0;
>>>>>        }
>>>>>    +    if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000,
>>>>> priv->plat->flags)) {
>>>>> +        if (cmd->base.speed == SPEED_1000 &&
>>>>> +            cmd->base.autoneg != AUTONEG_ENABLE)
>>>>> +            return -EOPNOTSUPP;
>>>>> +    }
>>>>> +
>>>>>        return phylink_ethtool_ksettings_set(priv->phylink, cmd);
>>>>>    }
>>>>>    diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>>>>> index f07f79d50b06..067030cdb60f 100644
>>>>> --- a/include/linux/stmmac.h
>>>>> +++ b/include/linux/stmmac.h
>>>>> @@ -222,6 +222,8 @@ struct dwmac4_addrs {
>>>>>    #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING    BIT(11)
>>>>>    #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY    BIT(12)
>>>>>    #define STMMAC_FLAG_HAS_LGMAC            BIT(13)
>>>>> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX    BIT(14)
>>>>> +#define STMMAC_FLAG_DISABLE_FORCE_1000    BIT(15)
>>>>>      struct plat_stmmacenet_data {
>>>>>        int bus_id;
>>>>> -- 
>>>>> 2.31.4
>>>>>
Serge Semin Jan. 25, 2024, 6:38 p.m. UTC | #8
On Thu, Jan 25, 2024 at 04:36:39PM +0800, Yanteng Si wrote:
> 
> 在 2024/1/24 21:51, Serge Semin 写道:
> > On Wed, Jan 24, 2024 at 05:21:03PM +0800, Yanteng Si wrote:
> > > 在 2024/1/1 15:27, Yanteng Si 写道:
> > > > 在 2023/12/21 10:34, Serge Semin 写道:
> > > > > On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
> > > > > > Add Loongson GNET (GMAC with PHY) support. Current GNET does not
> > > > > > support
> > > > > > half duplex mode, and GNET on LS7A only supports ANE when speed
> > > > > > is set to
> > > > > > 1000M.
> > > > > > 
> > > > > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > > > > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > > > > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > > > > > ---
> > > > > >    .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 79
> > > > > > +++++++++++++++++++
> > > > > >    .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
> > > > > >    include/linux/stmmac.h                        |  2 +
> > > > > >    3 files changed, 87 insertions(+)
> > > > > > 
> > > > > > diff --git
> > > > > > a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > index 2c08d5495214..9e4953c7e4e0 100644
> > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > > > > > @@ -168,6 +168,83 @@ static struct stmmac_pci_info
> > > > > > loongson_gmac_pci_info = {
> > > > > >        .config = loongson_gmac_config,
> > > > > >    };
> > > > > >    +static void loongson_gnet_fix_speed(void *priv, unsigned int
> > > > > > speed, unsigned int mode)
> > > > > > +{
> > > > > > +    struct net_device *ndev = dev_get_drvdata(priv);
> > > > > > +    struct stmmac_priv *ptr = netdev_priv(ndev);
> > > > > > +
> > > > > > +    /* The controller and PHY don't work well together.
> > > > > > +     * We need to use the PS bit to check if the controller's status
> > > > > > +     * is correct and reset PHY if necessary.
> > > > > > +     */
> > > > > > +    if (speed == SPEED_1000)
> > > > > > +        if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
> > > > > > +            phy_restart_aneg(ndev->phydev);
> > > > > {} around the outer if please.
> > > > OK.
> > > > > > +}
> > > > > > +
> > > > > > +static int loongson_gnet_data(struct pci_dev *pdev,
> > > > > > +                  struct plat_stmmacenet_data *plat)
> > > > > > +{
> > > > > > +    loongson_default_data(pdev, plat);
> > > > > > +
> > > > > > +    plat->multicast_filter_bins = 256;
> > > > > > +
> > > > > > +    plat->mdio_bus_data->phy_mask = 0xfffffffb;
> > > > > ~BIT(2)?
> > > > I still need to confirm, please allow me to get back to you later.
> > > Yes, that's fine.
> 

> Oops! A warning will be output:
> 
> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c: In function
> 'loongson_gnet_data':
> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:463:41: warning:
> conversion from
> 
> 'long unsigned int' to 'unsigned int' changes value from
> '18446744073709551611' to '4294967291' [-Woverflow]
>   463 |         plat->mdio_bus_data->phy_mask = ~BIT(2);
>       |                                         ^
> 
> Unfortunately, we don't have an unsigned int macro for BIT(nr).

Then the alternative ~(1 << 2) would be still more readable then the
open-coded literal like 0xfffffffb. What would be even better than
that:

#define LOONGSON_GNET_PHY_ADDR		0x2
...
	plat->mdio_bus_data->phy_mask = ~(1 << LOONGSON_GNET_PHY_ADDR);
...

-Serge(y)

> 
> 
> Thanks,
> 
> Yanteng
> 
> > 
> > -Serge(y)
> > 
> > > 
> > > Thanks,
> > > 
> > > Yanteng
> > > 
> > > 
> > > > > > +
> > > > > > +    plat->phy_addr = 2;
> > > > > > +    plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
> > > > > > +
> > > > > > +    plat->bsp_priv = &pdev->dev;
> > > > > > +    plat->fix_mac_speed = loongson_gnet_fix_speed;
> > > > > > +
> > > > > > +    plat->dma_cfg->pbl = 32;
> > > > > > +    plat->dma_cfg->pblx8 = true;
> > > > > > +
> > > > > > +    plat->clk_ref_rate = 125000000;
> > > > > > +    plat->clk_ptp_rate = 125000000;
> > > > > > +
> > > > > > +    return 0;
> > > > > > +}
> > > > > > +
> > > > > > +static int loongson_gnet_config(struct pci_dev *pdev,
> > > > > > +                struct plat_stmmacenet_data *plat,
> > > > > > +                struct stmmac_resources *res,
> > > > > > +                struct device_node *np)
> > > > > > +{
> > > > > > +    int ret;
> > > > > > +    u32 version = readl(res->addr + GMAC_VERSION);
> > > > > > +
> > > > > > +    switch (version & 0xff) {
> > > > > > +    case DWLGMAC_CORE_1_00:
> > > > > > +        ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
> > > > > > +        break;
> > > > > > +    default:
> > > > > > +        ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
> > > > > Hm, do you have two versions of Loongson GNET? What does the second
> > > > Yes.
> > > > > one contain in the GMAC_VERSION register then? Can't you distinguish
> > > > > them by the PCI IDs (device, subsystem, revision)?
> > > > I'm afraid that's not possible.
> > > > 
> > > > Because they have the same pci id and revision.
> > > > 
> > > > 
> > > > Thanks,
> > > > 
> > > > Yanteng
> > > > 
> > > > > -Serge(y)
> > > > > 
> > > > > > +        break;
> > > > > > +    }
> > > > > > +
> > > > > > +    switch (pdev->revision) {
> > > > > > +    case 0x00:
> > > > > > +        plat->flags |=
> > > > > > +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
> > > > > > +            FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
> > > > > > +        break;
> > > > > > +    case 0x01:
> > > > > > +        plat->flags |=
> > > > > > +            FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
> > > > > > +        break;
> > > > > > +    default:
> > > > > > +        break;
> > > > > > +    }
> > > > > > +
> > > > > > +    return ret;
> > > > > > +}
> > > > > > +
> > > > > > +static struct stmmac_pci_info loongson_gnet_pci_info = {
> > > > > > +    .setup = loongson_gnet_data,
> > > > > > +    .config = loongson_gnet_config,
> > > > > > +};
> > > > > > +
> > > > > >    static int loongson_dwmac_probe(struct pci_dev *pdev,
> > > > > >                    const struct pci_device_id *id)
> > > > > >    {
> > > > > > @@ -318,9 +395,11 @@ static
> > > > > > SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
> > > > > >                 loongson_dwmac_resume);
> > > > > >      #define PCI_DEVICE_ID_LOONGSON_GMAC    0x7a03
> > > > > > +#define PCI_DEVICE_ID_LOONGSON_GNET    0x7a13
> > > > > >      static const struct pci_device_id loongson_dwmac_id_table[] = {
> > > > > >        { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
> > > > > > +    { PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
> > > > > >        {}
> > > > > >    };
> > > > > >    MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
> > > > > > diff --git
> > > > > > a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > > > b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > > > index 8105ce47c6ad..d6939eb9a0d8 100644
> > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
> > > > > > @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct
> > > > > > net_device *dev,
> > > > > >            return 0;
> > > > > >        }
> > > > > >    +    if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000,
> > > > > > priv->plat->flags)) {
> > > > > > +        if (cmd->base.speed == SPEED_1000 &&
> > > > > > +            cmd->base.autoneg != AUTONEG_ENABLE)
> > > > > > +            return -EOPNOTSUPP;
> > > > > > +    }
> > > > > > +
> > > > > >        return phylink_ethtool_ksettings_set(priv->phylink, cmd);
> > > > > >    }
> > > > > >    diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> > > > > > index f07f79d50b06..067030cdb60f 100644
> > > > > > --- a/include/linux/stmmac.h
> > > > > > +++ b/include/linux/stmmac.h
> > > > > > @@ -222,6 +222,8 @@ struct dwmac4_addrs {
> > > > > >    #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING    BIT(11)
> > > > > >    #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY    BIT(12)
> > > > > >    #define STMMAC_FLAG_HAS_LGMAC            BIT(13)
> > > > > > +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX    BIT(14)
> > > > > > +#define STMMAC_FLAG_DISABLE_FORCE_1000    BIT(15)
> > > > > >      struct plat_stmmacenet_data {
> > > > > >        int bus_id;
> > > > > > -- 
> > > > > > 2.31.4
> > > > > > 
>
Russell King (Oracle) Jan. 25, 2024, 6:41 p.m. UTC | #9
On Thu, Jan 25, 2024 at 09:38:30PM +0300, Serge Semin wrote:
> On Thu, Jan 25, 2024 at 04:36:39PM +0800, Yanteng Si wrote:
> > drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c: In function
> > 'loongson_gnet_data':
> > drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:463:41: warning:
> > conversion from
> > 
> > 'long unsigned int' to 'unsigned int' changes value from
> > '18446744073709551611' to '4294967291' [-Woverflow]
> >   463 |         plat->mdio_bus_data->phy_mask = ~BIT(2);
> >       |                                         ^
> > 
> > Unfortunately, we don't have an unsigned int macro for BIT(nr).
> 
> Then the alternative ~(1 << 2) would be still more readable then the
> open-coded literal like 0xfffffffb. What would be even better than
> that:
> 
> #define LOONGSON_GNET_PHY_ADDR		0x2
> ...
> 	plat->mdio_bus_data->phy_mask = ~(1 << LOONGSON_GNET_PHY_ADDR);

	plat->mdio_bus_data->phy_mask = ~(u32)BIT(2);

would also work.
Serge Semin Jan. 25, 2024, 8:12 p.m. UTC | #10
On Thu, Jan 25, 2024 at 06:41:08PM +0000, Russell King (Oracle) wrote:
> On Thu, Jan 25, 2024 at 09:38:30PM +0300, Serge Semin wrote:
> > On Thu, Jan 25, 2024 at 04:36:39PM +0800, Yanteng Si wrote:
> > > drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c: In function
> > > 'loongson_gnet_data':
> > > drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:463:41: warning:
> > > conversion from
> > > 
> > > 'long unsigned int' to 'unsigned int' changes value from
> > > '18446744073709551611' to '4294967291' [-Woverflow]
> > >   463 |         plat->mdio_bus_data->phy_mask = ~BIT(2);
> > >       |                                         ^
> > > 
> > > Unfortunately, we don't have an unsigned int macro for BIT(nr).
> > 
> > Then the alternative ~(1 << 2) would be still more readable then the
> > open-coded literal like 0xfffffffb. What would be even better than
> > that:
> > 
> > #define LOONGSON_GNET_PHY_ADDR		0x2
> > ...
> > 	plat->mdio_bus_data->phy_mask = ~(1 << LOONGSON_GNET_PHY_ADDR);
> 
> 	plat->mdio_bus_data->phy_mask = ~(u32)BIT(2);
> 
> would also work.

Right, explicit type casting will work too. Something
deep inside always inclines me to avoid explicit casts, although in
this case your option may look more readable than the open-coded
bitwise shift.

-Serge(y)

> 
> 
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Yanteng Si Jan. 29, 2024, 11:18 a.m. UTC | #11
在 2024/1/26 04:12, Serge Semin 写道:
> On Thu, Jan 25, 2024 at 06:41:08PM +0000, Russell King (Oracle) wrote:
>> On Thu, Jan 25, 2024 at 09:38:30PM +0300, Serge Semin wrote:
>>> On Thu, Jan 25, 2024 at 04:36:39PM +0800, Yanteng Si wrote:
>>>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c: In function
>>>> 'loongson_gnet_data':
>>>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c:463:41: warning:
>>>> conversion from
>>>>
>>>> 'long unsigned int' to 'unsigned int' changes value from
>>>> '18446744073709551611' to '4294967291' [-Woverflow]
>>>>    463 |         plat->mdio_bus_data->phy_mask = ~BIT(2);
>>>>        |                                         ^
>>>>
>>>> Unfortunately, we don't have an unsigned int macro for BIT(nr).
>>> Then the alternative ~(1 << 2) would be still more readable then the
>>> open-coded literal like 0xfffffffb. What would be even better than
>>> that:
>>>
>>> #define LOONGSON_GNET_PHY_ADDR		0x2
>>> ...
>>> 	plat->mdio_bus_data->phy_mask = ~(1 << LOONGSON_GNET_PHY_ADDR);
>> 	plat->mdio_bus_data->phy_mask = ~(u32)BIT(2);
>>
>> would also work.
> Right, explicit type casting will work too. Something
> deep inside always inclines me to avoid explicit casts, although in
> this case your option may look more readable than the open-coded
> bitwise shift.

OK!


Thanks,

Yanteng

>
> -Serge(y)
>
>>
>> -- 
>> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
>> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Yanteng Si Jan. 29, 2024, 11:45 a.m. UTC | #12
在 2024/1/2 09:22, Serge Semin 写道:
> On Mon, Jan 01, 2024 at 03:27:07PM +0800, Yanteng Si wrote:
>> 在 2023/12/21 10:34, Serge Semin 写道:
>>> On Tue, Dec 19, 2023 at 10:26:47PM +0800, Yanteng Si wrote:
>>>> Add Loongson GNET (GMAC with PHY) support. Current GNET does not support
>>>> half duplex mode, and GNET on LS7A only supports ANE when speed is set to
>>>> 1000M.
>>>>
>>>> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>>>> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
>>>> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
>>>> ---
>>>>    .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 79 +++++++++++++++++++
>>>>    .../ethernet/stmicro/stmmac/stmmac_ethtool.c  |  6 ++
>>>>    include/linux/stmmac.h                        |  2 +
>>>>    3 files changed, 87 insertions(+)
>>>>
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> index 2c08d5495214..9e4953c7e4e0 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
>>>> @@ -168,6 +168,83 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
>>>>    	.config = loongson_gmac_config,
>>>>    };
>>>> +static void loongson_gnet_fix_speed(void *priv, unsigned int speed, unsigned int mode)
>>>> +{
>>>> +	struct net_device *ndev = dev_get_drvdata(priv);
>>>> +	struct stmmac_priv *ptr = netdev_priv(ndev);
>>>> +
>>>> +	/* The controller and PHY don't work well together.
>>>> +	 * We need to use the PS bit to check if the controller's status
>>>> +	 * is correct and reset PHY if necessary.
>>>> +	 */
>>>> +	if (speed == SPEED_1000)
>>>> +		if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
>>>> +			phy_restart_aneg(ndev->phydev);
>>> {} around the outer if please.
>> OK.
>>>> +}
>>>> +
>>>> +static int loongson_gnet_data(struct pci_dev *pdev,
>>>> +			      struct plat_stmmacenet_data *plat)
>>>> +{
>>>> +	loongson_default_data(pdev, plat);
>>>> +
>>>> +	plat->multicast_filter_bins = 256;
>>>> +
>>>> +	plat->mdio_bus_data->phy_mask = 0xfffffffb;
>>> ~BIT(2)?
>> I still need to confirm, please allow me to get back to you later.
>>>> +
>>>> +	plat->phy_addr = 2;
>>>> +	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
>>>> +
>>>> +	plat->bsp_priv = &pdev->dev;
>>>> +	plat->fix_mac_speed = loongson_gnet_fix_speed;
>>>> +
>>>> +	plat->dma_cfg->pbl = 32;
>>>> +	plat->dma_cfg->pblx8 = true;
>>>> +
>>>> +	plat->clk_ref_rate = 125000000;
>>>> +	plat->clk_ptp_rate = 125000000;
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>> +static int loongson_gnet_config(struct pci_dev *pdev,
>>>> +				struct plat_stmmacenet_data *plat,
>>>> +				struct stmmac_resources *res,
>>>> +				struct device_node *np)
>>>> +{
>>>> +	int ret;
>>>> +	u32 version = readl(res->addr + GMAC_VERSION);
>>>> +
>>>> +	switch (version & 0xff) {
>>>> +	case DWLGMAC_CORE_1_00:
>>>> +		ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
>>>> +		break;
>>>> +	default:
>>>> +		ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
>>> Hm, do you have two versions of Loongson GNET? What does the second
>> Yes.
>>> one contain in the GMAC_VERSION register then? Can't you distinguish
>>> them by the PCI IDs (device, subsystem, revision)?
>> I'm afraid that's not possible.
>>
>> Because they have the same pci id and revision.
> Please provide more details about what platform/devices support you
> are adding and what PCI IDs and DW GMAC IP-core version they have.

DWLGMAC_CORE_1_00 has been removed and I am already making patches.


Thanks,

Yanteng

>
>>
>> Thanks,
>>
>> Yanteng
>>
>>> -Serge(y)
>>>
>>>> +		break;
>>>> +	}
>>>> +
>>>> +	switch (pdev->revision) {
>>>> +	case 0x00:
>>>> +		plat->flags |=
>>>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
>>>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
>>>> +		break;
>>>> +	case 0x01:
>>>> +		plat->flags |=
>>>> +			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
>>>> +		break;
>>>> +	default:
>>>> +		break;
>>>> +	}
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>>> +static struct stmmac_pci_info loongson_gnet_pci_info = {
>>>> +	.setup = loongson_gnet_data,
>>>> +	.config = loongson_gnet_config,
>>>> +};
>>>> +
>>>>    static int loongson_dwmac_probe(struct pci_dev *pdev,
>>>>    				const struct pci_device_id *id)
>>>>    {
>>>> @@ -318,9 +395,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
>>>>    			 loongson_dwmac_resume);
>>>>    #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
>>>> +#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
>>>>    static const struct pci_device_id loongson_dwmac_id_table[] = {
>>>>    	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
>>>> +	{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
>>>>    	{}
>>>>    };
>>>>    MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
>>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>> index 8105ce47c6ad..d6939eb9a0d8 100644
>>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
>>>> @@ -420,6 +420,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
>>>>    		return 0;
>>>>    	}
>>>> +	if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000, priv->plat->flags)) {
>>>> +		if (cmd->base.speed == SPEED_1000 &&
>>>> +		    cmd->base.autoneg != AUTONEG_ENABLE)
>>>> +			return -EOPNOTSUPP;
>>>> +	}
>>>> +
>>>>    	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
>>>>    }
>>>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>>>> index f07f79d50b06..067030cdb60f 100644
>>>> --- a/include/linux/stmmac.h
>>>> +++ b/include/linux/stmmac.h
>>>> @@ -222,6 +222,8 @@ struct dwmac4_addrs {
>>>>    #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
>>>>    #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
>>>>    #define STMMAC_FLAG_HAS_LGMAC			BIT(13)
>>>> +#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
> Just noticed. I do not see this flag affecting any part of the code.
> Drop it if no actual action is implied by it.
>
> -Serge(y)
>
>>>> +#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
>>>>    struct plat_stmmacenet_data {
>>>>    	int bus_id;
>>>> -- 
>>>> 2.31.4
>>>>
diff mbox series

Patch

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 2c08d5495214..9e4953c7e4e0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -168,6 +168,83 @@  static struct stmmac_pci_info loongson_gmac_pci_info = {
 	.config = loongson_gmac_config,
 };
 
+static void loongson_gnet_fix_speed(void *priv, unsigned int speed, unsigned int mode)
+{
+	struct net_device *ndev = dev_get_drvdata(priv);
+	struct stmmac_priv *ptr = netdev_priv(ndev);
+
+	/* The controller and PHY don't work well together.
+	 * We need to use the PS bit to check if the controller's status
+	 * is correct and reset PHY if necessary.
+	 */
+	if (speed == SPEED_1000)
+		if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
+			phy_restart_aneg(ndev->phydev);
+}
+
+static int loongson_gnet_data(struct pci_dev *pdev,
+			      struct plat_stmmacenet_data *plat)
+{
+	loongson_default_data(pdev, plat);
+
+	plat->multicast_filter_bins = 256;
+
+	plat->mdio_bus_data->phy_mask = 0xfffffffb;
+
+	plat->phy_addr = 2;
+	plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
+
+	plat->bsp_priv = &pdev->dev;
+	plat->fix_mac_speed = loongson_gnet_fix_speed;
+
+	plat->dma_cfg->pbl = 32;
+	plat->dma_cfg->pblx8 = true;
+
+	plat->clk_ref_rate = 125000000;
+	plat->clk_ptp_rate = 125000000;
+
+	return 0;
+}
+
+static int loongson_gnet_config(struct pci_dev *pdev,
+				struct plat_stmmacenet_data *plat,
+				struct stmmac_resources *res,
+				struct device_node *np)
+{
+	int ret;
+	u32 version = readl(res->addr + GMAC_VERSION);
+
+	switch (version & 0xff) {
+	case DWLGMAC_CORE_1_00:
+		ret = loongson_dwmac_config_multi_msi(pdev, plat, res, np, 8);
+		break;
+	default:
+		ret = loongson_dwmac_config_legacy(pdev, plat, res, np);
+		break;
+	}
+
+	switch (pdev->revision) {
+	case 0x00:
+		plat->flags |=
+			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1) |
+			FIELD_PREP(STMMAC_FLAG_DISABLE_FORCE_1000, 1);
+		break;
+	case 0x01:
+		plat->flags |=
+			FIELD_PREP(STMMAC_FLAG_DISABLE_HALF_DUPLEX, 1);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static struct stmmac_pci_info loongson_gnet_pci_info = {
+	.setup = loongson_gnet_data,
+	.config = loongson_gnet_config,
+};
+
 static int loongson_dwmac_probe(struct pci_dev *pdev,
 				const struct pci_device_id *id)
 {
@@ -318,9 +395,11 @@  static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
 			 loongson_dwmac_resume);
 
 #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
+#define PCI_DEVICE_ID_LOONGSON_GNET	0x7a13
 
 static const struct pci_device_id loongson_dwmac_id_table[] = {
 	{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
+	{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
 	{}
 };
 MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 8105ce47c6ad..d6939eb9a0d8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -420,6 +420,12 @@  stmmac_ethtool_set_link_ksettings(struct net_device *dev,
 		return 0;
 	}
 
+	if (FIELD_GET(STMMAC_FLAG_DISABLE_FORCE_1000, priv->plat->flags)) {
+		if (cmd->base.speed == SPEED_1000 &&
+		    cmd->base.autoneg != AUTONEG_ENABLE)
+			return -EOPNOTSUPP;
+	}
+
 	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
 }
 
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index f07f79d50b06..067030cdb60f 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -222,6 +222,8 @@  struct dwmac4_addrs {
 #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING	BIT(11)
 #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY	BIT(12)
 #define STMMAC_FLAG_HAS_LGMAC			BIT(13)
+#define STMMAC_FLAG_DISABLE_HALF_DUPLEX	BIT(14)
+#define STMMAC_FLAG_DISABLE_FORCE_1000	BIT(15)
 
 struct plat_stmmacenet_data {
 	int bus_id;