1 From 6943ed031ee75f13a950e293f92db68ea2ec2786 Mon Sep 17 00:00:00 2001
2 From: Claudiu Manoil <claudiu.manoil@nxp.com>
3 Date: Wed, 14 Aug 2019 14:34:47 +0300
4 Subject: [PATCH] enetc: Initialize SerDes for SGMII and SXGMII protocols
6 ENETC has ethernet MACs capable of SGMII and SXGMII but
7 in order to use these protocols some serdes configurations
9 The serdes is configurable via an internal MDIO bus
10 connected to an internal PCS device, all reads/writes are
11 performed at address 0.
12 This patch basically removes the dependecy on a bootloader
13 regarding serdes initialization.
15 Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
16 Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
18 drivers/net/ethernet/freescale/enetc/enetc_hw.h | 17 +++++++
19 drivers/net/ethernet/freescale/enetc/enetc_mdio.c | 24 +++++++++
20 drivers/net/ethernet/freescale/enetc/enetc_pf.c | 59 +++++++++++++++++++++++
21 drivers/net/ethernet/freescale/enetc/enetc_pf.h | 2 +
22 4 files changed, 102 insertions(+)
24 --- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
25 +++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
26 @@ -221,6 +221,23 @@ enum enetc_bdr_type {TX, RX};
27 #define ENETC_PM0_MAXFRM 0x8014
28 #define ENETC_SET_TX_MTU(val) ((val) << 16)
29 #define ENETC_SET_MAXFRM(val) ((val) & 0xffff)
31 +#define ENETC_PM_IMDIO_BASE 0x8030
33 +#define ENETC_PCS_CR 0x0
34 +#define ENETC_PCS_CR_RESET_AN 0x1200
35 +#define ENETC_PCS_CR_DEF_VAL 0x0140
36 +#define ENETC_PCS_CR_LANE_RESET 0x8000
37 +#define ENETC_PCS_DEV_ABILITY 0x04
38 +#define ENETC_PCS_DEV_ABILITY_SGMII 0x4001
39 +#define ENETC_PCS_DEV_ABILITY_SXGMII 0x5001
40 +#define ENETC_PCS_LINK_TIMER1 0x12
41 +#define ENETC_PCS_LINK_TIMER1_VAL 0x06a0
42 +#define ENETC_PCS_LINK_TIMER2 0x13
43 +#define ENETC_PCS_LINK_TIMER2_VAL 0x0003
44 +#define ENETC_PCS_IF_MODE 0x14
45 +#define ENETC_PCS_IF_MODE_SGMII_AN 0x0003
47 #define ENETC_PM0_IF_MODE 0x8300
48 #define ENETC_PMO_IFM_RG BIT(2)
49 #define ENETC_PM0_IFM_RLP (BIT(5) | BIT(11))
50 --- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
51 +++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
52 @@ -200,3 +200,27 @@ void enetc_mdio_remove(struct enetc_pf *
54 mdiobus_unregister(pf->mdio);
57 +int enetc_imdio_init(struct enetc_pf *pf)
59 + struct device *dev = &pf->si->pdev->dev;
60 + struct enetc_mdio_priv *mdio_priv;
61 + struct mii_bus *bus;
63 + bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
67 + bus->name = "FSL ENETC internal MDIO Bus";
68 + bus->read = enetc_mdio_read;
69 + bus->write = enetc_mdio_write;
71 + mdio_priv = bus->priv;
72 + mdio_priv->hw = &pf->si->hw;
73 + mdio_priv->mdio_base = ENETC_PM_IMDIO_BASE;
74 + snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
80 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
81 +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
82 @@ -807,6 +807,61 @@ static void enetc_of_put_phy(struct enet
83 of_node_put(priv->phy_node);
86 +static void enetc_configure_sgmii(struct mii_bus *imdio)
88 + /* Set to SGMII mode, use AN */
89 + imdio->write(imdio, 0, ENETC_PCS_IF_MODE,
90 + ENETC_PCS_IF_MODE_SGMII_AN);
92 + /* Dev ability - SGMII */
93 + imdio->write(imdio, 0, ENETC_PCS_DEV_ABILITY,
94 + ENETC_PCS_DEV_ABILITY_SGMII);
96 + /* Adjust link timer for SGMII */
97 + imdio->write(imdio, 0, ENETC_PCS_LINK_TIMER1,
98 + ENETC_PCS_LINK_TIMER1_VAL);
99 + imdio->write(imdio, 0, ENETC_PCS_LINK_TIMER2,
100 + ENETC_PCS_LINK_TIMER2_VAL);
102 + /* restart PCS AN */
103 + imdio->write(imdio, 0, ENETC_PCS_CR,
104 + ENETC_PCS_CR_RESET_AN | ENETC_PCS_CR_DEF_VAL);
107 +static void enetc_configure_sxgmii(struct mii_bus *imdio)
109 + /* Dev ability - SXGMII */
110 + imdio->write(imdio, 0, MII_ADDR_C45 | (MDIO_MMD_VEND2 << 16) |
111 + ENETC_PCS_DEV_ABILITY, ENETC_PCS_DEV_ABILITY_SXGMII);
113 + /* Restart PCS AN */
114 + imdio->write(imdio, 0, MII_ADDR_C45 | (MDIO_MMD_VEND2 << 16) |
116 + ENETC_PCS_CR_LANE_RESET | ENETC_PCS_CR_RESET_AN);
119 +static int enetc_configure_serdes(struct enetc_ndev_priv *priv)
121 + struct enetc_pf *pf = enetc_si_priv(priv->si);
124 + if (priv->if_mode != PHY_INTERFACE_MODE_SGMII &&
125 + priv->if_mode != PHY_INTERFACE_MODE_XGMII)
128 + err = enetc_imdio_init(pf);
132 + if (priv->if_mode == PHY_INTERFACE_MODE_SGMII)
133 + enetc_configure_sgmii(pf->imdio);
135 + if (priv->if_mode == PHY_INTERFACE_MODE_XGMII)
136 + enetc_configure_sxgmii(pf->imdio);
141 static int enetc_pf_probe(struct pci_dev *pdev,
142 const struct pci_device_id *ent)
144 @@ -871,6 +926,10 @@ static int enetc_pf_probe(struct pci_dev
146 dev_warn(&pdev->dev, "Fallback to PHY-less operation\n");
148 + err = enetc_configure_serdes(priv);
150 + dev_warn(&pdev->dev, "Attempted serdes config but failed\n");
152 err = register_netdev(ndev);
155 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
156 +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
157 @@ -44,6 +44,7 @@ struct enetc_pf {
158 DECLARE_BITMAP(active_vlans, VLAN_N_VID);
160 struct mii_bus *mdio; /* saved for cleanup */
161 + struct mii_bus *imdio;
164 int enetc_msg_psi_init(struct enetc_pf *pf);
165 @@ -53,3 +54,4 @@ void enetc_msg_handle_rxmsg(struct enetc
167 int enetc_mdio_probe(struct enetc_pf *pf);
168 void enetc_mdio_remove(struct enetc_pf *pf);
169 +int enetc_imdio_init(struct enetc_pf *pf);