diff options
Diffstat (limited to 'drivers/net/sfc/qt202x_phy.c')
-rw-r--r-- | drivers/net/sfc/qt202x_phy.c | 59 |
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 | ||
68 | static int qt2025c_wait_reset(struct efx_nic *efx) | 73 | static 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 | |||
98 | static 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 | ||
120 | static 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 | |||
128 | static 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 | |||
107 | static void qt2025c_firmware_id(struct efx_nic *efx) | 152 | static 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); |