TI中文支持网
TI专业的中文技术问题搜集分享网站

DP83TC812R-Q1: DP83TC812设备608寄存器莫名其妙的发生值变化

Part Number:DP83TC812R-Q1

已知DP83TC812的608寄存器在值等于0x27a时phy通信正常,但偶发值会突变成0x132,我想知道为何会发生这个变化应该怎么避免这种变化?

Kailyn Chen:

您好,0x608的寄存器变化来看,像是serdes 的RX数据的顺序发生了变化,导致bit8这里SGMII RX bus invert polarity极性出现相反。

看下这里的配置bit15-14是不是也发生了变化。

,

?? ?:

4A0这个寄存器倒是没什么变化

,

?? ?:

将 608 寄存器值改为 27a 后,恢复正常;

,

Kailyn Chen:

您好,从寄存器值的改变来看,就是bit8这里的SGMII极性的交换,而DP83TC812不支持自动极性交换。所以我想是不是这里的原因导致。 

0x60A寄存器可以说明SGMII的link状态,当608的值改变之后,看下0x60A的bit 11的SGMII link是否down掉。

,

?? ?:

什么情况下会导致这个问题:bit8这里的SGMII极性的交换呢?

,

Kailyn Chen:

您好,这个问题应该是和SGMII协议标准有关,具体要看下协议标准。

我想DP83TC812传输的数据格式应该是遵循协议的,并且不支持自动极性交换。 而和MAC相连的MDI接口是不是自适应极性交换的,所以当传输的数据极性发生改变的时候,DP83TC812侧会报错。

,

?? ?:

但是这是一个偶发的事件,如果MDI接口出现极性相反了,应该会变成一个必现的

,

Kailyn Chen:

您好,偶发的事件只发生在一片芯片上还是多片?我帮您确认下。

,

?? ?:

多片,而且应该在忙的时候比较多出现,但我还是不太明白你说什么情况导致mdl极性反转sgmll极性反转,程序主动改变sgmll极性,最后导致link失败?

,

?? ?:

如果你是Ti公司研发支持,我感觉可以电话沟通:13950168929,我电话,如果你那边不方便的话那也没关系的

,

Kailyn Chen:

您好,抱歉我们目前的支持方式是以论坛的形式沟通的。

我刚已经把您的问题升级到英文E2E上了,请关注美国工程师的回复:

https://e2e.ti.com/support/interface-group/interface/f/interface-forum/1286014/dp83tc812r-q1-0x608-has-changed-from-0x27a-to-0x132

有任何问题,可直接跟进。

,

?? ?:

好的,谢谢你了

,

Kailyn Chen:

您好,E2E给出回复了,应该是driver的bug,并且给了配置例程,您试试是否可以解决您的问题。

3343.dp83tc812.c

