/*
* Intel IXP4xx Ethernet driver for Linux
*
* Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*
* Ethernet port config (0x00 is not present on IXP42X):
*
* logical port 0x00 0x10 0x20
* NPE 0 (NPE-A) 1 (NPE-B) 2 (NPE-C)
* physical PortId 2 0 1
* TX queue 23 24 25
* RX-free queue 26 27 28
* TX-done queue is always 31, per-port RX and TX-ready queues are configurable
*
*
* Queue entries:
* bits 0 -> 1 - NPE ID (RX and TX-done)
* bits 0 -> 2 - priority (TX, per 802.1D)
* bits 3 -> 4 - port ID (user-set?)
* bits 5 -> 31 - physical descriptor address
*/
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/etherdevice.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <mach/npe.h>
#include <mach/qmgr.h>
#define DEBUG_DESC 0
#define DEBUG_RX 0
#define DEBUG_TX 0
#define DEBUG_PKT_BYTES 0
#define DEBUG_MDIO 0
#define DEBUG_CLOSE 0
#define DRV_NAME "ixp4xx_eth"
#define MAX_NPES 3
#define RX_DESCS 64 /* also length of all RX queues */
#define TX_DESCS 16 /* also length of all TX queues */
#define TXDONE_QUEUE_LEN 64 /* dwords */
#define POOL_ALLOC_SIZE (sizeof(struct desc) * (RX_DESCS + TX_DESCS))
#define REGS_SIZE 0x1000
#define MAX_MRU 1536 /* 0x600 */
#define RX_BUFF_SIZE ALIGN((NET_IP_ALIGN) + MAX_MRU, 4)
#define NAPI_WEIGHT 16
#define MDIO_INTERVAL (3 * HZ)
#define MAX_MDIO_RETRIES 100 /* microseconds, typically 30 cycles */
#define MAX_CLOSE_WAIT 1000 /* microseconds, typically 2-3 cycles */
#define NPE_ID(port_id) ((port_id) >> 4)
#define PHYSICAL_ID(port_id) ((NPE_ID(port_id) + 2) % 3)
#define TX_QUEUE(port_id) (NPE_ID(port_id) + 23)
#define RXFREE_QUEUE(port_id) (NPE_ID(port_id) + 26)
#define TXDONE_QUEUE 31
/* TX Control Registers */
#define TX_CNTRL0_TX_EN 0x01
#define TX_CNTRL0_HALFDUPLEX 0x02
#define TX_CNTRL0_RETRY 0x04
#define TX_CNTRL0_PAD_EN 0x08
#define TX_CNTRL0_APPEND_FCS 0x10
#define TX_CNTRL0_2DEFER 0x20
#define TX_CNTRL0_RMII 0x40 /* reduced MII */
#define TX_CNTRL1_RETRIES 0x0F /* 4 bits */
/* RX Control Registers */
#define RX_CNTRL0_RX_EN 0x01
#define RX_CNTRL0_PADSTRIP_EN 0x02
#define RX_CNTRL0_SEND_FCS 0x04
#define RX_CNTRL0_PAUSE_EN 0x08
#define RX_CNTRL0_LOOP_EN 0x10
#define RX_CNTRL0_ADDR_FLTR_EN 0x20
#define RX_CNTRL0_RX_RUNT_EN 0x40
#define RX_CNTRL0_BCAST_DIS 0x80
#define RX_CNTRL1_DEFER_EN 0x01
/* Core Control Register */
#define CORE_RESET 0x01
#define CORE_RX_FIFO_FLUSH 0x02
#define CORE_TX_FIFO_FLUSH 0x04
#define CORE_SEND_JAM 0x08
#define CORE_MDC_EN 0x10 /* MDIO using NPE-B ETH-0 only */
#define DEFAULT_TX_CNTRL0 (TX_CNTRL0_TX_EN | TX_CNTRL0_RETRY | \
TX_CNTRL0_PAD_EN | TX_CNTRL0_APPEND_FCS | \
TX_CNTRL0_2DEFER)
#define DEFAULT_RX_CNTRL0 RX_CNTRL0_RX_EN
#define DEFAULT_CORE_CNTRL CORE_MDC_EN
/* NPE message codes */
#define NPE_GETSTATUS 0x00
#define NPE_EDB_SETPORTADDRESS 0x01
#define NPE_EDB_GETMACADDRESSDATABASE 0x02
#define NPE_EDB_SETMACADDRESSSDATABASE 0x03
#define NPE_GETSTATS 0x04
#define NPE_RESETSTATS 0x05
#define NPE_SETMAXFRAMELENGTHS 0x06
#define NPE_VLAN_SETRXTAGMODE 0x07
#define NPE_VLAN_SETDEFAULTRXVID 0x08
#define NPE_VLAN_SETPORTVLANTABLEENTRY 0x09
#define NPE_VLAN_SETPORTVLANTABLERANGE 0x0A
#define NPE_VLAN_SETRXQOSENTRY 0x0B
#define NPE_VLAN_SETPORTIDEXTRACTIONMODE 0x0C
#define NPE_STP_SETBLOCKINGSTATE 0x0D
#define NPE_FW_SETFIREWALLMODE 0x0E
#define NPE_PC_SETFRAMECONTROLDURATIONID 0x0F
#define NPE_PC_SETAPMACTABLE 0x11
#define NPE_SETLOOPBACK_MODE 0x12
#define NPE_PC_SETBSSIDTABLE 0x13
#define NPE_ADDRESS_FILTER_CONFIG 0x14
#define NPE_APPENDFCSCONFIG 0x15
#define NPE_NOTIFY_MAC_RECOVERY_DONE 0x16
#define NPE_MAC_RECOVERY_START 0x17
#ifdef __ARMEB__
typedef struct sk_buff buffer_t;
#define free_buffer dev_kfree_skb
#define free_buffer_irq dev_kfree_skb_irq
#else
typedef void buffer_t;
#define free_buffer kfree
#define free_buffer_irq kfree
#endif
struct eth_regs {
u32 tx_control[2], __res1[2]; /* 000 */
u32 rx_control[2], __res2[2]; /* 010 */
u32 random_seed, __res3[3]; /* 020 */
u32 partial_empty_threshold, __res4; /* 030 */
u32 partial_full_threshold, __res5; /* 038 */
u32 tx_start_bytes, __res6[3]; /* 040 */
u32 tx_deferral, rx_deferral, __res7[2];/* 050 */
u32 tx_2part_deferral[2], __res8[2]; /* 060 */
u32 slot_time, __res9[3]; /* 070 */
u32 mdio_command[4]; /* 080 */
u32 mdio_status[4]; /* 090 */