Skip to content

Commit ee268a3

Browse files
alexandrebelloniclaudiubeznea
authored andcommitted
net: macb: Properly handle phylink on at91rm9200
at91ether_init was handling the phy mode and speed but since the switch to phylink, the NCFGR register got overwritten by macb_mac_config(). The issue is that the RM9200_RMII bit and the MACB_CLK_DIV32 field are cleared but never restored as they conflict with the PAE, GBE and PCSSEL bits. Add new capability to differentiate between EMAC and the other versions of the IP and use it to set and avoid clearing the relevant bits. Also, this fixes a NULL pointer dereference in macb_mac_link_up as the EMAC doesn't use any rings/bufffers/queues. Fixes: 7897b07 ("net: macb: convert to phylink") Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 726927d commit ee268a3

2 files changed

Lines changed: 33 additions & 28 deletions

File tree

drivers/net/ethernet/cadence/macb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@
645645
#define MACB_CAPS_GEM_HAS_PTP 0x00000040
646646
#define MACB_CAPS_BD_RD_PREFETCH 0x00000080
647647
#define MACB_CAPS_NEEDS_RSTONUBR 0x00000100
648+
#define MACB_CAPS_MACB_IS_EMAC 0x08000000
648649
#define MACB_CAPS_FIFO_MODE 0x10000000
649650
#define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000
650651
#define MACB_CAPS_SG_DISABLED 0x40000000

drivers/net/ethernet/cadence/macb_main.c

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -529,8 +529,21 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,
529529
old_ctrl = ctrl = macb_or_gem_readl(bp, NCFGR);
530530

531531
/* Clear all the bits we might set later */
532-
ctrl &= ~(GEM_BIT(GBE) | MACB_BIT(SPD) | MACB_BIT(FD) | MACB_BIT(PAE) |
533-
GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));
532+
ctrl &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | MACB_BIT(PAE));
533+
534+
if (bp->caps & MACB_CAPS_MACB_IS_EMAC) {
535+
if (state->interface == PHY_INTERFACE_MODE_RMII)
536+
ctrl |= MACB_BIT(RM9200_RMII);
537+
} else {
538+
ctrl &= ~(GEM_BIT(GBE) | GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));
539+
540+
/* We do not support MLO_PAUSE_RX yet */
541+
if (state->pause & MLO_PAUSE_TX)
542+
ctrl |= MACB_BIT(PAE);
543+
544+
if (state->interface == PHY_INTERFACE_MODE_SGMII)
545+
ctrl |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
546+
}
534547

535548
if (state->speed == SPEED_1000)
536549
ctrl |= GEM_BIT(GBE);
@@ -540,13 +553,6 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,
540553
if (state->duplex)
541554
ctrl |= MACB_BIT(FD);
542555

543-
/* We do not support MLO_PAUSE_RX yet */
544-
if (state->pause & MLO_PAUSE_TX)
545-
ctrl |= MACB_BIT(PAE);
546-
547-
if (state->interface == PHY_INTERFACE_MODE_SGMII)
548-
ctrl |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
549-
550556
/* Apply the new configuration, if any */
551557
if (old_ctrl ^ ctrl)
552558
macb_or_gem_writel(bp, NCFGR, ctrl);
@@ -565,9 +571,10 @@ static void macb_mac_link_down(struct phylink_config *config, unsigned int mode,
565571
unsigned int q;
566572
u32 ctrl;
567573

568-
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
569-
queue_writel(queue, IDR,
570-
bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
574+
if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC))
575+
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
576+
queue_writel(queue, IDR,
577+
bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
571578

572579
/* Disable Rx and Tx */
573580
ctrl = macb_readl(bp, NCR) & ~(MACB_BIT(RE) | MACB_BIT(TE));
@@ -584,17 +591,19 @@ static void macb_mac_link_up(struct phylink_config *config, unsigned int mode,
584591
struct macb_queue *queue;
585592
unsigned int q;
586593

587-
macb_set_tx_clk(bp->tx_clk, bp->speed, ndev);
594+
if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) {
595+
macb_set_tx_clk(bp->tx_clk, bp->speed, ndev);
588596

589-
/* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
590-
* cleared the pipeline and control registers.
591-
*/
592-
bp->macbgem_ops.mog_init_rings(bp);
593-
macb_init_buffers(bp);
597+
/* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
598+
* cleared the pipeline and control registers.
599+
*/
600+
bp->macbgem_ops.mog_init_rings(bp);
601+
macb_init_buffers(bp);
594602

595-
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
596-
queue_writel(queue, IER,
597-
bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
603+
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
604+
queue_writel(queue, IER,
605+
bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
606+
}
598607

599608
/* Enable Rx and Tx */
600609
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(RE) | MACB_BIT(TE));
@@ -4003,7 +4012,6 @@ static int at91ether_init(struct platform_device *pdev)
40034012
struct net_device *dev = platform_get_drvdata(pdev);
40044013
struct macb *bp = netdev_priv(dev);
40054014
int err;
4006-
u32 reg;
40074015

40084016
bp->queues[0].bp = bp;
40094017

@@ -4017,11 +4025,7 @@ static int at91ether_init(struct platform_device *pdev)
40174025

40184026
macb_writel(bp, NCR, 0);
40194027

4020-
reg = MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG);
4021-
if (bp->phy_interface == PHY_INTERFACE_MODE_RMII)
4022-
reg |= MACB_BIT(RM9200_RMII);
4023-
4024-
macb_writel(bp, NCFGR, reg);
4028+
macb_writel(bp, NCFGR, MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG));
40254029

40264030
return 0;
40274031
}
@@ -4180,7 +4184,7 @@ static const struct macb_config sama5d4_config = {
41804184
};
41814185

41824186
static const struct macb_config emac_config = {
4183-
.caps = MACB_CAPS_NEEDS_RSTONUBR,
4187+
.caps = MACB_CAPS_NEEDS_RSTONUBR | MACB_CAPS_MACB_IS_EMAC,
41844188
.clk_init = at91ether_clk_init,
41854189
.init = at91ether_init,
41864190
};

0 commit comments

Comments
 (0)