Commit a50c0c05 authored by Bryan Wu's avatar Bryan Wu Committed by Jeff Garzik

Blackfin EMAC Driver: enable TXDWA new feature for new silicon (rev > 0.2)

Signed-off-by: default avatarBryan Wu <cooloney@kernel.org>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent d7b843d3
...@@ -605,36 +605,87 @@ adjust_head: ...@@ -605,36 +605,87 @@ adjust_head:
static int bfin_mac_hard_start_xmit(struct sk_buff *skb, static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
{ {
unsigned int data; u16 *data;
current_tx_ptr->skb = skb; current_tx_ptr->skb = skb;
if (ANOMALY_05000285) {
/* /*
* Is skb->data always 16-bit aligned? * TXDWA feature is not avaible to older revision < 0.3 silicon
* Do we need to memcpy((char *)(tail->packet + 2), skb->data, len)? * of BF537
*
* Only if data buffer is ODD WORD alignment, we do not
* need to memcpy
*/ */
if ((((unsigned int)(skb->data)) & 0x02) == 2) { u32 data_align = (u32)(skb->data) & 0x3;
if (data_align == 0x2) {
/* move skb->data to current_tx_ptr payload */ /* move skb->data to current_tx_ptr payload */
data = (unsigned int)(skb->data) - 2; data = (u16 *)(skb->data) - 1;
*((unsigned short *)data) = (unsigned short)(skb->len); *data = (u16)(skb->len);
current_tx_ptr->desc_a.start_addr = (unsigned long)data; current_tx_ptr->desc_a.start_addr = (u32)data;
/* this is important! */ /* this is important! */
blackfin_dcache_flush_range(data, (data + (skb->len)) + 2); blackfin_dcache_flush_range((u32)data,
(u32)((u8 *)data + skb->len + 4));
} else {
*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
skb->len);
current_tx_ptr->desc_a.start_addr =
(u32)current_tx_ptr->packet;
if (current_tx_ptr->status.status_word != 0)
current_tx_ptr->status.status_word = 0;
blackfin_dcache_flush_range(
(u32)current_tx_ptr->packet,
(u32)(current_tx_ptr->packet + skb->len + 2));
}
} else {
/*
* TXDWA feature is avaible to revision < 0.3 silicon of
* BF537 and always avaible to BF52x
*/
u32 data_align = (u32)(skb->data) & 0x3;
if (data_align == 0x0) {
u16 sysctl = bfin_read_EMAC_SYSCTL();
sysctl |= TXDWA;
bfin_write_EMAC_SYSCTL(sysctl);
/* move skb->data to current_tx_ptr payload */
data = (u16 *)(skb->data) - 2;
*data = (u16)(skb->len);
current_tx_ptr->desc_a.start_addr = (u32)data;
/* this is important! */
blackfin_dcache_flush_range(
(u32)data,
(u32)((u8 *)data + skb->len + 4));
} else if (data_align == 0x2) {
u16 sysctl = bfin_read_EMAC_SYSCTL();
sysctl &= ~TXDWA;
bfin_write_EMAC_SYSCTL(sysctl);
/* move skb->data to current_tx_ptr payload */
data = (u16 *)(skb->data) - 1;
*data = (u16)(skb->len);
current_tx_ptr->desc_a.start_addr = (u32)data;
/* this is important! */
blackfin_dcache_flush_range(
(u32)data,
(u32)((u8 *)data + skb->len + 4));
} else { } else {
*((unsigned short *)(current_tx_ptr->packet)) = u16 sysctl = bfin_read_EMAC_SYSCTL();
(unsigned short)(skb->len); sysctl &= ~TXDWA;
memcpy((char *)(current_tx_ptr->packet + 2), skb->data, bfin_write_EMAC_SYSCTL(sysctl);
(skb->len));
*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
skb->len);
current_tx_ptr->desc_a.start_addr = current_tx_ptr->desc_a.start_addr =
(unsigned long)current_tx_ptr->packet; (u32)current_tx_ptr->packet;
if (current_tx_ptr->status.status_word != 0) if (current_tx_ptr->status.status_word != 0)
current_tx_ptr->status.status_word = 0; current_tx_ptr->status.status_word = 0;
blackfin_dcache_flush_range((unsigned int)current_tx_ptr-> blackfin_dcache_flush_range(
packet, (u32)current_tx_ptr->packet,
(unsigned int)(current_tx_ptr-> (u32)(current_tx_ptr->packet + skb->len + 2));
packet + skb->len) + }
2);
} }
/* enable this packet's dma */ /* enable this packet's dma */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment