| /***********************license start*********************************** |
| * Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights |
| * reserved. |
| * |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * |
| * * Neither the name of Cavium Inc. nor the names of |
| * its contributors may be used to endorse or promote products |
| * derived from this software without specific prior written |
| * permission. |
| * |
| * This Software, including technical data, may be subject to U.S. export |
| * control laws, including the U.S. Export Administration Act and its |
| * associated regulations, and may be subject to export or import |
| * regulations in other countries. |
| * |
| * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" |
| * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR |
| * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT |
| * TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY |
| * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT |
| * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES |
| * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR |
| * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, |
| * QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK |
| * ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. |
| ***********************license end**************************************/ |
| #include <bdk.h> |
| #include <libbdk-hal/if/bdk-if.h> |
| #include <libbdk-hal/bdk-mdio.h> |
| #include <libbdk-hal/bdk-twsi.h> |
| |
| /* This code is an optional part of the BDK. It is only linked in |
| * if BDK_REQUIRE() needs it */ |
| //BDK_REQUIRE(TWSI); |
| BDK_REQUIRE_DEFINE(XFI); |
| |
| /* |
| Rate Select Settings |
| Mode State : 6/8 |
| Rate Select State : 0 |
| RSEL1 : 0 |
| RSEL0 : 0 |
| Ref Clock Gen(MHz) : 156.25 |
| Data Rate(Gbps) : 10.3125 |
| Description : 10 GbE |
| |
| |
| Data Rate Detection Configuration Registers |
| |
| Mode Pin Settings: |
| Mode State : 0 |
| MODE1 : 0 |
| MODE0 : 0 |
| Mode : Two-wire serial interface mode |
| |
| LOS Pin Strap Mode Settings |
| Mode State : 2/6/8 |
| State : 4 |
| LOS1 : Float |
| LOS0 : Float |
| LOS Amplitude(mVpp) : 20 |
| LOS Hysteresis(dB) : 2 |
| |
| Input Equalization Retimer Mode Settings |
| Mode State : 6/8 |
| EQ State : 0 |
| EQ1 : 0 |
| EQ0 : 0 |
| EQ(dB) : Auto |
| DFE : Auto |
| Comment : Full Auto |
| |
| Input Equalization Re-Driver Mode Settings |
| Mode State : |
| EQ State : 0 |
| EQ1 : 0 |
| EQ0 : 0 |
| EQ(dB) : Auto |
| DFE : APowered Down |
| Comment : Analog EQ Only |
| |
| |
| |
| Output De-Emphasis Retimer Mode Settings |
| Mode State : 6/8 |
| DE State : 3 |
| TX1 : Float |
| TX0 : 0 |
| PRE c(-1) mA : -1 |
| MAIN c( 0) mA : 15 |
| POST c(+1) mA : 4 |
| DC Amplitude(mV): 500 |
| De-Emphasis(dB) : -6.02 |
| Comment : |
| |
| |
| Output De-Emphasis Re-Driver Mode Settings |
| Mode State : 2 |
| DE State : 3 |
| TX1 : Float |
| TX0 : 0 |
| Frequency(Gbps) : 10.3125 |
| DC Amplitude(mV): 600 |
| De-Emphasis(dB) : 4 |
| Comment : 10GbE |
| |
| |
| */ |
| |
| static int debug = 0; |
| |
| #define xfi_printf(fmt, args...) \ |
| do { \ |
| if(debug == 1){ \ |
| printf(fmt, ##args); \ |
| } \ |
| } while(0) |
| |
| |
| int bdk_xfi_vsc7224_dump(int twsi_id, int unit){ |
| bdk_node_t node=0; |
| uint8_t dev_addr=0x10 + unit; |
| uint16_t internal_addr=0x7F; |
| int num_bytes=2; |
| int ia_width_bytes=1; |
| uint64_t data=0; |
| int p, i; |
| uint64_t result[0x100] = {0}; |
| |
| uint64_t pagenum[9] = {0x00, 0x01, 0x02, 0x03, 0x20, 0x21, 0x30, 0x31, 0x40}; |
| |
| for(p=0; p < ARRAY_SIZE(pagenum); p++){ |
| data = pagenum[p]; |
| bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, data); |
| for(i=0x80; i<=0xFF; i++){ |
| result[i] = 0x00; |
| result[i] = bdk_twsix_read_ia(node, twsi_id, dev_addr, (uint16_t)i, num_bytes, ia_width_bytes); |
| } |
| for(i=0x80; i<=0xFF; i++){ |
| if(i==0x80){ |
| printf("\npage_%02X[0x100] = {\n", (uint8_t)pagenum[p]); |
| } |
| if(i % 8 == 0){ |
| printf("/* 0x%2X */", i); |
| } |
| printf(" 0x%04X,", (uint16_t)result[i]); |
| if(i==0xFF){ |
| printf("};"); |
| } |
| if((i+1) % 8 == 0){ |
| printf("\n"); |
| } |
| } |
| } |
| |
| return 0; |
| } |
| |
| /* XFI ReTimer/ReDriver Mode Settings */ |
| |
| /* |
| power down regs: |
| Page Reg Position Mask val RegFieldName |
| 0x00 0x89 b07 0x0080 1 PD_INBUF |
| 0x00 0x8A b10 0x0400 1 PD_DFECRU |
| 0x00 0x8A b01 0x0002 1 PD_DFE |
| 0x00 0x8A b00 0x0001 1 PD_DFEADAPT |
| 0x00 0x97 b15 0x8000 1 ASYN_SYNN |
| 0x00 0x97 b09 0x0200 1 PD_OD |
| 0x00 0xA0 b11 0x0800 1 PD_LOS |
| 0x00 0xA4 b15 0x8000 1 PD_CH |
| 0x00 0xB5 b07 0x0080 1 PD_INBUF |
| 0x00 0xB9 b15 0x8000 1 ASYN_SYNN |
| 0x00 0xB9 b09 0x0200 1 PD_OD |
| 0x00 0xBF b07 0x0080 1 PD_INBUF |
| 0x00 0xF0 b15 0x8000 1 ASYN_SYNN |
| 0x00 0xF0 b09 0x0200 1 PD_OD |
| 0x00 0xF6 b07 0x0080 1 PD_INBUF |
| 0x00 0xFA b15 0x8000 1 ASYN_SYNN |
| 0x00 0xFA b09 0x0200 1 PD_OD |
| */ |
| struct regmap{ |
| short int page; |
| unsigned char reg; |
| unsigned short int retimer; |
| unsigned short int redriver; |
| }; |
| |
| /* This table only applies to SFF8104 */ |
| struct regmap xfiregmap[64] = { |
| //CH 0 |
| {0x00, 0x84, 0x0800, 0x0000}, //EQTABLE_DCOFF0 (0n_84) |
| {0x00, 0x8A, 0x7000, 0x0400}, //DFECRU_CTRL (0n_8A) |
| {0x00, 0x8B, 0x4060, 0x0000}, //DFECRU_CFVF_CFAP (0n_8B) |
| {0x00, 0x90, 0xDE85, 0x0000}, //DFECRU_DFEAUTO (0n_90) |
| {0x00, 0x91, 0x2020, 0x0000}, //DFECRU_BTMX_BFMX (0n_91) |
| {0x00, 0x92, 0x0860, 0x0000}, //DFECRU_DXMX_TRMX (0n_92) |
| {0x00, 0x93, 0x6000, 0x0000}, //DFECRU_TRMN_ERRI (0n_93) |
| {0x00, 0x94, 0x0001, 0x0000}, //DFECRU_DFEMODE (0n_94) |
| {0x00, 0x95, 0x0008, 0x0000}, //DFECRU_RATESEL (0n_95) |
| {0x00, 0x97, 0x0000, 0x8080}, //OUTDRVCTRL (0n_97) |
| {0x00, 0x99, 0x001E, 0x0014}, //KR_MAINTAP (0n_99) |
| {0x00, 0x9A, 0x000B, 0x0000}, //KR_PRETAP (0n_9A) |
| {0x00, 0x9B, 0x0010, 0x0000}, //KR_POSTTAP (0n_9B) |
| {0x00, 0x9E, 0x03E8, 0x07D0}, //LOSASSRT (0n_9E) |
| {0x00, 0x9F, 0x04EA, 0x09D5}, //LOSDASSRT (0n_9F) |
| {0x00, 0xB2, 0x0888, 0x0000}, //NA |
| |
| //CH 1 |
| {0x01, 0x84, 0x0800, 0x0000}, |
| {0x01, 0x8A, 0x7000, 0x0400}, |
| {0x01, 0x8B, 0x4060, 0x0000}, |
| {0x01, 0x90, 0xDE85, 0x0000}, |
| {0x01, 0x91, 0x2020, 0x0000}, |
| {0x01, 0x92, 0x0860, 0x0000}, |
| {0x01, 0x93, 0x6000, 0x0000}, |
| {0x01, 0x94, 0x0001, 0x0000}, |
| {0x01, 0x95, 0x0008, 0x0000}, |
| {0x01, 0x97, 0x0000, 0x8080}, |
| {0x01, 0x99, 0x001E, 0x0014}, |
| {0x01, 0x9A, 0x000B, 0x0000}, |
| {0x01, 0x9B, 0x0010, 0x0000}, |
| {0x01, 0x9E, 0x03E8, 0x07D0}, |
| {0x01, 0x9F, 0x04EA, 0x09D5}, |
| {0x01, 0xB2, 0x0888, 0x0000}, |
| |
| //POWER_DOWN Channel 2 and 3 |
| {0x02, 0x8A, 0x0400, 0x0400}, |
| {0x02, 0xA4, 0x8000, 0x8000}, |
| {0x03, 0x8A, 0x0400, 0x0400}, |
| {0x03, 0xA4, 0x8000, 0x8000}, |
| |
| {0x30, 0x80, 0x3453, 0x0000}, //FSYNM_NVAL (3f_80) |
| {0x30, 0x81, 0x00F6, 0x0000}, //FSYNFVAL_MSB (3f_81) |
| {0x30, 0x82, 0x8800, 0x0000}, //FSYNFVAL_LSB (3f_82) |
| {0x30, 0x83, 0x000F, 0x0000}, //FSYNRVAL_MSB (3f_83) |
| {0x30, 0x84, 0xB5E0, 0x0000}, //FSYNRVAL_LSB (3f_84) |
| {0x30, 0x85, 0x0000, 0x0400}, //FSYNTST (3f_85) |
| |
| {0x40, 0x80, 0x4C00, 0x0000}, //ANMUXSEL (40_80) |
| {0x40, 0x81, 0x4000, 0x0000}, //DGMUXCTRL (40_81) |
| {0x40, 0x82, 0x7800, 0xC000}, //RCKINCTRL (40_82) |
| {0x40, 0x84, 0x0020, 0x0000}, //CHRCKSEL (40_84) |
| |
| {-1, 0, 0, 0}, |
| }; |
| |
| int bdk_vsc7224_modeset(int twsi_id, int unit, int xfi_mode){ |
| bdk_node_t node=0; |
| uint8_t dev_addr=0x10 + unit; |
| uint16_t internal_addr=0x7F; |
| uint16_t page=0; |
| int num_bytes=2; |
| int ia_width_bytes=1; |
| uint64_t data=0; |
| int val=0; |
| int ret = 0, r=0; |
| uint16_t reg = 0; |
| |
| if(xfi_mode==0){ |
| printf("XFI Mode Retimer\n"); |
| }else{ |
| printf("XFI Mode Redriver\n"); |
| } |
| |
| while(xfiregmap[r].page != -1){ |
| page = xfiregmap[r].page; |
| reg = xfiregmap[r].reg; |
| if(xfi_mode==0){ |
| data = xfiregmap[r].retimer; |
| }else{ |
| data = xfiregmap[r].redriver; |
| } |
| ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, (uint64_t)page); |
| if(ret !=0){ |
| printf("XFI init Error\n"); |
| break; |
| } |
| ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, reg, num_bytes, ia_width_bytes, data); |
| if(ret !=0){ |
| printf("XFI init Error\n"); |
| break; |
| } |
| val = bdk_twsix_read_ia(node, twsi_id, dev_addr, reg, num_bytes, ia_width_bytes); |
| if(val == -1){ |
| printf("XFI Read Reg Failed @ page:reg :: %2X:%2X \n",page, reg); |
| break; |
| }else{ |
| xfi_printf(" Page: reg: data: val :: %2X:%2X:%04X:%04X\n", page, reg, (uint16_t)data, val); |
| } |
| r++; |
| } |
| |
| return ret; |
| } |
| |
| |
| int bdk_vsc7224_regmap_modeget(int twsi_id, int unit){ |
| bdk_node_t node=0; |
| uint8_t dev_addr=0x10 + unit; |
| uint16_t internal_addr=0x7F; |
| uint16_t page=0; |
| int num_bytes=2; |
| int ia_width_bytes=1; |
| //uint64_t data=0; |
| uint16_t reg = 0; |
| int ret = 0, r=0; |
| int data; |
| |
| printf("\n===========================================\n"); |
| printf("Page :Reg :Value :Retimer :Redriver\n"); |
| printf("===========================================\n"); |
| while(xfiregmap[r].page != -1){ |
| page = xfiregmap[r].page; |
| reg = xfiregmap[r].reg; |
| |
| ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, (uint64_t)page); |
| if(ret !=0){ |
| printf("XFI init Error\n"); |
| break; |
| } |
| data = bdk_twsix_read_ia(node, twsi_id, dev_addr, reg, num_bytes, ia_width_bytes); |
| if(data == -1){ |
| printf("XFI Read Reg Failed @ page:reg :: %2X:%2X \n",page, reg); |
| break; |
| } |
| printf(" %02X: %02X: %04X: %04X: %04X\n", page, reg, (uint16_t)data, xfiregmap[r].retimer, xfiregmap[r].redriver); |
| r++; |
| } |
| printf("=======================================\n"); |
| |
| return ret; |
| } |
| |
| int bdk_vsc7224_wp_regs(int twsi_id, int unit, int xfi_wp){ |
| bdk_node_t node=0; |
| uint8_t dev_addr=0x10 + unit; |
| uint16_t internal_addr=0x7E; |
| uint16_t data=0x0000; |
| int num_bytes=2; |
| int ia_width_bytes=1; |
| int ret =0; |
| |
| if(xfi_wp == 1){ |
| data = 0x0000; |
| }else{ |
| data = 0xFFFF; |
| } |
| |
| ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, (uint64_t)data); |
| if(ret !=0){ |
| printf("XFI VSC7224 Write Protect Error\n"); |
| } |
| |
| return ret; |
| } |
| |
| int bdk_vsc7224_set_reg(int twsi_id, int unit, int page, int reg, int val){ |
| bdk_node_t node=0; |
| uint8_t dev_addr=0x10 + unit; |
| uint16_t internal_addr = reg; |
| int num_bytes=2; |
| int ia_width_bytes=1; |
| int ret=0; |
| |
| xfi_printf(" Unit: Page: reg: val :: %02x:%2X:%2X:%04X\n", unit, page, reg, val & 0xFFFF); |
| ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, 0x7F, num_bytes, ia_width_bytes, (uint64_t)(page & 0xFF)); |
| if (ret) { |
| printf("XFI VSC7224 TWSI Set Page Register Error\n"); |
| } |
| |
| ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, (uint64_t)(val & 0xFFFF)); |
| if (ret) { |
| printf("XFI VSC7224 TWSI Set Register Error\n"); |
| } |
| |
| return ret; |
| } |
| |
| int bdk_vsc7224_debug(int _debug){ |
| debug =_debug; |
| return 0; |
| } |