Loading drivers/net/smsc9420.c +121 −0 Original line number Diff line number Diff line Loading @@ -293,6 +293,124 @@ static int smsc9420_ethtool_nway_reset(struct net_device *netdev) return phy_start_aneg(pd->phy_dev); } static void smsc9420_eeprom_enable_access(struct smsc9420_pdata *pd) { unsigned int temp = smsc9420_reg_read(pd, GPIO_CFG); temp &= ~GPIO_CFG_EEPR_EN_; smsc9420_reg_write(pd, GPIO_CFG, temp); msleep(1); } static int smsc9420_eeprom_send_cmd(struct smsc9420_pdata *pd, u32 op) { int timeout = 100; u32 e2cmd; smsc_dbg(HW, "op 0x%08x", op); if (smsc9420_reg_read(pd, E2P_CMD) & E2P_CMD_EPC_BUSY_) { smsc_warn(HW, "Busy at start"); return -EBUSY; } e2cmd = op | E2P_CMD_EPC_BUSY_; smsc9420_reg_write(pd, E2P_CMD, e2cmd); do { msleep(1); e2cmd = smsc9420_reg_read(pd, E2P_CMD); } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--)); if (!timeout) { smsc_info(HW, "TIMED OUT"); return -EAGAIN; } if (e2cmd & E2P_CMD_EPC_TIMEOUT_) { smsc_info(HW, "Error occured during eeprom operation"); return -EINVAL; } return 0; } static int smsc9420_eeprom_read_location(struct smsc9420_pdata *pd, u8 address, u8 *data) { u32 op = E2P_CMD_EPC_CMD_READ_ | address; int ret; smsc_dbg(HW, "address 0x%x", address); ret = smsc9420_eeprom_send_cmd(pd, op); if (!ret) data[address] = smsc9420_reg_read(pd, E2P_DATA); return ret; } static int smsc9420_eeprom_write_location(struct smsc9420_pdata *pd, u8 address, u8 data) { u32 op = E2P_CMD_EPC_CMD_ERASE_ | address; int ret; smsc_dbg(HW, "address 0x%x, data 0x%x", address, data); ret = smsc9420_eeprom_send_cmd(pd, op); if (!ret) { op = E2P_CMD_EPC_CMD_WRITE_ | address; smsc9420_reg_write(pd, E2P_DATA, (u32)data); ret = smsc9420_eeprom_send_cmd(pd, op); } return ret; } static int smsc9420_ethtool_get_eeprom_len(struct net_device *dev) { return SMSC9420_EEPROM_SIZE; } static int smsc9420_ethtool_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { struct smsc9420_pdata *pd = netdev_priv(dev); u8 eeprom_data[SMSC9420_EEPROM_SIZE]; int len, i; smsc9420_eeprom_enable_access(pd); len = min(eeprom->len, SMSC9420_EEPROM_SIZE); for (i = 0; i < len; i++) { int ret = smsc9420_eeprom_read_location(pd, i, eeprom_data); if (ret < 0) { eeprom->len = 0; return ret; } } memcpy(data, &eeprom_data[eeprom->offset], len); eeprom->len = len; return 0; } static int smsc9420_ethtool_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { struct smsc9420_pdata *pd = netdev_priv(dev); int ret; smsc9420_eeprom_enable_access(pd); smsc9420_eeprom_send_cmd(pd, E2P_CMD_EPC_CMD_EWEN_); ret = smsc9420_eeprom_write_location(pd, eeprom->offset, *data); smsc9420_eeprom_send_cmd(pd, E2P_CMD_EPC_CMD_EWDS_); /* Single byte write, according to man page */ eeprom->len = 1; return ret; } static const struct ethtool_ops smsc9420_ethtool_ops = { .get_settings = smsc9420_ethtool_get_settings, .set_settings = smsc9420_ethtool_set_settings, Loading @@ -301,6 +419,9 @@ static const struct ethtool_ops smsc9420_ethtool_ops = { .set_msglevel = smsc9420_ethtool_set_msglevel, .nway_reset = smsc9420_ethtool_nway_reset, .get_link = ethtool_op_get_link, .get_eeprom_len = smsc9420_ethtool_get_eeprom_len, .get_eeprom = smsc9420_ethtool_get_eeprom, .set_eeprom = smsc9420_ethtool_set_eeprom, }; /* Sets the device MAC address to dev_addr */ Loading drivers/net/smsc9420.h +3 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ #define LAN_REGISTER_EXTENT (0x400) #define SMSC9420_EEPROM_SIZE ((u32)11) #define FLOW_CTRL_TX (1) #define FLOW_CTRL_RX (2) Loading Loading @@ -238,6 +240,7 @@ #define GPIO_CFG_LED_3_ (0x40000000) #define GPIO_CFG_LED_2_ (0x20000000) #define GPIO_CFG_LED_1_ (0x10000000) #define GPIO_CFG_EEPR_EN_ (0x00700000) #define GPT_CFG (0xD4) #define GPT_CFG_TIMER_EN_ (0x20000000) Loading Loading
drivers/net/smsc9420.c +121 −0 Original line number Diff line number Diff line Loading @@ -293,6 +293,124 @@ static int smsc9420_ethtool_nway_reset(struct net_device *netdev) return phy_start_aneg(pd->phy_dev); } static void smsc9420_eeprom_enable_access(struct smsc9420_pdata *pd) { unsigned int temp = smsc9420_reg_read(pd, GPIO_CFG); temp &= ~GPIO_CFG_EEPR_EN_; smsc9420_reg_write(pd, GPIO_CFG, temp); msleep(1); } static int smsc9420_eeprom_send_cmd(struct smsc9420_pdata *pd, u32 op) { int timeout = 100; u32 e2cmd; smsc_dbg(HW, "op 0x%08x", op); if (smsc9420_reg_read(pd, E2P_CMD) & E2P_CMD_EPC_BUSY_) { smsc_warn(HW, "Busy at start"); return -EBUSY; } e2cmd = op | E2P_CMD_EPC_BUSY_; smsc9420_reg_write(pd, E2P_CMD, e2cmd); do { msleep(1); e2cmd = smsc9420_reg_read(pd, E2P_CMD); } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--)); if (!timeout) { smsc_info(HW, "TIMED OUT"); return -EAGAIN; } if (e2cmd & E2P_CMD_EPC_TIMEOUT_) { smsc_info(HW, "Error occured during eeprom operation"); return -EINVAL; } return 0; } static int smsc9420_eeprom_read_location(struct smsc9420_pdata *pd, u8 address, u8 *data) { u32 op = E2P_CMD_EPC_CMD_READ_ | address; int ret; smsc_dbg(HW, "address 0x%x", address); ret = smsc9420_eeprom_send_cmd(pd, op); if (!ret) data[address] = smsc9420_reg_read(pd, E2P_DATA); return ret; } static int smsc9420_eeprom_write_location(struct smsc9420_pdata *pd, u8 address, u8 data) { u32 op = E2P_CMD_EPC_CMD_ERASE_ | address; int ret; smsc_dbg(HW, "address 0x%x, data 0x%x", address, data); ret = smsc9420_eeprom_send_cmd(pd, op); if (!ret) { op = E2P_CMD_EPC_CMD_WRITE_ | address; smsc9420_reg_write(pd, E2P_DATA, (u32)data); ret = smsc9420_eeprom_send_cmd(pd, op); } return ret; } static int smsc9420_ethtool_get_eeprom_len(struct net_device *dev) { return SMSC9420_EEPROM_SIZE; } static int smsc9420_ethtool_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { struct smsc9420_pdata *pd = netdev_priv(dev); u8 eeprom_data[SMSC9420_EEPROM_SIZE]; int len, i; smsc9420_eeprom_enable_access(pd); len = min(eeprom->len, SMSC9420_EEPROM_SIZE); for (i = 0; i < len; i++) { int ret = smsc9420_eeprom_read_location(pd, i, eeprom_data); if (ret < 0) { eeprom->len = 0; return ret; } } memcpy(data, &eeprom_data[eeprom->offset], len); eeprom->len = len; return 0; } static int smsc9420_ethtool_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { struct smsc9420_pdata *pd = netdev_priv(dev); int ret; smsc9420_eeprom_enable_access(pd); smsc9420_eeprom_send_cmd(pd, E2P_CMD_EPC_CMD_EWEN_); ret = smsc9420_eeprom_write_location(pd, eeprom->offset, *data); smsc9420_eeprom_send_cmd(pd, E2P_CMD_EPC_CMD_EWDS_); /* Single byte write, according to man page */ eeprom->len = 1; return ret; } static const struct ethtool_ops smsc9420_ethtool_ops = { .get_settings = smsc9420_ethtool_get_settings, .set_settings = smsc9420_ethtool_set_settings, Loading @@ -301,6 +419,9 @@ static const struct ethtool_ops smsc9420_ethtool_ops = { .set_msglevel = smsc9420_ethtool_set_msglevel, .nway_reset = smsc9420_ethtool_nway_reset, .get_link = ethtool_op_get_link, .get_eeprom_len = smsc9420_ethtool_get_eeprom_len, .get_eeprom = smsc9420_ethtool_get_eeprom, .set_eeprom = smsc9420_ethtool_set_eeprom, }; /* Sets the device MAC address to dev_addr */ Loading
drivers/net/smsc9420.h +3 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ #define LAN_REGISTER_EXTENT (0x400) #define SMSC9420_EEPROM_SIZE ((u32)11) #define FLOW_CTRL_TX (1) #define FLOW_CTRL_RX (2) Loading Loading @@ -238,6 +240,7 @@ #define GPIO_CFG_LED_3_ (0x40000000) #define GPIO_CFG_LED_2_ (0x20000000) #define GPIO_CFG_LED_1_ (0x10000000) #define GPIO_CFG_EEPR_EN_ (0x00700000) #define GPT_CFG (0xD4) #define GPT_CFG_TIMER_EN_ (0x20000000) Loading