1 /* 2 * Copyright 2007-2013 Solarflare Communications Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include "efsys.h" 27 #include "efx.h" 28 #include "efx_types.h" 29 #include "efx_regs.h" 30 #include "efx_impl.h" 31 32 #if EFSYS_OPT_FALCON 33 34 static __checkReturn int 35 falcon_mdio_wait( 36 __in efx_nic_t *enp) 37 { 38 efx_oword_t oword; 39 unsigned int count; 40 int rc; 41 42 count = 0; 43 do { 44 EFSYS_PROBE1(wait, unsigned int, count); 45 46 EFX_BAR_READO(enp, FR_AB_MD_STAT_REG, &oword); 47 48 if (EFX_OWORD_FIELD(oword, FRF_AB_MD_BSY) == 0) 49 goto done; 50 51 /* Spin for 100 us */ 52 EFSYS_SPIN(100); 53 54 } while (++count < 100); 55 56 rc = ETIMEDOUT; 57 goto fail1; 58 59 done: 60 if (EFX_OWORD_FIELD(oword, FRF_AB_MD_LNFL) != 0) { 61 rc = EIO; 62 goto fail2; 63 } 64 65 if (EFX_OWORD_FIELD(oword, FRF_AB_MD_BSERR) != 0) { 66 rc = EIO; 67 goto fail3; 68 } 69 70 return (0); 71 72 fail3: 73 EFSYS_PROBE(fail3); 74 fail2: 75 EFSYS_PROBE(fail2); 76 fail1: 77 EFSYS_PROBE1(fail1, int, rc); 78 79 return (rc); 80 } 81 82 __checkReturn int 83 falcon_mdio_write( 84 __in efx_nic_t *enp, 85 __in uint8_t port, 86 __in uint8_t mmd, 87 __in uint16_t reg, 88 __in efx_word_t *ewp) 89 { 90 int state; 91 efx_oword_t oword; 92 uint32_t prtad; 93 uint32_t devad; 94 uint32_t addr; 95 uint16_t val; 96 int rc; 97 98 EFSYS_LOCK(enp->en_eslp, state); 99 100 /* Check MDIO is not currently being accessed */ 101 if ((rc = falcon_mdio_wait(enp)) != 0) 102 goto fail1; 103 104 prtad = port; 105 devad = mmd; 106 107 /* Write address */ 108 EFX_POPULATE_OWORD_2(oword, FRF_AB_MD_PRT_ADR, prtad, 109 FRF_AB_MD_DEV_ADR, devad); 110 EFX_BAR_WRITEO(enp, FR_AB_MD_ID_REG, &oword); 111 112 addr = reg; 113 114 EFX_POPULATE_OWORD_1(oword, FRF_AB_MD_PHY_ADR, addr); 115 EFX_BAR_WRITEO(enp, FR_AB_MD_PHY_ADR_REG, &oword); 116 117 /* Write data */ 118 val = EFX_WORD_FIELD(*ewp, EFX_WORD_0); 119 120 EFSYS_PROBE4(mdio_write, uint8_t, port, uint8_t, mmd, 121 uint16_t, reg, uint16_t, val); 122 123 EFX_POPULATE_OWORD_1(oword, FRF_AB_MD_TXD, (uint32_t)val); 124 EFX_BAR_WRITEO(enp, FR_AB_MD_TXD_REG, &oword); 125 126 /* Select clause 45 write cycle */ 127 EFX_POPULATE_OWORD_2(oword, FRF_AB_MD_WRC, 1, FRF_AB_MD_GC, 0); 128 EFX_BAR_WRITEO(enp, FR_AB_MD_CS_REG, &oword); 129 130 /* Wait for the cycle to complete */ 131 if ((rc = falcon_mdio_wait(enp)) != 0) 132 goto fail2; 133 134 EFSYS_UNLOCK(enp->en_eslp, state); 135 return (0); 136 137 fail2: 138 EFSYS_PROBE(fail2); 139 fail1: 140 EFSYS_PROBE1(fail1, int, rc); 141 142 EFSYS_UNLOCK(enp->en_eslp, state); 143 return (rc); 144 } 145 146 __checkReturn int 147 falcon_mdio_read( 148 __in efx_nic_t *enp, 149 __in uint8_t port, 150 __in uint8_t mmd, 151 __in uint16_t reg, 152 __out efx_word_t *ewp) 153 { 154 int state; 155 efx_oword_t oword; 156 uint32_t prtad; 157 uint32_t devad; 158 uint32_t addr; 159 uint16_t val; 160 int rc; 161 162 EFSYS_LOCK(enp->en_eslp, state); 163 164 /* Check MDIO is not currently being accessed */ 165 if ((rc = falcon_mdio_wait(enp)) != 0) 166 goto fail1; 167 168 prtad = port; 169 devad = mmd; 170 171 /* Write address */ 172 EFX_POPULATE_OWORD_2(oword, FRF_AB_MD_PRT_ADR, prtad, 173 FRF_AB_MD_DEV_ADR, devad); 174 EFX_BAR_WRITEO(enp, FR_AB_MD_ID_REG, &oword); 175 176 addr = reg; 177 178 EFX_POPULATE_OWORD_1(oword, FRF_AB_MD_PHY_ADR, addr); 179 EFX_BAR_WRITEO(enp, FR_AB_MD_PHY_ADR_REG, &oword); 180 181 /* Clear the data register */ 182 EFX_SET_OWORD(oword); 183 EFX_BAR_WRITEO(enp, FR_AB_MD_RXD_REG, &oword); 184 185 /* Select clause 45 read cycle */ 186 EFX_POPULATE_OWORD_2(oword, FRF_AB_MD_RDC, 1, FRF_AB_MD_GC, 0); 187 EFX_BAR_WRITEO(enp, FR_AB_MD_CS_REG, &oword); 188 189 /* Wait for the cycle to complete */ 190 if ((rc = falcon_mdio_wait(enp)) != 0) 191 goto fail2; 192 193 /* Read data */ 194 EFX_BAR_READO(enp, FR_AB_MD_RXD_REG, &oword); 195 val = (uint16_t)EFX_OWORD_FIELD(oword, FRF_AB_MD_RXD); 196 197 EFSYS_PROBE4(mdio_read, uint8_t, port, uint8_t, mmd, 198 uint16_t, reg, uint16_t, val); 199 200 EFX_POPULATE_WORD_1(*ewp, EFX_WORD_0, val); 201 202 EFSYS_UNLOCK(enp->en_eslp, state); 203 return (0); 204 205 fail2: 206 EFSYS_PROBE(fail2); 207 fail1: 208 EFSYS_PROBE1(fail1, int, rc); 209 210 EFSYS_UNLOCK(enp->en_eslp, state); 211 return (rc); 212 } 213 214 #endif /* EFSYS_OPT_FALCON */