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