diff options
author | Nicolas Ferre <nicolas.ferre@atmel.com> | 2013-05-13 23:00:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-05-14 16:04:02 -0400 |
commit | 581df9e1944194bfcabc57e1efae79b0fe171d6f (patch) | |
tree | c9965f5d51aaadee4bbaf3b1608876ac743015b3 /drivers/net | |
parent | faff57a92ba1d7247c5e86ecea2886d2c9d54507 (diff) |
net/macb: fix ISR clear-on-write behavior only for some SoC
Commit 749a2b6 (net/macb: clear tx/rx completion flags in ISR)
introduces clear-on-write on ISR register. This behavior is not always
implemented when using Cadence MACB/GEM and is breaking other platforms.
We are using the Design Configuration Register 1 information and a capability
property to actually activate this clear-on-write behavior on ISR.
Reported-by: Hein Tibosch <hein_tibosch@yahoo.es>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Tested-by: Hein Tibosch <hein_tibosch@yahoo.es>
Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/cadence/macb.c | 18 | ||||
-rw-r--r-- | drivers/net/ethernet/cadence/macb.h | 7 |
2 files changed, 23 insertions, 2 deletions
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 6be513deb17f..c89aa41dd448 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c | |||
@@ -485,7 +485,8 @@ static void macb_tx_interrupt(struct macb *bp) | |||
485 | status = macb_readl(bp, TSR); | 485 | status = macb_readl(bp, TSR); |
486 | macb_writel(bp, TSR, status); | 486 | macb_writel(bp, TSR, status); |
487 | 487 | ||
488 | macb_writel(bp, ISR, MACB_BIT(TCOMP)); | 488 | if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) |
489 | macb_writel(bp, ISR, MACB_BIT(TCOMP)); | ||
489 | 490 | ||
490 | netdev_vdbg(bp->dev, "macb_tx_interrupt status = 0x%03lx\n", | 491 | netdev_vdbg(bp->dev, "macb_tx_interrupt status = 0x%03lx\n", |
491 | (unsigned long)status); | 492 | (unsigned long)status); |
@@ -738,7 +739,8 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) | |||
738 | * now. | 739 | * now. |
739 | */ | 740 | */ |
740 | macb_writel(bp, IDR, MACB_RX_INT_FLAGS); | 741 | macb_writel(bp, IDR, MACB_RX_INT_FLAGS); |
741 | macb_writel(bp, ISR, MACB_BIT(RCOMP)); | 742 | if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) |
743 | macb_writel(bp, ISR, MACB_BIT(RCOMP)); | ||
742 | 744 | ||
743 | if (napi_schedule_prep(&bp->napi)) { | 745 | if (napi_schedule_prep(&bp->napi)) { |
744 | netdev_vdbg(bp->dev, "scheduling RX softirq\n"); | 746 | netdev_vdbg(bp->dev, "scheduling RX softirq\n"); |
@@ -1062,6 +1064,17 @@ static void macb_configure_dma(struct macb *bp) | |||
1062 | } | 1064 | } |
1063 | } | 1065 | } |
1064 | 1066 | ||
1067 | /* | ||
1068 | * Configure peripheral capacities according to integration options used | ||
1069 | */ | ||
1070 | static void macb_configure_caps(struct macb *bp) | ||
1071 | { | ||
1072 | if (macb_is_gem(bp)) { | ||
1073 | if (GEM_BF(IRQCOR, gem_readl(bp, DCFG1)) == 0) | ||
1074 | bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE; | ||
1075 | } | ||
1076 | } | ||
1077 | |||
1065 | static void macb_init_hw(struct macb *bp) | 1078 | static void macb_init_hw(struct macb *bp) |
1066 | { | 1079 | { |
1067 | u32 config; | 1080 | u32 config; |
@@ -1084,6 +1097,7 @@ static void macb_init_hw(struct macb *bp) | |||
1084 | bp->duplex = DUPLEX_HALF; | 1097 | bp->duplex = DUPLEX_HALF; |
1085 | 1098 | ||
1086 | macb_configure_dma(bp); | 1099 | macb_configure_dma(bp); |
1100 | macb_configure_caps(bp); | ||
1087 | 1101 | ||
1088 | /* Initialize TX and RX buffers */ | 1102 | /* Initialize TX and RX buffers */ |
1089 | macb_writel(bp, RBQP, bp->rx_ring_dma); | 1103 | macb_writel(bp, RBQP, bp->rx_ring_dma); |
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 993d70380688..548c0ecae869 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h | |||
@@ -300,6 +300,8 @@ | |||
300 | #define MACB_REV_SIZE 16 | 300 | #define MACB_REV_SIZE 16 |
301 | 301 | ||
302 | /* Bitfields in DCFG1. */ | 302 | /* Bitfields in DCFG1. */ |
303 | #define GEM_IRQCOR_OFFSET 23 | ||
304 | #define GEM_IRQCOR_SIZE 1 | ||
303 | #define GEM_DBWDEF_OFFSET 25 | 305 | #define GEM_DBWDEF_OFFSET 25 |
304 | #define GEM_DBWDEF_SIZE 3 | 306 | #define GEM_DBWDEF_SIZE 3 |
305 | 307 | ||
@@ -323,6 +325,9 @@ | |||
323 | #define MACB_MAN_READ 2 | 325 | #define MACB_MAN_READ 2 |
324 | #define MACB_MAN_CODE 2 | 326 | #define MACB_MAN_CODE 2 |
325 | 327 | ||
328 | /* Capability mask bits */ | ||
329 | #define MACB_CAPS_ISR_CLEAR_ON_WRITE 0x1 | ||
330 | |||
326 | /* Bit manipulation macros */ | 331 | /* Bit manipulation macros */ |
327 | #define MACB_BIT(name) \ | 332 | #define MACB_BIT(name) \ |
328 | (1 << MACB_##name##_OFFSET) | 333 | (1 << MACB_##name##_OFFSET) |
@@ -574,6 +579,8 @@ struct macb { | |||
574 | unsigned int speed; | 579 | unsigned int speed; |
575 | unsigned int duplex; | 580 | unsigned int duplex; |
576 | 581 | ||
582 | u32 caps; | ||
583 | |||
577 | phy_interface_t phy_interface; | 584 | phy_interface_t phy_interface; |
578 | 585 | ||
579 | /* AT91RM9200 transmit */ | 586 | /* AT91RM9200 transmit */ |