quadra28_micro_seq.c (37061B)
1 /* 2 * 3 * 4 * 5 5 * 6 5 * 7 5 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 8 5 * 9 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 10 5 * Broadcom Proprietary and Confidential. All rights reserved.$ 11 7 * 12 8 * File: quadra28.c 13 * Purpose: tier1 phymod microcode download support for Broadcom 40G Quadra28 14 * note 15 */ 16 17 /* 18 * Includes 19 */ 20 #include <phymod/phymod.h> 21 #include <phymod/phymod_system.h> 22 #include "quadra28_reg_access.h" 23 #include "quadra28_types.h" 24 #include "bcmi_quadra28_defs.h" 25 #include "quadra28_cfg_seq.h" 26 27 static int _quadra28_verify_fw_download(const phymod_access_t *pa, int edc); 28 29 /* If it is single PMD, we need to clear it before downloading FW*/ 30 int _quadra28_clear_mode_config(phymod_access_t *pa) 31 { 32 int speed = 0; 33 BCMI_QUADRA28_GENERAL_PURPOSE_3r_t gp_reg3_reg_val; 34 BCMI_QUADRA28_APPS_MODE_0r_t apps_mode0_reg_val; 35 PHYMOD_MEMSET(&gp_reg3_reg_val, 0, sizeof(BCMI_QUADRA28_GENERAL_PURPOSE_3r_t)); 36 PHYMOD_MEMSET(&apps_mode0_reg_val, 0, sizeof(BCMI_QUADRA28_APPS_MODE_0r_t)); 37 38 PHYMOD_IF_ERR_RETURN( 39 BCMI_QUADRA28_READ_GENERAL_PURPOSE_3r(pa, &gp_reg3_reg_val)); 40 speed = gp_reg3_reg_val.v[0] & 0xF ; 41 if (speed == 0x4 || speed == 0x7) { 42 PHYMOD_IF_ERR_RETURN( 43 quadra28_channel_select (pa, Q28_ALL_LANE)); 44 apps_mode0_reg_val.v[0] = gp_reg3_reg_val.v[0]; 45 BCMI_QUADRA28_APPS_MODE_0r_FINISH_CHANGEf_SET(apps_mode0_reg_val, 0); 46 PHYMOD_IF_ERR_RETURN( 47 BCMI_QUADRA28_WRITE_APPS_MODE_0r(pa, apps_mode0_reg_val)); 48 PHYMOD_USLEEP(100); 49 BCMI_QUADRA28_APPS_MODE_0r_SET(apps_mode0_reg_val, 0x8882); 50 PHYMOD_IF_ERR_RETURN( 51 BCMI_QUADRA28_WRITE_APPS_MODE_0r(pa, apps_mode0_reg_val)); 52 PHYMOD_USLEEP(100); 53 PHYMOD_IF_ERR_RETURN( 54 _quadra28_intf_update_wait_check(pa,apps_mode0_reg_val.v[0], 50000)); 55 } 56 57 return PHYMOD_E_NONE; 58 } 59 60 static int _quadra28_verify_fw_download(const phymod_access_t *pa, int edc) 61 { 62 MSG_OUTr_t msg_out_reg; 63 BOOT_CHECKSUMr_t checksum_reg; 64 PHYMOD_MEMSET(&msg_out_reg, 0, sizeof(MSG_OUTr_t)); 65 PHYMOD_MEMSET(&checksum_reg, 0, sizeof(BOOT_CHECKSUMr_t)); 66 PHYMOD_IF_ERR_RETURN((BCMI_QUADRA28_READ_MSG_OUTr(pa,&msg_out_reg))); 67 msg_out_reg.v[0] = MSG_OUTr_MESSAGE_OUTf_GET(msg_out_reg); 68 if (0x4321 == msg_out_reg.v[0]){ 69 /* step19: Wait 4ms */ 70 PHYMOD_USLEEP(4000); 71 } else { 72 return PHYMOD_E_FAIL; 73 } 74 /* Intermediate step in vbs */ 75 PHYMOD_IF_ERR_RETURN((BCMI_QUADRA28_READ_MSG_OUTr(pa,&msg_out_reg))); 76 msg_out_reg.v[0] = MSG_OUTr_MESSAGE_OUTf_GET(msg_out_reg); 77 if (0x300 != msg_out_reg.v[0]) { 78 return PHYMOD_E_FAIL; 79 } 80 if (!edc) { 81 /* step 20 Read checksum (expected 0x600D) */ 82 PHYMOD_IF_ERR_RETURN 83 (BCMI_QUADRA28_READ_BOOT_CHECKSUMr(pa, &checksum_reg)); 84 checksum_reg.v[0]=BCMI_QUADRA28_BOOT_CHECKSUMr_BOOT_CHKSUMf_GET(checksum_reg); 85 if (0x600D != checksum_reg.v[0]) { 86 /*Checksum is correct */ 87 return PHYMOD_E_FAIL; 88 } 89 } else { 90 BCMI_QUADRA28_GP_4r_t gp_4; 91 PHYMOD_MEMSET(&gp_4, 0, sizeof(BCMI_QUADRA28_GP_4r_t)); 92 PHYMOD_IF_ERR_RETURN( 93 BCMI_QUADRA28_READ_GP_4r(pa, &gp_4)); 94 if (0x600D != gp_4.v[0]) { 95 /*Checksum is not correct */ 96 return PHYMOD_E_FAIL; 97 } 98 } 99 100 return PHYMOD_E_NONE; 101 } 102 103 int quadra28_firmware_info_get(const phymod_access_t *pa, phymod_core_firmware_info_t *fw_info) 104 { 105 uint32_t fw_ver = 0; 106 BOOT_CHECKSUMr_t mst_running_chksum; 107 108 /* Read the firmware version */ 109 PHYMOD_IF_ERR_RETURN( 110 phymod_raw_iblk_read(pa, (0x10000 | (uint32_t) 0xC161), &fw_ver)); 111 112 fw_info->fw_version = (fw_ver & 0xff); 113 PHYMOD_IF_ERR_RETURN( 114 BCMI_QUADRA28_READ_BOOT_CHECKSUMr(pa, 115 &mst_running_chksum)); 116 fw_info->fw_crc = BCMI_QUADRA28_BOOT_CHECKSUMr_BOOT_CHKSUMf_GET(mst_running_chksum); 117 118 return PHYMOD_E_NONE; 119 } 120 121 int quadra28_write_message(const phymod_access_t *pa, int wrdata, int *rddata) 122 { 123 int tmp_data = 0, retry_cnt = 0; 124 BCMI_QUADRA28_MESSAGE_OUTr_t msg_out; 125 BCMI_QUADRA28_MESSAGE_INr_t msg_in; 126 BCMI_QUADRA28_GENERAL_STATUS_1r_t gen_sts; 127 128 PHYMOD_MEMSET(&msg_out, 0, sizeof(BCMI_QUADRA28_MESSAGE_OUTr_t)); 129 PHYMOD_MEMSET(&msg_in, 0, sizeof(BCMI_QUADRA28_MESSAGE_INr_t)); 130 PHYMOD_MEMSET(&gen_sts, 0, sizeof(BCMI_QUADRA28_GENERAL_STATUS_1r_t)); 131 132 /* Clear any lingering Message out from Micro.*/ 133 PHYMOD_IF_ERR_RETURN( 134 BCMI_QUADRA28_READ_MESSAGE_OUTr(pa, &msg_out)); 135 136 /* Write SPI Control Register Write Command.*/ 137 BCMI_QUADRA28_MESSAGE_INr_SET(msg_in, wrdata); 138 PHYMOD_IF_ERR_RETURN( 139 BCMI_QUADRA28_WRITE_MESSAGE_INr(pa, msg_in)); 140 do { 141 PHYMOD_IF_ERR_RETURN( 142 BCMI_QUADRA28_READ_GENERAL_STATUS_1r(pa, &gen_sts)); 143 tmp_data = BCMI_QUADRA28_GENERAL_STATUS_1r_GET (gen_sts); 144 retry_cnt ++; 145 } while (((tmp_data & 0x4000) == 0) && (retry_cnt < Q28_RETRY_CNT)); 146 147 if (retry_cnt >= Q28_RETRY_CNT) { 148 return PHYMOD_E_CONFIG; 149 } 150 151 PHYMOD_IF_ERR_RETURN( 152 BCMI_QUADRA28_READ_MESSAGE_OUTr(pa, &msg_out)); 153 *rddata = BCMI_QUADRA28_MESSAGE_OUTr_GET(msg_out); 154 155 return PHYMOD_E_NONE; 156 } 157 158 int q28_get_spi_eeprom_status(const phymod_access_t *pa) 159 { 160 int retry_cnt = 0, retry_cnt_1 = 0; 161 int SPI_READY = 1; 162 int wr_data = 0, rd_data = 0; 163 while ((SPI_READY == 1) && (retry_cnt_1 < Q28_RETRY_CNT)) { 164 /* Set-up SPI Controller To Receive SPI EEPROM Status. 165 * Write SPI Control Register Write Command.*/ 166 wr_data = ((Q28_WR_CPU_CTRL_REGS * 0x0100) | 0x1); 167 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 168 /* Write SPI Control -2 Register Address.*/ 169 wr_data = Q28_SPI_CTRL_2_H; 170 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 171 172 /* Write SPI Control -2 Register Word-2.*/ 173 wr_data = 0x0100; /* C402 = 0, clear all status. C403 = 1, to enable Done Status.*/ 174 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 175 176 /* Fill-up SPI Transmit Fifo To check SPI Status. 177 * Write SPI Control Register Write Command.*/ 178 /* Write to Transmit Fifo D000-onwards.*/ 179 wr_data = ((Q28_WR_CPU_CTRL_FIFO * 0x0100) | 2); 180 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 181 182 /* Write Tx Fifo Register Address.*/ 183 wr_data = Q28_SPI_TXFIFO; 184 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 185 186 /* Write SPI Tx Fifo Control Word-1.*/ 187 wr_data = ((0x0100) | Q28_MSGTYPE_HRD); /* D000 = Only 1 byte Message ( 1byte to transmit for RDSR opcode). */ 188 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 189 190 /* Write SPI Tx Fifo Control Word-2.*/ 191 wr_data = Q28_RDSR_OPCODE; /* D002 = RDSR Opcode for transmit. */ 192 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 193 194 /* Write SPI Control Register Write Command.*/ 195 wr_data = ((Q28_WR_CPU_CTRL_FIFO * 0x0100) | 2); 196 PHYMOD_IF_ERR_RETURN(quadra28_write_message(pa, wr_data, &rd_data)); 197 198 /* Write SPI Control -1 Register Address.*/ 199 wr_data = Q28_SPI_CTRL_1_L; 200 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 201 202 /* Write SPI Control -1 Register Word-1.*/ 203 wr_data = 0x0101; 204 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 205 206 /* Write SPI Control -1 Register Word-2.*/ 207 wr_data = 0x0100; 208 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 209 210 /*Write SPI Control Register Write Command.*/ 211 wr_data = ((Q28_WR_CPU_CTRL_REGS * 0x0100) | 1); 212 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 213 214 /* Write SPI Control -1 Register Address.*/ 215 wr_data = Q28_SPI_CTRL_1_H; 216 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 217 218 /* Write SPI Control -1 Register Word-2.*/ 219 wr_data = 0x0103; 220 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 221 222 do { 223 wr_data = ((Q28_RD_CPU_CTRL_REGS * 0x0100) | 1); 224 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 225 wr_data = Q28_SPI_CTRL_1_L; 226 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 227 retry_cnt ++; 228 } while (((rd_data & 0x0100) == 0) && (retry_cnt < Q28_RETRY_CNT)); 229 if (retry_cnt >= Q28_RETRY_CNT) { 230 PHYMOD_DIAG_OUT(("ERROR on retry cnt 1 \n")); 231 return PHYMOD_E_CONFIG; 232 } 233 retry_cnt = 0; 234 235 /* Write SPI Control Register Read Command.*/ 236 wr_data = ((Q28_RD_CPU_CTRL_REGS * 0x0100) | 1); 237 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 238 239 /* Write SPI Control -1 Register Address.*/ 240 wr_data = Q28_SPI_RXFIFO; 241 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 242 243 if ((rd_data & 1) == 0) { 244 SPI_READY = 0; 245 } 246 retry_cnt_1 ++; 247 } 248 if (retry_cnt_1 >= Q28_RETRY_CNT) { 249 PHYMOD_DIAG_OUT(("ERROR on retry cnt 2 \n")); 250 return PHYMOD_E_CONFIG; 251 } 252 253 return PHYMOD_E_NONE; 254 } 255 256 int quadra28_rom_dload(const phymod_access_t *pa, uint8_t *new_fw, uint32_t fw_length) 257 { 258 int retry_cnt = 0, retry_cnt_1 = 0; 259 BCMI_QUADRA28_GENERAL_CONTROL_2r_t gen_ctrl2; 260 BCMI_QUADRA28_BOOT_CONTROLr_t boot_ctrl; 261 BCMI_QUADRA28_GENERAL_CONTROL_1r_t gen_ctrl1; 262 BCMI_QUADRA28_MSG_OUTr_t q28_msg_out ; 263 int wr_data = 0, rd_data = 0, j = 0, i = 0,xfer_size = 0; 264 uint32_t temp = 0; 265 266 PHYMOD_MEMSET(&q28_msg_out, 0, sizeof(BCMI_QUADRA28_MSG_OUTr_t)); 267 PHYMOD_MEMSET(&gen_ctrl2, 0, sizeof(BCMI_QUADRA28_GENERAL_CONTROL_2r_t)); 268 PHYMOD_MEMSET(&gen_ctrl1, 0, sizeof(BCMI_QUADRA28_GENERAL_CONTROL_1r_t)); 269 PHYMOD_MEMSET(&boot_ctrl, 0, sizeof(BCMI_QUADRA28_BOOT_CONTROLr_t)); 270 271 /* clear bit 12 in FFD1 To use Countach address mapping */ 272 PHYMOD_IF_ERR_RETURN( 273 BCMI_QUADRA28_READ_GENERAL_CONTROL_2r(pa, &gen_ctrl2)); 274 BCMI_QUADRA28_GENERAL_CONTROL_2r_LEGACY_BOOT_SELf_SET(gen_ctrl2, 0); 275 PHYMOD_IF_ERR_RETURN( 276 BCMI_QUADRA28_WRITE_GENERAL_CONTROL_2r(pa, gen_ctrl2)); 277 278 /* SPI boot from ROM*/ 279 BCMI_QUADRA28_BOOT_CONTROLr_SET(boot_ctrl, 0x4); 280 PHYMOD_IF_ERR_RETURN( 281 BCMI_QUADRA28_WRITE_BOOT_CONTROLr(pa, boot_ctrl)); 282 283 /* reset micro*/ 284 BCMI_QUADRA28_GENERAL_CONTROL_1r_SET(gen_ctrl1, 1); 285 PHYMOD_IF_ERR_RETURN( 286 BCMI_QUADRA28_WRITE_GENERAL_CONTROL_1r(pa, gen_ctrl1)); 287 288 /* 5Ms sleep*/ 289 PHYMOD_USLEEP(5000); 290 BCMI_QUADRA28_GENERAL_CONTROL_1r_SET(gen_ctrl1, 0); 291 PHYMOD_IF_ERR_RETURN( 292 BCMI_QUADRA28_WRITE_GENERAL_CONTROL_1r(pa, gen_ctrl1)); 293 294 PHYMOD_IF_ERR_RETURN( 295 BCMI_QUADRA28_READ_GENERAL_CONTROL_2r(pa, &gen_ctrl2)); 296 BCMI_QUADRA28_GENERAL_CONTROL_2r_LEGACY_BOOT_SELf_SET(gen_ctrl2, 0); 297 PHYMOD_IF_ERR_RETURN( 298 BCMI_QUADRA28_WRITE_GENERAL_CONTROL_2r(pa, gen_ctrl2)); 299 300 /* Sleep for 2 sec*/ 301 PHYMOD_SLEEP(2); 302 303 /* Enable the LASI For Message out.*/ 304 PHYMOD_IF_ERR_RETURN(phymod_raw_iblk_write(pa, 0x19000, 0x4)); 305 PHYMOD_IF_ERR_RETURN(phymod_raw_iblk_write(pa, 0x19002, 0x4)); 306 307 /* De-assert SPI EEPROM Block Protection. 308 * Write SPI Control Register Write Command.*/ 309 /* Write to C400, C401, C402, C403 Registers.*/ 310 wr_data = ((Q28_WR_CPU_CTRL_FIFO * 0x0100) | 2); 311 PHYMOD_IF_ERR_RETURN (quadra28_write_message (pa, wr_data, &rd_data)); 312 if (rd_data != 0xABCD) { 313 PHYMOD_DIAG_OUT(("ERROR -MSG OUT register 0x%x It should be 0xABCD\n", rd_data)); 314 return PHYMOD_E_CONFIG; 315 } 316 317 /* Write SPI Control -2 Register Address*/ 318 wr_data = Q28_SPI_CTRL_2_L; 319 PHYMOD_IF_ERR_RETURN (quadra28_write_message (pa, wr_data, &rd_data)); 320 321 /* Write SPI Control -2 Register Word-1.*/ 322 wr_data = 0x8200; /* C400 = 0 for 0 Fill Byte. C401 = 02 for SPI Clcok to be divide by 2 and little endian fifo.*/ 323 PHYMOD_IF_ERR_RETURN (quadra28_write_message (pa, wr_data, &rd_data)); 324 if (rd_data != 0xABCD) { 325 PHYMOD_DIAG_OUT(("ERROR -MSG OUT register 0x%x It should be 0xABCD\n", rd_data)); 326 return PHYMOD_E_CONFIG; 327 } 328 329 /* Write SPI Control -2 Register Word-2.*/ 330 wr_data = 0x0100; /* C402 = 0, clear all status. C403 = 1, to enable Done Status.*/ 331 PHYMOD_IF_ERR_RETURN (quadra28_write_message (pa, wr_data, &rd_data)); 332 if (rd_data != 0x4321) { 333 PHYMOD_DIAG_OUT(("ERROR -MSG OUT register 0x%x It should be 0x4321\n", rd_data)); 334 return PHYMOD_E_CONFIG; 335 } 336 337 /* Fill-up SPI Transmit Fifo With SPI EEPROM Messages. 338 * Write SPI Control Register Write Command.*/ 339 /* Write to Transmit Fifo D000-onwards.*/ 340 wr_data = ((Q28_WR_CPU_CTRL_FIFO * 0x0100) | 4); 341 PHYMOD_IF_ERR_RETURN (quadra28_write_message (pa, wr_data, &rd_data)); 342 343 /* Write Tx Fifo Register Address.*/ 344 wr_data = Q28_SPI_TXFIFO; 345 PHYMOD_IF_ERR_RETURN (quadra28_write_message (pa, wr_data, &rd_data)); 346 347 /* Write SPI Tx Fifo Control Word-1.*/ 348 wr_data = (0x0100 | Q28_MSGTYPE_HWR); /* D000 = Only 1 byte Message ( 1byte to transmit for WREN opcode). */ 349 /* D001 = Write Message And Higher byte of Transfer Size. */ 350 PHYMOD_IF_ERR_RETURN (quadra28_write_message (pa, wr_data, &rd_data)); 351 352 /* Write SPI Tx Fifo Control Word-2.*/ 353 wr_data = ((Q28_MSGTYPE_HWR * 0x0100) | Q28_WREN_OPCODE); /*{MSGTYPE_HWR, WREN_OPCODE}; D002 = WREN Opcode For transmit. */ 354 /* D003 = 2 byte WREN OPCODE Message.*/ 355 PHYMOD_IF_ERR_RETURN (quadra28_write_message (pa, wr_data, &rd_data)); 356 357 /* Write SPI Tx Fifo Control Word-3.*/ 358 wr_data = ((Q28_WRSR_OPCODE * 0x0100) | 0x02); /* D004 = For this command transfer size =2 (1 byte opcode, 1 byte wr data),*/ 359 /* D005 = WRSR Opcode.*/ 360 PHYMOD_IF_ERR_RETURN (quadra28_write_message (pa, wr_data, &rd_data)); 361 362 /* Write SPI Tx Fifo Control Word-4.*/ 363 wr_data = ((0x02 * 0x0100) | 0x02); /* D006 = 0x02, byte for status register, 364 * Bit 7, WPEN = 0, Bit 3:2, BP1:0=0, No block protect, 365 * Bit 1, WEN = 1, Write Enabled. 366 * D005 = WRSR Opcode.*/ 367 PHYMOD_IF_ERR_RETURN (quadra28_write_message (pa, wr_data, &rd_data)); 368 369 /* Write SPI Control Register Write Command.*/ 370 /* Write to SPI Control Register C000 onwards.*/ 371 wr_data = ((Q28_WR_CPU_CTRL_FIFO * 0x0100) | 2); 372 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 373 374 /* Write SPI Control -1 Register Address.*/ 375 wr_data = Q28_SPI_CTRL_1_L; 376 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 377 378 /* Write SPI Control -1 Register Word-1.*/ 379 wr_data = 0x0101; /* C000 = 1 to clear CMD Done Status. C001 = 1 to clear CMD Done INT Status.*/ 380 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 381 382 /* Write SPI Control -1 Register Word-2.*/ 383 wr_data = 0x0003; /* C002 = 3, Start Immidiate Command. C003 = 0, No Prepend byte for Write.*/ 384 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 385 386 /* Wait For WRSR Command To be written*/ 387 do { 388 wr_data = ((Q28_RD_CPU_CTRL_REGS * 0x0100) | 1); 389 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 390 wr_data = Q28_SPI_CTRL_1_L; 391 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 392 retry_cnt++; 393 } while (((rd_data & 0x0100) == 0) && (retry_cnt < Q28_RETRY_CNT)); 394 if (retry_cnt >= Q28_RETRY_CNT) { 395 return PHYMOD_E_CONFIG; 396 } 397 retry_cnt = 0; 398 399 PHYMOD_IF_ERR_RETURN(q28_get_spi_eeprom_status(pa)); 400 401 for (j = 0 ; j < fw_length; j+= Q28_WR_BLOCK_SIZE) { 402 /* Setup SPI Controller.*/ 403 /* Write SPI Control Register Write Command.*/ 404 /* Write to C400, C401, C402, C403 Registers.*/ 405 wr_data = ( (Q28_WR_CPU_CTRL_FIFO* 0x0100) | 2); 406 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 407 408 /* Write SPI Control -2 Register Address.*/ 409 wr_data = Q28_SPI_CTRL_2_L; 410 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 411 412 /* Write SPI Control -2 Register Word-1.*/ 413 wr_data = 0x8200; /* C400 = 0 for 0 Fill Byte. C401 = 02 for SPI Clcok to be divide by 2 and little endian fifo.*/ 414 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 415 416 /* Write SPI Control -2 Register Word-2.*/ 417 wr_data = 0x0100; /* C402 = 0, clear all status. C403 = 1, to enable Done Status.*/ 418 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 419 420 /* Fill-up SPI Transmit Fifo.*/ 421 /* Write SPI Control Register Write Command.*/ 422 wr_data = ((Q28_WR_CPU_CTRL_FIFO * 0x0100) | (4 + (Q28_WR_BLOCK_SIZE/2))); 423 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 424 425 /* Write Tx Fifo Register Address.*/ 426 wr_data = Q28_SPI_TXFIFO; 427 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 428 429 /* Write SPI Tx Fifo Control Word-1.*/ 430 wr_data = ( 0x0100 | Q28_MSGTYPE_HWR); 431 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 432 433 /* Write SPI Tx Fifo Control Word-2.*/ 434 wr_data = ((Q28_MSGTYPE_HWR * 0x0100) | Q28_WREN_OPCODE); 435 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 436 437 438 /* Write SPI Tx Fifo Control Word-3.*/ 439 wr_data = ((Q28_WR_OPCODE * 0x0100) | (0x3 + Q28_WR_BLOCK_SIZE)); 440 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 441 442 443 /* Write SPI Tx Fifo Control Word-4.*/ 444 wr_data = (((j & 0x00FF) * 0x0100) | ((j & 0xFF00)/ 0x0100)); 445 /* D006 = SPI EEPROM Destination Address (higher byte sent out first). 446 * D007 = SPI EEPROM Destination Address (lower byte sent out later).*/ 447 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 448 449 xfer_size = fw_length - j; 450 if ( xfer_size > Q28_WR_BLOCK_SIZE) { 451 xfer_size = Q28_WR_BLOCK_SIZE; 452 } 453 for (i = 0 ; i<(xfer_size-1); i+=2) { 454 /* Write SPI Tx Fifo Data Word-4.*/ 455 wr_data = ((new_fw [i+j+1] * 0x0100) | new_fw [i+j]); /* D008 = Low Byte. D009 = High Byte.*/ 456 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 457 } 458 459 /* Set-up SPI Controller To Transmit.*/ 460 /* Write SPI Control Register Write Command.*/ 461 /* Write to SPI Control Register C000 onwards.*/ 462 wr_data = ((Q28_WR_CPU_CTRL_FIFO * 0x0100) | 2); 463 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 464 465 /* Write SPI Control -1 Register Address.*/ 466 wr_data = Q28_SPI_CTRL_1_L; 467 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 468 469 /* Write SPI Control -1 Register Word-1.*/ 470 wr_data = 0x0501; /* C000 = 1 to clear CMD Done Status. C001 = 1 to clear CMD Done INT Status.*/ 471 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 472 473 /* Write SPI Control -1 Register Word-2.*/ 474 wr_data = 0x0003; /* C002 = 3, Start Immidiate Command. C003 = 0, No Prepend byte for Write.*/ 475 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 476 477 /* Wait For 64 bytes To be written. */ 478 if ((j % 2048) == 0) { 479 PHYMOD_DIAG_OUT(("INFO -- Write SPI EEPROM at address: 0x%x\n", j)); 480 } 481 rd_data = 0; 482 while (((rd_data & 0x0100) == 0) && (retry_cnt < Q28_RETRY_CNT)) { 483 /* Write SPI Control Register Read Command.*/ 484 /* Read from SPI Controller register C000.*/ 485 wr_data = ((Q28_RD_CPU_CTRL_REGS * 0x0100) | 1); 486 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 487 488 /* Write SPI Control -1 Register Address.*/ 489 wr_data = Q28_SPI_CTRL_1_L; 490 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 491 retry_cnt ++; 492 } 493 if (retry_cnt >= Q28_RETRY_CNT) { 494 return PHYMOD_E_CONFIG; 495 } 496 retry_cnt = 0; 497 PHYMOD_IF_ERR_RETURN(q28_get_spi_eeprom_status(pa)); 498 } 499 PHYMOD_DIAG_OUT(("INFO -- Completes 0x%x bytes of SPI EEPROM write operation\n", j)); 500 501 /* Re-Assert SPI EEPROM Block Protection.*/ 502 /* Write SPI Control Register Write Command.*/ 503 /* Write to C400, C401, C402, C403 Registers.*/ 504 wr_data = ((Q28_WR_CPU_CTRL_FIFO * 0x0100) | 2); 505 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 506 507 /* Write SPI Control -2 Register Address.*/ 508 wr_data = Q28_SPI_CTRL_2_L; 509 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 510 511 /* Write SPI Control -2 Register Word-1.*/ 512 wr_data = 0x8200; /* C400 = 0 for 0 Fill Byte. C401 = 02 for SPI Clcok to be divide by 2 and little endian fifo.*/ 513 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 514 515 /* Write SPI Control -2 Register Word-2.*/ 516 wr_data = 0x0100; /* C402 = 0, clear all status. C403 = 1, to enable Done Status.*/ 517 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 518 519 /* Fill-up SPI Transmit Fifo With SPI EEPROM Messages.*/ 520 /* Write SPI Control Register Write Command.*/ 521 /* Write to Transmit Fifo D000-onwards.*/ 522 wr_data = ((Q28_WR_CPU_CTRL_FIFO * 0x0100) | 4); 523 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 524 525 /* Write Tx Fifo Register Address.*/ 526 wr_data = Q28_SPI_TXFIFO; /* D000.*/ 527 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 528 529 /* Write SPI Tx Fifo Control Word-1.*/ 530 wr_data = (0x0100 | Q28_MSGTYPE_HWR); 531 /* D000 = Only 1 byte Message ( 1byte to transmit for WREN opcode). */ 532 /* D001 = Write Message And Higher byte of Transfer Size. */ 533 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 534 535 /* Write SPI Tx Fifo Control Word-2.*/ 536 wr_data = ((Q28_MSGTYPE_HWR * 0x0100) | Q28_WREN_OPCODE) ; 537 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 538 /* D003 = 2 byte WREN OPCODE Message*/ 539 540 /* Write SPI Tx Fifo Control Word-3.*/ 541 wr_data = ((Q28_WRSR_OPCODE * 0x0100) | 0x02); 542 /* D004 = For this command transfer size =2 (1 byte opcode, 1 byte wr data),*/ 543 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 544 /* D005 = WRSR Opcode.*/ 545 546 /* Write SPI Tx Fifo Control Word-4.*/ 547 wr_data = ((0x0C * 0x0100) | 0x0C) ; 548 /* D006 = 0x02, byte for status register, 549 * Bit 7, WPEN = 0, Bit 3:2, BP1:0=3, All block protected, 550 * Bit 1, WEN = 0, Write Enabled. 551 * D005 = WRSR Opcode.*/ 552 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 553 554 /* Write SPI Control Register Write Command.*/ 555 /* Write to SPI Control Register C000 onwards.*/ 556 wr_data = ((Q28_WR_CPU_CTRL_FIFO * 0x0100) | 2); 557 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 558 559 /* Write SPI Control -1 Register Address.*/ 560 wr_data = Q28_SPI_CTRL_1_L; 561 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 562 563 /* Write SPI Control -1 Register Word-1.*/ 564 wr_data = 0x0101; /* C000 = 1 to clear CMD Done Status. C001 = 1 to clear CMD Done INT Status.*/ 565 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 566 567 /* Write SPI Control -1 Register Word-2.*/ 568 wr_data = 0x0003; /* C002 = 3, Start Immidiate Command. C003 = 0, No Prepend byte for Write.*/ 569 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 570 571 /* Wait For WRSR Command To be written. */ 572 rd_data = 0; 573 while (((rd_data & 0x0100) == 0) && (retry_cnt < Q28_RETRY_CNT)) { 574 /* Write SPI Control Register Read Command.*/ 575 /*Read from SPI Controller register C000.*/ 576 wr_data = ((Q28_RD_CPU_CTRL_REGS * 0x0100) | 1); 577 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 578 wr_data = Q28_SPI_CTRL_1_L; 579 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 580 retry_cnt ++; 581 } 582 if (retry_cnt >= Q28_RETRY_CNT) { 583 return PHYMOD_E_CONFIG; 584 } 585 retry_cnt = 0; 586 587 PHYMOD_IF_ERR_RETURN(q28_get_spi_eeprom_status(pa)); 588 589 /* Disable SPI EEPROM.*/ 590 /* Write SPI Control Register Write Command.*/ 591 /* Write to C400, C401, C402, C403 Registers.*/ 592 wr_data = ((Q28_WR_CPU_CTRL_FIFO * 0x0100) | 2); 593 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 594 595 /* Write SPI Control -2 Register Address.*/ 596 wr_data = Q28_SPI_CTRL_2_L; 597 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 598 599 /* Write SPI Control -2 Register Word-1.*/ 600 wr_data = 0x8200; /* C400 = 0 for 0 Fill Byte. C401 = 02 for SPI Clcok to be divide by 2 and little endian fifo.*/ 601 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 602 603 /* Write SPI Control -2 Register Word-2.*/ 604 wr_data = 0x0100; /* C402 = 0, clear all status. C403 = 1, to enable Done Status.*/ 605 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 606 607 608 /* Fill-up SPI Transmit Fifo With SPI EEPROM Messages.*/ 609 /* Write SPI Control Register Write Command.*/ 610 wr_data = ( (Q28_WR_CPU_CTRL_FIFO* 0x0100) | 2); 611 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 612 613 /* Write Tx Fifo Register Address.*/ 614 wr_data = Q28_SPI_TXFIFO; /* D000.*/ 615 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 616 617 618 /* Write SPI Tx Fifo Control Word-1.*/ 619 wr_data = ((0x0100) | Q28_MSGTYPE_HWR); /* D000 = Only 1 byte Message ( 1byte to transmit for WRDI opcode). */ 620 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); /* D001 = Write Message And Higher byte of Transfer Size.*/ 621 622 623 /* Write SPI Tx Fifo Control Word-2.*/ 624 wr_data = Q28_WRDI_OPCODE; /* D002 = WRDI Opcode for transmit. */ 625 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 626 627 /* Write SPI Control Register Write Command.*/ 628 /* Write to SPI Control Register C000 onwards.*/ 629 wr_data = ((Q28_WR_CPU_CTRL_FIFO * 0x0100) | 2); 630 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 631 632 /* Write SPI Control -1 Register Address.*/ 633 wr_data = Q28_SPI_CTRL_1_L; 634 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 635 636 /* Write SPI Control -1 Register Word-1.*/ 637 wr_data = 0x0101; /* C000 = 1 to clear CMD Done Status. C001 = 1 to clear CMD Done INT Status.*/ 638 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 639 640 /*Write SPI Control -1 Register Word-2.*/ 641 wr_data = 0x0003; /* C002 = 3, Start Immidiate Command. C003 = 0, No Prepend byte for Write.*/ 642 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 643 644 /* Wait For WRDI Command To be written.*/ 645 rd_data = 0; 646 while (((rd_data & 0x0100) == 0) && (retry_cnt < Q28_RETRY_CNT)) { 647 /* Write SPI Control Register Read Command.*/ 648 /* Read from SPI Controller register C000.*/ 649 wr_data = ((Q28_RD_CPU_CTRL_REGS * 0x0100) | 1); 650 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 651 if (rd_data != 0xABCD) { 652 PHYMOD_DIAG_OUT(("ERROR -MSG OUT register 0x%x It should be 0xABCD\n", rd_data)); 653 return PHYMOD_E_CONFIG; 654 } 655 /* Write SPI Control -1 Register Address.*/ 656 wr_data = Q28_SPI_CTRL_1_L; 657 PHYMOD_IF_ERR_RETURN(quadra28_write_message (pa, wr_data, &rd_data)); 658 659 temp = 0x0000; 660 while (((temp & 0x4) == 0) && (retry_cnt_1 < Q28_RETRY_CNT)) { 661 PHYMOD_IF_ERR_RETURN(phymod_raw_iblk_read(pa, 0x19005, &temp)); 662 retry_cnt_1 ++; 663 } 664 if (retry_cnt_1 >= Q28_RETRY_CNT) { 665 return PHYMOD_E_CONFIG; 666 } 667 retry_cnt_1 = 0; 668 669 PHYMOD_IF_ERR_RETURN( 670 BCMI_QUADRA28_READ_MSG_OUTr(pa, &q28_msg_out)); 671 wr_data = BCMI_QUADRA28_MSG_OUTr_GET(q28_msg_out); 672 retry_cnt ++; 673 } 674 if (retry_cnt >= Q28_RETRY_CNT) { 675 return PHYMOD_E_CONFIG; 676 } 677 PHYMOD_DIAG_OUT(("UCODE Downloaded on EEPROM \n")); 678 return PHYMOD_E_NONE; 679 } 680 681 int quadra28_before_fw_load(const phymod_core_access_t* core, 682 const phymod_core_init_config_t *init_config, 683 uint32_t chip_id) 684 { 685 phymod_access_t pa; 686 MDIO_BROADCAST_CONTROLr_t mdio_broadcast_ctrl_reg; 687 uint16_t index = 0, max_lane = 0; 688 689 max_lane = (chip_id == QUADRA28_82752_CHIP_ID) ? 1 : 3; 690 PHYMOD_MEMSET(&mdio_broadcast_ctrl_reg, 0, sizeof(MDIO_BROADCAST_CONTROLr_t)); 691 PHYMOD_MEMCPY(&pa, &core->access, sizeof( phymod_access_t)); 692 693 PHYMOD_IF_ERR_RETURN( 694 _quadra28_clear_mode_config(&pa)); 695 696 for (index = 0; index <= max_lane; index++) { 697 pa.addr &= ~max_lane; 698 pa.addr |= index; 699 /* Step1: Enable broadcast mode */ 700 PHYMOD_IF_ERR_RETURN 701 (READ_MDIO_BROADCAST_CONTROLr(&pa, &mdio_broadcast_ctrl_reg)); 702 MDIO_BROADCAST_CONTROLr_MDIO_BCAST_ENf_SET(mdio_broadcast_ctrl_reg, 1); 703 PHYMOD_IF_ERR_RETURN 704 (WRITE_MDIO_BROADCAST_CONTROLr(&pa, mdio_broadcast_ctrl_reg)); 705 } 706 707 return PHYMOD_E_NONE; 708 } 709 710 int quadra28_bcast_fw_load(const phymod_core_access_t* core, 711 const phymod_core_init_config_t *init_config, 712 uint8_t *new_fw, 713 uint32_t fw_length) 714 { 715 phymod_access_t pa; 716 GENERAL_CONTROL_2r_t general_ctrl_reg2; 717 GENERAL_CONTROL_1r_t general_ctrl_reg1; 718 GEN_CTRLr_t general_ctrl_reg; 719 SPI_PORT_CONTROL_STATUSr_t spi_port_ctrl_reg; 720 MSG_INr_t msg_in_reg; 721 CL73CONTROL8r_t cl73_ctrl8_reg; 722 uint32_t index = 0; 723 uint16_t data16; 724 725 PHYMOD_MEMSET(&cl73_ctrl8_reg, 0, sizeof(CL73CONTROL8r_t)); 726 PHYMOD_MEMSET(&general_ctrl_reg1, 0, sizeof(GENERAL_CONTROL_1r_t)); 727 PHYMOD_MEMSET(&general_ctrl_reg, 0, sizeof(GEN_CTRLr_t)); 728 PHYMOD_MEMSET(&spi_port_ctrl_reg, 0, sizeof(BCMI_QUADRA28_SPI_PORT_CONTROL_STATUSr_t)); 729 PHYMOD_MEMSET(&msg_in_reg, 0, sizeof(MSG_INr_t)); 730 PHYMOD_MEMSET(&general_ctrl_reg2, 0, sizeof(GENERAL_CONTROL_2r_t)); 731 PHYMOD_MEMCPY(&pa, &core->access, sizeof( phymod_access_t)); 732 733 734 /* Set 0xFFD1 to read from MGT-M8051 register */ 735 PHYMOD_IF_ERR_RETURN 736 (READ_GENERAL_CONTROL_2r(&pa,&general_ctrl_reg2)); 737 GENERAL_CONTROL_2r_LEGACY_BOOT_SELf_SET(general_ctrl_reg2, 1); 738 739 PHYMOD_IF_ERR_RETURN 740 (WRITE_GENERAL_CONTROL_2r(&pa,general_ctrl_reg2)); 741 PHYMOD_MEMSET(&general_ctrl_reg2, 0, sizeof(GENERAL_CONTROL_2r_t)); 742 743 /* Step5: Select MDIO interface for microcode download */ 744 PHYMOD_IF_ERR_RETURN 745 (BCMI_QUADRA28_READ_SPI_PORT_CONTROL_STATUSr(&pa, 746 &spi_port_ctrl_reg)); 747 748 BCMI_QUADRA28_SPI_PORT_CONTROL_STATUSr_SPI_PORT_USEDf_SET(spi_port_ctrl_reg, 0); 749 BCMI_QUADRA28_SPI_PORT_CONTROL_STATUSr_SPI_BOOTf_SET(spi_port_ctrl_reg, 1); 750 BCMI_QUADRA28_SPI_PORT_CONTROL_STATUSr_SPI_DWLD_DONEf_SET(spi_port_ctrl_reg, 0); 751 PHYMOD_IF_ERR_RETURN 752 (BCMI_QUADRA28_WRITE_SPI_PORT_CONTROL_STATUSr(&pa, 753 spi_port_ctrl_reg)); 754 755 /* Step3: Reset MGT-M8051 uc at address 1.FFD0 */ 756 BCMI_QUADRA28_GENERAL_CONTROL_1r_SET(general_ctrl_reg1, 1); 757 PHYMOD_IF_ERR_RETURN 758 (WRITE_GENERAL_CONTROL_1r(&pa, 759 general_ctrl_reg1)); 760 761 /* Step2: Reset EDc-M8051 uc at address 1.CA10 */ 762 PHYMOD_IF_ERR_RETURN 763 (BCMI_QUADRA28_READ_GEN_CTRLr(&pa, &general_ctrl_reg)); 764 765 BCMI_QUADRA28_GEN_CTRLr_UCRSTf_SET(general_ctrl_reg, 1); 766 767 PHYMOD_IF_ERR_RETURN 768 (BCMI_QUADRA28_WRITE_GEN_CTRLr(&pa, general_ctrl_reg)); 769 770 771 /* Step8: Release EDC-M8051 from reset */ 772 PHYMOD_IF_ERR_RETURN 773 (BCMI_QUADRA28_READ_GEN_CTRLr(&pa, &general_ctrl_reg)); 774 BCMI_QUADRA28_GEN_CTRLr_UCRSTf_SET(general_ctrl_reg, 0); 775 PHYMOD_IF_ERR_RETURN 776 (BCMI_QUADRA28_WRITE_GEN_CTRLr(&pa, general_ctrl_reg)); 777 778 /* step9: Release MGT_M8051 uc from reset */ 779 BCMI_QUADRA28_GENERAL_CONTROL_1r_SET(general_ctrl_reg1, 0); 780 PHYMOD_IF_ERR_RETURN 781 (WRITE_GENERAL_CONTROL_1r(&pa, general_ctrl_reg1)); 782 783 /* step10: wait 1 ms */ 784 PHYMOD_USLEEP(1000); 785 786 /* step11: send initial RAM address */ 787 BCMI_QUADRA28_MSG_INr_SET (msg_in_reg, 0x8000); 788 PHYMOD_IF_ERR_RETURN 789 (BCMI_QUADRA28_WRITE_MSG_INr(&pa, msg_in_reg)); 790 791 /* step12: wait 15 us */ 792 PHYMOD_USLEEP(20); 793 794 /* step13: send microcode size to 1.ca12 */ 795 BCMI_QUADRA28_MSG_INr_MESSAGE_INf_SET(msg_in_reg,fw_length/2); 796 PHYMOD_IF_ERR_RETURN 797 (BCMI_QUADRA28_WRITE_MSG_INr(&pa, msg_in_reg)); 798 799 PHYMOD_USLEEP(20); 800 /* step15 to step 16: send 16-bit microcode word */ 801 PHYMOD_IF_ERR_RETURN 802 (BCMI_QUADRA28_READ_MSG_INr(&pa, 803 &msg_in_reg)); 804 805 for (index = 0; index < (fw_length) - 1; index+=2){ 806 data16 = ((new_fw[index] << 8)| new_fw[index+1]); 807 PHYMOD_USLEEP(15); 808 BCMI_QUADRA28_MSG_INr_MESSAGE_INf_SET(msg_in_reg,data16); 809 PHYMOD_IF_ERR_RETURN 810 (BCMI_QUADRA28_WRITE_MSG_INr(&pa, msg_in_reg)); 811 } 812 813 return PHYMOD_E_NONE; 814 } 815 816 int quadra28_bcast_after_fw_load(const phymod_core_access_t* core, uint32_t chip_id) 817 { 818 uint32_t phy_addr = 0; 819 uint16_t index = 0, max_lane = 0; 820 phymod_access_t pa; 821 GENERAL_CONTROL_2r_t general_ctrl_reg2; 822 int ret_val = 0; 823 824 PHYMOD_MEMSET(&general_ctrl_reg2, 0, sizeof(GENERAL_CONTROL_2r_t)); 825 PHYMOD_MEMCPY(&pa, &core->access, sizeof( phymod_access_t)); 826 phy_addr = pa.addr; 827 max_lane = (chip_id == QUADRA28_82752_CHIP_ID) ? 1 : 3; 828 PHYMOD_IF_ERR_RETURN 829 (READ_GENERAL_CONTROL_2r(&pa,&general_ctrl_reg2)); 830 GENERAL_CONTROL_2r_LEGACY_BOOT_SELf_SET(general_ctrl_reg2, 1); 831 PHYMOD_IF_ERR_RETURN 832 (WRITE_GENERAL_CONTROL_2r(&pa,general_ctrl_reg2)); 833 834 PHYMOD_USLEEP(4000); 835 /* Do it from all three locations */ 836 /* if not read, they will be in wait and not update checksum */ 837 /* Q28 3 processors - flip FFD1 bits to read either from MGT-M8051 or EDC-M8051 */ 838 /* Verify for all processors - 3 in each */ 839 /* use phy address for other two EDC-M8051 lanes */ 840 /* Verify checksum on MGT-M8051 for a phy lane */ 841 for (index = 0; index <= max_lane; index+=2) { 842 int ret_val = 0; 843 pa.addr &= ~max_lane; 844 pa.addr |= index; 845 if ((pa.addr & 1) == 0) { 846 ret_val = _quadra28_verify_fw_download(&pa, 0); 847 if (ret_val != 0) { 848 return ret_val; 849 } 850 } 851 } 852 pa.addr = phy_addr ; 853 PHYMOD_IF_ERR_RETURN 854 (READ_GENERAL_CONTROL_2r(&pa,&general_ctrl_reg2)); 855 GENERAL_CONTROL_2r_LEGACY_BOOT_SELf_SET(general_ctrl_reg2, 0); 856 PHYMOD_IF_ERR_RETURN 857 (WRITE_GENERAL_CONTROL_2r(&pa,general_ctrl_reg2)); 858 PHYMOD_USLEEP(4000); 859 /* Verification for EDC*/ 860 for (index = 0; index <= max_lane; index++) { 861 pa.addr &= ~max_lane; 862 pa.addr |= index; 863 ret_val = _quadra28_verify_fw_download(&pa, 1); 864 if (ret_val != 0) { 865 return ret_val; 866 } 867 } 868 869 return PHYMOD_E_NONE; 870 } 871 872 int quadra28_bcast_disable(const phymod_core_access_t* core, uint32_t chip_id) 873 { 874 phymod_access_t pa; 875 MDIO_BROADCAST_CONTROLr_t mdio_broadcast_ctrl_reg; 876 uint16_t index = 0, max_lane = 0; 877 878 max_lane = (chip_id == QUADRA28_82752_CHIP_ID) ? 1 : 3; 879 PHYMOD_MEMSET(&mdio_broadcast_ctrl_reg, 0, sizeof(MDIO_BROADCAST_CONTROLr_t)); 880 PHYMOD_MEMCPY(&pa, &core->access, sizeof( phymod_access_t)); 881 882 for (index = 0; index <= max_lane; index++) { 883 pa.addr &= ~max_lane; 884 pa.addr |= index; 885 /* Step1: Enable broadcast mode */ 886 PHYMOD_IF_ERR_RETURN 887 (READ_MDIO_BROADCAST_CONTROLr(&pa, &mdio_broadcast_ctrl_reg)); 888 MDIO_BROADCAST_CONTROLr_MDIO_BCAST_ENf_SET(mdio_broadcast_ctrl_reg, 1); 889 PHYMOD_IF_ERR_RETURN 890 (WRITE_MDIO_BROADCAST_CONTROLr(&pa, mdio_broadcast_ctrl_reg)); 891 } 892 893 return PHYMOD_E_NONE; 894 } 895