Loading drivers/net/ethernet/broadcom/tg3.c +250 −250 Original line number Diff line number Diff line Loading @@ -2978,6 +2978,256 @@ static int tg3_nvram_read_be32(struct tg3 *tp, u32 offset, __be32 *val) return res; } static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int i, j, rc = 0; u32 val; for (i = 0; i < len; i += 4) { u32 addr; __be32 data; addr = offset + i; memcpy(&data, buf + i, 4); /* * The SEEPROM interface expects the data to always be opposite * the native endian format. We accomplish this by reversing * all the operations that would have been performed on the * data from a call to tg3_nvram_read_be32(). */ tw32(GRC_EEPROM_DATA, swab32(be32_to_cpu(data))); val = tr32(GRC_EEPROM_ADDR); tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK | EEPROM_ADDR_READ); tw32(GRC_EEPROM_ADDR, val | (0 << EEPROM_ADDR_DEVID_SHIFT) | (addr & EEPROM_ADDR_ADDR_MASK) | EEPROM_ADDR_START | EEPROM_ADDR_WRITE); for (j = 0; j < 1000; j++) { val = tr32(GRC_EEPROM_ADDR); if (val & EEPROM_ADDR_COMPLETE) break; msleep(1); } if (!(val & EEPROM_ADDR_COMPLETE)) { rc = -EBUSY; break; } } return rc; } /* offset and length are dword aligned */ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int ret = 0; u32 pagesize = tp->nvram_pagesize; u32 pagemask = pagesize - 1; u32 nvram_cmd; u8 *tmp; tmp = kmalloc(pagesize, GFP_KERNEL); if (tmp == NULL) return -ENOMEM; while (len) { int j; u32 phy_addr, page_off, size; phy_addr = offset & ~pagemask; for (j = 0; j < pagesize; j += 4) { ret = tg3_nvram_read_be32(tp, phy_addr + j, (__be32 *) (tmp + j)); if (ret) break; } if (ret) break; page_off = offset & pagemask; size = pagesize; if (len < size) size = len; len -= size; memcpy(tmp + page_off, buf, size); offset = offset + (pagesize - page_off); tg3_enable_nvram_access(tp); /* * Before we can erase the flash page, we need * to issue a special "write enable" command. */ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; if (tg3_nvram_exec_cmd(tp, nvram_cmd)) break; /* Erase the target page */ tw32(NVRAM_ADDR, phy_addr); nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR | NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE; if (tg3_nvram_exec_cmd(tp, nvram_cmd)) break; /* Issue another write enable to start the write. */ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; if (tg3_nvram_exec_cmd(tp, nvram_cmd)) break; for (j = 0; j < pagesize; j += 4) { __be32 data; data = *((__be32 *) (tmp + j)); tw32(NVRAM_WRDATA, be32_to_cpu(data)); tw32(NVRAM_ADDR, phy_addr + j); nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; if (j == 0) nvram_cmd |= NVRAM_CMD_FIRST; else if (j == (pagesize - 4)) nvram_cmd |= NVRAM_CMD_LAST; ret = tg3_nvram_exec_cmd(tp, nvram_cmd); if (ret) break; } if (ret) break; } nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE; tg3_nvram_exec_cmd(tp, nvram_cmd); kfree(tmp); return ret; } /* offset and length are dword aligned */ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int i, ret = 0; for (i = 0; i < len; i += 4, offset += 4) { u32 page_off, phy_addr, nvram_cmd; __be32 data; memcpy(&data, buf + i, 4); tw32(NVRAM_WRDATA, be32_to_cpu(data)); page_off = offset % tp->nvram_pagesize; phy_addr = tg3_nvram_phys_addr(tp, offset); tw32(NVRAM_ADDR, phy_addr); nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; if (page_off == 0 || i == 0) nvram_cmd |= NVRAM_CMD_FIRST; if (page_off == (tp->nvram_pagesize - 4)) nvram_cmd |= NVRAM_CMD_LAST; if (i == (len - 4)) nvram_cmd |= NVRAM_CMD_LAST; if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && !tg3_flag(tp, 5755_PLUS) && (tp->nvram_jedecnum == JEDEC_ST) && (nvram_cmd & NVRAM_CMD_FIRST)) { u32 cmd; cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; ret = tg3_nvram_exec_cmd(tp, cmd); if (ret) break; } if (!tg3_flag(tp, FLASH)) { /* We always do complete word writes to eeprom. */ nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST); } ret = tg3_nvram_exec_cmd(tp, nvram_cmd); if (ret) break; } return ret; } /* offset and length are dword aligned */ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int ret; if (tg3_flag(tp, EEPROM_WRITE_PROT)) { tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl & ~GRC_LCLCTRL_GPIO_OUTPUT1); udelay(40); } if (!tg3_flag(tp, NVRAM)) { ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf); } else { u32 grc_mode; ret = tg3_nvram_lock(tp); if (ret) return ret; tg3_enable_nvram_access(tp); if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) tw32(NVRAM_WRITE1, 0x406); grc_mode = tr32(GRC_MODE); tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE); if (tg3_flag(tp, NVRAM_BUFFERED) || !tg3_flag(tp, FLASH)) { ret = tg3_nvram_write_block_buffered(tp, offset, len, buf); } else { ret = tg3_nvram_write_block_unbuffered(tp, offset, len, buf); } grc_mode = tr32(GRC_MODE); tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE); tg3_disable_nvram_access(tp); tg3_nvram_unlock(tp); } if (tg3_flag(tp, EEPROM_WRITE_PROT)) { tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); udelay(40); } return ret; } #define RX_CPU_SCRATCH_BASE 0x30000 #define RX_CPU_SCRATCH_SIZE 0x04000 #define TX_CPU_SCRATCH_BASE 0x34000 Loading Loading @@ -10147,8 +10397,6 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, return 0; } static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf); static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { struct tg3 *tp = netdev_priv(dev); Loading Loading @@ -12745,254 +12993,6 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) } } static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int i, j, rc = 0; u32 val; for (i = 0; i < len; i += 4) { u32 addr; __be32 data; addr = offset + i; memcpy(&data, buf + i, 4); /* * The SEEPROM interface expects the data to always be opposite * the native endian format. We accomplish this by reversing * all the operations that would have been performed on the * data from a call to tg3_nvram_read_be32(). */ tw32(GRC_EEPROM_DATA, swab32(be32_to_cpu(data))); val = tr32(GRC_EEPROM_ADDR); tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK | EEPROM_ADDR_READ); tw32(GRC_EEPROM_ADDR, val | (0 << EEPROM_ADDR_DEVID_SHIFT) | (addr & EEPROM_ADDR_ADDR_MASK) | EEPROM_ADDR_START | EEPROM_ADDR_WRITE); for (j = 0; j < 1000; j++) { val = tr32(GRC_EEPROM_ADDR); if (val & EEPROM_ADDR_COMPLETE) break; msleep(1); } if (!(val & EEPROM_ADDR_COMPLETE)) { rc = -EBUSY; break; } } return rc; } /* offset and length are dword aligned */ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int ret = 0; u32 pagesize = tp->nvram_pagesize; u32 pagemask = pagesize - 1; u32 nvram_cmd; u8 *tmp; tmp = kmalloc(pagesize, GFP_KERNEL); if (tmp == NULL) return -ENOMEM; while (len) { int j; u32 phy_addr, page_off, size; phy_addr = offset & ~pagemask; for (j = 0; j < pagesize; j += 4) { ret = tg3_nvram_read_be32(tp, phy_addr + j, (__be32 *) (tmp + j)); if (ret) break; } if (ret) break; page_off = offset & pagemask; size = pagesize; if (len < size) size = len; len -= size; memcpy(tmp + page_off, buf, size); offset = offset + (pagesize - page_off); tg3_enable_nvram_access(tp); /* * Before we can erase the flash page, we need * to issue a special "write enable" command. */ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; if (tg3_nvram_exec_cmd(tp, nvram_cmd)) break; /* Erase the target page */ tw32(NVRAM_ADDR, phy_addr); nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR | NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE; if (tg3_nvram_exec_cmd(tp, nvram_cmd)) break; /* Issue another write enable to start the write. */ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; if (tg3_nvram_exec_cmd(tp, nvram_cmd)) break; for (j = 0; j < pagesize; j += 4) { __be32 data; data = *((__be32 *) (tmp + j)); tw32(NVRAM_WRDATA, be32_to_cpu(data)); tw32(NVRAM_ADDR, phy_addr + j); nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; if (j == 0) nvram_cmd |= NVRAM_CMD_FIRST; else if (j == (pagesize - 4)) nvram_cmd |= NVRAM_CMD_LAST; if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) break; } if (ret) break; } nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE; tg3_nvram_exec_cmd(tp, nvram_cmd); kfree(tmp); return ret; } /* offset and length are dword aligned */ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int i, ret = 0; for (i = 0; i < len; i += 4, offset += 4) { u32 page_off, phy_addr, nvram_cmd; __be32 data; memcpy(&data, buf + i, 4); tw32(NVRAM_WRDATA, be32_to_cpu(data)); page_off = offset % tp->nvram_pagesize; phy_addr = tg3_nvram_phys_addr(tp, offset); tw32(NVRAM_ADDR, phy_addr); nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; if (page_off == 0 || i == 0) nvram_cmd |= NVRAM_CMD_FIRST; if (page_off == (tp->nvram_pagesize - 4)) nvram_cmd |= NVRAM_CMD_LAST; if (i == (len - 4)) nvram_cmd |= NVRAM_CMD_LAST; if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && !tg3_flag(tp, 5755_PLUS) && (tp->nvram_jedecnum == JEDEC_ST) && (nvram_cmd & NVRAM_CMD_FIRST)) { if ((ret = tg3_nvram_exec_cmd(tp, NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE))) break; } if (!tg3_flag(tp, FLASH)) { /* We always do complete word writes to eeprom. */ nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST); } if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) break; } return ret; } /* offset and length are dword aligned */ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int ret; if (tg3_flag(tp, EEPROM_WRITE_PROT)) { tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl & ~GRC_LCLCTRL_GPIO_OUTPUT1); udelay(40); } if (!tg3_flag(tp, NVRAM)) { ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf); } else { u32 grc_mode; ret = tg3_nvram_lock(tp); if (ret) return ret; tg3_enable_nvram_access(tp); if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) tw32(NVRAM_WRITE1, 0x406); grc_mode = tr32(GRC_MODE); tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE); if (tg3_flag(tp, NVRAM_BUFFERED) || !tg3_flag(tp, FLASH)) { ret = tg3_nvram_write_block_buffered(tp, offset, len, buf); } else { ret = tg3_nvram_write_block_unbuffered(tp, offset, len, buf); } grc_mode = tr32(GRC_MODE); tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE); tg3_disable_nvram_access(tp); tg3_nvram_unlock(tp); } if (tg3_flag(tp, EEPROM_WRITE_PROT)) { tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); udelay(40); } return ret; } struct subsys_tbl_ent { u16 subsys_vendor, subsys_devid; u32 phy_id; Loading Loading
drivers/net/ethernet/broadcom/tg3.c +250 −250 Original line number Diff line number Diff line Loading @@ -2978,6 +2978,256 @@ static int tg3_nvram_read_be32(struct tg3 *tp, u32 offset, __be32 *val) return res; } static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int i, j, rc = 0; u32 val; for (i = 0; i < len; i += 4) { u32 addr; __be32 data; addr = offset + i; memcpy(&data, buf + i, 4); /* * The SEEPROM interface expects the data to always be opposite * the native endian format. We accomplish this by reversing * all the operations that would have been performed on the * data from a call to tg3_nvram_read_be32(). */ tw32(GRC_EEPROM_DATA, swab32(be32_to_cpu(data))); val = tr32(GRC_EEPROM_ADDR); tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK | EEPROM_ADDR_READ); tw32(GRC_EEPROM_ADDR, val | (0 << EEPROM_ADDR_DEVID_SHIFT) | (addr & EEPROM_ADDR_ADDR_MASK) | EEPROM_ADDR_START | EEPROM_ADDR_WRITE); for (j = 0; j < 1000; j++) { val = tr32(GRC_EEPROM_ADDR); if (val & EEPROM_ADDR_COMPLETE) break; msleep(1); } if (!(val & EEPROM_ADDR_COMPLETE)) { rc = -EBUSY; break; } } return rc; } /* offset and length are dword aligned */ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int ret = 0; u32 pagesize = tp->nvram_pagesize; u32 pagemask = pagesize - 1; u32 nvram_cmd; u8 *tmp; tmp = kmalloc(pagesize, GFP_KERNEL); if (tmp == NULL) return -ENOMEM; while (len) { int j; u32 phy_addr, page_off, size; phy_addr = offset & ~pagemask; for (j = 0; j < pagesize; j += 4) { ret = tg3_nvram_read_be32(tp, phy_addr + j, (__be32 *) (tmp + j)); if (ret) break; } if (ret) break; page_off = offset & pagemask; size = pagesize; if (len < size) size = len; len -= size; memcpy(tmp + page_off, buf, size); offset = offset + (pagesize - page_off); tg3_enable_nvram_access(tp); /* * Before we can erase the flash page, we need * to issue a special "write enable" command. */ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; if (tg3_nvram_exec_cmd(tp, nvram_cmd)) break; /* Erase the target page */ tw32(NVRAM_ADDR, phy_addr); nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR | NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE; if (tg3_nvram_exec_cmd(tp, nvram_cmd)) break; /* Issue another write enable to start the write. */ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; if (tg3_nvram_exec_cmd(tp, nvram_cmd)) break; for (j = 0; j < pagesize; j += 4) { __be32 data; data = *((__be32 *) (tmp + j)); tw32(NVRAM_WRDATA, be32_to_cpu(data)); tw32(NVRAM_ADDR, phy_addr + j); nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; if (j == 0) nvram_cmd |= NVRAM_CMD_FIRST; else if (j == (pagesize - 4)) nvram_cmd |= NVRAM_CMD_LAST; ret = tg3_nvram_exec_cmd(tp, nvram_cmd); if (ret) break; } if (ret) break; } nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE; tg3_nvram_exec_cmd(tp, nvram_cmd); kfree(tmp); return ret; } /* offset and length are dword aligned */ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int i, ret = 0; for (i = 0; i < len; i += 4, offset += 4) { u32 page_off, phy_addr, nvram_cmd; __be32 data; memcpy(&data, buf + i, 4); tw32(NVRAM_WRDATA, be32_to_cpu(data)); page_off = offset % tp->nvram_pagesize; phy_addr = tg3_nvram_phys_addr(tp, offset); tw32(NVRAM_ADDR, phy_addr); nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; if (page_off == 0 || i == 0) nvram_cmd |= NVRAM_CMD_FIRST; if (page_off == (tp->nvram_pagesize - 4)) nvram_cmd |= NVRAM_CMD_LAST; if (i == (len - 4)) nvram_cmd |= NVRAM_CMD_LAST; if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && !tg3_flag(tp, 5755_PLUS) && (tp->nvram_jedecnum == JEDEC_ST) && (nvram_cmd & NVRAM_CMD_FIRST)) { u32 cmd; cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; ret = tg3_nvram_exec_cmd(tp, cmd); if (ret) break; } if (!tg3_flag(tp, FLASH)) { /* We always do complete word writes to eeprom. */ nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST); } ret = tg3_nvram_exec_cmd(tp, nvram_cmd); if (ret) break; } return ret; } /* offset and length are dword aligned */ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int ret; if (tg3_flag(tp, EEPROM_WRITE_PROT)) { tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl & ~GRC_LCLCTRL_GPIO_OUTPUT1); udelay(40); } if (!tg3_flag(tp, NVRAM)) { ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf); } else { u32 grc_mode; ret = tg3_nvram_lock(tp); if (ret) return ret; tg3_enable_nvram_access(tp); if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) tw32(NVRAM_WRITE1, 0x406); grc_mode = tr32(GRC_MODE); tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE); if (tg3_flag(tp, NVRAM_BUFFERED) || !tg3_flag(tp, FLASH)) { ret = tg3_nvram_write_block_buffered(tp, offset, len, buf); } else { ret = tg3_nvram_write_block_unbuffered(tp, offset, len, buf); } grc_mode = tr32(GRC_MODE); tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE); tg3_disable_nvram_access(tp); tg3_nvram_unlock(tp); } if (tg3_flag(tp, EEPROM_WRITE_PROT)) { tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); udelay(40); } return ret; } #define RX_CPU_SCRATCH_BASE 0x30000 #define RX_CPU_SCRATCH_SIZE 0x04000 #define TX_CPU_SCRATCH_BASE 0x34000 Loading Loading @@ -10147,8 +10397,6 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, return 0; } static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf); static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { struct tg3 *tp = netdev_priv(dev); Loading Loading @@ -12745,254 +12993,6 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) } } static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int i, j, rc = 0; u32 val; for (i = 0; i < len; i += 4) { u32 addr; __be32 data; addr = offset + i; memcpy(&data, buf + i, 4); /* * The SEEPROM interface expects the data to always be opposite * the native endian format. We accomplish this by reversing * all the operations that would have been performed on the * data from a call to tg3_nvram_read_be32(). */ tw32(GRC_EEPROM_DATA, swab32(be32_to_cpu(data))); val = tr32(GRC_EEPROM_ADDR); tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK | EEPROM_ADDR_READ); tw32(GRC_EEPROM_ADDR, val | (0 << EEPROM_ADDR_DEVID_SHIFT) | (addr & EEPROM_ADDR_ADDR_MASK) | EEPROM_ADDR_START | EEPROM_ADDR_WRITE); for (j = 0; j < 1000; j++) { val = tr32(GRC_EEPROM_ADDR); if (val & EEPROM_ADDR_COMPLETE) break; msleep(1); } if (!(val & EEPROM_ADDR_COMPLETE)) { rc = -EBUSY; break; } } return rc; } /* offset and length are dword aligned */ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int ret = 0; u32 pagesize = tp->nvram_pagesize; u32 pagemask = pagesize - 1; u32 nvram_cmd; u8 *tmp; tmp = kmalloc(pagesize, GFP_KERNEL); if (tmp == NULL) return -ENOMEM; while (len) { int j; u32 phy_addr, page_off, size; phy_addr = offset & ~pagemask; for (j = 0; j < pagesize; j += 4) { ret = tg3_nvram_read_be32(tp, phy_addr + j, (__be32 *) (tmp + j)); if (ret) break; } if (ret) break; page_off = offset & pagemask; size = pagesize; if (len < size) size = len; len -= size; memcpy(tmp + page_off, buf, size); offset = offset + (pagesize - page_off); tg3_enable_nvram_access(tp); /* * Before we can erase the flash page, we need * to issue a special "write enable" command. */ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; if (tg3_nvram_exec_cmd(tp, nvram_cmd)) break; /* Erase the target page */ tw32(NVRAM_ADDR, phy_addr); nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR | NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE; if (tg3_nvram_exec_cmd(tp, nvram_cmd)) break; /* Issue another write enable to start the write. */ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; if (tg3_nvram_exec_cmd(tp, nvram_cmd)) break; for (j = 0; j < pagesize; j += 4) { __be32 data; data = *((__be32 *) (tmp + j)); tw32(NVRAM_WRDATA, be32_to_cpu(data)); tw32(NVRAM_ADDR, phy_addr + j); nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; if (j == 0) nvram_cmd |= NVRAM_CMD_FIRST; else if (j == (pagesize - 4)) nvram_cmd |= NVRAM_CMD_LAST; if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) break; } if (ret) break; } nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE; tg3_nvram_exec_cmd(tp, nvram_cmd); kfree(tmp); return ret; } /* offset and length are dword aligned */ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int i, ret = 0; for (i = 0; i < len; i += 4, offset += 4) { u32 page_off, phy_addr, nvram_cmd; __be32 data; memcpy(&data, buf + i, 4); tw32(NVRAM_WRDATA, be32_to_cpu(data)); page_off = offset % tp->nvram_pagesize; phy_addr = tg3_nvram_phys_addr(tp, offset); tw32(NVRAM_ADDR, phy_addr); nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; if (page_off == 0 || i == 0) nvram_cmd |= NVRAM_CMD_FIRST; if (page_off == (tp->nvram_pagesize - 4)) nvram_cmd |= NVRAM_CMD_LAST; if (i == (len - 4)) nvram_cmd |= NVRAM_CMD_LAST; if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && !tg3_flag(tp, 5755_PLUS) && (tp->nvram_jedecnum == JEDEC_ST) && (nvram_cmd & NVRAM_CMD_FIRST)) { if ((ret = tg3_nvram_exec_cmd(tp, NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE))) break; } if (!tg3_flag(tp, FLASH)) { /* We always do complete word writes to eeprom. */ nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST); } if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) break; } return ret; } /* offset and length are dword aligned */ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int ret; if (tg3_flag(tp, EEPROM_WRITE_PROT)) { tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl & ~GRC_LCLCTRL_GPIO_OUTPUT1); udelay(40); } if (!tg3_flag(tp, NVRAM)) { ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf); } else { u32 grc_mode; ret = tg3_nvram_lock(tp); if (ret) return ret; tg3_enable_nvram_access(tp); if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) tw32(NVRAM_WRITE1, 0x406); grc_mode = tr32(GRC_MODE); tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE); if (tg3_flag(tp, NVRAM_BUFFERED) || !tg3_flag(tp, FLASH)) { ret = tg3_nvram_write_block_buffered(tp, offset, len, buf); } else { ret = tg3_nvram_write_block_unbuffered(tp, offset, len, buf); } grc_mode = tr32(GRC_MODE); tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE); tg3_disable_nvram_access(tp); tg3_nvram_unlock(tp); } if (tg3_flag(tp, EEPROM_WRITE_PROT)) { tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); udelay(40); } return ret; } struct subsys_tbl_ent { u16 subsys_vendor, subsys_devid; u32 phy_id; Loading