aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/sfc/qt202x_phy.c59
1 files changed, 51 insertions, 8 deletions
diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c
index 0cd6eed02069..326ffa49fbd2 100644
--- a/drivers/net/sfc/qt202x_phy.c
+++ b/drivers/net/sfc/qt202x_phy.c
@@ -63,11 +63,16 @@ struct qt202x_phy_data {
63#define QT2022C2_MAX_RESET_TIME 500 63#define QT2022C2_MAX_RESET_TIME 500
64#define QT2022C2_RESET_WAIT 10 64#define QT2022C2_RESET_WAIT 10
65 65
66#define QT2025C_MAX_HEARTB_TIME (5 * HZ)
67#define QT2025C_HEARTB_WAIT 100
68#define QT2025C_MAX_FWSTART_TIME (25 * HZ / 10)
69#define QT2025C_FWSTART_WAIT 100
70
66#define BUG17190_INTERVAL (2 * HZ) 71#define BUG17190_INTERVAL (2 * HZ)
67 72
68static int qt2025c_wait_reset(struct efx_nic *efx) 73static int qt2025c_wait_heartbeat(struct efx_nic *efx)
69{ 74{
70 unsigned long timeout = jiffies + 10 * HZ; 75 unsigned long timeout = jiffies + QT2025C_MAX_HEARTB_TIME;
71 int reg, old_counter = 0; 76 int reg, old_counter = 0;
72 77
73 /* Wait for firmware heartbeat to start */ 78 /* Wait for firmware heartbeat to start */
@@ -84,9 +89,17 @@ static int qt2025c_wait_reset(struct efx_nic *efx)
84 break; 89 break;
85 if (time_after(jiffies, timeout)) 90 if (time_after(jiffies, timeout))
86 return -ETIMEDOUT; 91 return -ETIMEDOUT;
87 msleep(10); 92 msleep(QT2025C_HEARTB_WAIT);
88 } 93 }
89 94
95 return 0;
96}
97
98static int qt2025c_wait_fw_status_good(struct efx_nic *efx)
99{
100 unsigned long timeout = jiffies + QT2025C_MAX_FWSTART_TIME;
101 int reg;
102
90 /* Wait for firmware status to look good */ 103 /* Wait for firmware status to look good */
91 for (;;) { 104 for (;;) {
92 reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG); 105 reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG);
@@ -98,12 +111,44 @@ static int qt2025c_wait_reset(struct efx_nic *efx)
98 break; 111 break;
99 if (time_after(jiffies, timeout)) 112 if (time_after(jiffies, timeout))
100 return -ETIMEDOUT; 113 return -ETIMEDOUT;
101 msleep(100); 114 msleep(QT2025C_FWSTART_WAIT);
102 } 115 }
103 116
104 return 0; 117 return 0;
105} 118}
106 119
120static void qt2025c_restart_firmware(struct efx_nic *efx)
121{
122 /* Restart microcontroller execution of firmware from RAM */
123 efx_mdio_write(efx, 3, 0xe854, 0x00c0);
124 efx_mdio_write(efx, 3, 0xe854, 0x0040);
125 msleep(50);
126}
127
128static int qt2025c_wait_reset(struct efx_nic *efx)
129{
130 int rc;
131
132 rc = qt2025c_wait_heartbeat(efx);
133 if (rc != 0)
134 return rc;
135
136 rc = qt2025c_wait_fw_status_good(efx);
137 if (rc == -ETIMEDOUT) {
138 /* Bug 17689: occasionally heartbeat starts but firmware status
139 * code never progresses beyond 0x00. Try again, once, after
140 * restarting execution of the firmware image. */
141 EFX_LOG(efx, "bashing QT2025C microcontroller\n");
142 qt2025c_restart_firmware(efx);
143 rc = qt2025c_wait_heartbeat(efx);
144 if (rc != 0)
145 return rc;
146 rc = qt2025c_wait_fw_status_good(efx);
147 }
148
149 return rc;
150}
151
107static void qt2025c_firmware_id(struct efx_nic *efx) 152static void qt2025c_firmware_id(struct efx_nic *efx)
108{ 153{
109 struct qt202x_phy_data *phy_data = efx->phy_data; 154 struct qt202x_phy_data *phy_data = efx->phy_data;
@@ -229,10 +274,8 @@ static int qt2025c_select_phy_mode(struct efx_nic *efx)
229 efx_mdio_write(efx, 1, 0xc300, 0x0002); 274 efx_mdio_write(efx, 1, 0xc300, 0x0002);
230 msleep(20); 275 msleep(20);
231 276
232 /* Restart microcontroller execution from RAM */ 277 /* Restart microcontroller execution of firmware from RAM */
233 efx_mdio_write(efx, 3, 0xe854, 0x00c0); 278 qt2025c_restart_firmware(efx);
234 efx_mdio_write(efx, 3, 0xe854, 0x0040);
235 msleep(50);
236 279
237 /* Wait for the microcontroller to be ready again */ 280 /* Wait for the microcontroller to be ready again */
238 rc = qt2025c_wait_reset(efx); 281 rc = qt2025c_wait_reset(efx);