diff options
| author | Bryan Wu <cooloney@kernel.org> | 2008-07-27 10:45:04 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@redhat.com> | 2008-07-29 17:48:32 -0400 |
| commit | a50c0c05c3bdead1ac405ca8cefd8dc290043933 (patch) | |
| tree | fb1325daf36d9bc6fec06027c6127fbb489386be | |
| parent | d7b843d393cec677583e1aa971df09b140dcfd5e (diff) | |
Blackfin EMAC Driver: enable TXDWA new feature for new silicon (rev > 0.2)
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
| -rw-r--r-- | drivers/net/bfin_mac.c | 103 |
1 files changed, 77 insertions, 26 deletions
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index de777c28ec68..ab728006cfa5 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c | |||
| @@ -605,36 +605,87 @@ adjust_head: | |||
| 605 | static int bfin_mac_hard_start_xmit(struct sk_buff *skb, | 605 | static int bfin_mac_hard_start_xmit(struct sk_buff *skb, |
| 606 | struct net_device *dev) | 606 | struct net_device *dev) |
| 607 | { | 607 | { |
| 608 | unsigned int data; | 608 | u16 *data; |
| 609 | 609 | ||
| 610 | current_tx_ptr->skb = skb; | 610 | current_tx_ptr->skb = skb; |
| 611 | 611 | ||
| 612 | /* | 612 | if (ANOMALY_05000285) { |
| 613 | * Is skb->data always 16-bit aligned? | 613 | /* |
| 614 | * Do we need to memcpy((char *)(tail->packet + 2), skb->data, len)? | 614 | * TXDWA feature is not avaible to older revision < 0.3 silicon |
| 615 | */ | 615 | * of BF537 |
| 616 | if ((((unsigned int)(skb->data)) & 0x02) == 2) { | 616 | * |
| 617 | /* move skb->data to current_tx_ptr payload */ | 617 | * Only if data buffer is ODD WORD alignment, we do not |
| 618 | data = (unsigned int)(skb->data) - 2; | 618 | * need to memcpy |
| 619 | *((unsigned short *)data) = (unsigned short)(skb->len); | 619 | */ |
| 620 | current_tx_ptr->desc_a.start_addr = (unsigned long)data; | 620 | u32 data_align = (u32)(skb->data) & 0x3; |
| 621 | /* this is important! */ | 621 | if (data_align == 0x2) { |
| 622 | blackfin_dcache_flush_range(data, (data + (skb->len)) + 2); | 622 | /* move skb->data to current_tx_ptr payload */ |
| 623 | 623 | data = (u16 *)(skb->data) - 1; | |
| 624 | *data = (u16)(skb->len); | ||
| 625 | current_tx_ptr->desc_a.start_addr = (u32)data; | ||
| 626 | /* this is important! */ | ||
| 627 | blackfin_dcache_flush_range((u32)data, | ||
| 628 | (u32)((u8 *)data + skb->len + 4)); | ||
| 629 | } else { | ||
| 630 | *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); | ||
| 631 | memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, | ||
| 632 | skb->len); | ||
| 633 | current_tx_ptr->desc_a.start_addr = | ||
| 634 | (u32)current_tx_ptr->packet; | ||
| 635 | if (current_tx_ptr->status.status_word != 0) | ||
| 636 | current_tx_ptr->status.status_word = 0; | ||
| 637 | blackfin_dcache_flush_range( | ||
| 638 | (u32)current_tx_ptr->packet, | ||
| 639 | (u32)(current_tx_ptr->packet + skb->len + 2)); | ||
| 640 | } | ||
| 624 | } else { | 641 | } else { |
| 625 | *((unsigned short *)(current_tx_ptr->packet)) = | 642 | /* |
| 626 | (unsigned short)(skb->len); | 643 | * TXDWA feature is avaible to revision < 0.3 silicon of |
| 627 | memcpy((char *)(current_tx_ptr->packet + 2), skb->data, | 644 | * BF537 and always avaible to BF52x |
| 628 | (skb->len)); | 645 | */ |
| 629 | current_tx_ptr->desc_a.start_addr = | 646 | u32 data_align = (u32)(skb->data) & 0x3; |
| 630 | (unsigned long)current_tx_ptr->packet; | 647 | if (data_align == 0x0) { |
| 631 | if (current_tx_ptr->status.status_word != 0) | 648 | u16 sysctl = bfin_read_EMAC_SYSCTL(); |
| 632 | current_tx_ptr->status.status_word = 0; | 649 | sysctl |= TXDWA; |
| 633 | blackfin_dcache_flush_range((unsigned int)current_tx_ptr-> | 650 | bfin_write_EMAC_SYSCTL(sysctl); |
| 634 | packet, | 651 | |
| 635 | (unsigned int)(current_tx_ptr-> | 652 | /* move skb->data to current_tx_ptr payload */ |
| 636 | packet + skb->len) + | 653 | data = (u16 *)(skb->data) - 2; |
| 637 | 2); | 654 | *data = (u16)(skb->len); |
| 655 | current_tx_ptr->desc_a.start_addr = (u32)data; | ||
| 656 | /* this is important! */ | ||
| 657 | blackfin_dcache_flush_range( | ||
| 658 | (u32)data, | ||
| 659 | (u32)((u8 *)data + skb->len + 4)); | ||
| 660 | } else if (data_align == 0x2) { | ||
| 661 | u16 sysctl = bfin_read_EMAC_SYSCTL(); | ||
| 662 | sysctl &= ~TXDWA; | ||
| 663 | bfin_write_EMAC_SYSCTL(sysctl); | ||
| 664 | |||
| 665 | /* move skb->data to current_tx_ptr payload */ | ||
| 666 | data = (u16 *)(skb->data) - 1; | ||
| 667 | *data = (u16)(skb->len); | ||
| 668 | current_tx_ptr->desc_a.start_addr = (u32)data; | ||
| 669 | /* this is important! */ | ||
| 670 | blackfin_dcache_flush_range( | ||
| 671 | (u32)data, | ||
| 672 | (u32)((u8 *)data + skb->len + 4)); | ||
| 673 | } else { | ||
| 674 | u16 sysctl = bfin_read_EMAC_SYSCTL(); | ||
| 675 | sysctl &= ~TXDWA; | ||
| 676 | bfin_write_EMAC_SYSCTL(sysctl); | ||
| 677 | |||
| 678 | *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); | ||
| 679 | memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, | ||
| 680 | skb->len); | ||
| 681 | current_tx_ptr->desc_a.start_addr = | ||
| 682 | (u32)current_tx_ptr->packet; | ||
| 683 | if (current_tx_ptr->status.status_word != 0) | ||
| 684 | current_tx_ptr->status.status_word = 0; | ||
| 685 | blackfin_dcache_flush_range( | ||
| 686 | (u32)current_tx_ptr->packet, | ||
| 687 | (u32)(current_tx_ptr->packet + skb->len + 2)); | ||
| 688 | } | ||
| 638 | } | 689 | } |
| 639 | 690 | ||
| 640 | /* enable this packet's dma */ | 691 | /* enable this packet's dma */ |