// SPDX-License-Identifier: GPL-2.0
/** Driver for the Texas Instruments DP83TC812 PHY** Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/**/#include <linux/ethtool.h>
#include <linux/etherdevice.h>
#include <linux/kernel.h>
#include <linux/mii.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/phy.h>
#include <linux/netdevice.h>#define DP83TC812_CS1_0_PHY_ID	0x2000a270
#define DP83TC812_CS2_0_PHY_ID	0x2000a271
#define DP83TC813_CS2_0_PHY_ID	0x2000a211
#define DP83TC814_CS2_0_PHY_ID	0x2000a261#define DP83812_DEVADDR0x1f
#define DP83812_DEVADDR_MMD1	0x1#define DP83812_STRAP0x45d
#define MII_DP83812_SGMII_CTRL	0x608
#define SGMII_CONFIG_VAL	0x027B
#define MII_DP83812_RGMII_CTRL	0x600
#define MII_DP83812_INT_STAT1	0x12
#define MII_DP83812_INT_STAT2	0x13
#define MII_DP83812_INT_STAT3	0x18
#define MII_DP83812_RESET_CTRL	0x1f#define DP83812_HW_RESET	BIT(15)
#define DP83812_SW_RESET	BIT(14)/* INT_STAT1 bits */
#define DP83812_RX_ERR_CNT_HALF_FULL_INT_EN	BIT(0)
#define DP83812_TX_ERR_CNT_HALF_FULL_INT_EN	BIT(1)
#define DP83812_MS_TRAIN_DONE_INT_ENBIT(2)
#define DP83812_ESD_EVENT_INT_ENBIT(3)
#define DP83812_LINK_STAT_INT_ENBIT(5)
#define DP83812_ENERGY_DET_INT_ENBIT(6)
#define DP83812_LINK_QUAL_INT_ENBIT(7)/* INT_STAT2 bits */
#define DP83812_JABBER_INT_ENBIT(0)
#define DP83812_POL_INT_ENBIT(1)
#define DP83812_SLEEP_MODE_INT_EN	BIT(2)
#define DP83812_OVERTEMP_INT_ENBIT(3)
#define DP83812_FIFO_INT_ENBIT(4)
#define DP83812_PAGE_RXD_INT_ENBIT(5)
#define DP83812_OVERVOLTAGE_INT_EN	BIT(6)
#define DP83812_UNDERVOLTAGE_INT_EN	BIT(7)/* INT_STAT3 bits */
#define DP83812_LPS_INT_ENBIT(0)
#define DP83812_WUP_INT_ENBIT(1)
#define DP83812_WAKE_REQ_INT_ENBIT(2)
#define DP83811_NO_FRAME_INT_ENBIT(3)
#define DP83811_POR_DONE_INT_ENBIT(4)
#define DP83812_SLEEP_FAIL_INT_EN	BIT(5)/* RGMII_CTRL bits */
#define DP83812_RGMII_ENBIT(3)/* SGMII CTRL bits */
#define DP83812_SGMII_AUTO_NEG_EN	BIT(0)
#define DP83812_SGMII_ENBIT(9)/* Strap bits */
#define DP83812_MASTER_MODE	BIT(9)
#define DP83812_RGMII_IS_EN	BIT(7)/* RGMII ID CTRL */
#define DP83812_RGMII_ID_CTRL	0x602
#define DP83812_RX_CLK_SHIFT	BIT(1)
#define DP83812_TX_CLK_SHIFT	BIT(0)enum dp83812_chip_type {DP83812_CS1 = 0,DP83812_CS2,DP83813_CS2,DP83814_CS2,
};struct dp83812_init_reg {int	reg;int	val;
};static const struct dp83812_init_reg dp83812_master_cs1_0_init[] = {{0x523, 0x0001},{0x800, 0xf864},{0x803, 0x1552},{0x804, 0x1a66},{0x805, 0x1f7b},{0x81f, 0x2a88},{0x825, 0x40e5},{0x82b, 0x7f3f},{0x830, 0x0543},{0x836, 0x5008},{0x83a, 0x08e0},{0x83b, 0x0845},{0x83e, 0x0445},{0x855, 0x9b9a},{0x85f, 0x2010},{0x860, 0x6040},{0x86c, 0x1333},{0x86b, 0x3e10},{0x872, 0x88c0},{0x873, 0x0003},{0x879, 0x000f},{0x87b, 0x0070},{0x87c, 0x003f},{0x89e, 0x00aa},{0x523, 0x0000},
};static const struct dp83812_init_reg dp83812_master_cs2_0_init[] = {{0x523, 0x0001},{0x81C, 0x0fe2},{0x872, 0x0300},{0x879, 0x0f00},{0x806, 0x2952},{0x807, 0x3361},{0x808, 0x3D7B},{0x83E, 0x045F},{0x834, 0x8000},{0x862, 0x00E8},{0x896, 0x32CB},{0x03E, 0x0009},{0x01f, 0x4000},{0x523, 0x0000},
};static const struct dp83812_init_reg dp83812_slave_cs1_0_init[] = {{0x523, 0x0001},{0x803, 0x1b52},{0x804, 0x216c},{0x805, 0x277b},{0x827, 0x3000},{0x830, 0x0543},{0x83a, 0x0020},{0x83c, 0x0001},{0x855, 0x9b9a},{0x85f, 0x2010},{0x860, 0x6040},{0x86c, 0x0333},{0x872, 0x88c0},{0x873, 0x0021},{0x879, 0x000f},{0x87b, 0x0070},{0x87c, 0x0002},{0x897, 0x003f},{0x89e, 0x00a2},{0x510, 0x000f},{0x523, 0x0000},
};static const struct dp83812_init_reg dp83812_slave_cs2_0_init[] = {{0x523, 0x0001},{0x873, 0x0821},{0x896, 0x22ff},{0x89E, 0x0000},{0x01f, 0x4000},{0x523, 0x0000},
};struct dp83812_private {int chip;bool is_master;bool is_rgmii;bool is_sgmii;
};static int dp83812_read_straps(struct phy_device *phydev)
{struct dp83812_private *dp83812 = phydev->priv;int strap;strap = phy_read_mmd(phydev, DP83812_DEVADDR, DP83812_STRAP);if (strap < 0)return strap;printk("%s: Strap is 0x%X\n", __func__, strap);if (strap & DP83812_MASTER_MODE)dp83812->is_master = true;if (strap & DP83812_RGMII_IS_EN)dp83812->is_rgmii = true;return 0;
};static int dp83812_reset(struct phy_device *phydev, bool hw_reset)
{int ret;if (hw_reset)ret = phy_write_mmd(phydev, DP83812_DEVADDR, MII_DP83812_RESET_CTRL,DP83812_HW_RESET);elseret = phy_write_mmd(phydev, DP83812_DEVADDR, MII_DP83812_RESET_CTRL,DP83812_SW_RESET);if (ret)return ret;mdelay(100);return 0;
}static int dp83812_phy_reset(struct phy_device *phydev)
{int err;int ret;err = phy_write_mmd(phydev, DP83812_DEVADDR, MII_DP83812_RESET_CTRL, DP83812_HW_RESET);if (err < 0)return err;ret = dp83812_read_straps(phydev);if (ret)return ret;return 0;
}static int dp83812_write_seq(struct phy_device *phydev, const structdp83812_init_reg *init_data, int size)
{int ret;int i;for (i = 0; i < size; i++) {ret = phy_write_mmd(phydev, DP83812_DEVADDR, init_data[i].reg,init_data[i].val);if (ret)return ret;}return 0;
}static int dp83812_chip_init(struct phy_device *phydev)
{struct dp83812_private *dp83812 = phydev->priv;int ret;ret = dp83812_reset(phydev, true);if (ret)return ret;phydev->autoneg = AUTONEG_DISABLE;phydev->speed = SPEED_100;phydev->duplex = DUPLEX_FULL;linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,phydev->supported);if (dp83812->is_master)ret = phy_write_mmd(phydev, DP83812_DEVADDR_MMD1, 0x0834, 0xc001);// ret = phy_write_mmd(phydev, DP83812_DEVADDR, 0x0834, 0xc001);elseret = phy_write_mmd(phydev, DP83812_DEVADDR_MMD1, 0x0834, 0x8001);// ret = phy_write_mmd(phydev, DP83812_DEVADDR, 0x0834, 0x8001);switch (dp83812->chip) {case DP83812_CS1:if (dp83812->is_master)ret = dp83812_write_seq(phydev,dp83812_master_cs1_0_init,ARRAY_SIZE(dp83812_master_cs1_0_init));elseret = dp83812_write_seq(phydev,dp83812_slave_cs1_0_init,ARRAY_SIZE(dp83812_slave_cs1_0_init));break;case DP83812_CS2:if (dp83812->is_master)ret = dp83812_write_seq(phydev,dp83812_master_cs2_0_init,ARRAY_SIZE(dp83812_master_cs2_0_init));elseret = dp83812_write_seq(phydev,dp83812_slave_cs2_0_init,ARRAY_SIZE(dp83812_slave_cs2_0_init));break;case DP83813_CS2:if (dp83812->is_master)ret = dp83812_write_seq(phydev,dp83812_master_cs2_0_init,ARRAY_SIZE(dp83812_master_cs2_0_init));elseret = dp83812_write_seq(phydev,dp83812_slave_cs2_0_init,ARRAY_SIZE(dp83812_slave_cs2_0_init));break;case DP83814_CS2:if (dp83812->is_master)ret = dp83812_write_seq(phydev,dp83812_master_cs2_0_init,ARRAY_SIZE(dp83812_master_cs2_0_init));elseret = dp83812_write_seq(phydev,dp83812_slave_cs2_0_init,ARRAY_SIZE(dp83812_slave_cs2_0_init));break;default:return -EINVAL;};if (ret)return ret;mdelay(10);// phy_write_mmd(phydev, DP83812_DEVADDR, 0x523, 0x00);/* Do a soft reset to restart the PHY with updated values */return dp83812_reset(phydev, false);
}static int dp83812_config_init(struct phy_device *phydev)
{struct device *dev = &phydev->mdio.dev;s32 rx_int_delay;s32 tx_int_delay;int rgmii_delay;int value, ret;ret = dp83812_chip_init(phydev);if (ret)return ret;if (phy_interface_is_rgmii(phydev)) {rx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,true);if (rx_int_delay <= 0)rgmii_delay = 0;elsergmii_delay = DP83812_RX_CLK_SHIFT;tx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,false);if (tx_int_delay <= 0)rgmii_delay &= ~DP83812_TX_CLK_SHIFT;elsergmii_delay |= DP83812_TX_CLK_SHIFT;if (rgmii_delay) {ret = phy_set_bits_mmd(phydev, DP83812_DEVADDR_MMD1,DP83812_RGMII_ID_CTRL,rgmii_delay);if (ret)return ret;}}if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {value = phy_read(phydev, MII_DP83812_SGMII_CTRL);ret = phy_write_mmd(phydev, DP83812_DEVADDR, MII_DP83812_SGMII_CTRL,SGMII_CONFIG_VAL);if (ret < 0)return ret;}return 0;
}static int dp83812_ack_interrupt(struct phy_device *phydev)
{int err;err = phy_read(phydev, MII_DP83812_INT_STAT1);if (err < 0)return err;err = phy_read(phydev, MII_DP83812_INT_STAT2);if (err < 0)return err;err = phy_read(phydev, MII_DP83812_INT_STAT3);if (err < 0)return err;return 0;
}static int dp83812_config_intr(struct phy_device *phydev)
{int misr_status, err;if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {misr_status = phy_read(phydev, MII_DP83812_INT_STAT1);if (misr_status < 0)return misr_status;misr_status |= (DP83812_ESD_EVENT_INT_EN |DP83812_LINK_STAT_INT_EN |DP83812_ENERGY_DET_INT_EN |DP83812_LINK_QUAL_INT_EN);err = phy_write(phydev, MII_DP83812_INT_STAT1, misr_status);if (err < 0)return err;misr_status = phy_read(phydev, MII_DP83812_INT_STAT2);if (misr_status < 0)return misr_status;misr_status |= (DP83812_SLEEP_MODE_INT_EN |DP83812_OVERTEMP_INT_EN |DP83812_OVERVOLTAGE_INT_EN |DP83812_UNDERVOLTAGE_INT_EN);err = phy_write(phydev, MII_DP83812_INT_STAT2, misr_status);if (err < 0)return err;misr_status = phy_read(phydev, MII_DP83812_INT_STAT3);if (misr_status < 0)return misr_status;misr_status |= (DP83812_LPS_INT_EN |DP83812_WAKE_REQ_INT_EN |DP83811_NO_FRAME_INT_EN |DP83811_POR_DONE_INT_EN);err = phy_write(phydev, MII_DP83812_INT_STAT3, misr_status);} else {err = phy_write(phydev, MII_DP83812_INT_STAT1, 0);if (err < 0)return err;err = phy_write(phydev, MII_DP83812_INT_STAT2, 0);if (err < 0)return err;err = phy_write(phydev, MII_DP83812_INT_STAT3, 0);}return err;
}#if 0
static irqreturn_t dp83812_handle_interrupt(struct phy_device *phydev)
{bool trigger_machine = false;int irq_status;/* The INT_STAT registers 1, 2 and 3 are holding the interrupt status* in the upper half (15:8), while the lower half (7:0) is used for* controlling the interrupt enable state of those individual interrupt* sources. To determine the possible interrupt sources, just read the* INT_STAT* register and use it directly to know which interrupts have* been enabled previously or not.*/irq_status = phy_read(phydev, MII_DP83812_INT_STAT1);if (irq_status < 0) {phy_error(phydev);return IRQ_NONE;}if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))trigger_machine = true;irq_status = phy_read(phydev, MII_DP83812_INT_STAT2);if (irq_status < 0) {phy_error(phydev);return IRQ_NONE;}if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))trigger_machine = true;irq_status = phy_read(phydev, MII_DP83812_INT_STAT3);if (irq_status < 0) {phy_error(phydev);return IRQ_NONE;}if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))trigger_machine = true;if (!trigger_machine)return IRQ_NONE;phy_trigger_machine(phydev);return IRQ_HANDLED;
}
#endifstatic int dp83812_config_aneg(struct phy_device *phydev)
{int value, ret;if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {value = phy_read(phydev, MII_DP83812_SGMII_CTRL);ret = phy_write_mmd(phydev, DP83812_DEVADDR, MII_DP83812_SGMII_CTRL,SGMII_CONFIG_VAL);if (ret < 0)return ret;}return genphy_config_aneg(phydev);
}static int dp83812_probe(struct phy_device *phydev)
{struct dp83812_private *dp83812;int ret;dp83812 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83812), GFP_KERNEL);if (!dp83812)return -ENOMEM;phydev->priv = dp83812;ret = dp83812_read_straps(phydev);if (ret)return ret;switch (phydev->phy_id) {case DP83TC812_CS1_0_PHY_ID:dp83812->chip = DP83812_CS1;break;case DP83TC812_CS2_0_PHY_ID:dp83812->chip = DP83812_CS2;break;case DP83TC813_CS2_0_PHY_ID:dp83812->chip = DP83813_CS2;break;case DP83TC814_CS2_0_PHY_ID:dp83812->chip = DP83814_CS2;break;default:return -EINVAL;};
/* vikram : above code added to switch between different phy ids */return dp83812_config_init(phydev);
}#define DP83812_PHY_DRIVER(_id, _name)\{\PHY_ID_MATCH_EXACT(_id),\.name= (_name),\.probe= dp83812_probe,\/* PHY_BASIC_FEATURES */\.soft_reset= dp83812_phy_reset,\.config_init= dp83812_config_init,\.config_aneg = dp83812_config_aneg,\.ack_interrupt = dp83812_ack_interrupt,\
/*if 0\.handle_interrupt = dp83812_handle_interrupt,	\
#endif	*/\.config_intr = dp83812_config_intr,\.suspend = genphy_suspend,\.resume = genphy_resume,\}static struct phy_driver dp83812_driver[] = {DP83812_PHY_DRIVER(DP83TC812_CS1_0_PHY_ID, "TI DP83TC812CS1.0"),DP83812_PHY_DRIVER(DP83TC812_CS2_0_PHY_ID, "TI DP83TC812CS2.0"),DP83812_PHY_DRIVER(DP83TC813_CS2_0_PHY_ID, "TI DP83TC813CS2.0"),DP83812_PHY_DRIVER(DP83TC814_CS2_0_PHY_ID, "TI DP83TC814CS2.0"),};module_phy_driver(dp83812_driver);static struct mdio_device_id __maybe_unused dp83812_tbl[] = {{ PHY_ID_MATCH_EXACT(DP83TC812_CS1_0_PHY_ID) },{ PHY_ID_MATCH_EXACT(DP83TC812_CS2_0_PHY_ID) },{ PHY_ID_MATCH_EXACT(DP83TC813_CS2_0_PHY_ID) },{ PHY_ID_MATCH_EXACT(DP83TC814_CS2_0_PHY_ID) },{ },
};
MODULE_DEVICE_TABLE(mdio, dp83812_tbl);MODULE_DESCRIPTION("Texas Instruments DP83TC812 PHY driver");
MODULE_AUTHOR("Hari Nagalla <hnagalla@ti.com");
MODULE_LICENSE("GPL");

