/***************************************************************************
*
* Copyright (C) 2007-2010 SMSC
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*
*****************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "smsc75xx.h"
#define SMSC_CHIPNAME "smsc75xx"
#define SMSC_DRIVER_VERSION "1.0.0"
#define HS_USB_PKT_SIZE (512)
#define FS_USB_PKT_SIZE (64)
#define DEFAULT_HS_BURST_CAP_SIZE (16 * 1024 + 5 * HS_USB_PKT_SIZE)
#define DEFAULT_FS_BURST_CAP_SIZE (6 * 1024 + 33 * FS_USB_PKT_SIZE)
#define DEFAULT_BULK_IN_DELAY (0x00002000)
#define MAX_SINGLE_PACKET_SIZE (9000)
#define LAN75XX_EEPROM_MAGIC (0x7500)
#define EEPROM_MAC_OFFSET (0x01)
#define DEFAULT_TX_CSUM_ENABLE (true)
#define DEFAULT_RX_CSUM_ENABLE (true)
#define SMSC75XX_INTERNAL_PHY_ID (1)
#define SMSC75XX_TX_OVERHEAD (8)
#define MAX_RX_FIFO_SIZE (20 * 1024)
#define MAX_TX_FIFO_SIZE (12 * 1024)
#define USB_VENDOR_ID_SMSC (0x0424)
#define USB_PRODUCT_ID_LAN7500 (0x7500)
#define USB_PRODUCT_ID_LAN7505 (0x7505)
#define RXW_PADDING 2
#define SUPPORTED_WAKE (WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \
WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)
#define SUSPEND_SUSPEND0 (0x01)
#define SUSPEND_SUSPEND1 (0x02)
#define SUSPEND_SUSPEND2 (0x04)
#define SUSPEND_SUSPEND3 (0x08)
#define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
struct smsc75xx_priv {
struct usbnet *dev;
u32 rfe_ctl;
u32 wolopts;
u32 multicast_hash_table[DP_SEL_VHF_HASH_LEN];
struct mutex dataport_mutex;
spinlock_t rfe_ctl_lock;
struct work_struct set_multicast;
u8 suspend_flags;
};
struct usb_context {
struct usb_ctrlrequest req;
struct usbnet *dev;
};
static bool turbo_mode = true;
module_param(turbo_mode, bool, 0644);
MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index,
u32 *data, int in_pm)
{
u32 buf;
int ret;
int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
BUG_ON(!dev);
if (!in_pm)
fn = usbnet_read_cmd;
else
fn = usbnet_read_cmd_nopm;
ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
| USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, index, &buf, 4);
if (unlikely(ret < 0))
netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
index, ret);
le32_to_cpus(&buf);
*data = buf;
return ret;
}
static int __must_check __smsc75xx_write_reg(struct usbnet *dev, u32 index,
u32 data, int in_pm)
{
u32 buf;
int ret;
int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
BUG_ON(!dev);
if (!in_pm)
fn = usbnet_write_cmd;
else
fn = usbnet_write_cmd_nopm;
buf = data;
cpu_to_le32s(&buf);
ret = fn(dev, USB_VENDOR_REQUEST_WRITE_REGISTER, USB_DIR_OUT
| USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, index, &buf, 4);
if (unlikely(ret < 0))
netdev_warn(dev->net, "Failed to write reg index 0x%08x: %d\n",
index, ret);
return ret;
}
static int __must_check smsc75xx_read_reg_nopm(struct usbnet *dev, u32 index,
u32 *data)
{
return __smsc75xx_read_reg(dev, index, data, 1);
}
static int __must_check smsc75xx_write_reg_nopm(struct usbnet *dev, u32 index,
u32 data)
{
return __smsc75xx_write_reg(dev, index, data, 1);
}
static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index,
u32 *data)
{
return __smsc75xx_read_reg(dev, index, data, 0);
}
static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
u32 data)
{
return __smsc75xx_write_reg(dev, index, data, 0);
}
/* Loop until the read is completed with timeout
* called with phy_mutex held */
static __must_check int __smsc75xx_phy_wait_not_busy(struct usbnet *dev,
int in_pm)
{
unsigned long start_time = jiffies;
u32 val;
int ret;
do {
ret = __smsc75xx_read_reg(dev, MII_ACCESS, &val, in_pm);
if (ret < 0) {
netdev_warn(dev->net, "Error reading MII_ACCESS\n");
return ret;
}
if (!(val & MII_ACCESS_BUSY))
return 0;
} while (!time_after(jiffies, start_time + HZ));
return -EIO;
}
static int __smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx,
int in_pm)
{
struct usbnet *dev = netdev_priv(netdev);
u32 val, addr;
int ret;
mutex_lock(&dev->phy_mutex);
/* confirm MII not busy */
ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
if (ret < 0) {
netdev_warn(dev->net, "MII is busy in smsc75xx_mdio_read\n");
goto done;
}
/* set the address, index & direction (read from PHY) */
phy_id &= dev->mii.phy_id_mask;
idx &= dev->mii.reg_num_mask;
addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
| ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
| MII_ACCESS_READ | MII_ACCESS_BUSY;
ret = __smsc75xx_write_reg(dev, MII_ACCESS, addr, in_pm);
if (ret < 0) {
netdev_warn(dev->net, "Error writing MII_ACCESS\n");
goto done;
}
ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
if (ret < 0) {
netdev_warn(dev->net, "Timed out reading MII reg %02X\n", idx);
goto done;
}
ret = __smsc75xx_read_reg(dev, MII_DATA, &val, in_pm);
if (ret < 0) {
netdev_warn(dev->net, "Error reading MII_DATA\n");
goto done;
}
ret = (u16)(val & 0xFFFF);
done:
mutex_unlock(&dev->phy_mutex);
return ret;
}
static void __smsc75xx_mdio_write(struct net_device *netdev, int phy_id,
int idx, int regval, int in_pm)
{
struct usbnet *dev = netdev_priv(netdev);
u32 val, addr;
int ret;
mutex_lock(&dev->phy_mutex);
/* confirm MII not busy */
ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
if (ret < 0) {
netdev_warn(dev->net, "MII is busy in smsc75xx_mdio_write\n");
goto done;
}
val = regval;
ret = __smsc75xx_write_reg(dev, MII_DATA, val, in_pm);
if (ret < 0) {
netdev_warn(dev->net, "Error writing MII_DATA\n");
goto done;
}
/* set the address, index & direction (write to PHY) */
phy_id &= dev->mii.phy_id_mask;
idx &= dev->mii.reg_num_mask;
addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
| ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
| MII_ACCESS_WRITE | MII_ACCESS_BUSY;
ret = __smsc75xx_write_reg(dev, MII_ACCESS, addr, in_pm);
if (ret < 0) {
netdev_warn(dev->net, "Error writing MII_ACCESS\n");
goto done;
}
ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
if (ret < 0) {
netdev_warn(dev->net, "Timed out writing MII reg %02X\n", idx);
goto done;
}
done:
mutex_unlock(&dev->phy_mutex);
}
static int smsc75xx_mdio_read_nopm(struct net_device *netdev, int phy_id,
int idx)
{
return __smsc75xx_mdio_read(netdev, phy_id, idx, 1);
}
static void smsc75xx_mdio_write_nopm(struct net_device *netdev, int phy_id,
int idx, int regval)
{
__smsc75xx_mdio_write(netdev, phy_id, idx, regval, 1);
}
static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
{
return __smsc75xx_mdio_read(netdev, phy_id, idx, 0);
}
static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
int regval)
{
__smsc75xx_mdio_write(netdev, phy_id, idx, regval, 0);
}
static int smsc75xx_wait_eeprom(struct usbnet *dev)
{
unsigned long start_time = jiffies;
u32 val;
int ret;
do {
ret = smsc75xx_read_reg(dev, E2P_CMD, &val);
if (ret < 0) {
netdev_warn(dev->net, "Error reading E2P_CMD\n");
return ret;
}
if (!(val & E2P_CMD_BUSY) || (val & E2P_CMD_TIMEOUT))
break;
udelay(40);
} while (!time_after(jiffies, start_time + HZ));
if (val & (E2P_CMD_TIMEOUT | E2P_CMD_BUSY)) {
netdev_warn(dev->net, "EEPROM read operation timeout\n");
return -EIO;
}
return 0;
}
static int smsc75xx_eeprom_confirm_not_busy(struct usbnet *dev)
{
unsigned long start_time = jiffies;
u32 val;
int ret;
do {
ret = smsc75xx_read_reg(dev, E2P_CMD, &val);
if (ret < 0) {
netdev_warn(dev->net, "Error reading E2P_CMD\n");
return ret;
}
if (!(val & E2P_CMD_BUSY))
return 0;
udelay(40);
} while (!time_after(jiffies, start_time + HZ));
netdev_warn(dev->net, "EEPROM is busy\n");
return -EIO;
}
static int smsc75xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length,
u8 *data)
{
u32 val;
int i, ret;
BUG_ON(!dev);
BUG_ON(!data);
ret = smsc75xx_eeprom_confirm_not_busy(dev);
if (ret)
return ret;
for (i = 0; i < length; i++) {
val = E2P_CMD_BUSY | E2P_CMD_READ | (offset & E2P_CMD_ADDR);
ret = smsc75xx_write_reg(dev, E2P_CMD, val);
if (ret < 0) {
netdev_warn(dev->net, "Error writing E2P_CMD\n");
return ret;
}
ret = smsc75xx_wait_eeprom(dev);
if (ret < 0)
return ret;
ret = smsc75xx_read_reg(dev, E2P_DATA, &val);
if (ret < 0) {
netdev_warn(dev->net, "Error reading E2P_DATA\n");
return ret;
}
data[i] = val & 0xFF;
offset++;
}
return 0;
}
static int smsc75xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
u8 *data)
{
u32 val;
int i, ret;
BUG_ON(!dev);
BUG_ON(!data);
ret = smsc75xx_eeprom_confirm_not_busy(dev);
if (ret)
return ret;
/* Issue write/erase enable command */
val = E2P_CMD_BUSY | E2P_CMD_EWEN;
ret = smsc75xx_write_reg(dev, E2P_CMD, val);
if (ret < 0) {
netdev_warn(dev->net, "Error writing E2P_CMD\n");
return ret;
}
ret = smsc75xx_wait_eeprom(dev);
if (ret < 0)
return ret;
for (i = 0; i < length; i++) {
/* Fill data register */
val = data[i];
ret = smsc75xx_write_reg(dev, E2P_DATA, val);
if (ret < 0) {
netdev_warn(dev->net, "Error writing E2P_DATA\n");
return ret;
}
/* Send "write" command */
val = E2P_CMD_BUSY | E2P_CMD_WRITE | (offset & E2P_CMD_ADDR);
ret = smsc75xx_write_reg(dev, E2P_CMD, val);
if (ret < 0) {
netdev_warn(dev->net, "Error writing E2P_CMD\n");
return ret;
}
ret = smsc75xx_wait_eeprom(dev);
if (ret < 0)
return ret;
offset++;
}
return 0;
}
static int smsc75xx_dataport_wait_not_busy(struct usbnet *dev)
{
int i, ret;
for (i = 0; i < 100; i++) {
u32 dp_sel;
ret = smsc75xx_read_reg(dev, DP_SEL, &dp_sel);
if (ret < 0) {
netdev_warn(dev->net, "Error reading DP_SEL\n");
return ret;
}
if (dp_sel & DP_SEL_DPRDY)
return 0;
udelay(40);
}
netdev_warn(dev->net, "smsc75xx_dataport_wait_not_busy timed out\n");
return -EIO;
}
static int smsc75xx_dataport_write(struct usbnet *dev, u32 ram_select, u32 addr,
u32 length, u32 *buf)
{
struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
u32 dp_sel;
int i, ret;
mutex_lock(&pdata->dataport_mutex);
ret = smsc75xx_dataport_wait_not_busy(dev);
if (ret < 0) {
netdev_warn(dev->net, "smsc75xx_dataport_write busy on entry\n");
goto done;
}
ret = smsc75xx_read_reg(dev, DP_SEL, &dp_sel);
if (ret < 0) {
netdev_warn(dev->net, "Error reading DP_SEL\n");
goto done;
}
dp_sel &= ~DP_SEL_RSEL;
dp_sel |= ram_select;
ret = smsc75xx_write_reg(dev, DP_SEL, dp_sel);
if (ret < 0) {
netdev_warn(dev->net, "Error writing DP_SEL\n");
goto done;
}
for (i = 0; i < length; i++) {
ret = smsc75xx_write_reg(dev, DP_ADDR, addr + i);
if (ret < 0) {
netdev_warn(dev->net, "Error writing DP_ADDR\n");
goto done;
}
ret = smsc75xx_write_reg(dev, DP_DATA, buf[i]);
if (ret < 0) {
netdev_warn(d