/*
* Microchip ENC28J60 ethernet driver (MAC + PHY)
*
* Copyright (C) 2007 Eurek srl
* Author: Claudio Lanconelli <lanconelli.claudio@eptar.com>
* based on enc28j60.c written by David Anders for 2.4 kernel version
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* $Id: enc28j60.c,v 1.22 2007/12/20 10:47:01 claudio Exp $
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/workqueue.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/spi/spi.h>
#include "enc28j60_hw.h"
#define DRV_NAME "enc28j60"
#define DRV_VERSION "1.01"
#define SPI_OPLEN 1
#define ENC28J60_MSG_DEFAULT \
(NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN | NETIF_MSG_LINK)
/* Buffer size required for the largest SPI transfer (i.e., reading a
* frame). */
#define SPI_TRANSFER_BUF_LEN (4 + MAX_FRAMELEN)
#define TX_TIMEOUT (4 * HZ)
/* Max TX retries in case of collision as suggested by errata datasheet */
#define MAX_TX_RETRYCOUNT 16
enum {
RXFILTER_NORMAL,
RXFILTER_MULTI,
RXFILTER_PROMISC
};
/* Driver local data */
struct enc28j60_net {
struct net_device *netdev;
struct spi_device *spi;
struct mutex lock;
struct sk_buff *tx_skb;
struct workqueue_struct *workqueue;
struct work_struct tx_work;
struct work_struct irq_work;
struct work_struct setrx_work;
struct work_struct restart_work;
u8 bank; /* current register bank selected */
u16 next_pk_ptr; /* next packet pointer within FIFO */
u16 max_pk_counter; /* statistics: max packet counter */
u16 tx_retry_count;
bool hw_enable;
bool full_duplex;
int rxfilter;
u32 msg_enable;
u8 spi_transfer_buf[SPI_TRANSFER_BUF_LEN];
};
/* use ethtool to change the level for any given device */
static struct {
u32 msg_enable;
} debug = { -1 };
/*
* SPI read buffer
* wait for the SPI transfer and copy received data to destination
*/
static int
spi_read_buf(struct enc28j60_net *priv, int len, u8 *data)
{
u8 *rx_buf = priv->spi_transfer_buf + 4;
u8 *tx_buf = priv->spi_transfer_buf;
struct spi_transfer t = {
.tx_buf = tx_buf,
.rx_buf = rx_buf,
.len = SPI_OPLEN + len,
};
struct spi_message msg;
int ret;
tx_buf[0] = ENC28J60_READ_BUF_MEM;
tx_buf[1] = tx_buf[2] = tx_buf[3] = 0; /* don't care */
spi_message_init(&msg);
spi_message_add_tail(&t, &msg);
ret = spi_sync(priv->spi, &msg);
if (ret == 0) {
memcpy(data, &rx_buf[SPI_OPLEN], len);
ret = msg.status;
}
#if 0//modify by lxj 2011.11.04 for test
int i;
printk("%s(%d) recv_len=%d\n",__func__,__LINE__,len);
for(i=0;i<len;i++){
printk("%02X ",data[i]);
if((i+1)%16==0){
printk("\n");
}
}
printk("\n");
#endif
if (ret && netif_msg_drv(priv))
printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
__func__, ret);
return ret;
}
/*
* SPI write buffer
*/
static int spi_write_buf(struct enc28j60_net *priv, int len,
const u8 *data)
{
int ret;
if (len > SPI_TRANSFER_BUF_LEN - 1 || len <= 0)
ret = -EINVAL;
else {
priv->spi_transfer_buf[0] = ENC28J60_WRITE_BUF_MEM;
memcpy(&priv->spi_transfer_buf[1], data, len);
#if 0//modify by lxj 2011.11.04 for test
int i;
printk("%s(%d) send_len=%d\n",__func__,__LINE__,len);
for(i=0;i<len;i++){
printk("%02X ",data[i]);
if((i+1)%16==0){
printk("\n");
}
}
printk("\n");
#endif
ret = spi_write(priv->spi, priv->spi_transfer_buf, len + 1);
if (ret && netif_msg_drv(priv))
printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
__func__, ret);
}
#if 0//modify by lxj 2011.11.04 for test
while(1);
#endif
return ret;
}
/*
* basic SPI read operation
*/
static u8 spi_read_op(struct enc28j60_net *priv, u8 op,
u8 addr)
{
u8 tx_buf[2];
u8 rx_buf[4];
u8 val = 0;
int ret;
int slen = SPI_OPLEN;
/* do dummy read if needed */
if (addr & SPRD_MASK)
slen++;
tx_buf[0] = op | (addr & ADDR_MASK);
ret = spi_write_then_read(priv->spi, tx_buf, 1, rx_buf, slen);
if (ret)
printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
__func__, ret);
else
val = rx_buf[slen - 1];
return val;
}
/*
* basic SPI write operation
*/
static int spi_write_op(struct enc28j60_net *priv, u8 op,
u8 addr, u8 val)
{
int ret;
priv->spi_transfer_buf[0] = op | (addr & ADDR_MASK);
priv->spi_transfer_buf[1] = val;
ret = spi_write(priv->spi, priv->spi_transfer_buf, 2);
if (ret && netif_msg_drv(priv))
printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
__func__, ret);
return ret;
}
static int nolock_regb_read(struct enc28j60_net *priv,u8 address);
static void enc28j60_soft_reset(struct enc28j60_net *priv)
{
if (netif_msg_hw(priv))
printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
spi_write_op(priv, ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
/* Errata workaround #1, CLKRDY check is unreliable,
* delay at least 1 mS instead */
udelay(2000);
#if 1//modify by lxj 2011.11.04 for test
u8 reg = nolock_regb_read(priv, ESTAT);
printk("%s(%d) ESTAT=0x%02X\n",__func__,__LINE__,reg);
#endif
}
/*
* select the current register bank if necessary
*/
static void enc28j60_set_bank(struct enc28j60_net *priv, u8 addr)
{
if ((addr & BANK_MASK) != priv->bank) {
u8 b = (addr & BANK_MASK) >> 5;
if (b != (ECON1_BSEL1 | ECON1_BSEL0))
spi_write_op(priv, ENC28J60_BIT_FIELD_CLR, ECON1,
ECON1_BSEL1 | ECON1_BSEL0);
if (b != 0)
spi_write_op(priv, ENC28J60_BIT_FIELD_SET, ECON1, b);
priv->bank = (addr & BANK_MASK);
}
}
/*
* Register access routines through the SPI bus.
* Every register access comes in two flavours:
* - nolock_xxx: caller needs to invoke mutex_lock, usually to access
* atomically more than one register
* - locked_xxx: caller doesn't need to invoke mutex_lock, single access
*
* Some registers can be accessed through the bit field clear and
* bit field set to avoid a read modify write cycle.
*/
/*
* Register bit field Set
*/
static void nolock_reg_bfset(struct enc28j60_net *priv,
u8 addr, u8 mask)
{
enc28j60_set_bank(priv, addr);
spi_write_op(priv, ENC28J60_BIT_FIELD_SET, addr, mask);
}
static void locked_reg_bfset(struct enc28j60_net *priv,
u8 addr, u8 mask)
{
mutex_lock(&priv->lock);
nolock_reg_bfset(priv, addr, mask);
mutex_unlock(&priv->lock);
}
/*
* Register bit field Clear
*/
static void nolock_reg_bfclr(struct enc28j60_net *priv,
u8 addr, u8 mask)
{
enc28j60_set_bank(priv, addr);
spi_write_op(priv, ENC28J60_BIT_FIELD_CLR, addr, mask);
}
static void locked_reg_bfclr(struct enc28j60_net *priv,
u8 addr, u8 mask)
{
mutex_lock(&priv->lock);
nolock_reg_bfclr(priv, addr, mask);
mutex_unlock(&priv->lock);
}
/*
* Register byte read
*/
static int nolock_regb_read(struct enc28j60_net *priv,
u8 address)
{
enc28j60_set_bank(priv, address);
return spi_read_op(priv, ENC28J60_READ_CTRL_REG, address);
}
static int locked_regb_read(struct enc28j60_net *priv,
u8 address)
{
int ret;
mutex_lock(&priv->lock);
ret = nolock_regb_read(priv, address);
mutex_unlock(&priv->lock);
return ret;
}
/*
* Register word read
*/
static int nolock_regw_read(struct enc28j60_net *priv,
u8 address)
{
int rl, rh;
enc28j60_set_bank(priv, address);
rl = spi_read_op(priv, ENC28J60_READ_CTRL_REG, address);
rh = spi_read_op(priv, ENC28J60_READ_CTRL_REG, address + 1);
return (rh << 8) | rl;
}
static int locked_regw_read(struct enc28j60_net *priv,
u8 address)
{
int ret;
mutex_lock(&priv->lock);
ret = nolock_regw_read(priv, address);
mutex_unlock(&priv->lock);
return ret;
}
/*
* Register byte w