1233545Sjchandra/*- 2233545Sjchandra * Copyright (c) 2003-2012 Broadcom Corporation 3233545Sjchandra * All Rights Reserved 4233545Sjchandra * 5233545Sjchandra * Redistribution and use in source and binary forms, with or without 6233545Sjchandra * modification, are permitted provided that the following conditions 7233545Sjchandra * are met: 8233545Sjchandra * 9233545Sjchandra * 1. Redistributions of source code must retain the above copyright 10233545Sjchandra * notice, this list of conditions and the following disclaimer. 11233545Sjchandra * 2. Redistributions in binary form must reproduce the above copyright 12233545Sjchandra * notice, this list of conditions and the following disclaimer in 13233545Sjchandra * the documentation and/or other materials provided with the 14233545Sjchandra * distribution. 15233545Sjchandra * 16233545Sjchandra * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR 17233545Sjchandra * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18233545Sjchandra * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19233545Sjchandra * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE 20233545Sjchandra * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21233545Sjchandra * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22233545Sjchandra * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23233545Sjchandra * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24233545Sjchandra * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25233545Sjchandra * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26233545Sjchandra * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27233545Sjchandra */ 28233545Sjchandra 29233545Sjchandra#include <sys/cdefs.h> 30233545Sjchandra__FBSDID("$FreeBSD$"); 31233545Sjchandra#include <sys/types.h> 32233545Sjchandra#include <sys/systm.h> 33233545Sjchandra 34233545Sjchandra#include <mips/nlm/hal/mips-extns.h> 35233545Sjchandra#include <mips/nlm/hal/haldefs.h> 36233545Sjchandra#include <mips/nlm/hal/iomap.h> 37233545Sjchandra#include <mips/nlm/hal/sys.h> 38233545Sjchandra#include <mips/nlm/hal/nae.h> 39233545Sjchandra#include <mips/nlm/hal/mdio.h> 40233545Sjchandra 41238293Sjchandra#include <mips/nlm/xlp.h> 42238293Sjchandra 43233545Sjchandra/* Internal MDIO READ/WRITE Routines */ 44233545Sjchandraint 45233545Sjchandranlm_int_gmac_mdio_read(uint64_t nae_base, int bus, int block, 46233545Sjchandra int intf_type, int phyaddr, int regidx) 47233545Sjchandra{ 48233545Sjchandra uint32_t mdio_ld_cmd; 49233545Sjchandra uint32_t ctrlval; 50233545Sjchandra 51233545Sjchandra ctrlval = INT_MDIO_CTRL_SMP | 52233545Sjchandra (phyaddr << INT_MDIO_CTRL_PHYADDR_POS) | 53233545Sjchandra (regidx << INT_MDIO_CTRL_DEVTYPE_POS) | 54233545Sjchandra (2 << INT_MDIO_CTRL_OP_POS) | 55233545Sjchandra (1 << INT_MDIO_CTRL_ST_POS) | 56233545Sjchandra (7 << INT_MDIO_CTRL_XDIV_POS) | 57233545Sjchandra (2 << INT_MDIO_CTRL_TA_POS) | 58233545Sjchandra (2 << INT_MDIO_CTRL_MIIM_POS) | 59233545Sjchandra (1 << INT_MDIO_CTRL_MCDIV_POS); 60233545Sjchandra 61233545Sjchandra mdio_ld_cmd = nlm_read_nae_reg(nae_base, 62233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4))); 63233545Sjchandra if (mdio_ld_cmd & INT_MDIO_CTRL_CMD_LOAD) { 64233545Sjchandra nlm_write_nae_reg(nae_base, 65233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus*4)), 66233545Sjchandra (mdio_ld_cmd & ~INT_MDIO_CTRL_CMD_LOAD)); 67233545Sjchandra } 68233545Sjchandra 69233545Sjchandra nlm_write_nae_reg(nae_base, 70233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 71233545Sjchandra ctrlval); 72233545Sjchandra 73233545Sjchandra /* Toggle Load Cmd Bit */ 74233545Sjchandra nlm_write_nae_reg(nae_base, 75233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 76233545Sjchandra ctrlval | (1 << INT_MDIO_CTRL_LOAD_POS)); 77233545Sjchandra 78233545Sjchandra /* poll master busy bit until it is not busy */ 79233545Sjchandra while(nlm_read_nae_reg(nae_base, 80233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))) & 81233545Sjchandra INT_MDIO_STAT_MBSY) { 82233545Sjchandra } 83233545Sjchandra 84233545Sjchandra nlm_write_nae_reg(nae_base, 85233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 86233545Sjchandra ctrlval); 87233545Sjchandra 88233545Sjchandra /* Read the data back */ 89233545Sjchandra return nlm_read_nae_reg(nae_base, 90233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))); 91233545Sjchandra} 92233545Sjchandra 93233545Sjchandra/* Internal MDIO WRITE Routines */ 94233545Sjchandraint 95233545Sjchandranlm_int_gmac_mdio_write(uint64_t nae_base, int bus, int block, 96233545Sjchandra int intf_type, int phyaddr, int regidx, uint16_t val) 97233545Sjchandra{ 98233545Sjchandra uint32_t mdio_ld_cmd; 99233545Sjchandra uint32_t ctrlval; 100233545Sjchandra 101233545Sjchandra ctrlval = INT_MDIO_CTRL_SMP | 102233545Sjchandra (phyaddr << INT_MDIO_CTRL_PHYADDR_POS) | 103233545Sjchandra (regidx << INT_MDIO_CTRL_DEVTYPE_POS) | 104233545Sjchandra (1 << INT_MDIO_CTRL_OP_POS) | 105233545Sjchandra (1 << INT_MDIO_CTRL_ST_POS) | 106233545Sjchandra (7 << INT_MDIO_CTRL_XDIV_POS) | 107233545Sjchandra (2 << INT_MDIO_CTRL_TA_POS) | 108233545Sjchandra (1 << INT_MDIO_CTRL_MIIM_POS) | 109233545Sjchandra (1 << INT_MDIO_CTRL_MCDIV_POS); 110233545Sjchandra 111233545Sjchandra mdio_ld_cmd = nlm_read_nae_reg(nae_base, 112233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4))); 113233545Sjchandra if (mdio_ld_cmd & INT_MDIO_CTRL_CMD_LOAD) { 114233545Sjchandra nlm_write_nae_reg(nae_base, 115233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus*4)), 116233545Sjchandra (mdio_ld_cmd & ~INT_MDIO_CTRL_CMD_LOAD)); 117233545Sjchandra } 118233545Sjchandra 119233545Sjchandra /* load data into ctrl data reg */ 120233545Sjchandra nlm_write_nae_reg(nae_base, 121233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_CTRL_DATA + bus * 4)), 122233545Sjchandra val); 123233545Sjchandra 124233545Sjchandra nlm_write_nae_reg(nae_base, 125233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 126233545Sjchandra ctrlval); 127233545Sjchandra 128233545Sjchandra nlm_write_nae_reg(nae_base, 129233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 130233545Sjchandra ctrlval | (1 << INT_MDIO_CTRL_LOAD_POS)); 131233545Sjchandra 132233545Sjchandra /* poll master busy bit until it is not busy */ 133233545Sjchandra while(nlm_read_nae_reg(nae_base, 134233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))) & 135233545Sjchandra INT_MDIO_STAT_MBSY) { 136233545Sjchandra } 137233545Sjchandra 138233545Sjchandra nlm_write_nae_reg(nae_base, 139233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 140233545Sjchandra ctrlval); 141233545Sjchandra 142233545Sjchandra return (0); 143233545Sjchandra} 144233545Sjchandra 145233545Sjchandraint 146233545Sjchandranlm_int_gmac_mdio_reset(uint64_t nae_base, int bus, int block, 147233545Sjchandra int intf_type) 148233545Sjchandra{ 149233545Sjchandra uint32_t val; 150233545Sjchandra 151233545Sjchandra val = (7 << INT_MDIO_CTRL_XDIV_POS) | 152245881Sjchandra (1 << INT_MDIO_CTRL_MCDIV_POS) | 153245881Sjchandra (INT_MDIO_CTRL_SMP); 154233545Sjchandra 155233545Sjchandra nlm_write_nae_reg(nae_base, 156233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 157233545Sjchandra val | INT_MDIO_CTRL_RST); 158233545Sjchandra 159233545Sjchandra nlm_write_nae_reg(nae_base, 160233545Sjchandra NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), 161233545Sjchandra val); 162233545Sjchandra 163233545Sjchandra return (0); 164233545Sjchandra} 165233545Sjchandra 166233545Sjchandra/* 167233545Sjchandra * nae_gmac_mdio_read - Read sgmii phy register 168233545Sjchandra * 169233545Sjchandra * Input parameters: 170233545Sjchandra * bus - bus number, nae has two external gmac bus: 0 and 1 171233545Sjchandra * phyaddr - PHY's address 172233545Sjchandra * regidx - index of register to read 173233545Sjchandra * 174233545Sjchandra * Return value: 175233545Sjchandra * value read (16 bits), or 0xffffffff if an error occurred. 176233545Sjchandra */ 177233545Sjchandraint 178233545Sjchandranlm_gmac_mdio_read(uint64_t nae_base, int bus, int block, 179233545Sjchandra int intf_type, int phyaddr, int regidx) 180233545Sjchandra{ 181233545Sjchandra uint32_t mdio_ld_cmd; 182238293Sjchandra uint32_t ctrlval; 183233545Sjchandra 184233545Sjchandra mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, 185233545Sjchandra (EXT_G0_MDIO_CTRL + bus * 4))); 186233545Sjchandra if (mdio_ld_cmd & EXT_G_MDIO_CMD_LCD) { 187233545Sjchandra nlm_write_nae_reg(nae_base, 188233545Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 189233545Sjchandra (mdio_ld_cmd & ~EXT_G_MDIO_CMD_LCD)); 190233545Sjchandra while(nlm_read_nae_reg(nae_base, 191233545Sjchandra NAE_REG(block, intf_type, 192233545Sjchandra (EXT_G0_MDIO_RD_STAT + bus * 4))) & 193233545Sjchandra EXT_G_MDIO_STAT_MBSY); 194233545Sjchandra } 195233545Sjchandra 196238293Sjchandra ctrlval = EXT_G_MDIO_CMD_SP | 197238293Sjchandra (phyaddr << EXT_G_MDIO_PHYADDR_POS) | 198238293Sjchandra (regidx << EXT_G_MDIO_REGADDR_POS); 199238293Sjchandra if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax()) 200238293Sjchandra ctrlval |= EXT_G_MDIO_DIV; 201238293Sjchandra else 202238293Sjchandra ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64; 203238293Sjchandra 204238293Sjchandra nlm_write_nae_reg(nae_base, 205233545Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 206238293Sjchandra ctrlval); 207233545Sjchandra 208233545Sjchandra nlm_write_nae_reg(nae_base, 209233545Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 210238293Sjchandra ctrlval | (1<<18)); 211238293Sjchandra DELAY(1000); 212233545Sjchandra /* poll master busy bit until it is not busy */ 213233545Sjchandra while(nlm_read_nae_reg(nae_base, 214233545Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_RD_STAT + bus * 4))) & 215233545Sjchandra EXT_G_MDIO_STAT_MBSY); 216233545Sjchandra 217233545Sjchandra nlm_write_nae_reg(nae_base, 218233545Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 219238293Sjchandra ctrlval); 220233545Sjchandra 221233545Sjchandra /* Read the data back */ 222233545Sjchandra return nlm_read_nae_reg(nae_base, 223233545Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_RD_STAT + bus * 4))); 224233545Sjchandra} 225233545Sjchandra 226233545Sjchandra/* 227233545Sjchandra * nae_gmac_mdio_write -Write sgmac mii PHY register. 228233545Sjchandra * 229233545Sjchandra * Input parameters: 230233545Sjchandra * bus - bus number, nae has two external gmac bus: 0 and 1 231233545Sjchandra * phyaddr - PHY to use 232233545Sjchandra * regidx - register within the PHY 233233545Sjchandra * val - data to write to register 234233545Sjchandra * 235233545Sjchandra * Return value: 236233545Sjchandra * 0 - success 237233545Sjchandra */ 238233545Sjchandraint 239233545Sjchandranlm_gmac_mdio_write(uint64_t nae_base, int bus, int block, 240233545Sjchandra int intf_type, int phyaddr, int regidx, uint16_t val) 241233545Sjchandra{ 242233545Sjchandra uint32_t mdio_ld_cmd; 243233545Sjchandra uint32_t ctrlval; 244233545Sjchandra 245233545Sjchandra mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, 246233545Sjchandra (EXT_G0_MDIO_CTRL + bus * 4))); 247233545Sjchandra if (mdio_ld_cmd & EXT_G_MDIO_CMD_LCD) { 248233545Sjchandra nlm_write_nae_reg(nae_base, 249233545Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 250233545Sjchandra (mdio_ld_cmd & ~EXT_G_MDIO_CMD_LCD)); 251233545Sjchandra while(nlm_read_nae_reg(nae_base, 252233545Sjchandra NAE_REG(block, intf_type, 253233545Sjchandra (EXT_G0_MDIO_RD_STAT + bus * 4))) & 254233545Sjchandra EXT_G_MDIO_STAT_MBSY); 255233545Sjchandra } 256233545Sjchandra 257233545Sjchandra /* load data into ctrl data reg */ 258233545Sjchandra nlm_write_nae_reg(nae_base, 259233545Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL_DATA+bus*4)), 260233545Sjchandra val); 261233545Sjchandra 262238293Sjchandra ctrlval = EXT_G_MDIO_CMD_SP | 263238293Sjchandra (phyaddr << EXT_G_MDIO_PHYADDR_POS) | 264238293Sjchandra (regidx << EXT_G_MDIO_REGADDR_POS); 265238293Sjchandra if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax()) 266238293Sjchandra ctrlval |= EXT_G_MDIO_DIV; 267238293Sjchandra else 268238293Sjchandra ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64; 269238293Sjchandra 270233545Sjchandra nlm_write_nae_reg(nae_base, 271233545Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 272233545Sjchandra ctrlval); 273233545Sjchandra 274233545Sjchandra nlm_write_nae_reg(nae_base, 275233545Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 276233545Sjchandra ctrlval | EXT_G_MDIO_CMD_LCD); 277238293Sjchandra DELAY(1000); 278233545Sjchandra 279233545Sjchandra /* poll master busy bit until it is not busy */ 280233545Sjchandra while(nlm_read_nae_reg(nae_base, 281233545Sjchandra NAE_REG(block, intf_type, 282233545Sjchandra (EXT_G0_MDIO_RD_STAT + bus * 4))) & EXT_G_MDIO_STAT_MBSY); 283233545Sjchandra 284233545Sjchandra nlm_write_nae_reg(nae_base, 285233545Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), 286233545Sjchandra ctrlval); 287233545Sjchandra 288233545Sjchandra return (0); 289233545Sjchandra} 290233545Sjchandra 291233545Sjchandra/* 292233545Sjchandra * nae_gmac_mdio_reset -Reset sgmii mdio module. 293233545Sjchandra * 294233545Sjchandra * Input parameters: 295233545Sjchandra * bus - bus number, nae has two external gmac bus: 0 and 1 296233545Sjchandra * 297233545Sjchandra * Return value: 298233545Sjchandra * 0 - success 299233545Sjchandra */ 300233545Sjchandraint 301233545Sjchandranlm_gmac_mdio_reset(uint64_t nae_base, int bus, int block, 302233545Sjchandra int intf_type) 303233545Sjchandra{ 304238293Sjchandra uint32_t ctrlval; 305238293Sjchandra 306245881Sjchandra ctrlval = nlm_read_nae_reg(nae_base, 307245881Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4))); 308245881Sjchandra 309238293Sjchandra if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax()) 310245881Sjchandra ctrlval |= EXT_G_MDIO_DIV; 311238293Sjchandra else 312245881Sjchandra ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64; 313238293Sjchandra 314233545Sjchandra nlm_write_nae_reg(nae_base, 315238293Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)), 316238293Sjchandra EXT_G_MDIO_MMRST | ctrlval); 317233545Sjchandra nlm_write_nae_reg(nae_base, 318238293Sjchandra NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)), ctrlval); 319233545Sjchandra return (0); 320233545Sjchandra} 321245881Sjchandra 322245881Sjchandra/* 323245881Sjchandra * nlm_mdio_reset_all : reset all internal and external MDIO 324245881Sjchandra */ 325245881Sjchandravoid 326245881Sjchandranlm_mdio_reset_all(uint64_t nae_base) 327245881Sjchandra{ 328245881Sjchandra /* reset internal MDIO */ 329245881Sjchandra nlm_int_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG); 330245881Sjchandra /* reset external MDIO */ 331245881Sjchandra nlm_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG); 332245881Sjchandra nlm_gmac_mdio_reset(nae_base, 1, BLOCK_7, LANE_CFG); 333245881Sjchandra} 334