[PATCH net-next 1/2] drivers: net: xgene: Add support RGMII TX/RX delay configuration
Iyappan Subramanian
isubramanian at apm.com
Fri Oct 23 11:02:19 PDT 2015
On Fri, Oct 16, 2015 at 2:36 PM, Florian Fainelli <f.fainelli at gmail.com> wrote:
> On 16/10/15 13:35, Iyappan Subramanian wrote:
>> Add RGMII TX/RX delay configuration support. RGMII standard requires 2ns
>> delay to help the RGMII bridge receiver to sample data correctly. If the
>> default value does not provide proper centering of the data sample, the
>> TX/RX delay parameters can be used to adjust accordingly.
>
> There is a standard 'phy-mode' property which can take multiple values
> for RGMII: "rgmii" (no delay), "rgmii-txid" (transmit delay),
> "rgmii-rxid" (receive delay) and "rgmii-id" (symetric delay). There does
> not seem to be any verification of whether the rx or tx delay parameters
> you introduce are going to be either sensible, or not conflicting with
> the 'phy-mode' that should be configured.
X-Gene RGMII ethernet controller has a RGMII bridge that performs the
task of converting the RGMII signal {RX_CLK,RX_CTL, RX_DATA[3:0]} from
PHY to GMII signal {RX_DV,RX_ER,RX_DATA[7:0]} and vice versa. This
RGMII bridge has a provision to internally delay the input RX_CLK and
the output TX_CLK using configuration registers. This will help in
maintain the CLK-CTL delay relationship in various operating
conditions.
This is similar to the following patch that got accepted.
https://lkml.org/lkml/2014/12/29/77
I will submit v2 with updated documentation.
>
>>
>> Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
>> ---
>> drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 8 +++-
>> drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 1 +
>> drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 49 ++++++++++++++++++++++++
>> drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 2 +
>> 4 files changed, 59 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
>> index 652f218..33850a0 100644
>> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
>> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
>> @@ -461,6 +461,7 @@ static void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
>>
>> static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
>> {
>> + struct device *dev = &pdata->pdev->dev;
>> u32 value, mc2;
>> u32 intf_ctl, rgmii;
>> u32 icm0, icm2;
>> @@ -490,7 +491,12 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
>> default:
>> ENET_INTERFACE_MODE2_SET(&mc2, 2);
>> intf_ctl |= ENET_GHD_MODE;
>> - CFG_TXCLK_MUXSEL0_SET(&rgmii, 4);
>> +
>> + if (dev->of_node) {
>> + CFG_TXCLK_MUXSEL0_SET(&rgmii, pdata->tx_delay);
>> + CFG_RXCLK_MUXSEL0_SET(&rgmii, pdata->rx_delay);
>> + }
>> +
>> xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, &value);
>> value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
>> xgene_enet_wr_csr(pdata, DEBUG_REG_ADDR, value);
>> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
>> index ff05bbc..6dee73c 100644
>> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
>> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
>> @@ -144,6 +144,7 @@ enum xgene_enet_rm {
>> #define CFG_BYPASS_UNISEC_RX BIT(1)
>> #define CFG_CLE_BYPASS_EN0 BIT(31)
>> #define CFG_TXCLK_MUXSEL0_SET(dst, val) xgene_set_bits(dst, val, 29, 3)
>> +#define CFG_RXCLK_MUXSEL0_SET(dst, val) xgene_set_bits(dst, val, 26, 3)
>>
>> #define CFG_CLE_IP_PROTOCOL0_SET(dst, val) xgene_set_bits(dst, val, 16, 2)
>> #define CFG_CLE_DSTQID0_SET(dst, val) xgene_set_bits(dst, val, 0, 12)
>> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
>> index 6b1846d..ce10687 100644
>> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
>> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
>> @@ -1118,6 +1118,47 @@ static int xgene_get_port_id_dt(struct device *dev, struct xgene_enet_pdata *pda
>> return ret;
>> }
>>
>> +static int xgene_get_tx_delay(struct xgene_enet_pdata *pdata)
>> +{
>> + struct device *dev = &pdata->pdev->dev;
>> + int delay, ret;
>> +
>> + ret = of_property_read_u32(dev->of_node, "tx-delay", &delay);
>> + if (ret) {
>> + pdata->tx_delay = 4;
>> + return 0;
>> + }
>> +
>> + if (delay < 0 || delay > 7) {
>> + dev_err(dev, "Invalid tx-delay specified\n");
>> + return -EINVAL;
>> + }
>> +
>> + pdata->tx_delay = delay;
>> +
>> + return 0;
>> +}
>> +
>> +static int xgene_get_rx_delay(struct xgene_enet_pdata *pdata)
>> +{
>> + struct device *dev = &pdata->pdev->dev;
>> + int delay, ret;
>> +
>> + ret = of_property_read_u32(dev->of_node, "rx-delay", &delay);
>> + if (ret) {
>> + pdata->rx_delay = 2;
>> + return 0;
>> + }
>> +
>> + if (delay < 0 || delay > 7) {
>> + dev_err(dev, "Invalid rx-delay specified\n");
>> + return -EINVAL;
>> + }
>> +
>> + pdata->rx_delay = delay;
>> +
>> + return 0;
>> +}
>>
>> static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
>> {
>> @@ -1194,6 +1235,14 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
>> return -ENODEV;
>> }
>>
>> + ret = xgene_get_tx_delay(pdata);
>> + if (ret)
>> + return ret;
>> +
>> + ret = xgene_get_rx_delay(pdata);
>> + if (ret)
>> + return ret;
>> +
>> ret = platform_get_irq(pdev, 0);
>> if (ret <= 0) {
>> dev_err(dev, "Unable to get ENET Rx IRQ\n");
>> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
>> index ff89a5d..a6e56b8 100644
>> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
>> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
>> @@ -184,6 +184,8 @@ struct xgene_enet_pdata {
>> u8 bp_bufnum;
>> u16 ring_num;
>> u32 mss;
>> + u8 tx_delay;
>> + u8 rx_delay;
>> };
>>
>> struct xgene_indirect_ctl {
>>
>
>
> --
> Florian
More information about the linux-arm-kernel
mailing list