aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ, KEERTHY2019-12-05 08:29:30 -0600
committerMurali Karicheri2019-12-10 15:40:39 -0600
commite2b89fe8e8a17570ba0785e91dedd15e0e006889 (patch)
treeb21b8991cc4d435ae925c750c477025fd593c7d7
parent8e7ad5c94d872f6fc312b35036707133ccffa4ee (diff)
downloadprocessor-sdk-u-boot-e2b89fe8e8a17570ba0785e91dedd15e0e006889.tar.gz
processor-sdk-u-boot-e2b89fe8e8a17570ba0785e91dedd15e0e006889.tar.xz
processor-sdk-u-boot-e2b89fe8e8a17570ba0785e91dedd15e0e006889.zip
net: ti: icssg-prueth: Add support for 100M links
Currently driver doesn't set the speed and full duplex parameters in RGMII CFG based on PHY auto negotiated parameters. This patch make updates so that both 100M/1G link speed and full duplex are configured in RGMII CFG register based on PHY negotiated values. Also Firmware requires that minimum inter packet gap (TX_IPG0/1 field of ICSSG_TX_IPG0/1 register) is to be set to desired values based on the PHY link speed. This patch updates the same based on PHY link speed. Both of the above together add support for 100M. Signed-off-by: Keerthy <j-keerthy@ti.com> Acked-by: Roger Quadros <rogerq@ti.com>
-rw-r--r--drivers/net/ti/icssg-prueth.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/drivers/net/ti/icssg-prueth.c b/drivers/net/ti/icssg-prueth.c
index 3a7f39da4b..4090d22d03 100644
--- a/drivers/net/ti/icssg-prueth.c
+++ b/drivers/net/ti/icssg-prueth.c
@@ -82,6 +82,7 @@ enum pruss_pru_id {
82struct prueth { 82struct prueth {
83 struct udevice *dev; 83 struct udevice *dev;
84 struct regmap *miig_rt; 84 struct regmap *miig_rt;
85 struct regmap *mii_rt;
85 fdt_addr_t mdio_base; 86 fdt_addr_t mdio_base;
86 phys_addr_t pruss_shrdram2; 87 phys_addr_t pruss_shrdram2;
87 phys_addr_t tmaddr; 88 phys_addr_t tmaddr;
@@ -104,6 +105,85 @@ struct prueth {
104 int slice; 105 int slice;
105}; 106};
106 107
108/**
109 * TX IPG Values to be set for 100M and 1G link speeds. These values are
110 * in ocp_clk cycles. So need change if ocp_clk is changed for a specific
111 * h/w design.
112 */
113#define MII_RT_TX_IPG_100M 0x166
114#define MII_RT_TX_IPG_1G 0x18
115
116#define RGMII_CFG_OFFSET 4
117
118/* Constant to choose between MII0 and MII1 */
119#define ICSS_MII0 0
120#define ICSS_MII1 1
121
122/* RGMII CFG Register bits */
123#define RGMII_CFG_GIG_EN_MII0 BIT(17)
124#define RGMII_CFG_GIG_EN_MII1 BIT(21)
125#define RGMII_CFG_FULL_DUPLEX_MII0 BIT(18)
126#define RGMII_CFG_FULL_DUPLEX_MII1 BIT(22)
127
128/* PRUSS_MII_RT Registers */
129#define PRUSS_MII_RT_RXCFG0 0x0
130#define PRUSS_MII_RT_RXCFG1 0x4
131#define PRUSS_MII_RT_TXCFG0 0x10
132#define PRUSS_MII_RT_TXCFG1 0x14
133#define PRUSS_MII_RT_TX_CRC0 0x20
134#define PRUSS_MII_RT_TX_CRC1 0x24
135#define PRUSS_MII_RT_TX_IPG0 0x30
136#define PRUSS_MII_RT_TX_IPG1 0x34
137#define PRUSS_MII_RT_PRS0 0x38
138#define PRUSS_MII_RT_PRS1 0x3c
139#define PRUSS_MII_RT_RX_FRMS0 0x40
140#define PRUSS_MII_RT_RX_FRMS1 0x44
141#define PRUSS_MII_RT_RX_PCNT0 0x48
142#define PRUSS_MII_RT_RX_PCNT1 0x4c
143#define PRUSS_MII_RT_RX_ERR0 0x50
144#define PRUSS_MII_RT_RX_ERR1 0x54
145
146static inline void icssg_update_rgmii_cfg(struct regmap *miig_rt, bool gig_en,
147 bool full_duplex, int mii)
148{
149 u32 gig_en_mask, gig_val = 0, full_duplex_mask, full_duplex_val = 0;
150
151 gig_en_mask = (mii == ICSS_MII0) ? RGMII_CFG_GIG_EN_MII0 :
152 RGMII_CFG_GIG_EN_MII1;
153 if (gig_en)
154 gig_val = gig_en_mask;
155 regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, gig_en_mask, gig_val);
156
157 full_duplex_mask = (mii == ICSS_MII0) ? RGMII_CFG_FULL_DUPLEX_MII0 :
158 RGMII_CFG_FULL_DUPLEX_MII1;
159 if (full_duplex)
160 full_duplex_val = full_duplex_mask;
161 regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, full_duplex_mask,
162 full_duplex_val);
163}
164
165static inline void icssg_update_mii_rt_cfg(struct regmap *mii_rt, int speed,
166 int mii)
167{
168 u32 ipg_reg, val;
169
170 ipg_reg = (mii == ICSS_MII0) ? PRUSS_MII_RT_TX_IPG0 :
171 PRUSS_MII_RT_TX_IPG1;
172 switch (speed) {
173 case SPEED_1000:
174 val = MII_RT_TX_IPG_1G;
175 break;
176 case SPEED_100:
177 val = MII_RT_TX_IPG_100M;
178 break;
179 default:
180 /* Other links speeds not supported */
181 pr_err("Unsupported link speed\n");
182 return;
183 }
184 regmap_write(mii_rt, ipg_reg, val);
185}
186
107static int icssg_phy_init(struct udevice *dev) 187static int icssg_phy_init(struct udevice *dev)
108{ 188{
109 struct prueth *priv = dev_get_priv(dev); 189 struct prueth *priv = dev_get_priv(dev);
@@ -160,6 +240,34 @@ static void icssg_config_set(struct prueth *prueth)
160 memcpy_toio(va, &prueth->config[0], sizeof(prueth->config[0])); 240 memcpy_toio(va, &prueth->config[0], sizeof(prueth->config[0]));
161} 241}
162 242
243static int icssg_update_link(struct prueth *priv)
244{
245 struct phy_device *phy = priv->phydev;
246 bool gig_en = false, full_duplex = false;
247
248 if (phy->link) { /* link up */
249 if (phy->speed == 1000)
250 gig_en = true;
251 if (phy->duplex == 0x1)
252 full_duplex = true;
253 if (phy->speed == 100)
254 gig_en = false;
255 /* Set the RGMII cfg for gig en and full duplex */
256 icssg_update_rgmii_cfg(priv->miig_rt, gig_en, full_duplex,
257 priv->slice);
258 /* update the Tx IPG based on 100M/1G speed */
259 icssg_update_mii_rt_cfg(priv->mii_rt, phy->speed, priv->slice);
260
261 printf("link up on port %d, speed %d, %s duplex\n",
262 priv->port_id, phy->speed,
263 (phy->duplex == DUPLEX_FULL) ? "full" : "half");
264 } else {
265 printf("link down on port %d\n", priv->port_id);
266 }
267
268 return phy->link;
269}
270
163static int prueth_start(struct udevice *dev) 271static int prueth_start(struct udevice *dev)
164{ 272{
165 struct prueth *priv = dev_get_priv(dev); 273 struct prueth *priv = dev_get_priv(dev);
@@ -210,7 +318,16 @@ static int prueth_start(struct udevice *dev)
210 goto phy_fail; 318 goto phy_fail;
211 } 319 }
212 320
321 ret = icssg_update_link(priv);
322 if (!ret) {
323 ret = -ENODEV;
324 goto phy_shut;
325 }
326
213 return 0; 327 return 0;
328
329phy_shut:
330 phy_shutdown(priv->phydev);
214phy_fail: 331phy_fail:
215 dma_disable(&priv->dma_rx); 332 dma_disable(&priv->dma_rx);
216rx_fail: 333rx_fail:
@@ -430,6 +547,12 @@ static int prueth_probe(struct udevice *dev)
430 return -ENODEV; 547 return -ENODEV;
431 } 548 }
432 549
550 prueth->mii_rt = syscon_regmap_lookup_by_phandle(dev, "mii-rt");
551 if (!prueth->mii_rt) {
552 dev_err(dev, "couldn't get mii-rt syscon regmap\n");
553 return -ENODEV;
554 }
555
433 ret = clk_get_by_name(dev, "mdio_fck", &prueth->mdiofck); 556 ret = clk_get_by_name(dev, "mdio_fck", &prueth->mdiofck);
434 if (ret) { 557 if (ret) {
435 dev_err(dev, "failed to get clock %d\n", ret); 558 dev_err(dev, "failed to get clock %d\n", ret);