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 */ |