1e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu/* 22fb9d6f5a39d7753d2d2cc286079a94e92440bcdMike Frysinger * Blackfin On-Chip MAC Driver 3e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * 402460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang * Copyright 2004-2010 Analog Devices Inc. 5e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * 62fb9d6f5a39d7753d2d2cc286079a94e92440bcdMike Frysinger * Enter bugs at http://blackfin.uclinux.org/ 7e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * 82fb9d6f5a39d7753d2d2cc286079a94e92440bcdMike Frysinger * Licensed under the GPL-2 or later. 9e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu */ 10e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 11c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger#define DRV_VERSION "1.1" 12c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger#define DRV_DESC "Blackfin on-chip Ethernet MAC driver" 13c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger 14c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger 16e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/init.h> 17e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/module.h> 18e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/kernel.h> 19e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/sched.h> 20e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/slab.h> 21e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/delay.h> 22e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/timer.h> 23e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/errno.h> 24e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/irq.h> 25e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/io.h> 26e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/ioport.h> 27e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/crc32.h> 28e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/device.h> 29e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/spinlock.h> 30e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/mii.h> 31e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/netdevice.h> 32e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/etherdevice.h> 33679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu#include <linux/ethtool.h> 34e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/skbuff.h> 35e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/platform_device.h> 36e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 37e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <asm/dma.h> 38e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <linux/dma-mapping.h> 39e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 40fe92afedee23e1d91f0133360a24d2bf48270739Barry Song#include <asm/div64.h> 4198f672ca9978c6e5997dbe905c91a73593148a7eMike Frysinger#include <asm/dpmc.h> 42e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <asm/blackfin.h> 43e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <asm/cacheflush.h> 44e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include <asm/portmux.h> 453dcc1e7f9fd48f20beefd41a684cd471a96565c5David Howells#include <mach/pll.h> 46e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 47e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#include "bfin_mac.h" 48e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 49c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike FrysingerMODULE_AUTHOR("Bryan Wu, Luke Yang"); 50e190d6b140079c104ba57e5130a9b4ebea618e92Bryan WuMODULE_LICENSE("GPL"); 51e190d6b140079c104ba57e5130a9b4ebea618e92Bryan WuMODULE_DESCRIPTION(DRV_DESC); 5272abb46101fb5c47a9592914adb221b430ff26bdKay SieversMODULE_ALIAS("platform:bfin_mac"); 53e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 54e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#if defined(CONFIG_BFIN_MAC_USE_L1) 55118133e6580a0c912cda86109b6468b5ffe73f1cSonic Zhang# define bfin_mac_alloc(dma_handle, size, num) l1_data_sram_zalloc(size*num) 56118133e6580a0c912cda86109b6468b5ffe73f1cSonic Zhang# define bfin_mac_free(dma_handle, ptr, num) l1_data_sram_free(ptr) 57e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#else 58118133e6580a0c912cda86109b6468b5ffe73f1cSonic Zhang# define bfin_mac_alloc(dma_handle, size, num) \ 59118133e6580a0c912cda86109b6468b5ffe73f1cSonic Zhang dma_alloc_coherent(NULL, size*num, dma_handle, GFP_KERNEL) 60118133e6580a0c912cda86109b6468b5ffe73f1cSonic Zhang# define bfin_mac_free(dma_handle, ptr, num) \ 61118133e6580a0c912cda86109b6468b5ffe73f1cSonic Zhang dma_free_coherent(NULL, sizeof(*ptr)*num, ptr, dma_handle) 62e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#endif 63e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 64e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#define PKT_BUF_SZ 1580 65e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 66e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#define MAX_TIMEOUT_CNT 500 67e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 68e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu/* pointers to maintain transmit list */ 69e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wustatic struct net_dma_desc_tx *tx_list_head; 70e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wustatic struct net_dma_desc_tx *tx_list_tail; 71e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wustatic struct net_dma_desc_rx *rx_list_head; 72e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wustatic struct net_dma_desc_rx *rx_list_tail; 73e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wustatic struct net_dma_desc_rx *current_rx_ptr; 74e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wustatic struct net_dma_desc_tx *current_tx_ptr; 75e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wustatic struct net_dma_desc_tx *tx_desc; 76e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wustatic struct net_dma_desc_rx *rx_desc; 77e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 78e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wustatic void desc_list_free(void) 79e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 80e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu struct net_dma_desc_rx *r; 81e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu struct net_dma_desc_tx *t; 82e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu int i; 83e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#if !defined(CONFIG_BFIN_MAC_USE_L1) 84e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu dma_addr_t dma_handle = 0; 85e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#endif 86e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 87e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (tx_desc) { 88e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu t = tx_list_head; 89e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu for (i = 0; i < CONFIG_BFIN_TX_DESC_NUM; i++) { 90e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (t) { 91e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (t->skb) { 92e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu dev_kfree_skb(t->skb); 93e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu t->skb = NULL; 94e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 95e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu t = t->next; 96e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 97e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 98118133e6580a0c912cda86109b6468b5ffe73f1cSonic Zhang bfin_mac_free(dma_handle, tx_desc, CONFIG_BFIN_TX_DESC_NUM); 99e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 100e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 101e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (rx_desc) { 102e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu r = rx_list_head; 103e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu for (i = 0; i < CONFIG_BFIN_RX_DESC_NUM; i++) { 104e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (r) { 105e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (r->skb) { 106e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu dev_kfree_skb(r->skb); 107e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu r->skb = NULL; 108e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 109e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu r = r->next; 110e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 111e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 112118133e6580a0c912cda86109b6468b5ffe73f1cSonic Zhang bfin_mac_free(dma_handle, rx_desc, CONFIG_BFIN_RX_DESC_NUM); 113e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 114e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 115e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1161ab0d2ec9aeb4489c05158e8a2b00bad89f67e03Pradeep A. Dalvistatic int desc_list_init(struct net_device *dev) 117e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 118e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu int i; 119e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu struct sk_buff *new_skb; 120e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#if !defined(CONFIG_BFIN_MAC_USE_L1) 121e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* 122e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * This dma_handle is useless in Blackfin dma_alloc_coherent(). 123e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * The real dma handler is the return value of dma_alloc_coherent(). 124e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu */ 125e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu dma_addr_t dma_handle; 126e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#endif 127e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 128e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu tx_desc = bfin_mac_alloc(&dma_handle, 129118133e6580a0c912cda86109b6468b5ffe73f1cSonic Zhang sizeof(struct net_dma_desc_tx), 130e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu CONFIG_BFIN_TX_DESC_NUM); 131e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (tx_desc == NULL) 132e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu goto init_error; 133e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 134e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu rx_desc = bfin_mac_alloc(&dma_handle, 135118133e6580a0c912cda86109b6468b5ffe73f1cSonic Zhang sizeof(struct net_dma_desc_rx), 136e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu CONFIG_BFIN_RX_DESC_NUM); 137e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (rx_desc == NULL) 138e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu goto init_error; 139e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 140e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* init tx_list */ 141e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu tx_list_head = tx_list_tail = tx_desc; 142e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 143e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu for (i = 0; i < CONFIG_BFIN_TX_DESC_NUM; i++) { 144e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu struct net_dma_desc_tx *t = tx_desc + i; 145e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu struct dma_descriptor *a = &(t->desc_a); 146e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu struct dma_descriptor *b = &(t->desc_b); 147e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 148e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* 149e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * disable DMA 150e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * read from memory WNR = 0 151e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * wordsize is 32 bits 152e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * 6 half words is desc size 153e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * large desc flow 154e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu */ 155e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu a->config = WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE; 156e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu a->start_addr = (unsigned long)t->packet; 157e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu a->x_count = 0; 158e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu a->next_dma_desc = b; 159e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 160e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* 161e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * enabled DMA 162e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * write to memory WNR = 1 163e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * wordsize is 32 bits 164e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * disable interrupt 165e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * 6 half words is desc size 166e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * large desc flow 167e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu */ 168e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu b->config = DMAEN | WNR | WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE; 169e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu b->start_addr = (unsigned long)(&(t->status)); 170e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu b->x_count = 0; 171e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 172e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu t->skb = NULL; 173e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu tx_list_tail->desc_b.next_dma_desc = a; 174e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu tx_list_tail->next = t; 175e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu tx_list_tail = t; 176e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 177e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu tx_list_tail->next = tx_list_head; /* tx_list is a circle */ 178e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu tx_list_tail->desc_b.next_dma_desc = &(tx_list_head->desc_a); 179e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu current_tx_ptr = tx_list_head; 180e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 181e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* init rx_list */ 182e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu rx_list_head = rx_list_tail = rx_desc; 183e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 184e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu for (i = 0; i < CONFIG_BFIN_RX_DESC_NUM; i++) { 185e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu struct net_dma_desc_rx *r = rx_desc + i; 186e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu struct dma_descriptor *a = &(r->desc_a); 187e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu struct dma_descriptor *b = &(r->desc_b); 188e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 189e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* allocate a new skb for next time receive */ 1901ab0d2ec9aeb4489c05158e8a2b00bad89f67e03Pradeep A. Dalvi new_skb = netdev_alloc_skb(dev, PKT_BUF_SZ + NET_IP_ALIGN); 191e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (!new_skb) { 192c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger pr_notice("init: low on mem - packet dropped\n"); 193e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu goto init_error; 194e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 195015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich skb_reserve(new_skb, NET_IP_ALIGN); 196f6e1e4f3e511589dd0c47d42b870501659e7195fSonic Zhang /* Invidate the data cache of skb->data range when it is write back 197f6e1e4f3e511589dd0c47d42b870501659e7195fSonic Zhang * cache. It will prevent overwritting the new data from DMA 198f6e1e4f3e511589dd0c47d42b870501659e7195fSonic Zhang */ 199f6e1e4f3e511589dd0c47d42b870501659e7195fSonic Zhang blackfin_dcache_invalidate_range((unsigned long)new_skb->head, 200f6e1e4f3e511589dd0c47d42b870501659e7195fSonic Zhang (unsigned long)new_skb->end); 201e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu r->skb = new_skb; 202e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 203e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* 204e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * enabled DMA 205e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * write to memory WNR = 1 206e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * wordsize is 32 bits 207e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * disable interrupt 208e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * 6 half words is desc size 209e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * large desc flow 210e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu */ 211e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu a->config = DMAEN | WNR | WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE; 212e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* since RXDWA is enabled */ 213e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu a->start_addr = (unsigned long)new_skb->data - 2; 214e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu a->x_count = 0; 215e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu a->next_dma_desc = b; 216e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 217e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* 218e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * enabled DMA 219e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * write to memory WNR = 1 220e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * wordsize is 32 bits 221e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * enable interrupt 222e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * 6 half words is desc size 223e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * large desc flow 224e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu */ 225e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu b->config = DMAEN | WNR | WDSIZE_32 | DI_EN | 226e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu NDSIZE_6 | DMAFLOW_LARGE; 227e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu b->start_addr = (unsigned long)(&(r->status)); 228e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu b->x_count = 0; 229e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 230e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu rx_list_tail->desc_b.next_dma_desc = a; 231e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu rx_list_tail->next = r; 232e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu rx_list_tail = r; 233e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 234e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu rx_list_tail->next = rx_list_head; /* rx_list is a circle */ 235e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu rx_list_tail->desc_b.next_dma_desc = &(rx_list_head->desc_a); 236e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu current_rx_ptr = rx_list_head; 237e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 238e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu return 0; 239e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 240e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wuinit_error: 241e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu desc_list_free(); 242c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger pr_err("kmalloc failed\n"); 243e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu return -ENOMEM; 244e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 245e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 246e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 247e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/ 248e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 2494ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu/* 2504ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu * MII operations 2514ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu */ 252e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu/* Wait until the previous MDC/MDIO transaction has completed */ 2532bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysingerstatic int bfin_mdio_poll(void) 254e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 255e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu int timeout_cnt = MAX_TIMEOUT_CNT; 256e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 257e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* poll the STABUSY bit */ 258e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu while ((bfin_read_EMAC_STAADD()) & STABUSY) { 2596db9e4617e9bdf9d31fbea165b10cb95318adf8cBryan Wu udelay(1); 260e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (timeout_cnt-- < 0) { 261c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger pr_err("wait MDC/MDIO transaction to complete timeout\n"); 2622bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger return -ETIMEDOUT; 263e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 264e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 2652bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger 2662bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger return 0; 267e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 268e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 269e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu/* Read an off-chip register in a PHY through the MDC/MDIO port */ 2700ed0563e14dcb9986241d30f08ecd33f9bcc3572Adrian Bunkstatic int bfin_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum) 271e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 2722bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger int ret; 2732bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger 2742bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger ret = bfin_mdio_poll(); 2752bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger if (ret) 2762bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger return ret; 2774ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 278e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* read mode */ 2794ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) | 2804ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu SET_REGAD((u16) regnum) | 281e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu STABUSY); 282e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 2832bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger ret = bfin_mdio_poll(); 2842bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger if (ret) 2852bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger return ret; 2864ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 2874ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu return (int) bfin_read_EMAC_STADAT(); 288e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 289e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 290e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu/* Write an off-chip register in a PHY through the MDC/MDIO port */ 2910ed0563e14dcb9986241d30f08ecd33f9bcc3572Adrian Bunkstatic int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, 2920ed0563e14dcb9986241d30f08ecd33f9bcc3572Adrian Bunk u16 value) 293e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 2942bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger int ret; 2952bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger 2962bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger ret = bfin_mdio_poll(); 2972bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger if (ret) 2982bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger return ret; 2994ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 3004ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu bfin_write_EMAC_STADAT((u32) value); 301e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 302e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* write mode */ 3034ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) | 3044ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu SET_REGAD((u16) regnum) | 305e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu STAOP | 306e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu STABUSY); 307e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 3082bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger return bfin_mdio_poll(); 309e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 310e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 3110ed0563e14dcb9986241d30f08ecd33f9bcc3572Adrian Bunkstatic int bfin_mdiobus_reset(struct mii_bus *bus) 312e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 3134ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu return 0; 314e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 315e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 3167ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wustatic void bfin_mac_adjust_link(struct net_device *dev) 317e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 3187ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu struct bfin_mac_local *lp = netdev_priv(dev); 3194ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu struct phy_device *phydev = lp->phydev; 3204ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu unsigned long flags; 3214ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu int new_state = 0; 3224ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 3234ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu spin_lock_irqsave(&lp->lock, flags); 3244ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu if (phydev->link) { 3254ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu /* Now we make sure that we can be in full duplex mode. 3264ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu * If not, we operate in half-duplex mode. */ 3274ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu if (phydev->duplex != lp->old_duplex) { 3284ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu u32 opmode = bfin_read_EMAC_OPMODE(); 3294ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu new_state = 1; 3304ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 3314ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu if (phydev->duplex) 3324ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu opmode |= FDMODE; 3334ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu else 3344ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu opmode &= ~(FDMODE); 3354ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 3364ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu bfin_write_EMAC_OPMODE(opmode); 3374ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu lp->old_duplex = phydev->duplex; 3384ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu } 339e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 3404ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu if (phydev->speed != lp->old_speed) { 34102460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang if (phydev->interface == PHY_INTERFACE_MODE_RMII) { 34202460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang u32 opmode = bfin_read_EMAC_OPMODE(); 34302460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang switch (phydev->speed) { 34402460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang case 10: 34502460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang opmode |= RMII_10; 34602460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang break; 34702460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang case 100: 34802460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang opmode &= ~RMII_10; 34902460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang break; 35002460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang default: 351c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger netdev_warn(dev, 352c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger "Ack! Speed (%d) is not 10/100!\n", 353c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger phydev->speed); 35402460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang break; 35502460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang } 35602460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang bfin_write_EMAC_OPMODE(opmode); 3574ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu } 358e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 3594ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu new_state = 1; 3604ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu lp->old_speed = phydev->speed; 3614ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu } 362e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 3634ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu if (!lp->old_link) { 3644ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu new_state = 1; 3654ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu lp->old_link = 1; 3664ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu } 3674ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu } else if (lp->old_link) { 3684ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu new_state = 1; 3694ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu lp->old_link = 0; 3704ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu lp->old_speed = 0; 3714ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu lp->old_duplex = -1; 372e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 373e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 3744ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu if (new_state) { 3754ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu u32 opmode = bfin_read_EMAC_OPMODE(); 3764ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu phy_print_status(phydev); 3774ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu pr_debug("EMAC_OPMODE = 0x%08x\n", opmode); 378e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 3794ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 3804ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu spin_unlock_irqrestore(&lp->lock, flags); 381e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 382e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 3837cc8f38188133e0c278b9f207d63c2c2b4d98236Bryan Wu/* MDC = 2.5 MHz */ 3847cc8f38188133e0c278b9f207d63c2c2b4d98236Bryan Wu#define MDC_CLK 2500000 3857cc8f38188133e0c278b9f207d63c2c2b4d98236Bryan Wu 38602460d08930656b3a50381cfb119864efcd4eef9Sonic Zhangstatic int mii_probe(struct net_device *dev, int phy_mode) 387e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 3887ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu struct bfin_mac_local *lp = netdev_priv(dev); 3894ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu struct phy_device *phydev = NULL; 3904ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu unsigned short sysctl; 3914ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu int i; 3927cc8f38188133e0c278b9f207d63c2c2b4d98236Bryan Wu u32 sclk, mdc_div; 393e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 3944ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu /* Enable PHY output early */ 39598f672ca9978c6e5997dbe905c91a73593148a7eMike Frysinger if (!(bfin_read_VR_CTL() & CLKBUFOE)) 39698f672ca9978c6e5997dbe905c91a73593148a7eMike Frysinger bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE); 397e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 3987cc8f38188133e0c278b9f207d63c2c2b4d98236Bryan Wu sclk = get_sclk(); 3997cc8f38188133e0c278b9f207d63c2c2b4d98236Bryan Wu mdc_div = ((sclk / MDC_CLK) / 2) - 1; 4007cc8f38188133e0c278b9f207d63c2c2b4d98236Bryan Wu 4014ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu sysctl = bfin_read_EMAC_SYSCTL(); 4029dc7f30e3bac329998a2a9bb814bd0abc7cb58e2Bryan Wu sysctl = (sysctl & ~MDCDIV) | SET_MDCDIV(mdc_div); 403e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_EMAC_SYSCTL(sysctl); 404e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 40502460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang /* search for connected PHY device */ 40602460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang for (i = 0; i < PHY_MAX_ADDR; ++i) { 407298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek struct phy_device *const tmp_phydev = lp->mii_bus->phy_map[i]; 408e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 4094ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu if (!tmp_phydev) 4104ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu continue; /* no PHY here... */ 411e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 4124ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu phydev = tmp_phydev; 4134ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu break; /* found it */ 4144ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu } 4154ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 4164ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu /* now we are supposed to have a proper phydev, to attach to... */ 4174ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu if (!phydev) { 418c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger netdev_err(dev, "no phy device found\n"); 4194ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu return -ENODEV; 420e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 421e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 42202460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang if (phy_mode != PHY_INTERFACE_MODE_RMII && 42302460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang phy_mode != PHY_INTERFACE_MODE_MII) { 424c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger netdev_err(dev, "invalid phy interface mode\n"); 42502460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang return -EINVAL; 42602460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang } 42702460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang 428c23135573f37facd18edb2e8e8512c67928c54acKay Sievers phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link, 42902460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang 0, phy_mode); 430e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 4314ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu if (IS_ERR(phydev)) { 432c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger netdev_err(dev, "could not attach PHY\n"); 4334ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu return PTR_ERR(phydev); 4344ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu } 4354ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 4364ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu /* mask with MAC supported features */ 4374ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu phydev->supported &= (SUPPORTED_10baseT_Half 4384ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu | SUPPORTED_10baseT_Full 4394ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu | SUPPORTED_100baseT_Half 4404ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu | SUPPORTED_100baseT_Full 4414ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu | SUPPORTED_Autoneg 4424ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu | SUPPORTED_Pause | SUPPORTED_Asym_Pause 4434ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu | SUPPORTED_MII 4444ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu | SUPPORTED_TP); 4454ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 4464ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu phydev->advertising = phydev->supported; 4474ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 4484ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu lp->old_link = 0; 4494ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu lp->old_speed = 0; 4504ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu lp->old_duplex = -1; 4514ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu lp->phydev = phydev; 4524ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 453c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger pr_info("attached PHY driver [%s] " 454c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger "(mii_bus:phy_addr=%s, irq=%d, mdc_clk=%dHz(mdc_div=%d)@sclk=%dMHz)\n", 455c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger phydev->drv->name, dev_name(&phydev->dev), phydev->irq, 456c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger MDC_CLK, mdc_div, sclk/1000000); 4574ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 4584ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu return 0; 4594ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu} 4604ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 461679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu/* 462679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu * Ethtool support 463679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu */ 464679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu 46553fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich/* 46653fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich * interrupt routine for magic packet wakeup 46753fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich */ 46853fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerichstatic irqreturn_t bfin_mac_wake_interrupt(int irq, void *dev_id) 46953fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich{ 47053fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich return IRQ_HANDLED; 47153fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich} 47253fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich 473679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wustatic int 474679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wubfin_mac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) 475679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu{ 476679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu struct bfin_mac_local *lp = netdev_priv(dev); 477679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu 478679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu if (lp->phydev) 479679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu return phy_ethtool_gset(lp->phydev, cmd); 480679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu 481679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu return -EINVAL; 482679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu} 483679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu 484679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wustatic int 485679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wubfin_mac_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd) 486679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu{ 487679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu struct bfin_mac_local *lp = netdev_priv(dev); 488679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu 489679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu if (!capable(CAP_NET_ADMIN)) 490679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu return -EPERM; 491679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu 492679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu if (lp->phydev) 493679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu return phy_ethtool_sset(lp->phydev, cmd); 494679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu 495679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu return -EINVAL; 496679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu} 497679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu 498679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wustatic void bfin_mac_ethtool_getdrvinfo(struct net_device *dev, 499679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu struct ethtool_drvinfo *info) 500679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu{ 501c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger strcpy(info->driver, KBUILD_MODNAME); 502679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu strcpy(info->version, DRV_VERSION); 503679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu strcpy(info->fw_version, "N/A"); 504c23135573f37facd18edb2e8e8512c67928c54acKay Sievers strcpy(info->bus_info, dev_name(&dev->dev)); 505679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu} 506679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu 50753fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerichstatic void bfin_mac_ethtool_getwol(struct net_device *dev, 50853fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich struct ethtool_wolinfo *wolinfo) 50953fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich{ 51053fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich struct bfin_mac_local *lp = netdev_priv(dev); 51153fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich 51253fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich wolinfo->supported = WAKE_MAGIC; 51353fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich wolinfo->wolopts = lp->wol; 51453fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich} 51553fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich 51653fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerichstatic int bfin_mac_ethtool_setwol(struct net_device *dev, 51753fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich struct ethtool_wolinfo *wolinfo) 51853fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich{ 51953fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich struct bfin_mac_local *lp = netdev_priv(dev); 52053fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich int rc; 52153fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich 52253fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich if (wolinfo->wolopts & (WAKE_MAGICSECURE | 52353fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich WAKE_UCAST | 52453fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich WAKE_MCAST | 52553fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich WAKE_BCAST | 52653fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich WAKE_ARP)) 52753fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich return -EOPNOTSUPP; 52853fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich 52953fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich lp->wol = wolinfo->wolopts; 53053fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich 53153fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich if (lp->wol && !lp->irq_wake_requested) { 53253fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich /* register wake irq handler */ 53353fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich rc = request_irq(IRQ_MAC_WAKEDET, bfin_mac_wake_interrupt, 53453fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich IRQF_DISABLED, "EMAC_WAKE", dev); 53553fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich if (rc) 53653fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich return rc; 53753fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich lp->irq_wake_requested = true; 53853fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich } 53953fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich 54053fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich if (!lp->wol && lp->irq_wake_requested) { 54153fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich free_irq(IRQ_MAC_WAKEDET, dev); 54253fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich lp->irq_wake_requested = false; 54353fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich } 54453fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich 54553fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich /* Make sure the PHY driver doesn't suspend */ 54653fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich device_init_wakeup(&dev->dev, lp->wol); 54753fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich 54853fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich return 0; 54953fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich} 55053fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich 5510fc0b732eaa38beb93a6fb62f77c7bd9622c76ecStephen Hemmingerstatic const struct ethtool_ops bfin_mac_ethtool_ops = { 552679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu .get_settings = bfin_mac_ethtool_getsettings, 553679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu .set_settings = bfin_mac_ethtool_setsettings, 554679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu .get_link = ethtool_op_get_link, 555679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu .get_drvinfo = bfin_mac_ethtool_getdrvinfo, 55653fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich .get_wol = bfin_mac_ethtool_getwol, 55753fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich .set_wol = bfin_mac_ethtool_setwol, 558679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu}; 559679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu 5604ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu/**************************************************************************/ 5615ca1bb5aceb0bccf532ffc21588585a925cdee20Mike Frysingerstatic void setup_system_regs(struct net_device *dev) 5624ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu{ 56302460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang struct bfin_mac_local *lp = netdev_priv(dev); 56402460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang int i; 5654ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu unsigned short sysctl; 5664ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 5674ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu /* 5684ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu * Odd word alignment for Receive Frame DMA word 5694ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu * Configure checksum support and rcve frame word alignment 5704ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu */ 5714ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu sysctl = bfin_read_EMAC_SYSCTL(); 57202460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang /* 57302460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang * check if interrupt is requested for any PHY, 57402460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang * enable PHY interrupt only if needed 57502460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang */ 57602460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang for (i = 0; i < PHY_MAX_ADDR; ++i) 57702460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang if (lp->mii_bus->irq[i] != PHY_POLL) 57802460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang break; 57902460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang if (i < PHY_MAX_ADDR) 58002460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang sysctl |= PHYIE; 581812a9de71512e5da6f3177f7249a2448b6a4322eSonic Zhang sysctl |= RXDWA; 5824ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu#if defined(BFIN_MAC_CSUM_OFFLOAD) 583812a9de71512e5da6f3177f7249a2448b6a4322eSonic Zhang sysctl |= RXCKS; 5844ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu#else 585812a9de71512e5da6f3177f7249a2448b6a4322eSonic Zhang sysctl &= ~RXCKS; 5864ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu#endif 5874ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu bfin_write_EMAC_SYSCTL(sysctl); 588e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 589e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_EMAC_MMC_CTL(RSTC | CROLL); 590e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 591c599bd6b9ac8926b03e6bf332a8c14ae2ffb43a3Mike Frysinger /* Set vlan regs to let 1522 bytes long packets pass through */ 592c599bd6b9ac8926b03e6bf332a8c14ae2ffb43a3Mike Frysinger bfin_write_EMAC_VLAN1(lp->vlan1_mask); 593c599bd6b9ac8926b03e6bf332a8c14ae2ffb43a3Mike Frysinger bfin_write_EMAC_VLAN2(lp->vlan2_mask); 594c599bd6b9ac8926b03e6bf332a8c14ae2ffb43a3Mike Frysinger 595e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* Initialize the TX DMA channel registers */ 596e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA2_X_COUNT(0); 597e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA2_X_MODIFY(4); 598e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA2_Y_COUNT(0); 599e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA2_Y_MODIFY(0); 600e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 601e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* Initialize the RX DMA channel registers */ 602e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA1_X_COUNT(0); 603e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA1_X_MODIFY(4); 604e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA1_Y_COUNT(0); 605e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA1_Y_MODIFY(0); 606e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 607e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 60873f83182862a2c9113421720997c75ee939902f8Alex Landaustatic void setup_mac_addr(u8 *mac_addr) 609e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 610e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu u32 addr_low = le32_to_cpu(*(__le32 *) & mac_addr[0]); 611e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu u16 addr_hi = le16_to_cpu(*(__le16 *) & mac_addr[4]); 612e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 613e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* this depends on a little-endian machine */ 614e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_EMAC_ADDRLO(addr_low); 615e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_EMAC_ADDRHI(addr_hi); 616e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 617e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 6187ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wustatic int bfin_mac_set_mac_address(struct net_device *dev, void *p) 61973f83182862a2c9113421720997c75ee939902f8Alex Landau{ 62073f83182862a2c9113421720997c75ee939902f8Alex Landau struct sockaddr *addr = p; 62173f83182862a2c9113421720997c75ee939902f8Alex Landau if (netif_running(dev)) 62273f83182862a2c9113421720997c75ee939902f8Alex Landau return -EBUSY; 62373f83182862a2c9113421720997c75ee939902f8Alex Landau memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); 6245055d2f236e1495d68c468eeb684fd5789673f1dDanny Kukawka dev->addr_assign_type &= ~NET_ADDR_RANDOM; 62573f83182862a2c9113421720997c75ee939902f8Alex Landau setup_mac_addr(dev->dev_addr); 62673f83182862a2c9113421720997c75ee939902f8Alex Landau return 0; 62773f83182862a2c9113421720997c75ee939902f8Alex Landau} 62873f83182862a2c9113421720997c75ee939902f8Alex Landau 629fe92afedee23e1d91f0133360a24d2bf48270739Barry Song#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP 630fe92afedee23e1d91f0133360a24d2bf48270739Barry Song#define bfin_mac_hwtstamp_is_none(cfg) ((cfg) == HWTSTAMP_FILTER_NONE) 631fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 632fe92afedee23e1d91f0133360a24d2bf48270739Barry Songstatic int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, 633fe92afedee23e1d91f0133360a24d2bf48270739Barry Song struct ifreq *ifr, int cmd) 634fe92afedee23e1d91f0133360a24d2bf48270739Barry Song{ 635fe92afedee23e1d91f0133360a24d2bf48270739Barry Song struct hwtstamp_config config; 636fe92afedee23e1d91f0133360a24d2bf48270739Barry Song struct bfin_mac_local *lp = netdev_priv(netdev); 637fe92afedee23e1d91f0133360a24d2bf48270739Barry Song u16 ptpctl; 638fe92afedee23e1d91f0133360a24d2bf48270739Barry Song u32 ptpfv1, ptpfv2, ptpfv3, ptpfoff; 639fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 640fe92afedee23e1d91f0133360a24d2bf48270739Barry Song if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) 641fe92afedee23e1d91f0133360a24d2bf48270739Barry Song return -EFAULT; 642fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 643fe92afedee23e1d91f0133360a24d2bf48270739Barry Song pr_debug("%s config flag:0x%x, tx_type:0x%x, rx_filter:0x%x\n", 644fe92afedee23e1d91f0133360a24d2bf48270739Barry Song __func__, config.flags, config.tx_type, config.rx_filter); 645fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 646fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* reserved for future extensions */ 647fe92afedee23e1d91f0133360a24d2bf48270739Barry Song if (config.flags) 648fe92afedee23e1d91f0133360a24d2bf48270739Barry Song return -EINVAL; 649fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 650fe92afedee23e1d91f0133360a24d2bf48270739Barry Song if ((config.tx_type != HWTSTAMP_TX_OFF) && 651fe92afedee23e1d91f0133360a24d2bf48270739Barry Song (config.tx_type != HWTSTAMP_TX_ON)) 652fe92afedee23e1d91f0133360a24d2bf48270739Barry Song return -ERANGE; 653fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 654fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpctl = bfin_read_EMAC_PTP_CTL(); 655fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 656fe92afedee23e1d91f0133360a24d2bf48270739Barry Song switch (config.rx_filter) { 657fe92afedee23e1d91f0133360a24d2bf48270739Barry Song case HWTSTAMP_FILTER_NONE: 658fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 659fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * Dont allow any timestamping 660fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 661fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpfv3 = 0xFFFFFFFF; 662fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_FV3(ptpfv3); 663fe92afedee23e1d91f0133360a24d2bf48270739Barry Song break; 664fe92afedee23e1d91f0133360a24d2bf48270739Barry Song case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 665fe92afedee23e1d91f0133360a24d2bf48270739Barry Song case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: 666fe92afedee23e1d91f0133360a24d2bf48270739Barry Song case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: 667fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 668fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * Clear the five comparison mask bits (bits[12:8]) in EMAC_PTP_CTL) 669fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * to enable all the field matches. 670fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 671fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpctl &= ~0x1F00; 672fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_CTL(ptpctl); 673fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 674fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * Keep the default values of the EMAC_PTP_FOFF register. 675fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 676fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpfoff = 0x4A24170C; 677fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_FOFF(ptpfoff); 678fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 679fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2 680fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * registers. 681fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 682fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpfv1 = 0x11040800; 683fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_FV1(ptpfv1); 684fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpfv2 = 0x0140013F; 685fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_FV2(ptpfv2); 686fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 687fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * The default value (0xFFFC) allows the timestamping of both 688fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * received Sync messages and Delay_Req messages. 689fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 690fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpfv3 = 0xFFFFFFFC; 691fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_FV3(ptpfv3); 692fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 693fe92afedee23e1d91f0133360a24d2bf48270739Barry Song config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; 694fe92afedee23e1d91f0133360a24d2bf48270739Barry Song break; 695fe92afedee23e1d91f0133360a24d2bf48270739Barry Song case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 696fe92afedee23e1d91f0133360a24d2bf48270739Barry Song case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 697fe92afedee23e1d91f0133360a24d2bf48270739Barry Song case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 698fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* Clear all five comparison mask bits (bits[12:8]) in the 699fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * EMAC_PTP_CTL register to enable all the field matches. 700fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 701fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpctl &= ~0x1F00; 702fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_CTL(ptpctl); 703fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 704fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * Keep the default values of the EMAC_PTP_FOFF register, except set 705fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * the PTPCOF field to 0x2A. 706fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 707fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpfoff = 0x2A24170C; 708fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_FOFF(ptpfoff); 709fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 710fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2 711fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * registers. 712fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 713fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpfv1 = 0x11040800; 714fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_FV1(ptpfv1); 715fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpfv2 = 0x0140013F; 716fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_FV2(ptpfv2); 717fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 718fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * To allow the timestamping of Pdelay_Req and Pdelay_Resp, set 719fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * the value to 0xFFF0. 720fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 721fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpfv3 = 0xFFFFFFF0; 722fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_FV3(ptpfv3); 723fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 724fe92afedee23e1d91f0133360a24d2bf48270739Barry Song config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; 725fe92afedee23e1d91f0133360a24d2bf48270739Barry Song break; 726fe92afedee23e1d91f0133360a24d2bf48270739Barry Song case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 727fe92afedee23e1d91f0133360a24d2bf48270739Barry Song case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 728fe92afedee23e1d91f0133360a24d2bf48270739Barry Song case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 729fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 730fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * Clear bits 8 and 12 of the EMAC_PTP_CTL register to enable only the 731fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * EFTM and PTPCM field comparison. 732fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 733fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpctl &= ~0x1100; 734fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_CTL(ptpctl); 735fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 736fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * Keep the default values of all the fields of the EMAC_PTP_FOFF 737fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * register, except set the PTPCOF field to 0x0E. 738fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 739fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpfoff = 0x0E24170C; 740fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_FOFF(ptpfoff); 741fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 742fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * Program bits [15:0] of the EMAC_PTP_FV1 register to 0x88F7, which 743fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * corresponds to PTP messages on the MAC layer. 744fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 745fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpfv1 = 0x110488F7; 746fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_FV1(ptpfv1); 747fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpfv2 = 0x0140013F; 748fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_FV2(ptpfv2); 749fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 750fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * To allow the timestamping of Pdelay_Req and Pdelay_Resp 751fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * messages, set the value to 0xFFF0. 752fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 753fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpfv3 = 0xFFFFFFF0; 754fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_FV3(ptpfv3); 755fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 756fe92afedee23e1d91f0133360a24d2bf48270739Barry Song config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; 757fe92afedee23e1d91f0133360a24d2bf48270739Barry Song break; 758fe92afedee23e1d91f0133360a24d2bf48270739Barry Song default: 759fe92afedee23e1d91f0133360a24d2bf48270739Barry Song return -ERANGE; 760fe92afedee23e1d91f0133360a24d2bf48270739Barry Song } 761fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 762fe92afedee23e1d91f0133360a24d2bf48270739Barry Song if (config.tx_type == HWTSTAMP_TX_OFF && 763fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_mac_hwtstamp_is_none(config.rx_filter)) { 764fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpctl &= ~PTP_EN; 765fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_CTL(ptpctl); 766fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 767fe92afedee23e1d91f0133360a24d2bf48270739Barry Song SSYNC(); 768fe92afedee23e1d91f0133360a24d2bf48270739Barry Song } else { 769fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ptpctl |= PTP_EN; 770fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_CTL(ptpctl); 771fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 772fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 773fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * clear any existing timestamp 774fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 775fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_read_EMAC_PTP_RXSNAPLO(); 776fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_read_EMAC_PTP_RXSNAPHI(); 777fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 778fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_read_EMAC_PTP_TXSNAPLO(); 779fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_read_EMAC_PTP_TXSNAPHI(); 780fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 781fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 782fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * Set registers so that rollover occurs soon to test this. 783fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 784fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_TIMELO(0x00000000); 785fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_TIMEHI(0xFF800000); 786fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 787fe92afedee23e1d91f0133360a24d2bf48270739Barry Song SSYNC(); 788fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 789fe92afedee23e1d91f0133360a24d2bf48270739Barry Song lp->compare.last_update = 0; 790fe92afedee23e1d91f0133360a24d2bf48270739Barry Song timecounter_init(&lp->clock, 791fe92afedee23e1d91f0133360a24d2bf48270739Barry Song &lp->cycles, 792fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ktime_to_ns(ktime_get_real())); 793fe92afedee23e1d91f0133360a24d2bf48270739Barry Song timecompare_update(&lp->compare, 0); 794fe92afedee23e1d91f0133360a24d2bf48270739Barry Song } 795fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 796fe92afedee23e1d91f0133360a24d2bf48270739Barry Song lp->stamp_cfg = config; 797fe92afedee23e1d91f0133360a24d2bf48270739Barry Song return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? 798fe92afedee23e1d91f0133360a24d2bf48270739Barry Song -EFAULT : 0; 799fe92afedee23e1d91f0133360a24d2bf48270739Barry Song} 800fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 801fe92afedee23e1d91f0133360a24d2bf48270739Barry Songstatic void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompare *cmp) 802fe92afedee23e1d91f0133360a24d2bf48270739Barry Song{ 803fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ktime_t sys = ktime_get_real(); 804fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 805fe92afedee23e1d91f0133360a24d2bf48270739Barry Song pr_debug("%s %s hardware:%d,%d transform system:%d,%d system:%d,%d, cmp:%lld, %lld\n", 806fe92afedee23e1d91f0133360a24d2bf48270739Barry Song __func__, s, hw->tv.sec, hw->tv.nsec, ts->tv.sec, ts->tv.nsec, sys.tv.sec, 807fe92afedee23e1d91f0133360a24d2bf48270739Barry Song sys.tv.nsec, cmp->offset, cmp->skew); 808fe92afedee23e1d91f0133360a24d2bf48270739Barry Song} 809fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 810fe92afedee23e1d91f0133360a24d2bf48270739Barry Songstatic void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) 811fe92afedee23e1d91f0133360a24d2bf48270739Barry Song{ 812fe92afedee23e1d91f0133360a24d2bf48270739Barry Song struct bfin_mac_local *lp = netdev_priv(netdev); 813fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 8142244d07bfa2097cb00600da91c715a8aa547917eOliver Hartkopp if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) { 815fe92afedee23e1d91f0133360a24d2bf48270739Barry Song int timeout_cnt = MAX_TIMEOUT_CNT; 816fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 817fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* When doing time stamping, keep the connection to the socket 818fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * a while longer 819fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 8202244d07bfa2097cb00600da91c715a8aa547917eOliver Hartkopp skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 821fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 822fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 823fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * The timestamping is done at the EMAC module's MII/RMII interface 824fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * when the module sees the Start of Frame of an event message packet. This 825fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * interface is the closest possible place to the physical Ethernet transmission 826fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * medium, providing the best timing accuracy. 827fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 828fe92afedee23e1d91f0133360a24d2bf48270739Barry Song while ((!(bfin_read_EMAC_PTP_ISTAT() & TXTL)) && (--timeout_cnt)) 829fe92afedee23e1d91f0133360a24d2bf48270739Barry Song udelay(1); 830fe92afedee23e1d91f0133360a24d2bf48270739Barry Song if (timeout_cnt == 0) 831c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger netdev_err(netdev, "timestamp the TX packet failed\n"); 832fe92afedee23e1d91f0133360a24d2bf48270739Barry Song else { 833fe92afedee23e1d91f0133360a24d2bf48270739Barry Song struct skb_shared_hwtstamps shhwtstamps; 834fe92afedee23e1d91f0133360a24d2bf48270739Barry Song u64 ns; 835fe92afedee23e1d91f0133360a24d2bf48270739Barry Song u64 regval; 836fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 837fe92afedee23e1d91f0133360a24d2bf48270739Barry Song regval = bfin_read_EMAC_PTP_TXSNAPLO(); 838fe92afedee23e1d91f0133360a24d2bf48270739Barry Song regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32; 839fe92afedee23e1d91f0133360a24d2bf48270739Barry Song memset(&shhwtstamps, 0, sizeof(shhwtstamps)); 840fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ns = timecounter_cyc2time(&lp->clock, 841fe92afedee23e1d91f0133360a24d2bf48270739Barry Song regval); 842fe92afedee23e1d91f0133360a24d2bf48270739Barry Song timecompare_update(&lp->compare, ns); 843fe92afedee23e1d91f0133360a24d2bf48270739Barry Song shhwtstamps.hwtstamp = ns_to_ktime(ns); 844fe92afedee23e1d91f0133360a24d2bf48270739Barry Song shhwtstamps.syststamp = 845fe92afedee23e1d91f0133360a24d2bf48270739Barry Song timecompare_transform(&lp->compare, ns); 846fe92afedee23e1d91f0133360a24d2bf48270739Barry Song skb_tstamp_tx(skb, &shhwtstamps); 847fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 848fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_dump_hwtamp("TX", &shhwtstamps.hwtstamp, &shhwtstamps.syststamp, &lp->compare); 849fe92afedee23e1d91f0133360a24d2bf48270739Barry Song } 850fe92afedee23e1d91f0133360a24d2bf48270739Barry Song } 851fe92afedee23e1d91f0133360a24d2bf48270739Barry Song} 852fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 853fe92afedee23e1d91f0133360a24d2bf48270739Barry Songstatic void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) 854fe92afedee23e1d91f0133360a24d2bf48270739Barry Song{ 855fe92afedee23e1d91f0133360a24d2bf48270739Barry Song struct bfin_mac_local *lp = netdev_priv(netdev); 856fe92afedee23e1d91f0133360a24d2bf48270739Barry Song u32 valid; 857fe92afedee23e1d91f0133360a24d2bf48270739Barry Song u64 regval, ns; 858fe92afedee23e1d91f0133360a24d2bf48270739Barry Song struct skb_shared_hwtstamps *shhwtstamps; 859fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 860fe92afedee23e1d91f0133360a24d2bf48270739Barry Song if (bfin_mac_hwtstamp_is_none(lp->stamp_cfg.rx_filter)) 861fe92afedee23e1d91f0133360a24d2bf48270739Barry Song return; 862fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 863fe92afedee23e1d91f0133360a24d2bf48270739Barry Song valid = bfin_read_EMAC_PTP_ISTAT() & RXEL; 864fe92afedee23e1d91f0133360a24d2bf48270739Barry Song if (!valid) 865fe92afedee23e1d91f0133360a24d2bf48270739Barry Song return; 866fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 867fe92afedee23e1d91f0133360a24d2bf48270739Barry Song shhwtstamps = skb_hwtstamps(skb); 868fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 869fe92afedee23e1d91f0133360a24d2bf48270739Barry Song regval = bfin_read_EMAC_PTP_RXSNAPLO(); 870fe92afedee23e1d91f0133360a24d2bf48270739Barry Song regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32; 871fe92afedee23e1d91f0133360a24d2bf48270739Barry Song ns = timecounter_cyc2time(&lp->clock, regval); 872fe92afedee23e1d91f0133360a24d2bf48270739Barry Song timecompare_update(&lp->compare, ns); 873fe92afedee23e1d91f0133360a24d2bf48270739Barry Song memset(shhwtstamps, 0, sizeof(*shhwtstamps)); 874fe92afedee23e1d91f0133360a24d2bf48270739Barry Song shhwtstamps->hwtstamp = ns_to_ktime(ns); 875fe92afedee23e1d91f0133360a24d2bf48270739Barry Song shhwtstamps->syststamp = timecompare_transform(&lp->compare, ns); 876fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 877fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_dump_hwtamp("RX", &shhwtstamps->hwtstamp, &shhwtstamps->syststamp, &lp->compare); 878fe92afedee23e1d91f0133360a24d2bf48270739Barry Song} 879fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 880fe92afedee23e1d91f0133360a24d2bf48270739Barry Song/* 881fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * bfin_read_clock - read raw cycle counter (to be used by time counter) 882fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 883fe92afedee23e1d91f0133360a24d2bf48270739Barry Songstatic cycle_t bfin_read_clock(const struct cyclecounter *tc) 884fe92afedee23e1d91f0133360a24d2bf48270739Barry Song{ 885fe92afedee23e1d91f0133360a24d2bf48270739Barry Song u64 stamp; 886fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 887fe92afedee23e1d91f0133360a24d2bf48270739Barry Song stamp = bfin_read_EMAC_PTP_TIMELO(); 888fe92afedee23e1d91f0133360a24d2bf48270739Barry Song stamp |= (u64)bfin_read_EMAC_PTP_TIMEHI() << 32ULL; 889fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 890fe92afedee23e1d91f0133360a24d2bf48270739Barry Song return stamp; 891fe92afedee23e1d91f0133360a24d2bf48270739Barry Song} 892fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 893fe92afedee23e1d91f0133360a24d2bf48270739Barry Song#define PTP_CLK 25000000 894fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 895fe92afedee23e1d91f0133360a24d2bf48270739Barry Songstatic void bfin_mac_hwtstamp_init(struct net_device *netdev) 896fe92afedee23e1d91f0133360a24d2bf48270739Barry Song{ 897fe92afedee23e1d91f0133360a24d2bf48270739Barry Song struct bfin_mac_local *lp = netdev_priv(netdev); 898fe92afedee23e1d91f0133360a24d2bf48270739Barry Song u64 append; 899fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 900fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* Initialize hardware timer */ 901fe92afedee23e1d91f0133360a24d2bf48270739Barry Song append = PTP_CLK * (1ULL << 32); 902fe92afedee23e1d91f0133360a24d2bf48270739Barry Song do_div(append, get_sclk()); 903fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_write_EMAC_PTP_ADDEND((u32)append); 904fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 905fe92afedee23e1d91f0133360a24d2bf48270739Barry Song memset(&lp->cycles, 0, sizeof(lp->cycles)); 906fe92afedee23e1d91f0133360a24d2bf48270739Barry Song lp->cycles.read = bfin_read_clock; 907fe92afedee23e1d91f0133360a24d2bf48270739Barry Song lp->cycles.mask = CLOCKSOURCE_MASK(64); 908fe92afedee23e1d91f0133360a24d2bf48270739Barry Song lp->cycles.mult = 1000000000 / PTP_CLK; 909fe92afedee23e1d91f0133360a24d2bf48270739Barry Song lp->cycles.shift = 0; 910fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 911fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* Synchronize our NIC clock against system wall clock */ 912fe92afedee23e1d91f0133360a24d2bf48270739Barry Song memset(&lp->compare, 0, sizeof(lp->compare)); 913fe92afedee23e1d91f0133360a24d2bf48270739Barry Song lp->compare.source = &lp->clock; 914fe92afedee23e1d91f0133360a24d2bf48270739Barry Song lp->compare.target = ktime_get_real; 915fe92afedee23e1d91f0133360a24d2bf48270739Barry Song lp->compare.num_samples = 10; 916fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 917fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* Initialize hwstamp config */ 918fe92afedee23e1d91f0133360a24d2bf48270739Barry Song lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE; 919fe92afedee23e1d91f0133360a24d2bf48270739Barry Song lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF; 920fe92afedee23e1d91f0133360a24d2bf48270739Barry Song} 921fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 922fe92afedee23e1d91f0133360a24d2bf48270739Barry Song#else 923fe92afedee23e1d91f0133360a24d2bf48270739Barry Song# define bfin_mac_hwtstamp_is_none(cfg) 0 924fe92afedee23e1d91f0133360a24d2bf48270739Barry Song# define bfin_mac_hwtstamp_init(dev) 925fe92afedee23e1d91f0133360a24d2bf48270739Barry Song# define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP) 926fe92afedee23e1d91f0133360a24d2bf48270739Barry Song# define bfin_rx_hwtstamp(dev, skb) 927fe92afedee23e1d91f0133360a24d2bf48270739Barry Song# define bfin_tx_hwtstamp(dev, skb) 928fe92afedee23e1d91f0133360a24d2bf48270739Barry Song#endif 929fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 9304fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhangstatic inline void _tx_reclaim_skb(void) 9314fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang{ 9324fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang do { 9334fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang tx_list_head->desc_a.config &= ~DMAEN; 9344fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang tx_list_head->status.status_word = 0; 9354fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang if (tx_list_head->skb) { 9364fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang dev_kfree_skb(tx_list_head->skb); 9374fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang tx_list_head->skb = NULL; 9384fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang } 9394fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang tx_list_head = tx_list_head->next; 9404fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang 9414fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang } while (tx_list_head->status.status_word != 0); 9424fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang} 9434fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang 9444fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhangstatic void tx_reclaim_skb(struct bfin_mac_local *lp) 945e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 946e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu int timeout_cnt = MAX_TIMEOUT_CNT; 947e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 9484fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang if (tx_list_head->status.status_word != 0) 9494fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang _tx_reclaim_skb(); 950e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 9514fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang if (current_tx_ptr->next == tx_list_head) { 952e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu while (tx_list_head->status.status_word == 0) { 9534fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang /* slow down polling to avoid too many queue stop. */ 954015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich udelay(10); 9554fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang /* reclaim skb if DMA is not running. */ 9564fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang if (!(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)) 9574fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang break; 9584fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang if (timeout_cnt-- < 0) 959e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu break; 960e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 9614fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang 9624fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang if (timeout_cnt >= 0) 9634fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang _tx_reclaim_skb(); 9644fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang else 9654fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang netif_stop_queue(lp->ndev); 966e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 967e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 9684fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang if (current_tx_ptr->next != tx_list_head && 9694fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang netif_queue_stopped(lp->ndev)) 9704fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang netif_wake_queue(lp->ndev); 9714fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang 9724fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang if (tx_list_head != current_tx_ptr) { 9734fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang /* shorten the timer interval if tx queue is stopped */ 9744fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang if (netif_queue_stopped(lp->ndev)) 9754fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang lp->tx_reclaim_timer.expires = 9764fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang jiffies + (TX_RECLAIM_JIFFIES >> 4); 9774fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang else 9784fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang lp->tx_reclaim_timer.expires = 9794fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang jiffies + TX_RECLAIM_JIFFIES; 9804fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang 9814fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang mod_timer(&lp->tx_reclaim_timer, 9824fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang lp->tx_reclaim_timer.expires); 9834fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang } 984e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 985e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu return; 9864fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang} 987e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 9884fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhangstatic void tx_reclaim_skb_timeout(unsigned long lp) 9894fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang{ 9904fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang tx_reclaim_skb((struct bfin_mac_local *)lp); 991e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 992e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 9937ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wustatic int bfin_mac_hard_start_xmit(struct sk_buff *skb, 994e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu struct net_device *dev) 995e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 9964fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang struct bfin_mac_local *lp = netdev_priv(dev); 997a50c0c05c3bdead1ac405ca8cefd8dc290043933Bryan Wu u16 *data; 998015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich u32 data_align = (unsigned long)(skb->data) & 0x3; 999fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 1000e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu current_tx_ptr->skb = skb; 1001e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1002015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich if (data_align == 0x2) { 1003015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich /* move skb->data to current_tx_ptr payload */ 1004015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich data = (u16 *)(skb->data) - 1; 1005fe92afedee23e1d91f0133360a24d2bf48270739Barry Song *data = (u16)(skb->len); 1006fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* 1007fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * When transmitting an Ethernet packet, the PTP_TSYNC module requires 1008fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * a DMA_Length_Word field associated with the packet. The lower 12 bits 1009fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * of this field are the length of the packet payload in bytes and the higher 1010fe92afedee23e1d91f0133360a24d2bf48270739Barry Song * 4 bits are the timestamping enable field. 1011fe92afedee23e1d91f0133360a24d2bf48270739Barry Song */ 10122244d07bfa2097cb00600da91c715a8aa547917eOliver Hartkopp if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) 1013fe92afedee23e1d91f0133360a24d2bf48270739Barry Song *data |= 0x1000; 1014fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 1015015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich current_tx_ptr->desc_a.start_addr = (u32)data; 1016015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich /* this is important! */ 1017015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich blackfin_dcache_flush_range((u32)data, 1018015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich (u32)((u8 *)data + skb->len + 4)); 1019e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } else { 1020015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); 1021fe92afedee23e1d91f0133360a24d2bf48270739Barry Song /* enable timestamping for the sent packet */ 10222244d07bfa2097cb00600da91c715a8aa547917eOliver Hartkopp if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) 1023fe92afedee23e1d91f0133360a24d2bf48270739Barry Song *((u16 *)(current_tx_ptr->packet)) |= 0x1000; 1024015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, 1025015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich skb->len); 1026015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich current_tx_ptr->desc_a.start_addr = 1027015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich (u32)current_tx_ptr->packet; 1028015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich blackfin_dcache_flush_range( 1029015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich (u32)current_tx_ptr->packet, 1030015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich (u32)(current_tx_ptr->packet + skb->len + 2)); 1031e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 1032e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1033805a8ab3ce1be83e9a98c21a625ebbb549a2d317Sonic Zhang /* make sure the internal data buffers in the core are drained 1034805a8ab3ce1be83e9a98c21a625ebbb549a2d317Sonic Zhang * so that the DMA descriptors are completely written when the 1035805a8ab3ce1be83e9a98c21a625ebbb549a2d317Sonic Zhang * DMA engine goes to fetch them below 1036805a8ab3ce1be83e9a98c21a625ebbb549a2d317Sonic Zhang */ 1037805a8ab3ce1be83e9a98c21a625ebbb549a2d317Sonic Zhang SSYNC(); 1038805a8ab3ce1be83e9a98c21a625ebbb549a2d317Sonic Zhang 10394fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang /* always clear status buffer before start tx dma */ 10404fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang current_tx_ptr->status.status_word = 0; 10414fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang 1042e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* enable this packet's dma */ 1043e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu current_tx_ptr->desc_a.config |= DMAEN; 1044e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1045e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* tx dma is running, just return */ 1046015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich if (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN) 1047e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu goto out; 1048e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1049e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* tx dma is not running */ 1050e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA2_NEXT_DESC_PTR(&(current_tx_ptr->desc_a)); 1051e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* dma enabled, read from memory, size is 6 */ 1052e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA2_CONFIG(current_tx_ptr->desc_a.config); 1053e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* Turn on the EMAC tx */ 1054e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE); 1055e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1056e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wuout: 1057fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_tx_hwtstamp(dev, skb); 1058fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 1059e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu current_tx_ptr = current_tx_ptr->next; 106009f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_packets++; 106109f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_bytes += (skb->len); 10624fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang 10634fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang tx_reclaim_skb(lp); 10644fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang 10656ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy return NETDEV_TX_OK; 1066e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1067e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1068ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang#define IP_HEADER_OFF 0 1069ec497b32c311b1e1aac22a76d294d24285d06331Peter Meerwald#define RX_ERROR_MASK (RX_LONG | RX_ALIGN | RX_CRC | RX_LEN | \ 1070ec497b32c311b1e1aac22a76d294d24285d06331Peter Meerwald RX_FRAG | RX_ADDR | RX_DMAO | RX_PHY | RX_LATE | RX_RANGE) 1071ec497b32c311b1e1aac22a76d294d24285d06331Peter Meerwald 10727ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wustatic void bfin_mac_rx(struct net_device *dev) 1073e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 1074e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu struct sk_buff *skb, *new_skb; 1075e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu unsigned short len; 1076fe92afedee23e1d91f0133360a24d2bf48270739Barry Song struct bfin_mac_local *lp __maybe_unused = netdev_priv(dev); 1077ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang#if defined(BFIN_MAC_CSUM_OFFLOAD) 1078ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang unsigned int i; 1079ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang unsigned char fcs[ETH_FCS_LEN + 1]; 1080ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang#endif 1081e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1082ec497b32c311b1e1aac22a76d294d24285d06331Peter Meerwald /* check if frame status word reports an error condition 1083ec497b32c311b1e1aac22a76d294d24285d06331Peter Meerwald * we which case we simply drop the packet 1084ec497b32c311b1e1aac22a76d294d24285d06331Peter Meerwald */ 1085ec497b32c311b1e1aac22a76d294d24285d06331Peter Meerwald if (current_rx_ptr->status.status_word & RX_ERROR_MASK) { 1086c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger netdev_notice(dev, "rx: receive error - packet dropped\n"); 1087ec497b32c311b1e1aac22a76d294d24285d06331Peter Meerwald dev->stats.rx_dropped++; 1088ec497b32c311b1e1aac22a76d294d24285d06331Peter Meerwald goto out; 1089ec497b32c311b1e1aac22a76d294d24285d06331Peter Meerwald } 1090ec497b32c311b1e1aac22a76d294d24285d06331Peter Meerwald 1091e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* allocate a new skb for next time receive */ 1092e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu skb = current_rx_ptr->skb; 1093fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 10941ab0d2ec9aeb4489c05158e8a2b00bad89f67e03Pradeep A. Dalvi new_skb = netdev_alloc_skb(dev, PKT_BUF_SZ + NET_IP_ALIGN); 1095e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (!new_skb) { 1096c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger netdev_notice(dev, "rx: low on mem - packet dropped\n"); 109709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_dropped++; 1098e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu goto out; 1099e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 1100e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* reserve 2 bytes for RXDWA padding */ 1101015dac8886b5c48d62ebc33a964b9086d6a71bd7Michael Hennerich skb_reserve(new_skb, NET_IP_ALIGN); 11026e01d1a4b2f7110201e7fe16e561a721d76fab3eAlexey Demin /* Invidate the data cache of skb->data range when it is write back 11036e01d1a4b2f7110201e7fe16e561a721d76fab3eAlexey Demin * cache. It will prevent overwritting the new data from DMA 11046e01d1a4b2f7110201e7fe16e561a721d76fab3eAlexey Demin */ 11056e01d1a4b2f7110201e7fe16e561a721d76fab3eAlexey Demin blackfin_dcache_invalidate_range((unsigned long)new_skb->head, 11066e01d1a4b2f7110201e7fe16e561a721d76fab3eAlexey Demin (unsigned long)new_skb->end); 11076e01d1a4b2f7110201e7fe16e561a721d76fab3eAlexey Demin 1108f6e1e4f3e511589dd0c47d42b870501659e7195fSonic Zhang current_rx_ptr->skb = new_skb; 1109f6e1e4f3e511589dd0c47d42b870501659e7195fSonic Zhang current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2; 1110f6e1e4f3e511589dd0c47d42b870501659e7195fSonic Zhang 1111e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu len = (unsigned short)((current_rx_ptr->status.status_word) & RX_FRLEN); 1112ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang /* Deduce Ethernet FCS length from Ethernet payload length */ 1113ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang len -= ETH_FCS_LEN; 1114e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu skb_put(skb, len); 1115e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1116e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu skb->protocol = eth_type_trans(skb, dev); 1117fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 1118fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_rx_hwtstamp(dev, skb); 1119fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 1120e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#if defined(BFIN_MAC_CSUM_OFFLOAD) 1121ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang /* Checksum offloading only works for IPv4 packets with the standard IP header 1122ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang * length of 20 bytes, because the blackfin MAC checksum calculation is 1123ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang * based on that assumption. We must NOT use the calculated checksum if our 1124ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang * IP version or header break that assumption. 1125ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang */ 1126ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang if (skb->data[IP_HEADER_OFF] == 0x45) { 1127ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang skb->csum = current_rx_ptr->status.ip_payload_csum; 1128ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang /* 1129ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang * Deduce Ethernet FCS from hardware generated IP payload checksum. 1130ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang * IP checksum is based on 16-bit one's complement algorithm. 1131ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang * To deduce a value from checksum is equal to add its inversion. 1132ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang * If the IP payload len is odd, the inversed FCS should also 1133ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang * begin from odd address and leave first byte zero. 1134ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang */ 1135ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang if (skb->len % 2) { 1136ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang fcs[0] = 0; 1137ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang for (i = 0; i < ETH_FCS_LEN; i++) 1138ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang fcs[i + 1] = ~skb->data[skb->len + i]; 1139ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang skb->csum = csum_partial(fcs, ETH_FCS_LEN + 1, skb->csum); 1140ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang } else { 1141ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang for (i = 0; i < ETH_FCS_LEN; i++) 1142ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang fcs[i] = ~skb->data[skb->len + i]; 1143ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang skb->csum = csum_partial(fcs, ETH_FCS_LEN, skb->csum); 1144ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang } 1145ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang skb->ip_summed = CHECKSUM_COMPLETE; 1146ad2864d88718714d8b347b6209b07abb2ecd3a49Sonic Zhang } 1147e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#endif 1148e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1149e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu netif_rx(skb); 115009f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_packets++; 115109f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_bytes += len; 1152ec497b32c311b1e1aac22a76d294d24285d06331Peter Meerwaldout: 1153e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu current_rx_ptr->status.status_word = 0x00000000; 1154e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu current_rx_ptr = current_rx_ptr->next; 1155e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1156e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1157e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu/* interrupt routine to handle rx and error signal */ 11587ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wustatic irqreturn_t bfin_mac_interrupt(int irq, void *dev_id) 1159e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 1160e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu struct net_device *dev = dev_id; 1161e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu int number = 0; 1162e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1163e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wuget_one_packet: 1164e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (current_rx_ptr->status.status_word == 0) { 1165e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* no more new packet received */ 1166e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (number == 0) { 1167e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (current_rx_ptr->next->status.status_word != 0) { 1168e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu current_rx_ptr = current_rx_ptr->next; 1169e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu goto real_rx; 1170e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 1171e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 1172e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA1_IRQ_STATUS(bfin_read_DMA1_IRQ_STATUS() | 1173e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu DMA_DONE | DMA_ERR); 1174e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu return IRQ_HANDLED; 1175e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 1176e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1177e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wureal_rx: 11787ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu bfin_mac_rx(dev); 1179e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu number++; 1180e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu goto get_one_packet; 1181e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1182e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1183e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#ifdef CONFIG_NET_POLL_CONTROLLER 11847ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wustatic void bfin_mac_poll(struct net_device *dev) 1185e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 11864fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang struct bfin_mac_local *lp = netdev_priv(dev); 11874fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang 1188e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu disable_irq(IRQ_MAC_RX); 11897ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu bfin_mac_interrupt(IRQ_MAC_RX, dev); 11904fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang tx_reclaim_skb(lp); 1191e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu enable_irq(IRQ_MAC_RX); 1192e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1193e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#endif /* CONFIG_NET_POLL_CONTROLLER */ 1194e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 11957ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wustatic void bfin_mac_disable(void) 1196e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 1197e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu unsigned int opmode; 1198e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1199e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu opmode = bfin_read_EMAC_OPMODE(); 1200e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu opmode &= (~RE); 1201e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu opmode &= (~TE); 1202e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* Turn off the EMAC */ 1203e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_EMAC_OPMODE(opmode); 1204e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1205e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1206e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu/* 1207e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * Enable Interrupts, Receive, and Transmit 1208e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu */ 120902460d08930656b3a50381cfb119864efcd4eef9Sonic Zhangstatic int bfin_mac_enable(struct phy_device *phydev) 1210e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 12112bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger int ret; 1212e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu u32 opmode; 1213e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1214c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger pr_debug("%s\n", __func__); 1215e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1216e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* Set RX DMA */ 1217e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA1_NEXT_DESC_PTR(&(rx_list_head->desc_a)); 1218e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config); 1219e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1220e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* Wait MII done */ 12212bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger ret = bfin_mdio_poll(); 12222bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger if (ret) 12232bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger return ret; 1224e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1225e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* We enable only RX here */ 1226e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* ASTP : Enable Automatic Pad Stripping 1227e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu PR : Promiscuous Mode for test 1228e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu PSF : Receive frames with total length less than 64 bytes. 1229e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu FDMODE : Full Duplex Mode 1230e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu LB : Internal Loopback for test 1231e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu RE : Receiver Enable */ 1232e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu opmode = bfin_read_EMAC_OPMODE(); 1233e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (opmode & FDMODE) 1234e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu opmode |= PSF; 1235e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu else 1236e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu opmode |= DRO | DC | PSF; 1237e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu opmode |= RE; 1238e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 123902460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang if (phydev->interface == PHY_INTERFACE_MODE_RMII) { 124002460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang opmode |= RMII; /* For Now only 100MBit are supported */ 124172f49050ba18959472aac723cd9d094bc3547e89Mike Frysinger#if defined(CONFIG_BF537) || defined(CONFIG_BF536) 124272f49050ba18959472aac723cd9d094bc3547e89Mike Frysinger if (__SILICON_REVISION__ < 3) { 124372f49050ba18959472aac723cd9d094bc3547e89Mike Frysinger /* 124472f49050ba18959472aac723cd9d094bc3547e89Mike Frysinger * This isn't publicly documented (fun times!), but in 124572f49050ba18959472aac723cd9d094bc3547e89Mike Frysinger * silicon <=0.2, the RX and TX pins are clocked together. 124672f49050ba18959472aac723cd9d094bc3547e89Mike Frysinger * So in order to recv, we must enable the transmit side 124772f49050ba18959472aac723cd9d094bc3547e89Mike Frysinger * as well. This will cause a spurious TX interrupt too, 124872f49050ba18959472aac723cd9d094bc3547e89Mike Frysinger * but we can easily consume that. 124972f49050ba18959472aac723cd9d094bc3547e89Mike Frysinger */ 125072f49050ba18959472aac723cd9d094bc3547e89Mike Frysinger opmode |= TE; 125172f49050ba18959472aac723cd9d094bc3547e89Mike Frysinger } 1252e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu#endif 125302460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang } 125402460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang 1255e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* Turn on the EMAC rx */ 1256e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_EMAC_OPMODE(opmode); 12572bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger 12582bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger return 0; 1259e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1260e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1261e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu/* Our watchdog timed out. Called by the networking layer */ 12627ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wustatic void bfin_mac_timeout(struct net_device *dev) 1263e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 12644fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang struct bfin_mac_local *lp = netdev_priv(dev); 12654fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang 1266b39d66a81fb4f5ab555f86a2e49f3714f8369a3dHarvey Harrison pr_debug("%s: %s\n", dev->name, __func__); 1267e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 12687ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu bfin_mac_disable(); 1269e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 12704fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang del_timer(&lp->tx_reclaim_timer); 12714fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang 12724fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang /* reset tx queue and free skb */ 12734fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang while (tx_list_head != current_tx_ptr) { 12744fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang tx_list_head->desc_a.config &= ~DMAEN; 12754fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang tx_list_head->status.status_word = 0; 12764fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang if (tx_list_head->skb) { 12774fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang dev_kfree_skb(tx_list_head->skb); 12784fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang tx_list_head->skb = NULL; 12794fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang } 12804fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang tx_list_head = tx_list_head->next; 12814fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang } 12824fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang 12834fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang if (netif_queue_stopped(lp->ndev)) 12844fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang netif_wake_queue(lp->ndev); 1285e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 128602460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang bfin_mac_enable(lp->phydev); 1287e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1288e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* We can accept TX packets again */ 12891ae5dc342ac78d7a42965fd1f323815f6f5ef2c1Eric Dumazet dev->trans_start = jiffies; /* prevent tx timeout */ 1290e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu netif_wake_queue(dev); 1291e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1292e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 12937ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wustatic void bfin_mac_multicast_hash(struct net_device *dev) 1294775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams{ 1295775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams u32 emac_hashhi, emac_hashlo; 129622bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko struct netdev_hw_addr *ha; 1297775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams u32 crc; 1298775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams 1299775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams emac_hashhi = emac_hashlo = 0; 1300775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams 130122bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko netdev_for_each_mc_addr(ha, dev) { 1302f767b6df8a796f901b2bd595ae22234636be4124Joe Perches crc = ether_crc(ETH_ALEN, ha->addr); 1303775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams crc >>= 26; 1304775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams 1305775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams if (crc & 0x20) 1306775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams emac_hashhi |= 1 << (crc & 0x1f); 1307775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams else 1308775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams emac_hashlo |= 1 << (crc & 0x1f); 1309775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams } 1310775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams 1311775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams bfin_write_EMAC_HASHHI(emac_hashhi); 1312775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams bfin_write_EMAC_HASHLO(emac_hashlo); 1313775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams} 1314775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams 1315e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu/* 1316e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * This routine will, depending on the values passed to it, 1317e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * either make it accept multicast packets, go into 1318e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * promiscuous mode (for TCPDUMP and cousins) or accept 1319e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * a select set of multicast packets 1320e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu */ 13217ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wustatic void bfin_mac_set_multicast_list(struct net_device *dev) 1322e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 1323e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu u32 sysctl; 1324e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1325e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (dev->flags & IFF_PROMISC) { 1326c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger netdev_info(dev, "set promisc mode\n"); 1327e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu sysctl = bfin_read_EMAC_OPMODE(); 1328c0da776bde79e5d5e2c955ff37a8a09fe05433b2Sonic Zhang sysctl |= PR; 1329e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_EMAC_OPMODE(sysctl); 1330775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams } else if (dev->flags & IFF_ALLMULTI) { 1331e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* accept all multicast */ 1332e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu sysctl = bfin_read_EMAC_OPMODE(); 1333e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu sysctl |= PAM; 1334e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_EMAC_OPMODE(sysctl); 13354cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko } else if (!netdev_mc_empty(dev)) { 1336775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams /* set up multicast hash table */ 1337775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams sysctl = bfin_read_EMAC_OPMODE(); 1338775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams sysctl |= HM; 1339775919bc23880f250ca1029a6420187ee4bb5b26Aidan Williams bfin_write_EMAC_OPMODE(sysctl); 13407ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu bfin_mac_multicast_hash(dev); 1341e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } else { 1342e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* clear promisc or multicast mode */ 1343e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu sysctl = bfin_read_EMAC_OPMODE(); 1344e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu sysctl &= ~(RAF | PAM); 1345e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_EMAC_OPMODE(sysctl); 1346e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 1347e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1348e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1349fe92afedee23e1d91f0133360a24d2bf48270739Barry Songstatic int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) 1350fe92afedee23e1d91f0133360a24d2bf48270739Barry Song{ 135102460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang struct bfin_mac_local *lp = netdev_priv(netdev); 135202460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang 135302460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang if (!netif_running(netdev)) 135402460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang return -EINVAL; 135502460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang 1356fe92afedee23e1d91f0133360a24d2bf48270739Barry Song switch (cmd) { 1357fe92afedee23e1d91f0133360a24d2bf48270739Barry Song case SIOCSHWTSTAMP: 1358fe92afedee23e1d91f0133360a24d2bf48270739Barry Song return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd); 1359fe92afedee23e1d91f0133360a24d2bf48270739Barry Song default: 136002460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang if (lp->phydev) 136102460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang return phy_mii_ioctl(lp->phydev, ifr, cmd); 136202460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang else 136302460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang return -EOPNOTSUPP; 1364fe92afedee23e1d91f0133360a24d2bf48270739Barry Song } 1365fe92afedee23e1d91f0133360a24d2bf48270739Barry Song} 1366fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 1367e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu/* 1368e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * this puts the device in an inactive state 1369e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu */ 13707ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wustatic void bfin_mac_shutdown(struct net_device *dev) 1371e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 1372e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* Turn off the EMAC */ 1373e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_EMAC_OPMODE(0x00000000); 1374e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* Turn off the EMAC RX DMA */ 1375e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA1_CONFIG(0x0000); 1376e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_DMA2_CONFIG(0x0000); 1377e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1378e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1379e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu/* 1380e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * Open and Initialize the interface 1381e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * 1382e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * Set up everything, reset the card, etc.. 1383e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu */ 13847ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wustatic int bfin_mac_open(struct net_device *dev) 1385e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 13867ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu struct bfin_mac_local *lp = netdev_priv(dev); 13872bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger int ret; 1388b39d66a81fb4f5ab555f86a2e49f3714f8369a3dHarvey Harrison pr_debug("%s: %s\n", dev->name, __func__); 1389e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1390e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* 1391e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * Check that the address is valid. If its not, refuse 1392e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * to bring the device up. The user must specify an 1393e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx 1394e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu */ 1395e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (!is_valid_ether_addr(dev->dev_addr)) { 1396c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger netdev_warn(dev, "no valid ethernet hw addr\n"); 1397e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu return -EINVAL; 1398e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 1399e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1400e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* initial rx and tx list */ 14011ab0d2ec9aeb4489c05158e8a2b00bad89f67e03Pradeep A. Dalvi ret = desc_list_init(dev); 14022bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger if (ret) 14032bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger return ret; 1404e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 14054ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu phy_start(lp->phydev); 1406136492b275e0dd02d842b94507d66267d18d341cVitja Makarov phy_write(lp->phydev, MII_BMCR, BMCR_RESET); 1407e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu setup_system_regs(dev); 1408ee02fee8f698aee72f43b3ee5fd818393b110402Michael Hennerich setup_mac_addr(dev->dev_addr); 14092bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger 14107ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu bfin_mac_disable(); 141102460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang ret = bfin_mac_enable(lp->phydev); 14122bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger if (ret) 14132bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger return ret; 1414e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu pr_debug("hardware init finished\n"); 14152bfa0f0c9a37460ee69128da411f6d310c1c983dMike Frysinger 1416e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu netif_start_queue(dev); 1417e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu netif_carrier_on(dev); 1418e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1419e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu return 0; 1420e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1421e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1422e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu/* 1423e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * this makes the board clean up everything that it can 1424e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * and not talk to the outside world. Caused by 1425e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu * an 'ifconfig ethX down' 1426e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu */ 14277ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wustatic int bfin_mac_close(struct net_device *dev) 1428e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 14297ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu struct bfin_mac_local *lp = netdev_priv(dev); 1430b39d66a81fb4f5ab555f86a2e49f3714f8369a3dHarvey Harrison pr_debug("%s: %s\n", dev->name, __func__); 1431e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1432e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu netif_stop_queue(dev); 1433e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu netif_carrier_off(dev); 1434e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 14354ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu phy_stop(lp->phydev); 1436136492b275e0dd02d842b94507d66267d18d341cVitja Makarov phy_write(lp->phydev, MII_BMCR, BMCR_PDOWN); 14374ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 1438e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* clear everything */ 14397ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu bfin_mac_shutdown(dev); 1440e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1441e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* free the rx/tx buffers */ 1442e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu desc_list_free(); 1443e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1444e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu return 0; 1445e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1446e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1447b63dc8fef7ca5c51d163295d824e78c770d48ccfMike Frysingerstatic const struct net_device_ops bfin_mac_netdev_ops = { 1448b63dc8fef7ca5c51d163295d824e78c770d48ccfMike Frysinger .ndo_open = bfin_mac_open, 1449b63dc8fef7ca5c51d163295d824e78c770d48ccfMike Frysinger .ndo_stop = bfin_mac_close, 1450b63dc8fef7ca5c51d163295d824e78c770d48ccfMike Frysinger .ndo_start_xmit = bfin_mac_hard_start_xmit, 1451b63dc8fef7ca5c51d163295d824e78c770d48ccfMike Frysinger .ndo_set_mac_address = bfin_mac_set_mac_address, 1452b63dc8fef7ca5c51d163295d824e78c770d48ccfMike Frysinger .ndo_tx_timeout = bfin_mac_timeout, 1453afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko .ndo_set_rx_mode = bfin_mac_set_multicast_list, 1454fe92afedee23e1d91f0133360a24d2bf48270739Barry Song .ndo_do_ioctl = bfin_mac_ioctl, 1455b63dc8fef7ca5c51d163295d824e78c770d48ccfMike Frysinger .ndo_validate_addr = eth_validate_addr, 1456b63dc8fef7ca5c51d163295d824e78c770d48ccfMike Frysinger .ndo_change_mtu = eth_change_mtu, 1457b63dc8fef7ca5c51d163295d824e78c770d48ccfMike Frysinger#ifdef CONFIG_NET_POLL_CONTROLLER 1458b63dc8fef7ca5c51d163295d824e78c770d48ccfMike Frysinger .ndo_poll_controller = bfin_mac_poll, 1459b63dc8fef7ca5c51d163295d824e78c770d48ccfMike Frysinger#endif 1460b63dc8fef7ca5c51d163295d824e78c770d48ccfMike Frysinger}; 1461b63dc8fef7ca5c51d163295d824e78c770d48ccfMike Frysinger 1462d7b843d393cec677583e1aa971df09b140dcfd5eMike Frysingerstatic int __devinit bfin_mac_probe(struct platform_device *pdev) 1463e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 14647ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu struct net_device *ndev; 14657ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu struct bfin_mac_local *lp; 1466080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang struct platform_device *pd; 146702460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang struct bfin_mii_bus_platform_data *mii_bus_data; 1468080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang int rc; 14697ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu 14707ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu ndev = alloc_etherdev(sizeof(struct bfin_mac_local)); 147141de8d4cff21a2e81e3d9ff66f5f7c903f9c3ab1Joe Perches if (!ndev) 14727ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu return -ENOMEM; 14737ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu 14747ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu SET_NETDEV_DEV(ndev, &pdev->dev); 14757ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu platform_set_drvdata(pdev, ndev); 14767ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu lp = netdev_priv(ndev); 14774fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang lp->ndev = ndev; 1478e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1479e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* Grab the MAC address in the MAC */ 14807ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu *(__le32 *) (&(ndev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO()); 14817ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu *(__le16 *) (&(ndev->dev_addr[4])) = cpu_to_le16((u16) bfin_read_EMAC_ADDRHI()); 1482e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1483e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* probe mac */ 1484e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /*todo: how to proble? which is revision_register */ 1485e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu bfin_write_EMAC_ADDRLO(0x12345678); 1486e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu if (bfin_read_EMAC_ADDRLO() != 0x12345678) { 14877ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu dev_err(&pdev->dev, "Cannot detect Blackfin on-chip ethernet MAC controller!\n"); 14887ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu rc = -ENODEV; 14897ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu goto out_err_probe_mac; 1490e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 1491e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1492e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 14937ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu /* 14947ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu * Is it valid? (Did bootloader initialize it?) 14957ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu * Grab the MAC from the board somehow 14967ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu * this is done in the arch/blackfin/mach-bfxxx/boards/eth_mac.c 14977ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu */ 14985055d2f236e1495d68c468eeb684fd5789673f1dDanny Kukawka if (!is_valid_ether_addr(ndev->dev_addr)) { 14995055d2f236e1495d68c468eeb684fd5789673f1dDanny Kukawka if (bfin_get_ether_addr(ndev->dev_addr) || 15005055d2f236e1495d68c468eeb684fd5789673f1dDanny Kukawka !is_valid_ether_addr(ndev->dev_addr)) { 15015055d2f236e1495d68c468eeb684fd5789673f1dDanny Kukawka /* Still not valid, get a random one */ 15025055d2f236e1495d68c468eeb684fd5789673f1dDanny Kukawka netdev_warn(ndev, "Setting Ethernet MAC to a random one\n"); 15035055d2f236e1495d68c468eeb684fd5789673f1dDanny Kukawka eth_hw_addr_random(ndev); 15045055d2f236e1495d68c468eeb684fd5789673f1dDanny Kukawka } 15055055d2f236e1495d68c468eeb684fd5789673f1dDanny Kukawka } 1506e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 15077ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu setup_mac_addr(ndev->dev_addr); 1508e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1509080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang if (!pdev->dev.platform_data) { 1510080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang dev_err(&pdev->dev, "Cannot get platform device bfin_mii_bus!\n"); 1511080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang rc = -ENODEV; 1512080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang goto out_err_probe_mac; 15137ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu } 1514080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang pd = pdev->dev.platform_data; 1515080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang lp->mii_bus = platform_get_drvdata(pd); 15160e995cd3d3c78377a0bc7d38236fc50e5438fabbSonic Zhang if (!lp->mii_bus) { 15170e995cd3d3c78377a0bc7d38236fc50e5438fabbSonic Zhang dev_err(&pdev->dev, "Cannot get mii_bus!\n"); 15180e995cd3d3c78377a0bc7d38236fc50e5438fabbSonic Zhang rc = -ENODEV; 151902460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang goto out_err_probe_mac; 15200e995cd3d3c78377a0bc7d38236fc50e5438fabbSonic Zhang } 1521080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang lp->mii_bus->priv = ndev; 152202460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang mii_bus_data = pd->dev.platform_data; 15234ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 152402460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang rc = mii_probe(ndev, mii_bus_data->phy_mode); 15257ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu if (rc) { 15267ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu dev_err(&pdev->dev, "MII Probe failed!\n"); 15277ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu goto out_err_mii_probe; 15287ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu } 15294ae5a3ad5aa35972863f9c656ebd35446fbb5192Bryan Wu 1530c599bd6b9ac8926b03e6bf332a8c14ae2ffb43a3Mike Frysinger lp->vlan1_mask = ETH_P_8021Q | mii_bus_data->vlan1_mask; 1531c599bd6b9ac8926b03e6bf332a8c14ae2ffb43a3Mike Frysinger lp->vlan2_mask = ETH_P_8021Q | mii_bus_data->vlan2_mask; 1532c599bd6b9ac8926b03e6bf332a8c14ae2ffb43a3Mike Frysinger 1533e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* Fill in the fields of the device structure with ethernet values. */ 15347ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu ether_setup(ndev); 15357ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu 1536149da651bf340b796576a078574fbb49ed09b7aeAlexander Beregalov ndev->netdev_ops = &bfin_mac_netdev_ops; 1537679dce39e3cdfcc641b2888ce04f1cd5ff0b3b92Bryan Wu ndev->ethtool_ops = &bfin_mac_ethtool_ops; 1538e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 15394fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang init_timer(&lp->tx_reclaim_timer); 15404fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang lp->tx_reclaim_timer.data = (unsigned long)lp; 15414fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang lp->tx_reclaim_timer.function = tx_reclaim_skb_timeout; 15424fcc3d3409b0ab37c1f790e04a1f7c984b436167Sonic Zhang 1543e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu spin_lock_init(&lp->lock); 1544e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1545e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* now, enable interrupts */ 1546e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu /* register irq handler */ 15477ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt, 154891a455f089810625eb94a36ccc40ae963f451b06Michael Hennerich IRQF_DISABLED, "EMAC_RX", ndev); 15497ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu if (rc) { 15507ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n"); 15517ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu rc = -EBUSY; 15527ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu goto out_err_request_irq; 1553e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 1554e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 15557ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu rc = register_netdev(ndev); 15567ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu if (rc) { 15577ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu dev_err(&pdev->dev, "Cannot register net device!\n"); 15587ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu goto out_err_reg_ndev; 1559e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu } 1560e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1561fe92afedee23e1d91f0133360a24d2bf48270739Barry Song bfin_mac_hwtstamp_init(ndev); 1562fe92afedee23e1d91f0133360a24d2bf48270739Barry Song 15637ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu /* now, print out the card info, in a short format.. */ 1564c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger netdev_info(ndev, "%s, Version %s\n", DRV_DESC, DRV_VERSION); 1565e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 15667ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu return 0; 1567e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 15687ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wuout_err_reg_ndev: 15697ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu free_irq(IRQ_MAC_RX, ndev); 15707ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wuout_err_request_irq: 15717ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wuout_err_mii_probe: 1572298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek mdiobus_unregister(lp->mii_bus); 1573298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek mdiobus_free(lp->mii_bus); 15747ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wuout_err_probe_mac: 15757ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu platform_set_drvdata(pdev, NULL); 15767ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu free_netdev(ndev); 1577e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 15787ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu return rc; 1579e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1580e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1581d7b843d393cec677583e1aa971df09b140dcfd5eMike Frysingerstatic int __devexit bfin_mac_remove(struct platform_device *pdev) 1582e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 1583e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu struct net_device *ndev = platform_get_drvdata(pdev); 15847ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu struct bfin_mac_local *lp = netdev_priv(ndev); 1585e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1586e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu platform_set_drvdata(pdev, NULL); 1587e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1588080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang lp->mii_bus->priv = NULL; 15897ef0a7ee2f9ac7ee8e2a597821adb2a78b882791Bryan Wu 1590e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu unregister_netdev(ndev); 1591e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1592e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu free_irq(IRQ_MAC_RX, ndev); 1593e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1594e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu free_netdev(ndev); 1595e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1596e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu return 0; 1597e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1598e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1599496a34c2249fecc87ee689eede2bb8510c1b37a9Bryan Wu#ifdef CONFIG_PM 1600496a34c2249fecc87ee689eede2bb8510c1b37a9Bryan Wustatic int bfin_mac_suspend(struct platform_device *pdev, pm_message_t mesg) 1601e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 1602496a34c2249fecc87ee689eede2bb8510c1b37a9Bryan Wu struct net_device *net_dev = platform_get_drvdata(pdev); 160353fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich struct bfin_mac_local *lp = netdev_priv(net_dev); 1604496a34c2249fecc87ee689eede2bb8510c1b37a9Bryan Wu 160553fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich if (lp->wol) { 160653fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich bfin_write_EMAC_OPMODE((bfin_read_EMAC_OPMODE() & ~TE) | RE); 160753fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich bfin_write_EMAC_WKUP_CTL(MPKE); 160853fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich enable_irq_wake(IRQ_MAC_WAKEDET); 160953fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich } else { 161053fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich if (netif_running(net_dev)) 161153fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich bfin_mac_close(net_dev); 161253fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich } 1613496a34c2249fecc87ee689eede2bb8510c1b37a9Bryan Wu 1614e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu return 0; 1615e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1616e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1617e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wustatic int bfin_mac_resume(struct platform_device *pdev) 1618e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 1619496a34c2249fecc87ee689eede2bb8510c1b37a9Bryan Wu struct net_device *net_dev = platform_get_drvdata(pdev); 162053fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich struct bfin_mac_local *lp = netdev_priv(net_dev); 1621496a34c2249fecc87ee689eede2bb8510c1b37a9Bryan Wu 162253fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich if (lp->wol) { 162353fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE); 162453fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich bfin_write_EMAC_WKUP_CTL(0); 162553fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich disable_irq_wake(IRQ_MAC_WAKEDET); 162653fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich } else { 162753fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich if (netif_running(net_dev)) 162853fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich bfin_mac_open(net_dev); 162953fd3f2829268703729a2db0e24c0e36360b68a2Michael Hennerich } 1630496a34c2249fecc87ee689eede2bb8510c1b37a9Bryan Wu 1631e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu return 0; 1632e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1633496a34c2249fecc87ee689eede2bb8510c1b37a9Bryan Wu#else 1634496a34c2249fecc87ee689eede2bb8510c1b37a9Bryan Wu#define bfin_mac_suspend NULL 1635496a34c2249fecc87ee689eede2bb8510c1b37a9Bryan Wu#define bfin_mac_resume NULL 1636496a34c2249fecc87ee689eede2bb8510c1b37a9Bryan Wu#endif /* CONFIG_PM */ 1637e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1638080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yangstatic int __devinit bfin_mii_bus_probe(struct platform_device *pdev) 1639080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang{ 1640080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang struct mii_bus *miibus; 164102460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang struct bfin_mii_bus_platform_data *mii_bus_pd; 164202460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang const unsigned short *pin_req; 1643080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang int rc, i; 1644080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang 164502460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang mii_bus_pd = dev_get_platdata(&pdev->dev); 164602460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang if (!mii_bus_pd) { 164702460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang dev_err(&pdev->dev, "No peripherals in platform data!\n"); 164802460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang return -EINVAL; 164902460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang } 165002460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang 1651080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang /* 1652080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang * We are setting up a network card, 1653080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang * so set the GPIO pins to Ethernet mode 1654080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang */ 165502460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang pin_req = mii_bus_pd->mac_peripherals; 1656c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger rc = peripheral_request_list(pin_req, KBUILD_MODNAME); 1657080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang if (rc) { 1658080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang dev_err(&pdev->dev, "Requesting peripherals failed!\n"); 1659080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang return rc; 1660080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang } 1661080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang 1662080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang rc = -ENOMEM; 1663080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang miibus = mdiobus_alloc(); 1664080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang if (miibus == NULL) 1665080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang goto out_err_alloc; 1666080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang miibus->read = bfin_mdiobus_read; 1667080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang miibus->write = bfin_mdiobus_write; 1668080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang miibus->reset = bfin_mdiobus_reset; 1669080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang 1670080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang miibus->parent = &pdev->dev; 1671080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang miibus->name = "bfin_mii_bus"; 167202460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang miibus->phy_mask = mii_bus_pd->phy_mask; 167302460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang 167475432fd2913e03696f56289a853754ef0124545fFlorian Fainelli snprintf(miibus->id, MII_BUS_ID_SIZE, "%s-%x", 167575432fd2913e03696f56289a853754ef0124545fFlorian Fainelli pdev->name, pdev->id); 1676080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); 167702460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang if (!miibus->irq) 167802460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang goto out_err_irq_alloc; 167902460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang 168002460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang for (i = rc; i < PHY_MAX_ADDR; ++i) 1681080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang miibus->irq[i] = PHY_POLL; 1682080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang 168302460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang rc = clamp(mii_bus_pd->phydev_number, 0, PHY_MAX_ADDR); 168402460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang if (rc != mii_bus_pd->phydev_number) 168502460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang dev_err(&pdev->dev, "Invalid number (%i) of phydevs\n", 168602460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang mii_bus_pd->phydev_number); 168702460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang for (i = 0; i < rc; ++i) { 168802460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang unsigned short phyaddr = mii_bus_pd->phydev_data[i].addr; 168902460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang if (phyaddr < PHY_MAX_ADDR) 169002460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang miibus->irq[phyaddr] = mii_bus_pd->phydev_data[i].irq; 169102460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang else 169202460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang dev_err(&pdev->dev, 169302460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang "Invalid PHY address %i for phydev %i\n", 169402460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang phyaddr, i); 169502460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang } 169602460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang 1697080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang rc = mdiobus_register(miibus); 1698080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang if (rc) { 1699080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); 1700080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang goto out_err_mdiobus_register; 1701080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang } 1702080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang 1703080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang platform_set_drvdata(pdev, miibus); 1704080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang return 0; 1705080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang 1706080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yangout_err_mdiobus_register: 17077f267de41fde594500cbbccb1b29acb4475f2da2Denis Kirjanov kfree(miibus->irq); 170802460d08930656b3a50381cfb119864efcd4eef9Sonic Zhangout_err_irq_alloc: 1709080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang mdiobus_free(miibus); 1710080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yangout_err_alloc: 1711080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang peripheral_free_list(pin_req); 1712080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang 1713080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang return rc; 1714080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang} 1715080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang 1716080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yangstatic int __devexit bfin_mii_bus_remove(struct platform_device *pdev) 1717080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang{ 1718080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang struct mii_bus *miibus = platform_get_drvdata(pdev); 171902460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang struct bfin_mii_bus_platform_data *mii_bus_pd = 172002460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang dev_get_platdata(&pdev->dev); 172102460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang 1722080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang platform_set_drvdata(pdev, NULL); 1723080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang mdiobus_unregister(miibus); 17247f267de41fde594500cbbccb1b29acb4475f2da2Denis Kirjanov kfree(miibus->irq); 1725080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang mdiobus_free(miibus); 172602460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang peripheral_free_list(mii_bus_pd->mac_peripherals); 172702460d08930656b3a50381cfb119864efcd4eef9Sonic Zhang 1728080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang return 0; 1729080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang} 1730080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang 1731080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yangstatic struct platform_driver bfin_mii_bus_driver = { 1732080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang .probe = bfin_mii_bus_probe, 1733080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang .remove = __devexit_p(bfin_mii_bus_remove), 1734080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang .driver = { 1735080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang .name = "bfin_mii_bus", 1736080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang .owner = THIS_MODULE, 1737080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang }, 1738080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang}; 1739080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang 1740e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wustatic struct platform_driver bfin_mac_driver = { 1741e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu .probe = bfin_mac_probe, 1742d7b843d393cec677583e1aa971df09b140dcfd5eMike Frysinger .remove = __devexit_p(bfin_mac_remove), 1743e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu .resume = bfin_mac_resume, 1744e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu .suspend = bfin_mac_suspend, 1745e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu .driver = { 1746c6dd5098f47268976f7d0af3dad29084fd8b6b98Mike Frysinger .name = KBUILD_MODNAME, 174772abb46101fb5c47a9592914adb221b430ff26bdKay Sievers .owner = THIS_MODULE, 174872abb46101fb5c47a9592914adb221b430ff26bdKay Sievers }, 1749e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu}; 1750e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1751e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wustatic int __init bfin_mac_init(void) 1752e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 1753080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang int ret; 1754080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang ret = platform_driver_register(&bfin_mii_bus_driver); 1755080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang if (!ret) 1756080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang return platform_driver_register(&bfin_mac_driver); 1757080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang return -ENODEV; 1758e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1759e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1760e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wumodule_init(bfin_mac_init); 1761e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1762e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wustatic void __exit bfin_mac_cleanup(void) 1763e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu{ 1764e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu platform_driver_unregister(&bfin_mac_driver); 1765080c82550dc1dc3c0d4207ce32d7a8d0ae96fba5Graf Yang platform_driver_unregister(&bfin_mii_bus_driver); 1766e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu} 1767e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wu 1768e190d6b140079c104ba57e5130a9b4ebea618e92Bryan Wumodule_exit(bfin_mac_cleanup); 176972abb46101fb5c47a9592914adb221b430ff26bdKay Sievers 1770