1/* 2 * Copyright (c) 2007-2011, ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <stdbool.h> 11#include <stdio.h> 12 13#include <barrelfish/barrelfish.h> 14 15#include "sleep.h" 16#include "e10k.h" 17 18//#define DEBUG(x...) printf("e10k: " x) 19#define DEBUG(x...) do {} while (0) 20 21 22/** Acquire SWFW semaphore */ 23static bool e10k_swfwsem_acquire(e10k_t* d) 24{ 25 while (e10k_swsm_smbi_rdf(d) != 0); // TODO: Timeout 26 e10k_swsm_swesmbi_wrf(d, 1); 27 while (e10k_swsm_swesmbi_rdf(d) == 0); // TODO: Timeout 28 return true; 29} 30 31/** Release SWFW semaphore */ 32static void e10k_swfwsem_release(e10k_t* d) 33{ 34 e10k_swsm_swesmbi_wrf(d, 0); 35 e10k_swsm_smbi_wrf(d, 0); 36} 37 38 39static bool e10k_swfwlock_phy(e10k_t* d) 40{ 41 bool good = false; 42 43 // See 10.5.4 44again: 45 if (!e10k_swfwsem_acquire(d)) { 46 return false; 47 } 48 49 if ((e10k_status_lan_id_rdf(d) == 0) && 50 (e10k_swfw_sync_sw_physm0_rdf(d) == 0) && 51 (e10k_swfw_sync_fw_physm0_rdf(d) == 0)) 52 { 53 e10k_swfw_sync_sw_physm0_wrf(d, 1); 54 good = true; 55 } else if ((e10k_swfw_sync_sw_physm1_rdf(d) == 0) && 56 (e10k_swfw_sync_fw_physm1_rdf(d) == 0)) 57 { 58 e10k_swfw_sync_sw_physm1_wrf(d, 1); 59 good = true; 60 } 61 e10k_swfwsem_release(d); 62 63 if (!good) { 64 DEBUG("Failed, try again\n"); 65 milli_sleep(20); 66 goto again; 67 } 68 69 return true; 70} 71 72static bool e10k_swfwunlock_phy(e10k_t* d) 73{ 74 if (!e10k_swfwsem_acquire(d)) { 75 return false; 76 } 77 78 if (e10k_status_lan_id_rdf(d) == 0) { 79 e10k_swfw_sync_sw_physm0_wrf(d, 0); 80 } else { 81 e10k_swfw_sync_sw_physm1_wrf(d, 0); 82 } 83 84 e10k_swfwsem_release(d); 85 86 // Technically this is only necessary in the case that the semaphore is 87 // acquired again. 88 milli_sleep(10); 89 return true; 90} 91 92#if 0 93static bool e10k_mdi_command(uint16_t mdi, uint8_t dev, uint8_t phy, 94 e10k_mdi_opcode_t op) 95{ 96 e10k_msca_t msca = e10k_msca_default; 97 98 msca = e10k_msca_mdiadd_insert(msca, mdi); 99 msca = e10k_msca_devadd_insert(msca, dev); 100 msca = e10k_msca_phyadd_insert(msca, phy); 101 msca = e10k_msca_opcode_insert(msca, op); 102 msca = e10k_msca_stcode_insert(msca, e10k_new_proto); 103 msca = e10k_msca_mdicmd_insert(msca, 1); 104 105 106 // Issue command 107 e10k_msca_wr(d, msca); 108 109 // Wait for completion 110 while (e10k_msca_mdicmd_rdf(d) != 0); // TODO: Timeout 111 112 return true; 113} 114 115static bool e10k_phy_readreg(uint16_t mdi, uint8_t dev, uint8_t phy, 116 uint16_t* value) 117{ 118 bool success = true; 119 120 if (!e10k_swfwlock_phy()) { 121 return false; 122 } 123 124 if (!e10k_mdi_command(mdi, dev, phy, e10k_addr_cycle)) { 125 success = false; 126 goto out; 127 } 128 129 if (!e10k_mdi_command(mdi, dev, phy, e10k_read_op)) { 130 success = false; 131 goto out; 132 } 133 *value = e10k_msrwd_mdirddata_rdf(d); 134 135out: 136 e10k_swfwunlock_phy(); 137 return success; 138} 139 140static bool e10k_phy_writereg(uint16_t mdi, uint8_t dev, uint8_t phy, 141 uint16_t value) 142{ 143 bool success = true; 144 145 if (!e10k_swfwlock_phy()) { 146 return false; 147 } 148 149 if (!e10k_mdi_command(mdi, dev, phy, e10k_addr_cycle)) { 150 success = false; 151 goto out; 152 } 153 154 e10k_msrwd_mdiwrdata_wrf(d, value); 155 if (!e10k_mdi_command(mdi, dev, phy, e10k_read_op)) { 156 success = false; 157 goto out; 158 } 159 160out: 161 e10k_swfwunlock_phy(); 162 return success; 163} 164 165static bool e10k_phy_validate_address(uint8_t phy) 166{ 167 bool success; 168 uint16_t value; 169 uint16_t v; 170 171 /* IXGBE_MDIO_PHY_ID_HIGH */ /* IXGBE_MDIO_PMA_PMD_DEV_TYPE */ 172 success = e10k_phy_readreg(0x2, 0x1, phy, &value); 173 if (!success) { 174 DEBUG("Error reading\n"); 175 } 176 177 uint8_t i; 178 179 for (i = 0; i < 32; i++) { 180 e10k_phy_readreg(i, 0x1, phy, &v); 181 DEBUG(" [%x][%x] %x\n", phy, i, v); 182 } 183 184 return success && (value != 0xFFFF) && (value != 0x0); 185} 186 187static bool e10k_phy_read_id(uint8_t phy, uint16_t* id) 188{ 189 /* IXGBE_MDIO_PHY_ID_HIGH */ /* IXGBE_MDIO_PMA_PMD_DEV_TYPE */ 190 return e10k_phy_readreg(0x2, 0x1, phy, id); 191} 192 193static bool e10k_phy_identify(void) 194{ 195 uint8_t i; 196 uint16_t id; 197 for (i = 0; i < 32; i++) { 198 if (e10k_phy_validate_address(i)) { 199 if (!e10k_phy_read_id(i, &id)) { 200 return false; 201 } 202 DEBUG("Found PHY addr=%x id=%x\n", i, id); 203 return true; 204 } 205 } 206 return false; 207} 208#endif 209 210static uint16_t e10k_eeprom_read(e10k_t* d, uint16_t offset) 211{ 212 e10k_eerd_t eerd = e10k_eerd_default; 213 214 eerd = e10k_eerd_start_insert(eerd, 1); 215 eerd = e10k_eerd_addr_insert(eerd, offset); 216 e10k_eerd_wr(d, eerd); 217 218 while (e10k_eerd_done_rdf(d) == 0); // TODO: Timeout 219 220 return e10k_eerd_data_rdf(d); 221} 222 223void e10k_phy_init(e10k_t* d) 224{ 225 /* IXGBE_PHY_INIT_OFFSET_NL */ 226 uint16_t list_offset; 227 uint16_t data_offset = 0x0; 228 uint16_t data_value; 229 uint16_t sfp_id; 230 uint16_t sfp_type = 0x4; /* SPF_DA_CORE1 */ 231 e10k_autoc_t autoc; 232 233 list_offset = e10k_eeprom_read(d, 0x002B); 234 DEBUG("list_offset=%x\n", list_offset); 235 if ((list_offset == 0x0) || (list_offset == 0xFFFF)) { 236 return; 237 } 238 239 list_offset++; 240 241 sfp_id = e10k_eeprom_read(d, list_offset); 242 DEBUG("sfp_id = %x\n", sfp_id); 243 while (sfp_id != 0xFFFF) { 244 if (sfp_id == sfp_type) { 245 list_offset++; 246 data_offset = e10k_eeprom_read(d, list_offset); 247 if ((data_offset == 0x0) || (data_offset == 0xFFFF)) { 248 DEBUG("sfp init failed\n"); 249 return; 250 } else { 251 break; 252 } 253 } else { 254 list_offset += 2; 255 sfp_id = e10k_eeprom_read(d, list_offset); 256 } 257 list_offset++; 258 } 259 260 if (sfp_id == 0xFFFF) { 261 DEBUG("sfp init failed\n"); 262 return; 263 } 264 265 DEBUG("data_offset=%x\n", data_offset); 266 267 e10k_swfwlock_phy(d); 268 data_value = e10k_eeprom_read(d, ++data_offset); 269 while (data_value != 0xFFFF) { 270 DEBUG(" v=%x\n", data_value); 271 e10k_corectl_wr(d, data_value); 272 data_value = e10k_eeprom_read(d, ++data_offset); 273 } 274 e10k_swfwunlock_phy(d); 275 276 milli_sleep(50); 277 278 279 autoc = e10k_autoc_rd(d); 280 autoc = e10k_autoc_lms_insert(autoc, 0x0); 281 autoc = e10k_autoc_restart_an_insert(autoc, 1); 282 e10k_autoc_wr(d, autoc); 283 while (e10k_anlp1_anas_rdf(d) != 0); // TODO: Timeout 284 285 286 autoc = e10k_autoc_rd(d); 287 autoc = e10k_autoc_lms_insert(autoc, e10k_l10g_sfi); 288 autoc = e10k_autoc_restart_an_insert(autoc, 1); 289 e10k_autoc_wr(d, autoc); 290 while (e10k_autoc_restart_an_rdf(d) != 0); // TODO: Timeout 291 292 DEBUG("PHY init done\n"); 293} 294 295 296