1/*- 2 * Copyright (c) 2003-2012 Broadcom Corporation 3 * All Rights Reserved 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD$"); 31#include <sys/types.h> 32#include <sys/systm.h> 33 34#include <mips/nlm/hal/mips-extns.h> 35#include <mips/nlm/hal/haldefs.h> 36#include <mips/nlm/hal/iomap.h> 37#include <mips/nlm/hal/sys.h> 38#include <mips/nlm/hal/nae.h> 39#include <mips/nlm/hal/mdio.h> 40 41#include <mips/nlm/xlp.h> 42 43/* Internal MDIO READ/WRITE Routines */ 44int 45nlm_int_gmac_mdio_read(uint64_t nae_base, int bus, int block, 46 int intf_type, int phyaddr, int regidx) 47{ 48 uint32_t mdio_ld_cmd; 49 uint32_t ctrlval; 50 51 ctrlval = INT_MDIO_CTRL_SMP | 52 (phyaddr << INT_MDIO_CTRL_PHYADDR_POS) | 53 (regidx << INT_MDIO_CTRL_DEVTYPE_POS) | 54 (2 << INT_MDIO_CTRL_OP_POS) | 55 (1 << INT_MDIO_CTRL_ST_POS) | 56 (7 << INT_MDIO_CTRL_XDIV_POS) | 57 (2 << INT_MDIO_CTRL_TA_POS) | 58 (2 << INT_MDIO_CTRL_MIIM_POS) | 59 (1 << INT_MDIO_CTRL_MCDIV_POS); 60 61 mdio_ld_cmd = nlm_read_nae_reg(nae_base, 62 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4))); 63 if (mdio_ld_cmd & INT_MDIO_CTRL_CMD_LOAD) { 64 nlm_write_nae_reg(nae_base, 65 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus*4)), 66 (mdio_ld_cmd & ~INT_MDIO_CTRL_CMD_LOAD)); 67 } 68 69 nlm_write_nae_reg(nae_base, 70 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 71 ctrlval); 72 73 /* Toggle Load Cmd Bit */ 74 nlm_write_nae_reg(nae_base, 75 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 76 ctrlval | (1 << INT_MDIO_CTRL_LOAD_POS)); 77 78 /* poll master busy bit until it is not busy */ 79 while(nlm_read_nae_reg(nae_base, 80 NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))) & 81 INT_MDIO_STAT_MBSY) { 82 } 83 84 nlm_write_nae_reg(nae_base, 85 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 86 ctrlval); 87 88 /* Read the data back */ 89 return nlm_read_nae_reg(nae_base, 90 NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))); 91} 92 93/* Internal MDIO WRITE Routines */ 94int 95nlm_int_gmac_mdio_write(uint64_t nae_base, int bus, int block, 96 int intf_type, int phyaddr, int regidx, uint16_t val) 97{ 98 uint32_t mdio_ld_cmd; 99 uint32_t ctrlval; 100 101 ctrlval = INT_MDIO_CTRL_SMP | 102 (phyaddr << INT_MDIO_CTRL_PHYADDR_POS) | 103 (regidx << INT_MDIO_CTRL_DEVTYPE_POS) | 104 (1 << INT_MDIO_CTRL_OP_POS) | 105 (1 << INT_MDIO_CTRL_ST_POS) | 106 (7 << INT_MDIO_CTRL_XDIV_POS) | 107 (2 << INT_MDIO_CTRL_TA_POS) | 108 (1 << INT_MDIO_CTRL_MIIM_POS) | 109 (1 << INT_MDIO_CTRL_MCDIV_POS); 110 111 mdio_ld_cmd = nlm_read_nae_reg(nae_base, 112 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4))); 113 if (mdio_ld_cmd & INT_MDIO_CTRL_CMD_LOAD) { 114 nlm_write_nae_reg(nae_base, 115 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus*4)), 116 (mdio_ld_cmd & ~INT_MDIO_CTRL_CMD_LOAD)); 117 } 118 119 /* load data into ctrl data reg */ 120 nlm_write_nae_reg(nae_base, 121 NAE_REG(block, intf_type, (INT_MDIO_CTRL_DATA + bus * 4)), 122 val); 123 124 nlm_write_nae_reg(nae_base, 125 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 126 ctrlval); 127 128 nlm_write_nae_reg(nae_base, 129 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 130 ctrlval | (1 << INT_MDIO_CTRL_LOAD_POS)); 131 132 /* poll master busy bit until it is not busy */ 133 while(nlm_read_nae_reg(nae_base, 134 NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))) & 135 INT_MDIO_STAT_MBSY) { 136 } 137 138 nlm_write_nae_reg(nae_base, 139 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 140 ctrlval); 141 142 return (0); 143} 144 145int 146nlm_int_gmac_mdio_reset(uint64_t nae_base, int bus, int block, 147 int intf_type) 148{ 149 uint32_t val; 150 151 val = (7 << INT_MDIO_CTRL_XDIV_POS) | 152 (1 << INT_MDIO_CTRL_MCDIV_POS) | 153 (INT_MDIO_CTRL_SMP); 154 155 nlm_write_nae_reg(nae_base, 156 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 157 val | INT_MDIO_CTRL_RST); 158 159 nlm_write_nae_reg(nae_base, 160 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 161 val); 162 163 return (0); 164} 165 166/* 167 * nae_gmac_mdio_read - Read sgmii phy register 168 * 169 * Input parameters: 170 * bus - bus number, nae has two external gmac bus: 0 and 1 171 * phyaddr - PHY's address 172 * regidx - index of register to read 173 * 174 * Return value: 175 * value read (16 bits), or 0xffffffff if an error occurred. 176 */ 177int 178nlm_gmac_mdio_read(uint64_t nae_base, int bus, int block, 179 int intf_type, int phyaddr, int regidx) 180{ 181 uint32_t mdio_ld_cmd; 182 uint32_t ctrlval; 183 184 mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, 185 (EXT_G0_MDIO_CTRL + bus * 4))); 186 if (mdio_ld_cmd & EXT_G_MDIO_CMD_LCD) { 187 nlm_write_nae_reg(nae_base, 188 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 189 (mdio_ld_cmd & ~EXT_G_MDIO_CMD_LCD)); 190 while(nlm_read_nae_reg(nae_base, 191 NAE_REG(block, intf_type, 192 (EXT_G0_MDIO_RD_STAT + bus * 4))) & 193 EXT_G_MDIO_STAT_MBSY); 194 } 195 196 ctrlval = EXT_G_MDIO_CMD_SP | 197 (phyaddr << EXT_G_MDIO_PHYADDR_POS) | 198 (regidx << EXT_G_MDIO_REGADDR_POS); 199 if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax()) 200 ctrlval |= EXT_G_MDIO_DIV; 201 else 202 ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64; 203 204 nlm_write_nae_reg(nae_base, 205 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 206 ctrlval); 207 208 nlm_write_nae_reg(nae_base, 209 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 210 ctrlval | (1<<18)); 211 DELAY(1000); 212 /* poll master busy bit until it is not busy */ 213 while(nlm_read_nae_reg(nae_base, 214 NAE_REG(block, intf_type, (EXT_G0_MDIO_RD_STAT + bus * 4))) & 215 EXT_G_MDIO_STAT_MBSY); 216 217 nlm_write_nae_reg(nae_base, 218 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 219 ctrlval); 220 221 /* Read the data back */ 222 return nlm_read_nae_reg(nae_base, 223 NAE_REG(block, intf_type, (EXT_G0_MDIO_RD_STAT + bus * 4))); 224} 225 226/* 227 * nae_gmac_mdio_write -Write sgmac mii PHY register. 228 * 229 * Input parameters: 230 * bus - bus number, nae has two external gmac bus: 0 and 1 231 * phyaddr - PHY to use 232 * regidx - register within the PHY 233 * val - data to write to register 234 * 235 * Return value: 236 * 0 - success 237 */ 238int 239nlm_gmac_mdio_write(uint64_t nae_base, int bus, int block, 240 int intf_type, int phyaddr, int regidx, uint16_t val) 241{ 242 uint32_t mdio_ld_cmd; 243 uint32_t ctrlval; 244 245 mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, 246 (EXT_G0_MDIO_CTRL + bus * 4))); 247 if (mdio_ld_cmd & EXT_G_MDIO_CMD_LCD) { 248 nlm_write_nae_reg(nae_base, 249 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 250 (mdio_ld_cmd & ~EXT_G_MDIO_CMD_LCD)); 251 while(nlm_read_nae_reg(nae_base, 252 NAE_REG(block, intf_type, 253 (EXT_G0_MDIO_RD_STAT + bus * 4))) & 254 EXT_G_MDIO_STAT_MBSY); 255 } 256 257 /* load data into ctrl data reg */ 258 nlm_write_nae_reg(nae_base, 259 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL_DATA+bus*4)), 260 val); 261 262 ctrlval = EXT_G_MDIO_CMD_SP | 263 (phyaddr << EXT_G_MDIO_PHYADDR_POS) | 264 (regidx << EXT_G_MDIO_REGADDR_POS); 265 if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax()) 266 ctrlval |= EXT_G_MDIO_DIV; 267 else 268 ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64; 269 270 nlm_write_nae_reg(nae_base, 271 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 272 ctrlval); 273 274 nlm_write_nae_reg(nae_base, 275 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 276 ctrlval | EXT_G_MDIO_CMD_LCD); 277 DELAY(1000); 278 279 /* poll master busy bit until it is not busy */ 280 while(nlm_read_nae_reg(nae_base, 281 NAE_REG(block, intf_type, 282 (EXT_G0_MDIO_RD_STAT + bus * 4))) & EXT_G_MDIO_STAT_MBSY); 283 284 nlm_write_nae_reg(nae_base, 285 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 286 ctrlval); 287 288 return (0); 289} 290 291/* 292 * nae_gmac_mdio_reset -Reset sgmii mdio module. 293 * 294 * Input parameters: 295 * bus - bus number, nae has two external gmac bus: 0 and 1 296 * 297 * Return value: 298 * 0 - success 299 */ 300int 301nlm_gmac_mdio_reset(uint64_t nae_base, int bus, int block, 302 int intf_type) 303{ 304 uint32_t ctrlval; 305 306 ctrlval = nlm_read_nae_reg(nae_base, 307 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4))); 308 309 if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax()) 310 ctrlval |= EXT_G_MDIO_DIV; 311 else 312 ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64; 313 314 nlm_write_nae_reg(nae_base, 315 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)), 316 EXT_G_MDIO_MMRST | ctrlval); 317 nlm_write_nae_reg(nae_base, 318 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)), ctrlval); 319 return (0); 320} 321 322/* 323 * nlm_mdio_reset_all : reset all internal and external MDIO 324 */ 325void 326nlm_mdio_reset_all(uint64_t nae_base) 327{ 328 /* reset internal MDIO */ 329 nlm_int_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG); 330 /* reset external MDIO */ 331 nlm_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG); 332 nlm_gmac_mdio_reset(nae_base, 1, BLOCK_7, LANE_CFG); 333} 334