Commit c4dab506 authored by Nithin Sujir's avatar Nithin Sujir Committed by David S. Miller

tg3: Download 57766 EEE service patch firmware

This patch downloads the EEE service patch firmware and enables the necessary
EEE flags.
Reviewed-by: default avatarBenjamin Li <benli@broadcom.com>
Signed-off-by: default avatarNithin Nayak Sujir <nsujir@broadcom.com>
Signed-off-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 31f11a95
...@@ -212,6 +212,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) ...@@ -212,6 +212,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
#define TG3_FW_UPDATE_FREQ_SEC (TG3_FW_UPDATE_TIMEOUT_SEC / 2) #define TG3_FW_UPDATE_FREQ_SEC (TG3_FW_UPDATE_TIMEOUT_SEC / 2)
#define FIRMWARE_TG3 "tigon/tg3.bin" #define FIRMWARE_TG3 "tigon/tg3.bin"
#define FIRMWARE_TG357766 "tigon/tg357766.bin"
#define FIRMWARE_TG3TSO "tigon/tg3_tso.bin" #define FIRMWARE_TG3TSO "tigon/tg3_tso.bin"
#define FIRMWARE_TG3TSO5 "tigon/tg3_tso5.bin" #define FIRMWARE_TG3TSO5 "tigon/tg3_tso5.bin"
...@@ -3568,7 +3569,7 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, ...@@ -3568,7 +3569,7 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base,
u32 cpu_scratch_base, int cpu_scratch_size, u32 cpu_scratch_base, int cpu_scratch_size,
const struct tg3_firmware_hdr *fw_hdr) const struct tg3_firmware_hdr *fw_hdr)
{ {
int err, lock_err, i; int err, i;
void (*write_op)(struct tg3 *, u32, u32); void (*write_op)(struct tg3 *, u32, u32);
int total_len = tp->fw->size; int total_len = tp->fw->size;
...@@ -3579,25 +3580,34 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, ...@@ -3579,25 +3580,34 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base,
return -EINVAL; return -EINVAL;
} }
if (tg3_flag(tp, 5705_PLUS)) if (tg3_flag(tp, 5705_PLUS) && tg3_asic_rev(tp) != ASIC_REV_57766)
write_op = tg3_write_mem; write_op = tg3_write_mem;
else else
write_op = tg3_write_indirect_reg32; write_op = tg3_write_indirect_reg32;
/* It is possible that bootcode is still loading at this point. if (tg3_asic_rev(tp) != ASIC_REV_57766) {
* Get the nvram lock first before halting the cpu. /* It is possible that bootcode is still loading at this point.
*/ * Get the nvram lock first before halting the cpu.
lock_err = tg3_nvram_lock(tp); */
err = tg3_halt_cpu(tp, cpu_base); int lock_err = tg3_nvram_lock(tp);
if (!lock_err) err = tg3_halt_cpu(tp, cpu_base);
tg3_nvram_unlock(tp); if (!lock_err)
if (err) tg3_nvram_unlock(tp);
goto out; if (err)
goto out;
for (i = 0; i < cpu_scratch_size; i += sizeof(u32)) for (i = 0; i < cpu_scratch_size; i += sizeof(u32))
write_op(tp, cpu_scratch_base + i, 0); write_op(tp, cpu_scratch_base + i, 0);
tw32(cpu_base + CPU_STATE, 0xffffffff); tw32(cpu_base + CPU_STATE, 0xffffffff);
tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT); tw32(cpu_base + CPU_MODE,
tr32(cpu_base + CPU_MODE) | CPU_MODE_HALT);
} else {
/* Subtract additional main header for fragmented firmware and
* advance to the first fragment
*/
total_len -= TG3_FW_HDR_LEN;
fw_hdr++;
}
do { do {
u32 *fw_data = (u32 *)(fw_hdr + 1); u32 *fw_data = (u32 *)(fw_hdr + 1);
...@@ -3683,6 +3693,78 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) ...@@ -3683,6 +3693,78 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
return 0; return 0;
} }
static int tg3_validate_rxcpu_state(struct tg3 *tp)
{
const int iters = 1000;
int i;
u32 val;
/* Wait for boot code to complete initialization and enter service
* loop. It is then safe to download service patches
*/
for (i = 0; i < iters; i++) {
if (tr32(RX_CPU_HWBKPT) == TG3_SBROM_IN_SERVICE_LOOP)
break;
udelay(10);
}
if (i == iters) {
netdev_err(tp->dev, "Boot code not ready for service patches\n");
return -EBUSY;
}
val = tg3_read_indirect_reg32(tp, TG3_57766_FW_HANDSHAKE);
if (val & 0xff) {
netdev_warn(tp->dev,
"Other patches exist. Not downloading EEE patch\n");
return -EEXIST;
}
return 0;
}
/* tp->lock is held. */
static void tg3_load_57766_firmware(struct tg3 *tp)
{
struct tg3_firmware_hdr *fw_hdr;
if (!tg3_flag(tp, NO_NVRAM))
return;
if (tg3_validate_rxcpu_state(tp))
return;
if (!tp->fw)
return;
/* This firmware blob has a different format than older firmware
* releases as given below. The main difference is we have fragmented
* data to be written to non-contiguous locations.
*
* In the beginning we have a firmware header identical to other
* firmware which consists of version, base addr and length. The length
* here is unused and set to 0xffffffff.
*
* This is followed by a series of firmware fragments which are
* individually identical to previous firmware. i.e. they have the
* firmware header and followed by data for that fragment. The version
* field of the individual fragment header is unused.
*/
fw_hdr = (struct tg3_firmware_hdr *)tp->fw->data;
if (be32_to_cpu(fw_hdr->base_addr) != TG3_57766_FW_BASE_ADDR)
return;
if (tg3_rxcpu_pause(tp))
return;
/* tg3_load_firmware_cpu() will always succeed for the 57766 */
tg3_load_firmware_cpu(tp, 0, TG3_57766_FW_BASE_ADDR, 0, fw_hdr);
tg3_rxcpu_resume(tp);
}
/* tp->lock is held. */ /* tp->lock is held. */
static int tg3_load_tso_firmware(struct tg3 *tp) static int tg3_load_tso_firmware(struct tg3 *tp)
{ {
...@@ -9836,6 +9918,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) ...@@ -9836,6 +9918,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
return err; return err;
} }
if (tg3_asic_rev(tp) == ASIC_REV_57766) {
/* Ignore any errors for the firmware download. If download
* fails, the device will operate with EEE disabled
*/
tg3_load_57766_firmware(tp);
}
if (tg3_flag(tp, TSO_CAPABLE)) { if (tg3_flag(tp, TSO_CAPABLE)) {
err = tg3_load_tso_firmware(tp); err = tg3_load_tso_firmware(tp);
if (err) if (err)
...@@ -10940,7 +11029,15 @@ static int tg3_open(struct net_device *dev) ...@@ -10940,7 +11029,15 @@ static int tg3_open(struct net_device *dev)
if (tp->fw_needed) { if (tp->fw_needed) {
err = tg3_request_firmware(tp); err = tg3_request_firmware(tp);
if (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0) { if (tg3_asic_rev(tp) == ASIC_REV_57766) {
if (err) {
netdev_warn(tp->dev, "EEE capability disabled\n");
tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP;
} else if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) {
netdev_warn(tp->dev, "EEE capability restored\n");
tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
}
} else if (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0) {
if (err) if (err)
return err; return err;
} else if (err) { } else if (err) {
...@@ -14570,6 +14667,7 @@ static int tg3_phy_probe(struct tg3 *tp) ...@@ -14570,6 +14667,7 @@ static int tg3_phy_probe(struct tg3 *tp)
if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
(tg3_asic_rev(tp) == ASIC_REV_5719 || (tg3_asic_rev(tp) == ASIC_REV_5719 ||
tg3_asic_rev(tp) == ASIC_REV_5720 || tg3_asic_rev(tp) == ASIC_REV_5720 ||
tg3_asic_rev(tp) == ASIC_REV_57766 ||
tg3_asic_rev(tp) == ASIC_REV_5762 || tg3_asic_rev(tp) == ASIC_REV_5762 ||
(tg3_asic_rev(tp) == ASIC_REV_5717 && (tg3_asic_rev(tp) == ASIC_REV_5717 &&
tg3_chip_rev_id(tp) != CHIPREV_ID_5717_A0) || tg3_chip_rev_id(tp) != CHIPREV_ID_5717_A0) ||
...@@ -15379,6 +15477,9 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent) ...@@ -15379,6 +15477,9 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
if (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0) if (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0)
tp->fw_needed = FIRMWARE_TG3; tp->fw_needed = FIRMWARE_TG3;
if (tg3_asic_rev(tp) == ASIC_REV_57766)
tp->fw_needed = FIRMWARE_TG357766;
tp->irq_max = 1; tp->irq_max = 1;
if (tg3_flag(tp, 5750_PLUS)) { if (tg3_flag(tp, 5750_PLUS)) {
...@@ -15839,6 +15940,11 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent) ...@@ -15839,6 +15940,11 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
udelay(50); udelay(50);
tg3_nvram_init(tp); tg3_nvram_init(tp);
/* If the device has an NVRAM, no need to load patch firmware */
if (tg3_asic_rev(tp) == ASIC_REV_57766 &&
!tg3_flag(tp, NO_NVRAM))
tp->fw_needed = NULL;
grc_misc_cfg = tr32(GRC_MISC_CFG); grc_misc_cfg = tr32(GRC_MISC_CFG);
grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK; grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
......
...@@ -2222,6 +2222,12 @@ ...@@ -2222,6 +2222,12 @@
#define NIC_SRAM_MBUF_POOL_BASE5705 0x00010000 #define NIC_SRAM_MBUF_POOL_BASE5705 0x00010000
#define NIC_SRAM_MBUF_POOL_SIZE5705 0x0000e000 #define NIC_SRAM_MBUF_POOL_SIZE5705 0x0000e000
#define TG3_SRAM_RXCPU_SCRATCH_BASE_57766 0x00030000
#define TG3_SRAM_RXCPU_SCRATCH_SIZE_57766 0x00010000
#define TG3_57766_FW_BASE_ADDR 0x00030000
#define TG3_57766_FW_HANDSHAKE 0x0003fccc
#define TG3_SBROM_IN_SERVICE_LOOP 0x51
#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5700 128 #define TG3_SRAM_RX_STD_BDCACHE_SIZE_5700 128
#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5755 64 #define TG3_SRAM_RX_STD_BDCACHE_SIZE_5755 64
#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5906 32 #define TG3_SRAM_RX_STD_BDCACHE_SIZE_5906 32
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment