1210284Sjmallett/***********************license start*************** 2232812Sjmallett * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3215990Sjmallett * reserved. 4210284Sjmallett * 5210284Sjmallett * 6215990Sjmallett * Redistribution and use in source and binary forms, with or without 7215990Sjmallett * modification, are permitted provided that the following conditions are 8215990Sjmallett * met: 9210284Sjmallett * 10215990Sjmallett * * Redistributions of source code must retain the above copyright 11215990Sjmallett * notice, this list of conditions and the following disclaimer. 12210284Sjmallett * 13215990Sjmallett * * Redistributions in binary form must reproduce the above 14215990Sjmallett * copyright notice, this list of conditions and the following 15215990Sjmallett * disclaimer in the documentation and/or other materials provided 16215990Sjmallett * with the distribution. 17215990Sjmallett 18232812Sjmallett * * Neither the name of Cavium Inc. nor the names of 19215990Sjmallett * its contributors may be used to endorse or promote products 20215990Sjmallett * derived from this software without specific prior written 21215990Sjmallett * permission. 22215990Sjmallett 23215990Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215990Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215990Sjmallett * regulations, and may be subject to export or import regulations in other 26215990Sjmallett * countries. 27215990Sjmallett 28215990Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30215990Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215990Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215990Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215990Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215990Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215990Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215990Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215990Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38210284Sjmallett ***********************license end**************************************/ 39210284Sjmallett 40210284Sjmallett 41210284Sjmallett 42210284Sjmallett 43210284Sjmallett 44210284Sjmallett 45215990Sjmallett 46210284Sjmallett/** 47210284Sjmallett * @file 48210284Sjmallett * 49210284Sjmallett * Interface to the SMI/MDIO hardware, including support for both IEEE 802.3 50210284Sjmallett * clause 22 and clause 45 operations. 51210284Sjmallett * 52232812Sjmallett * <hr>$Revision: 70030 $<hr> 53210284Sjmallett */ 54210284Sjmallett 55210284Sjmallett#ifndef __CVMX_MIO_H__ 56210284Sjmallett#define __CVMX_MIO_H__ 57210284Sjmallett 58215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 59215990Sjmallett#include <asm/octeon/octeon.h> 60215990Sjmallett#include <asm/octeon/cvmx-clock.h> 61215990Sjmallett#else 62215990Sjmallett#include "cvmx-clock.h" 63215990Sjmallett#endif 64215990Sjmallett 65210284Sjmallett#ifdef __cplusplus 66210284Sjmallettextern "C" { 67210284Sjmallett#endif 68210284Sjmallett 69210284Sjmallett/** 70210284Sjmallett * PHY register 0 from the 802.3 spec 71210284Sjmallett */ 72210284Sjmallett#define CVMX_MDIO_PHY_REG_CONTROL 0 73210284Sjmalletttypedef union 74210284Sjmallett{ 75210284Sjmallett uint16_t u16; 76210284Sjmallett struct 77210284Sjmallett { 78210284Sjmallett uint16_t reset : 1; 79210284Sjmallett uint16_t loopback : 1; 80210284Sjmallett uint16_t speed_lsb : 1; 81210284Sjmallett uint16_t autoneg_enable : 1; 82210284Sjmallett uint16_t power_down : 1; 83210284Sjmallett uint16_t isolate : 1; 84210284Sjmallett uint16_t restart_autoneg : 1; 85210284Sjmallett uint16_t duplex : 1; 86210284Sjmallett uint16_t collision_test : 1; 87210284Sjmallett uint16_t speed_msb : 1; 88210284Sjmallett uint16_t unidirectional_enable : 1; 89210284Sjmallett uint16_t reserved_0_4 : 5; 90210284Sjmallett } s; 91210284Sjmallett} cvmx_mdio_phy_reg_control_t; 92210284Sjmallett 93210284Sjmallett/** 94210284Sjmallett * PHY register 1 from the 802.3 spec 95210284Sjmallett */ 96210284Sjmallett#define CVMX_MDIO_PHY_REG_STATUS 1 97210284Sjmalletttypedef union 98210284Sjmallett{ 99210284Sjmallett uint16_t u16; 100210284Sjmallett struct 101210284Sjmallett { 102210284Sjmallett uint16_t capable_100base_t4 : 1; 103210284Sjmallett uint16_t capable_100base_x_full : 1; 104210284Sjmallett uint16_t capable_100base_x_half : 1; 105210284Sjmallett uint16_t capable_10_full : 1; 106210284Sjmallett uint16_t capable_10_half : 1; 107210284Sjmallett uint16_t capable_100base_t2_full : 1; 108210284Sjmallett uint16_t capable_100base_t2_half : 1; 109210284Sjmallett uint16_t capable_extended_status : 1; 110210284Sjmallett uint16_t capable_unidirectional : 1; 111210284Sjmallett uint16_t capable_mf_preamble_suppression : 1; 112210284Sjmallett uint16_t autoneg_complete : 1; 113210284Sjmallett uint16_t remote_fault : 1; 114210284Sjmallett uint16_t capable_autoneg : 1; 115210284Sjmallett uint16_t link_status : 1; 116210284Sjmallett uint16_t jabber_detect : 1; 117210284Sjmallett uint16_t capable_extended_registers : 1; 118210284Sjmallett 119210284Sjmallett } s; 120210284Sjmallett} cvmx_mdio_phy_reg_status_t; 121210284Sjmallett 122210284Sjmallett/** 123210284Sjmallett * PHY register 2 from the 802.3 spec 124210284Sjmallett */ 125210284Sjmallett#define CVMX_MDIO_PHY_REG_ID1 2 126210284Sjmalletttypedef union 127210284Sjmallett{ 128210284Sjmallett uint16_t u16; 129210284Sjmallett struct 130210284Sjmallett { 131210284Sjmallett uint16_t oui_bits_3_18; 132210284Sjmallett } s; 133210284Sjmallett} cvmx_mdio_phy_reg_id1_t; 134210284Sjmallett 135210284Sjmallett/** 136210284Sjmallett * PHY register 3 from the 802.3 spec 137210284Sjmallett */ 138210284Sjmallett#define CVMX_MDIO_PHY_REG_ID2 3 139210284Sjmalletttypedef union 140210284Sjmallett{ 141210284Sjmallett uint16_t u16; 142210284Sjmallett struct 143210284Sjmallett { 144210284Sjmallett uint16_t oui_bits_19_24 : 6; 145210284Sjmallett uint16_t model : 6; 146210284Sjmallett uint16_t revision : 4; 147210284Sjmallett } s; 148210284Sjmallett} cvmx_mdio_phy_reg_id2_t; 149210284Sjmallett 150210284Sjmallett/** 151210284Sjmallett * PHY register 4 from the 802.3 spec 152210284Sjmallett */ 153210284Sjmallett#define CVMX_MDIO_PHY_REG_AUTONEG_ADVER 4 154210284Sjmalletttypedef union 155210284Sjmallett{ 156210284Sjmallett uint16_t u16; 157210284Sjmallett struct 158210284Sjmallett { 159210284Sjmallett uint16_t next_page : 1; 160210284Sjmallett uint16_t reserved_14 : 1; 161210284Sjmallett uint16_t remote_fault : 1; 162210284Sjmallett uint16_t reserved_12 : 1; 163210284Sjmallett uint16_t asymmetric_pause : 1; 164210284Sjmallett uint16_t pause : 1; 165210284Sjmallett uint16_t advert_100base_t4 : 1; 166210284Sjmallett uint16_t advert_100base_tx_full : 1; 167210284Sjmallett uint16_t advert_100base_tx_half : 1; 168210284Sjmallett uint16_t advert_10base_tx_full : 1; 169210284Sjmallett uint16_t advert_10base_tx_half : 1; 170210284Sjmallett uint16_t selector : 5; 171210284Sjmallett } s; 172210284Sjmallett} cvmx_mdio_phy_reg_autoneg_adver_t; 173210284Sjmallett 174210284Sjmallett/** 175210284Sjmallett * PHY register 5 from the 802.3 spec 176210284Sjmallett */ 177210284Sjmallett#define CVMX_MDIO_PHY_REG_LINK_PARTNER_ABILITY 5 178210284Sjmalletttypedef union 179210284Sjmallett{ 180210284Sjmallett uint16_t u16; 181210284Sjmallett struct 182210284Sjmallett { 183210284Sjmallett uint16_t next_page : 1; 184210284Sjmallett uint16_t ack : 1; 185210284Sjmallett uint16_t remote_fault : 1; 186210284Sjmallett uint16_t reserved_12 : 1; 187210284Sjmallett uint16_t asymmetric_pause : 1; 188210284Sjmallett uint16_t pause : 1; 189210284Sjmallett uint16_t advert_100base_t4 : 1; 190210284Sjmallett uint16_t advert_100base_tx_full : 1; 191210284Sjmallett uint16_t advert_100base_tx_half : 1; 192210284Sjmallett uint16_t advert_10base_tx_full : 1; 193210284Sjmallett uint16_t advert_10base_tx_half : 1; 194210284Sjmallett uint16_t selector : 5; 195210284Sjmallett } s; 196210284Sjmallett} cvmx_mdio_phy_reg_link_partner_ability_t; 197210284Sjmallett 198210284Sjmallett/** 199210284Sjmallett * PHY register 6 from the 802.3 spec 200210284Sjmallett */ 201210284Sjmallett#define CVMX_MDIO_PHY_REG_AUTONEG_EXPANSION 6 202210284Sjmalletttypedef union 203210284Sjmallett{ 204210284Sjmallett uint16_t u16; 205210284Sjmallett struct 206210284Sjmallett { 207210284Sjmallett uint16_t reserved_5_15 : 11; 208210284Sjmallett uint16_t parallel_detection_fault : 1; 209210284Sjmallett uint16_t link_partner_next_page_capable : 1; 210210284Sjmallett uint16_t local_next_page_capable : 1; 211210284Sjmallett uint16_t page_received : 1; 212210284Sjmallett uint16_t link_partner_autoneg_capable : 1; 213210284Sjmallett 214210284Sjmallett } s; 215210284Sjmallett} cvmx_mdio_phy_reg_autoneg_expansion_t; 216210284Sjmallett 217210284Sjmallett/** 218210284Sjmallett * PHY register 9 from the 802.3 spec 219210284Sjmallett */ 220210284Sjmallett#define CVMX_MDIO_PHY_REG_CONTROL_1000 9 221210284Sjmalletttypedef union 222210284Sjmallett{ 223210284Sjmallett uint16_t u16; 224210284Sjmallett struct 225210284Sjmallett { 226210284Sjmallett uint16_t test_mode : 3; 227210284Sjmallett uint16_t manual_master_slave : 1; 228210284Sjmallett uint16_t master : 1; 229210284Sjmallett uint16_t port_type : 1; 230210284Sjmallett uint16_t advert_1000base_t_full : 1; 231210284Sjmallett uint16_t advert_1000base_t_half : 1; 232210284Sjmallett uint16_t reserved_0_7 : 8; 233210284Sjmallett } s; 234210284Sjmallett} cvmx_mdio_phy_reg_control_1000_t; 235210284Sjmallett 236210284Sjmallett/** 237210284Sjmallett * PHY register 10 from the 802.3 spec 238210284Sjmallett */ 239210284Sjmallett#define CVMX_MDIO_PHY_REG_STATUS_1000 10 240210284Sjmalletttypedef union 241210284Sjmallett{ 242210284Sjmallett uint16_t u16; 243210284Sjmallett struct 244210284Sjmallett { 245210284Sjmallett uint16_t master_slave_fault : 1; 246210284Sjmallett uint16_t is_master : 1; 247210284Sjmallett uint16_t local_receiver_ok : 1; 248210284Sjmallett uint16_t remote_receiver_ok : 1; 249210284Sjmallett uint16_t remote_capable_1000base_t_full : 1; 250210284Sjmallett uint16_t remote_capable_1000base_t_half : 1; 251210284Sjmallett uint16_t reserved_8_9 : 2; 252210284Sjmallett uint16_t idle_error_count : 8; 253210284Sjmallett } s; 254210284Sjmallett} cvmx_mdio_phy_reg_status_1000_t; 255210284Sjmallett 256210284Sjmallett/** 257210284Sjmallett * PHY register 15 from the 802.3 spec 258210284Sjmallett */ 259210284Sjmallett#define CVMX_MDIO_PHY_REG_EXTENDED_STATUS 15 260210284Sjmalletttypedef union 261210284Sjmallett{ 262210284Sjmallett uint16_t u16; 263210284Sjmallett struct 264210284Sjmallett { 265210284Sjmallett uint16_t capable_1000base_x_full : 1; 266210284Sjmallett uint16_t capable_1000base_x_half : 1; 267210284Sjmallett uint16_t capable_1000base_t_full : 1; 268210284Sjmallett uint16_t capable_1000base_t_half : 1; 269210284Sjmallett uint16_t reserved_0_11 : 12; 270210284Sjmallett } s; 271210284Sjmallett} cvmx_mdio_phy_reg_extended_status_t; 272210284Sjmallett 273210284Sjmallett 274210284Sjmallett/** 275210284Sjmallett * PHY register 13 from the 802.3 spec 276210284Sjmallett */ 277210284Sjmallett#define CVMX_MDIO_PHY_REG_MMD_CONTROL 13 278210284Sjmalletttypedef union 279210284Sjmallett{ 280210284Sjmallett uint16_t u16; 281210284Sjmallett struct 282210284Sjmallett { 283210284Sjmallett uint16_t function : 2; 284210284Sjmallett uint16_t reserved_5_13 : 9; 285210284Sjmallett uint16_t devad : 5; 286210284Sjmallett } s; 287210284Sjmallett} cvmx_mdio_phy_reg_mmd_control_t; 288210284Sjmallett 289210284Sjmallett/** 290210284Sjmallett * PHY register 14 from the 802.3 spec 291210284Sjmallett */ 292210284Sjmallett#define CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA 14 293210284Sjmalletttypedef union 294210284Sjmallett{ 295210284Sjmallett uint16_t u16; 296210284Sjmallett struct 297210284Sjmallett { 298210284Sjmallett uint16_t address_data : 16; 299210284Sjmallett } s; 300210284Sjmallett} cvmx_mdio_phy_reg_mmd_address_data_t; 301210284Sjmallett 302210284Sjmallett/* Operating request encodings. */ 303210284Sjmallett#define MDIO_CLAUSE_22_WRITE 0 304210284Sjmallett#define MDIO_CLAUSE_22_READ 1 305210284Sjmallett 306210284Sjmallett#define MDIO_CLAUSE_45_ADDRESS 0 307210284Sjmallett#define MDIO_CLAUSE_45_WRITE 1 308210284Sjmallett#define MDIO_CLAUSE_45_READ_INC 2 309210284Sjmallett#define MDIO_CLAUSE_45_READ 3 310210284Sjmallett 311232812Sjmallett/* MMD identifiers, mostly for accessing devices within XENPAK modules. */ 312210284Sjmallett#define CVMX_MMD_DEVICE_PMA_PMD 1 313210284Sjmallett#define CVMX_MMD_DEVICE_WIS 2 314210284Sjmallett#define CVMX_MMD_DEVICE_PCS 3 315210284Sjmallett#define CVMX_MMD_DEVICE_PHY_XS 4 316210284Sjmallett#define CVMX_MMD_DEVICE_DTS_XS 5 317210284Sjmallett#define CVMX_MMD_DEVICE_TC 6 318210284Sjmallett#define CVMX_MMD_DEVICE_CL22_EXT 29 319210284Sjmallett#define CVMX_MMD_DEVICE_VENDOR_1 30 320210284Sjmallett#define CVMX_MMD_DEVICE_VENDOR_2 31 321210284Sjmallett 322215990Sjmallett#define CVMX_MDIO_TIMEOUT 100000 /* 100 millisec */ 323215990Sjmallett 324210284Sjmallett/* Helper function to put MDIO interface into clause 45 mode */ 325210284Sjmallettstatic inline void __cvmx_mdio_set_clause45_mode(int bus_id) 326210284Sjmallett{ 327210284Sjmallett cvmx_smix_clk_t smi_clk; 328210284Sjmallett /* Put bus into clause 45 mode */ 329210284Sjmallett smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id)); 330210284Sjmallett smi_clk.s.mode = 1; 331210284Sjmallett smi_clk.s.preamble = 1; 332210284Sjmallett cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64); 333210284Sjmallett} 334210284Sjmallett/* Helper function to put MDIO interface into clause 22 mode */ 335210284Sjmallettstatic inline void __cvmx_mdio_set_clause22_mode(int bus_id) 336210284Sjmallett{ 337210284Sjmallett cvmx_smix_clk_t smi_clk; 338210284Sjmallett /* Put bus into clause 22 mode */ 339210284Sjmallett smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id)); 340210284Sjmallett smi_clk.s.mode = 0; 341210284Sjmallett cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64); 342210284Sjmallett} 343210284Sjmallett 344210284Sjmallett/** 345215990Sjmallett * @INTERNAL 346215990Sjmallett * Function to read SMIX_RD_DAT and check for timeouts. This 347215990Sjmallett * code sequence is done fairly often, so put in in one spot. 348215990Sjmallett * 349215990Sjmallett * @param bus_id SMI/MDIO bus to read 350215990Sjmallett * 351215990Sjmallett * @return Value of SMIX_RD_DAT. pending will be set on 352215990Sjmallett * a timeout. 353215990Sjmallett */ 354215990Sjmallettstatic inline cvmx_smix_rd_dat_t __cvmx_mdio_read_rd_dat(int bus_id) 355215990Sjmallett{ 356215990Sjmallett cvmx_smix_rd_dat_t smi_rd; 357215990Sjmallett uint64_t done = cvmx_get_cycle() + (uint64_t)CVMX_MDIO_TIMEOUT * 358215990Sjmallett cvmx_clock_get_rate(CVMX_CLOCK_CORE) / 1000000; 359215990Sjmallett do 360215990Sjmallett { 361215990Sjmallett cvmx_wait(1000); 362215990Sjmallett smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id)); 363215990Sjmallett } while (smi_rd.s.pending && (cvmx_get_cycle() < done)); 364215990Sjmallett return smi_rd; 365215990Sjmallett} 366215990Sjmallett 367215990Sjmallett 368215990Sjmallett/** 369210284Sjmallett * Perform an MII read. This function is used to read PHY 370210284Sjmallett * registers controlling auto negotiation. 371210284Sjmallett * 372210284Sjmallett * @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX) 373210284Sjmallett * support multiple busses. 374210284Sjmallett * @param phy_id The MII phy id 375210284Sjmallett * @param location Register location to read 376210284Sjmallett * 377210284Sjmallett * @return Result from the read or -1 on failure 378210284Sjmallett */ 379210284Sjmallettstatic inline int cvmx_mdio_read(int bus_id, int phy_id, int location) 380210284Sjmallett{ 381215990Sjmallett#if defined(CVMX_BUILD_FOR_LINUX_KERNEL) && defined(CONFIG_PHYLIB) 382215990Sjmallett struct mii_bus *bus; 383215990Sjmallett int rv; 384215990Sjmallett 385232812Sjmallett BUG_ON(bus_id > 3 || bus_id < 0); 386215990Sjmallett 387215990Sjmallett bus = octeon_mdiobuses[bus_id]; 388215990Sjmallett if (bus == NULL) 389215990Sjmallett return -1; 390215990Sjmallett 391215990Sjmallett rv = mdiobus_read(bus, phy_id, location); 392215990Sjmallett 393215990Sjmallett if (rv < 0) 394215990Sjmallett return -1; 395215990Sjmallett return rv; 396215990Sjmallett#else 397210284Sjmallett cvmx_smix_cmd_t smi_cmd; 398210284Sjmallett cvmx_smix_rd_dat_t smi_rd; 399210284Sjmallett 400210284Sjmallett if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) 401210284Sjmallett __cvmx_mdio_set_clause22_mode(bus_id); 402210284Sjmallett 403210284Sjmallett smi_cmd.u64 = 0; 404210284Sjmallett smi_cmd.s.phy_op = MDIO_CLAUSE_22_READ; 405210284Sjmallett smi_cmd.s.phy_adr = phy_id; 406210284Sjmallett smi_cmd.s.reg_adr = location; 407210284Sjmallett cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); 408210284Sjmallett 409215990Sjmallett smi_rd = __cvmx_mdio_read_rd_dat(bus_id); 410210284Sjmallett if (smi_rd.s.val) 411210284Sjmallett return smi_rd.s.dat; 412210284Sjmallett else 413210284Sjmallett return -1; 414215990Sjmallett#endif 415210284Sjmallett} 416210284Sjmallett 417210284Sjmallett 418210284Sjmallett/** 419210284Sjmallett * Perform an MII write. This function is used to write PHY 420210284Sjmallett * registers controlling auto negotiation. 421210284Sjmallett * 422210284Sjmallett * @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX) 423210284Sjmallett * support multiple busses. 424210284Sjmallett * @param phy_id The MII phy id 425210284Sjmallett * @param location Register location to write 426210284Sjmallett * @param val Value to write 427210284Sjmallett * 428210284Sjmallett * @return -1 on error 429210284Sjmallett * 0 on success 430210284Sjmallett */ 431210284Sjmallettstatic inline int cvmx_mdio_write(int bus_id, int phy_id, int location, int val) 432210284Sjmallett{ 433215990Sjmallett#if defined(CVMX_BUILD_FOR_LINUX_KERNEL) && defined(CONFIG_PHYLIB) 434215990Sjmallett struct mii_bus *bus; 435215990Sjmallett int rv; 436215990Sjmallett 437232812Sjmallett BUG_ON(bus_id > 3 || bus_id < 0); 438215990Sjmallett 439215990Sjmallett bus = octeon_mdiobuses[bus_id]; 440215990Sjmallett if (bus == NULL) 441215990Sjmallett return -1; 442215990Sjmallett 443215990Sjmallett rv = mdiobus_write(bus, phy_id, location, (u16)val); 444215990Sjmallett 445215990Sjmallett if (rv < 0) 446215990Sjmallett return -1; 447215990Sjmallett return 0; 448215990Sjmallett#else 449215990Sjmallett cvmx_smix_cmd_t smi_cmd; 450210284Sjmallett cvmx_smix_wr_dat_t smi_wr; 451210284Sjmallett 452210284Sjmallett if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) 453210284Sjmallett __cvmx_mdio_set_clause22_mode(bus_id); 454210284Sjmallett 455210284Sjmallett smi_wr.u64 = 0; 456210284Sjmallett smi_wr.s.dat = val; 457210284Sjmallett cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); 458210284Sjmallett 459210284Sjmallett smi_cmd.u64 = 0; 460210284Sjmallett smi_cmd.s.phy_op = MDIO_CLAUSE_22_WRITE; 461210284Sjmallett smi_cmd.s.phy_adr = phy_id; 462210284Sjmallett smi_cmd.s.reg_adr = location; 463210284Sjmallett cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); 464210284Sjmallett 465215990Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SMIX_WR_DAT(bus_id), 466215990Sjmallett cvmx_smix_wr_dat_t, pending, ==, 0, CVMX_MDIO_TIMEOUT)) 467210284Sjmallett return -1; 468210284Sjmallett 469210284Sjmallett return 0; 470215990Sjmallett#endif 471210284Sjmallett} 472210284Sjmallett 473215990Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_KERNEL 474210284Sjmallett/** 475210284Sjmallett * Perform an IEEE 802.3 clause 45 MII read. This function is used to read PHY 476210284Sjmallett * registers controlling auto negotiation. 477210284Sjmallett * 478210284Sjmallett * @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX) 479210284Sjmallett * support multiple busses. 480210284Sjmallett * @param phy_id The MII phy id 481210284Sjmallett * @param device MDIO Managable Device (MMD) id 482210284Sjmallett * @param location Register location to read 483210284Sjmallett * 484210284Sjmallett * @return Result from the read or -1 on failure 485210284Sjmallett */ 486210284Sjmallett 487210284Sjmallettstatic inline int cvmx_mdio_45_read(int bus_id, int phy_id, int device, int location) 488210284Sjmallett{ 489210284Sjmallett cvmx_smix_cmd_t smi_cmd; 490210284Sjmallett cvmx_smix_rd_dat_t smi_rd; 491210284Sjmallett cvmx_smix_wr_dat_t smi_wr; 492210284Sjmallett 493210284Sjmallett if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) 494210284Sjmallett return -1; 495210284Sjmallett 496210284Sjmallett __cvmx_mdio_set_clause45_mode(bus_id); 497210284Sjmallett 498210284Sjmallett smi_wr.u64 = 0; 499210284Sjmallett smi_wr.s.dat = location; 500210284Sjmallett cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); 501210284Sjmallett 502210284Sjmallett smi_cmd.u64 = 0; 503210284Sjmallett smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS; 504210284Sjmallett smi_cmd.s.phy_adr = phy_id; 505210284Sjmallett smi_cmd.s.reg_adr = device; 506210284Sjmallett cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); 507210284Sjmallett 508215990Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SMIX_WR_DAT(bus_id), 509215990Sjmallett cvmx_smix_wr_dat_t, pending, ==, 0, CVMX_MDIO_TIMEOUT)) 510210284Sjmallett { 511210284Sjmallett cvmx_dprintf ("cvmx_mdio_45_read: bus_id %d phy_id %2d device %2d register %2d TIME OUT(address)\n", bus_id, phy_id, device, location); 512210284Sjmallett return -1; 513210284Sjmallett } 514210284Sjmallett 515210284Sjmallett smi_cmd.u64 = 0; 516210284Sjmallett smi_cmd.s.phy_op = MDIO_CLAUSE_45_READ; 517210284Sjmallett smi_cmd.s.phy_adr = phy_id; 518210284Sjmallett smi_cmd.s.reg_adr = device; 519210284Sjmallett cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); 520210284Sjmallett 521215990Sjmallett smi_rd = __cvmx_mdio_read_rd_dat(bus_id); 522215990Sjmallett if (smi_rd.s.pending) 523210284Sjmallett { 524210284Sjmallett cvmx_dprintf ("cvmx_mdio_45_read: bus_id %d phy_id %2d device %2d register %2d TIME OUT(data)\n", bus_id, phy_id, device, location); 525210284Sjmallett return -1; 526210284Sjmallett } 527210284Sjmallett 528210284Sjmallett if (smi_rd.s.val) 529210284Sjmallett return smi_rd.s.dat; 530210284Sjmallett else 531210284Sjmallett { 532210284Sjmallett cvmx_dprintf ("cvmx_mdio_45_read: bus_id %d phy_id %2d device %2d register %2d INVALID READ\n", bus_id, phy_id, device, location); 533210284Sjmallett return -1; 534210284Sjmallett } 535210284Sjmallett} 536210284Sjmallett 537210284Sjmallett/** 538210284Sjmallett * Perform an IEEE 802.3 clause 45 MII write. This function is used to write PHY 539210284Sjmallett * registers controlling auto negotiation. 540210284Sjmallett * 541210284Sjmallett * @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX) 542210284Sjmallett * support multiple busses. 543210284Sjmallett * @param phy_id The MII phy id 544210284Sjmallett * @param device MDIO Managable Device (MMD) id 545210284Sjmallett * @param location Register location to write 546210284Sjmallett * @param val Value to write 547210284Sjmallett * 548210284Sjmallett * @return -1 on error 549210284Sjmallett * 0 on success 550210284Sjmallett */ 551210284Sjmallettstatic inline int cvmx_mdio_45_write(int bus_id, int phy_id, int device, int location, 552210284Sjmallett int val) 553210284Sjmallett{ 554210284Sjmallett cvmx_smix_cmd_t smi_cmd; 555210284Sjmallett cvmx_smix_wr_dat_t smi_wr; 556210284Sjmallett 557210284Sjmallett if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) 558210284Sjmallett return -1; 559210284Sjmallett 560210284Sjmallett __cvmx_mdio_set_clause45_mode(bus_id); 561210284Sjmallett 562210284Sjmallett smi_wr.u64 = 0; 563210284Sjmallett smi_wr.s.dat = location; 564210284Sjmallett cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); 565210284Sjmallett 566210284Sjmallett smi_cmd.u64 = 0; 567210284Sjmallett smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS; 568210284Sjmallett smi_cmd.s.phy_adr = phy_id; 569210284Sjmallett smi_cmd.s.reg_adr = device; 570210284Sjmallett cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); 571210284Sjmallett 572215990Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SMIX_WR_DAT(bus_id), 573215990Sjmallett cvmx_smix_wr_dat_t, pending, ==, 0, CVMX_MDIO_TIMEOUT)) 574210284Sjmallett return -1; 575210284Sjmallett 576210284Sjmallett smi_wr.u64 = 0; 577210284Sjmallett smi_wr.s.dat = val; 578210284Sjmallett cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); 579210284Sjmallett 580210284Sjmallett smi_cmd.u64 = 0; 581210284Sjmallett smi_cmd.s.phy_op = MDIO_CLAUSE_45_WRITE; 582210284Sjmallett smi_cmd.s.phy_adr = phy_id; 583210284Sjmallett smi_cmd.s.reg_adr = device; 584210284Sjmallett cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); 585210284Sjmallett 586215990Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SMIX_WR_DAT(bus_id), 587215990Sjmallett cvmx_smix_wr_dat_t, pending, ==, 0, CVMX_MDIO_TIMEOUT)) 588210284Sjmallett return -1; 589210284Sjmallett 590210284Sjmallett return 0; 591210284Sjmallett} 592215990Sjmallett#endif 593210284Sjmallett 594210284Sjmallett#ifdef __cplusplus 595210284Sjmallett} 596210284Sjmallett#endif 597210284Sjmallett 598210284Sjmallett#endif 599210284Sjmallett 600