Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+77 −26
Original line number Diff line number Diff line
@@ -605,36 +605,87 @@ static void adjust_tx_list(void)
static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
				struct net_device *dev)
{
	unsigned int data;
	u16 *data;

	current_tx_ptr->skb = skb;

	if (ANOMALY_05000285) {
		/*
	 * Is skb->data always 16-bit aligned?
	 * Do we need to memcpy((char *)(tail->packet + 2), skb->data, len)?
		 * TXDWA feature is not avaible to older revision < 0.3 silicon
		 * 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 */
		data = (unsigned int)(skb->data) - 2;
		*((unsigned short *)data) = (unsigned short)(skb->len);
		current_tx_ptr->desc_a.start_addr = (unsigned long)data;
			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(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 {
		*((unsigned short *)(current_tx_ptr->packet)) =
		    (unsigned short)(skb->len);
		memcpy((char *)(current_tx_ptr->packet + 2), skb->data,
		       (skb->len));
			u16 sysctl = bfin_read_EMAC_SYSCTL();
			sysctl &= ~TXDWA;
			bfin_write_EMAC_SYSCTL(sysctl);

			*((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 =
		    (unsigned long)current_tx_ptr->packet;
				(u32)current_tx_ptr->packet;
			if (current_tx_ptr->status.status_word != 0)
				current_tx_ptr->status.status_word = 0;
		blackfin_dcache_flush_range((unsigned int)current_tx_ptr->
					    packet,
					    (unsigned int)(current_tx_ptr->
							   packet + skb->len) +
					    2);
			blackfin_dcache_flush_range(
				(u32)current_tx_ptr->packet,
				(u32)(current_tx_ptr->packet + skb->len + 2));
		}
	}

	/* enable this packet's dma */