,

?? ?:

是否标注一下,您更改的地方?

,

Kailyn Chen:

这个是DP83TC812的driver,您的意思是和您的对比,哪里进行了更改是吗?建议是您直接使用这个driver试试,是否能解决寄存器偶发突变的问题。

,

?? ?:

暂时编译有问题,我需要修改才能回复你,也可能对应的.h也有不同,是否发送一个对应这版.c的.h?

,

Kailyn Chen:

?? ? said:是否发送一个对应这版.c的.h?

抱歉没有对应这版.c的h文件呢,您可以直接在E2E上跟进下。或者我这边帮您确认下也行。

,

?? ?:

你那边帮忙一下吧

,

Kailyn Chen:

可以的。

,

Kailyn Chen:

已经跟进到E2E上了,请关注E2E的回复。

,

Kailyn Chen:

Kailyn Chen said:抱歉没有对应这版.c的h文件呢,您可以直接在E2E上跟进下。或者我这边帮您确认下也行。

您好,E2E已经给出回复,对应的h文件在包含在linux的SDK里:

The related .h files are included as part of the standard Linux SDK:

https://elixir.bootlin.com/linux/latest/source/include/linux

,

?? ?:

好吧,都用6.0v了,我这的内核还在3.18v

,

Kailyn Chen:

是的,那是否还使用这个driver进行验证,确认下是否能解决寄存器偶发突变的现象?

,

?? ?:

我改了一个版本,以太网没起来

,

Kailyn Chen:

使用E2E提供的driver,以太网没起来吗?

那您这边还需要我这边帮您跟进其他问题吗?

,

?? ?:

嗯嗯,暂时是这样的,我还在找原因

,

Kailyn Chen:

好的,有什么问题再沟通。

赞(0)
未经允许不得转载:TI中文支持网 » DP83TC812R-Q1: DP83TC812设备608寄存器莫名其妙的发生值变化
分享到: 更多 (0)