cvmx-mdio.h revision 210284
150477Speter/***********************license start*************** 235388Smjacob * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights 335388Smjacob * reserved. 435388Smjacob * 566189Smjacob * 635388Smjacob * Redistribution and use in source and binary forms, with or without 752347Smjacob * modification, are permitted provided that the following conditions are 835388Smjacob * met: 935388Smjacob * 1035388Smjacob * * Redistributions of source code must retain the above copyright 1135388Smjacob * notice, this list of conditions and the following disclaimer. 1235388Smjacob * 1335388Smjacob * * Redistributions in binary form must reproduce the above 1466189Smjacob * copyright notice, this list of conditions and the following 1535388Smjacob * disclaimer in the documentation and/or other materials provided 1635388Smjacob * with the distribution. 1735388Smjacob * 1835388Smjacob * * Neither the name of Cavium Networks nor the names of 1935388Smjacob * its contributors may be used to endorse or promote products 2035388Smjacob * derived from this software without specific prior written 2135388Smjacob * permission. 2235388Smjacob * 2335388Smjacob * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 2435388Smjacob * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS 2535388Smjacob * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH 2635388Smjacob * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY 2735388Smjacob * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT 2835388Smjacob * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES 2935388Smjacob * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR 3035388Smjacob * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET 3135388Smjacob * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT 3235388Smjacob * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 3335388Smjacob * 3444819Smjacob * 3535388Smjacob * For any questions regarding licensing please contact marketing@caviumnetworks.com 3653487Smjacob * 3753487Smjacob ***********************license end**************************************/ 3856004Smjacob 3935388Smjacob 4053487Smjacob 4135388Smjacob 4235388Smjacob 4353487Smjacob 4453487Smjacob/** 4556004Smjacob * @file 4635388Smjacob * 4753487Smjacob * Interface to the SMI/MDIO hardware, including support for both IEEE 802.3 4835388Smjacob * clause 22 and clause 45 operations. 4942131Smjacob * 5053487Smjacob * <hr>$Revision: 41586 $<hr> 5153487Smjacob */ 5256004Smjacob 5335388Smjacob#ifndef __CVMX_MIO_H__ 5453487Smjacob#define __CVMX_MIO_H__ 5535388Smjacob 5664087Smjacob#ifdef __cplusplus 5764087Smjacobextern "C" { 5839235Sgibbs#endif 5935388Smjacob 6043420Smjacob/** 6135388Smjacob * PHY register 0 from the 802.3 spec 6235388Smjacob */ 6335388Smjacob#define CVMX_MDIO_PHY_REG_CONTROL 0 6435388Smjacobtypedef union 6535388Smjacob{ 6635388Smjacob uint16_t u16; 6735388Smjacob struct 6864087Smjacob { 6935388Smjacob uint16_t reset : 1; 7064087Smjacob uint16_t loopback : 1; 7135388Smjacob uint16_t speed_lsb : 1; 7235388Smjacob uint16_t autoneg_enable : 1; 7364087Smjacob uint16_t power_down : 1; 7461772Smjacob uint16_t isolate : 1; 7535388Smjacob uint16_t restart_autoneg : 1; 7635388Smjacob uint16_t duplex : 1; 7735388Smjacob uint16_t collision_test : 1; 7835388Smjacob uint16_t speed_msb : 1; 7964087Smjacob uint16_t unidirectional_enable : 1; 8064087Smjacob uint16_t reserved_0_4 : 5; 8164087Smjacob } s; 8235388Smjacob} cvmx_mdio_phy_reg_control_t; 8344819Smjacob 8444819Smjacob/** 8544819Smjacob * PHY register 1 from the 802.3 spec 8635388Smjacob */ 8744819Smjacob#define CVMX_MDIO_PHY_REG_STATUS 1 8835388Smjacobtypedef union 8949909Smjacob{ 9061772Smjacob uint16_t u16; 9149909Smjacob struct 9253487Smjacob { 9353487Smjacob uint16_t capable_100base_t4 : 1; 9464087Smjacob uint16_t capable_100base_x_full : 1; 9564087Smjacob uint16_t capable_100base_x_half : 1; 9653487Smjacob uint16_t capable_10_full : 1; 9753487Smjacob uint16_t capable_10_half : 1; 9853487Smjacob uint16_t capable_100base_t2_full : 1; 9953487Smjacob uint16_t capable_100base_t2_half : 1; 10053487Smjacob uint16_t capable_extended_status : 1; 10153487Smjacob uint16_t capable_unidirectional : 1; 10253487Smjacob uint16_t capable_mf_preamble_suppression : 1; 10353487Smjacob uint16_t autoneg_complete : 1; 10453487Smjacob uint16_t remote_fault : 1; 10553487Smjacob uint16_t capable_autoneg : 1; 10653487Smjacob uint16_t link_status : 1; 10753487Smjacob uint16_t jabber_detect : 1; 10853487Smjacob uint16_t capable_extended_registers : 1; 10953487Smjacob 11053487Smjacob } s; 11153487Smjacob} cvmx_mdio_phy_reg_status_t; 11253487Smjacob 11353487Smjacob/** 11453487Smjacob * PHY register 2 from the 802.3 spec 11553487Smjacob */ 11653487Smjacob#define CVMX_MDIO_PHY_REG_ID1 2 11753487Smjacobtypedef union 11864087Smjacob{ 11964087Smjacob uint16_t u16; 12053487Smjacob struct 12153487Smjacob { 12253487Smjacob uint16_t oui_bits_3_18; 12353487Smjacob } s; 12453487Smjacob} cvmx_mdio_phy_reg_id1_t; 12553487Smjacob 12653487Smjacob/** 12764087Smjacob * PHY register 3 from the 802.3 spec 12864087Smjacob */ 12964087Smjacob#define CVMX_MDIO_PHY_REG_ID2 3 13064087Smjacobtypedef union 13164087Smjacob{ 13264087Smjacob uint16_t u16; 13364087Smjacob struct 13464087Smjacob { 13564087Smjacob uint16_t oui_bits_19_24 : 6; 13664087Smjacob uint16_t model : 6; 13764087Smjacob uint16_t revision : 4; 13864087Smjacob } s; 13964087Smjacob} cvmx_mdio_phy_reg_id2_t; 14064087Smjacob 14164087Smjacob/** 14264087Smjacob * PHY register 4 from the 802.3 spec 14364087Smjacob */ 14439235Sgibbs#define CVMX_MDIO_PHY_REG_AUTONEG_ADVER 4 14564087Smjacobtypedef union 14664087Smjacob{ 14764087Smjacob uint16_t u16; 14864087Smjacob struct 14939235Sgibbs { 15039235Sgibbs uint16_t next_page : 1; 15139235Sgibbs uint16_t reserved_14 : 1; 15265140Smjacob uint16_t remote_fault : 1; 15339235Sgibbs uint16_t reserved_12 : 1; 15452347Smjacob uint16_t asymmetric_pause : 1; 15565140Smjacob uint16_t pause : 1; 15665140Smjacob uint16_t advert_100base_t4 : 1; 15753487Smjacob uint16_t advert_100base_tx_full : 1; 15853487Smjacob uint16_t advert_100base_tx_half : 1; 15964087Smjacob uint16_t advert_10base_tx_full : 1; 16064087Smjacob uint16_t advert_10base_tx_half : 1; 16164087Smjacob uint16_t selector : 5; 16253487Smjacob } s; 16335388Smjacob} cvmx_mdio_phy_reg_autoneg_adver_t; 16446968Smjacob 16535388Smjacob/** 16635388Smjacob * PHY register 5 from the 802.3 spec 16735388Smjacob */ 16846968Smjacob#define CVMX_MDIO_PHY_REG_LINK_PARTNER_ABILITY 5 16952347Smjacobtypedef union 17052347Smjacob{ 17135388Smjacob uint16_t u16; 17235388Smjacob struct 17342461Smjacob { 17443420Smjacob uint16_t next_page : 1; 17535388Smjacob uint16_t ack : 1; 17645040Smjacob uint16_t remote_fault : 1; 17765140Smjacob uint16_t reserved_12 : 1; 17835388Smjacob uint16_t asymmetric_pause : 1; 17952347Smjacob uint16_t pause : 1; 18052347Smjacob uint16_t advert_100base_t4 : 1; 18152347Smjacob uint16_t advert_100base_tx_full : 1; 18235388Smjacob uint16_t advert_100base_tx_half : 1; 18352347Smjacob uint16_t advert_10base_tx_full : 1; 18452347Smjacob uint16_t advert_10base_tx_half : 1; 18552347Smjacob uint16_t selector : 5; 18635388Smjacob } s; 18746968Smjacob} cvmx_mdio_phy_reg_link_partner_ability_t; 18846968Smjacob 18943420Smjacob/** 19043420Smjacob * PHY register 6 from the 802.3 spec 19145040Smjacob */ 19245040Smjacob#define CVMX_MDIO_PHY_REG_AUTONEG_EXPANSION 6 19345040Smjacobtypedef union 19445040Smjacob{ 19545040Smjacob uint16_t u16; 19645040Smjacob struct 19745040Smjacob { 19835388Smjacob uint16_t reserved_5_15 : 11; 19946968Smjacob uint16_t parallel_detection_fault : 1; 20035388Smjacob uint16_t link_partner_next_page_capable : 1; 20135388Smjacob uint16_t local_next_page_capable : 1; 20235388Smjacob uint16_t page_received : 1; 20335388Smjacob uint16_t link_partner_autoneg_capable : 1; 20439235Sgibbs 20539235Sgibbs } s; 20639235Sgibbs} cvmx_mdio_phy_reg_autoneg_expansion_t; 20739235Sgibbs 20839235Sgibbs/** 20939235Sgibbs * PHY register 9 from the 802.3 spec 21039235Sgibbs */ 21139235Sgibbs#define CVMX_MDIO_PHY_REG_CONTROL_1000 9 21265140Smjacobtypedef union 21365140Smjacob{ 21465140Smjacob uint16_t u16; 21543793Smjacob struct 21639235Sgibbs { 21735388Smjacob uint16_t test_mode : 3; 21839235Sgibbs uint16_t manual_master_slave : 1; 21945040Smjacob uint16_t master : 1; 22065140Smjacob uint16_t port_type : 1; 22165140Smjacob uint16_t advert_1000base_t_full : 1; 22265140Smjacob uint16_t advert_1000base_t_half : 1; 22365140Smjacob uint16_t reserved_0_7 : 8; 22452347Smjacob } s; 22552347Smjacob} cvmx_mdio_phy_reg_control_1000_t; 22652347Smjacob 22752347Smjacob/** 22835388Smjacob * PHY register 10 from the 802.3 spec 22935388Smjacob */ 23035388Smjacob#define CVMX_MDIO_PHY_REG_STATUS_1000 10 23135388Smjacobtypedef union 23252347Smjacob{ 23352347Smjacob uint16_t u16; 23452347Smjacob struct 23552347Smjacob { 23635388Smjacob uint16_t master_slave_fault : 1; 23752347Smjacob uint16_t is_master : 1; 23859454Smjacob uint16_t local_receiver_ok : 1; 23948484Smjacob uint16_t remote_receiver_ok : 1; 24048484Smjacob uint16_t remote_capable_1000base_t_full : 1; 24148484Smjacob uint16_t remote_capable_1000base_t_half : 1; 24248484Smjacob uint16_t reserved_8_9 : 2; 24359454Smjacob uint16_t idle_error_count : 8; 24448484Smjacob } s; 24539235Sgibbs} cvmx_mdio_phy_reg_status_1000_t; 24639235Sgibbs 24752347Smjacob/** 24848484Smjacob * PHY register 15 from the 802.3 spec 24939235Sgibbs */ 25052347Smjacob#define CVMX_MDIO_PHY_REG_EXTENDED_STATUS 15 25152347Smjacobtypedef union 25252347Smjacob{ 25339235Sgibbs uint16_t u16; 25439235Sgibbs struct 25548484Smjacob { 25648484Smjacob uint16_t capable_1000base_x_full : 1; 25735388Smjacob uint16_t capable_1000base_x_half : 1; 25848484Smjacob uint16_t capable_1000base_t_full : 1; 25948484Smjacob uint16_t capable_1000base_t_half : 1; 26048484Smjacob uint16_t reserved_0_11 : 12; 26148484Smjacob } s; 26248484Smjacob} cvmx_mdio_phy_reg_extended_status_t; 26348484Smjacob 26448484Smjacob 26544819Smjacob/** 26648484Smjacob * PHY register 13 from the 802.3 spec 26752347Smjacob */ 26860221Smjacob#define CVMX_MDIO_PHY_REG_MMD_CONTROL 13 26960221Smjacobtypedef union 27060221Smjacob{ 27160221Smjacob uint16_t u16; 27260221Smjacob struct 27352347Smjacob { 27448484Smjacob uint16_t function : 2; 27548484Smjacob uint16_t reserved_5_13 : 9; 27652347Smjacob uint16_t devad : 5; 27744819Smjacob } s; 27844819Smjacob} cvmx_mdio_phy_reg_mmd_control_t; 27935388Smjacob 28035388Smjacob/** 28148195Smjacob * PHY register 14 from the 802.3 spec 28235388Smjacob */ 28335388Smjacob#define CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA 14 28435388Smjacobtypedef union 28548484Smjacob{ 28648484Smjacob uint16_t u16; 28748484Smjacob struct 28848484Smjacob { 28948484Smjacob uint16_t address_data : 16; 29048484Smjacob } s; 29148484Smjacob} cvmx_mdio_phy_reg_mmd_address_data_t; 29248484Smjacob 29335388Smjacob/* Operating request encodings. */ 29448484Smjacob#define MDIO_CLAUSE_22_WRITE 0 29548484Smjacob#define MDIO_CLAUSE_22_READ 1 29648484Smjacob 29748484Smjacob#define MDIO_CLAUSE_45_ADDRESS 0 29835388Smjacob#define MDIO_CLAUSE_45_WRITE 1 29959454Smjacob#define MDIO_CLAUSE_45_READ_INC 2 30059454Smjacob#define MDIO_CLAUSE_45_READ 3 30159454Smjacob 30259454Smjacob/* MMD identifiers, mostly for accessing devices withing XENPAK modules. */ 30359454Smjacob#define CVMX_MMD_DEVICE_PMA_PMD 1 30459454Smjacob#define CVMX_MMD_DEVICE_WIS 2 30542131Smjacob#define CVMX_MMD_DEVICE_PCS 3 30635388Smjacob#define CVMX_MMD_DEVICE_PHY_XS 4 30735388Smjacob#define CVMX_MMD_DEVICE_DTS_XS 5 30865140Smjacob#define CVMX_MMD_DEVICE_TC 6 30935388Smjacob#define CVMX_MMD_DEVICE_CL22_EXT 29 31035388Smjacob#define CVMX_MMD_DEVICE_VENDOR_1 30 31135388Smjacob#define CVMX_MMD_DEVICE_VENDOR_2 31 31235388Smjacob 31335388Smjacob/* Helper function to put MDIO interface into clause 45 mode */ 31435388Smjacobstatic inline void __cvmx_mdio_set_clause45_mode(int bus_id) 31553487Smjacob{ 31635388Smjacob cvmx_smix_clk_t smi_clk; 31735388Smjacob /* Put bus into clause 45 mode */ 31835388Smjacob smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id)); 31935388Smjacob smi_clk.s.mode = 1; 32053487Smjacob smi_clk.s.preamble = 1; 32153487Smjacob cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64); 32235388Smjacob} 32335388Smjacob/* Helper function to put MDIO interface into clause 22 mode */ 32453487Smjacobstatic inline void __cvmx_mdio_set_clause22_mode(int bus_id) 32553487Smjacob{ 32653487Smjacob cvmx_smix_clk_t smi_clk; 32753487Smjacob /* Put bus into clause 22 mode */ 32853487Smjacob smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id)); 32953487Smjacob smi_clk.s.mode = 0; 33061772Smjacob cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64); 33135388Smjacob} 33264087Smjacob 33353487Smjacob/** 33465140Smjacob * Perform an MII read. This function is used to read PHY 33553487Smjacob * registers controlling auto negotiation. 33665140Smjacob * 33764087Smjacob * @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX) 33853487Smjacob * support multiple busses. 33953487Smjacob * @param phy_id The MII phy id 34069522Smjacob * @param location Register location to read 34169522Smjacob * 34269522Smjacob * @return Result from the read or -1 on failure 34369522Smjacob */ 34469522Smjacobstatic inline int cvmx_mdio_read(int bus_id, int phy_id, int location) 34539235Sgibbs{ 34635388Smjacob cvmx_smix_cmd_t smi_cmd; 34739235Sgibbs cvmx_smix_rd_dat_t smi_rd; 34835388Smjacob int timeout = 1000; 34935388Smjacob 35062171Smjacob if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) 35162171Smjacob __cvmx_mdio_set_clause22_mode(bus_id); 35262171Smjacob 35339235Sgibbs smi_cmd.u64 = 0; 35446968Smjacob smi_cmd.s.phy_op = MDIO_CLAUSE_22_READ; 35546968Smjacob smi_cmd.s.phy_adr = phy_id; 35652347Smjacob smi_cmd.s.reg_adr = location; 35752347Smjacob cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); 35852347Smjacob 35952347Smjacob do 36052347Smjacob { 36162171Smjacob cvmx_wait(1000); 36235388Smjacob smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id)); 36335388Smjacob } while (smi_rd.s.pending && timeout--); 36453487Smjacob 36535388Smjacob if (smi_rd.s.val) 36664087Smjacob return smi_rd.s.dat; 36735388Smjacob else 36835388Smjacob return -1; 36952347Smjacob} 37035388Smjacob 37148195Smjacob 37248195Smjacob/** 37335388Smjacob * Perform an MII write. This function is used to write PHY 37435388Smjacob * registers controlling auto negotiation. 37565140Smjacob * 37635388Smjacob * @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX) 37749909Smjacob * support multiple busses. 37849909Smjacob * @param phy_id The MII phy id 37949909Smjacob * @param location Register location to write 38035388Smjacob * @param val Value to write 38164087Smjacob * 38235388Smjacob * @return -1 on error 38335388Smjacob * 0 on success 38435388Smjacob */ 38535388Smjacobstatic inline int cvmx_mdio_write(int bus_id, int phy_id, int location, int val) 38635388Smjacob{ 38735388Smjacob cvmx_smix_cmd_t smi_cmd; 38835388Smjacob cvmx_smix_wr_dat_t smi_wr; 38935388Smjacob int timeout = 1000; 39035388Smjacob 39135388Smjacob if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) 39243793Smjacob __cvmx_mdio_set_clause22_mode(bus_id); 39370490Smjacob 39453487Smjacob smi_wr.u64 = 0; 39553487Smjacob smi_wr.s.dat = val; 39669522Smjacob cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); 39769522Smjacob 39869522Smjacob smi_cmd.u64 = 0; 39969522Smjacob smi_cmd.s.phy_op = MDIO_CLAUSE_22_WRITE; 40069522Smjacob smi_cmd.s.phy_adr = phy_id; 40135388Smjacob smi_cmd.s.reg_adr = location; 40264087Smjacob cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); 40364087Smjacob 40464087Smjacob do 40564087Smjacob { 40645282Smjacob cvmx_wait(1000); 40746968Smjacob smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); 40839235Sgibbs } while (smi_wr.s.pending && --timeout); 40935388Smjacob if (timeout <= 0) 41039235Sgibbs return -1; 41135388Smjacob 41239235Sgibbs return 0; 41339235Sgibbs} 41439235Sgibbs 41539235Sgibbs/** 41639235Sgibbs * Perform an IEEE 802.3 clause 45 MII read. This function is used to read PHY 41739235Sgibbs * registers controlling auto negotiation. 41835388Smjacob * 41939235Sgibbs * @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX) 42039235Sgibbs * support multiple busses. 42139235Sgibbs * @param phy_id The MII phy id 42239235Sgibbs * @param device MDIO Managable Device (MMD) id 42339235Sgibbs * @param location Register location to read 42439235Sgibbs * 42545282Smjacob * @return Result from the read or -1 on failure 42654671Smjacob */ 42754671Smjacob 42854671Smjacobstatic inline int cvmx_mdio_45_read(int bus_id, int phy_id, int device, int location) 42957145Smjacob{ 43035388Smjacob cvmx_smix_cmd_t smi_cmd; 43135388Smjacob cvmx_smix_rd_dat_t smi_rd; 43248484Smjacob cvmx_smix_wr_dat_t smi_wr; 43335388Smjacob int timeout = 1000; 43444819Smjacob 43554671Smjacob if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) 43644819Smjacob return -1; 43754671Smjacob 43857145Smjacob __cvmx_mdio_set_clause45_mode(bus_id); 43957145Smjacob 44057145Smjacob smi_wr.u64 = 0; 44157145Smjacob smi_wr.s.dat = location; 44257145Smjacob cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); 44357145Smjacob 44457145Smjacob smi_cmd.u64 = 0; 44544819Smjacob smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS; 44657145Smjacob smi_cmd.s.phy_adr = phy_id; 44757145Smjacob smi_cmd.s.reg_adr = device; 44844819Smjacob cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); 44964087Smjacob 45064087Smjacob do 45164087Smjacob { 45264087Smjacob cvmx_wait(1000); 45364087Smjacob smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); 45457145Smjacob } while (smi_wr.s.pending && --timeout); 45535388Smjacob if (timeout <= 0) 45664087Smjacob { 45735388Smjacob 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); 45835388Smjacob return -1; 45935388Smjacob } 46039235Sgibbs 46139235Sgibbs smi_cmd.u64 = 0; 46235388Smjacob smi_cmd.s.phy_op = MDIO_CLAUSE_45_READ; 46335388Smjacob smi_cmd.s.phy_adr = phy_id; 46435388Smjacob smi_cmd.s.reg_adr = device; 46535388Smjacob cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); 46635388Smjacob 46735388Smjacob do 46835388Smjacob { 46935388Smjacob cvmx_wait(1000); 47035388Smjacob smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id)); 47139235Sgibbs } while (smi_rd.s.pending && timeout--); 47239235Sgibbs 47364087Smjacob if(timeout <= 0) 47439235Sgibbs { 47539235Sgibbs 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); 47635388Smjacob return -1; 47735388Smjacob } 47835388Smjacob 47935388Smjacob if (smi_rd.s.val) 48035388Smjacob return smi_rd.s.dat; 48164087Smjacob else 48235388Smjacob { 48364087Smjacob 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); 48464087Smjacob return -1; 48564087Smjacob } 48664087Smjacob} 48764087Smjacob 48864087Smjacob/** 48935388Smjacob * Perform an IEEE 802.3 clause 45 MII write. This function is used to write PHY 49039235Sgibbs * registers controlling auto negotiation. 49164087Smjacob * 49264087Smjacob * @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX) 49364087Smjacob * support multiple busses. 49464087Smjacob * @param phy_id The MII phy id 49564087Smjacob * @param device MDIO Managable Device (MMD) id 49643420Smjacob * @param location Register location to write 49739235Sgibbs * @param val Value to write 49848484Smjacob * 49939235Sgibbs * @return -1 on error 50039235Sgibbs * 0 on success 50139235Sgibbs */ 50248484Smjacobstatic inline int cvmx_mdio_45_write(int bus_id, int phy_id, int device, int location, 50348484Smjacob int val) 50448484Smjacob{ 50548484Smjacob cvmx_smix_cmd_t smi_cmd; 50655364Smjacob cvmx_smix_wr_dat_t smi_wr; 50755364Smjacob int timeout = 1000; 50855364Smjacob 50939235Sgibbs if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) 51039235Sgibbs return -1; 51139235Sgibbs 51243420Smjacob __cvmx_mdio_set_clause45_mode(bus_id); 51339235Sgibbs 51443420Smjacob smi_wr.u64 = 0; 51543420Smjacob smi_wr.s.dat = location; 51643420Smjacob cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); 51748484Smjacob 51843420Smjacob smi_cmd.u64 = 0; 51943420Smjacob smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS; 52043420Smjacob smi_cmd.s.phy_adr = phy_id; 52143420Smjacob smi_cmd.s.reg_adr = device; 52243793Smjacob cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); 52348484Smjacob 52448484Smjacob do 52548484Smjacob { 52648484Smjacob cvmx_wait(1000); 52748484Smjacob smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); 52848484Smjacob } while (smi_wr.s.pending && --timeout); 52955364Smjacob if (timeout <= 0) 53055364Smjacob return -1; 53155364Smjacob 53243420Smjacob smi_wr.u64 = 0; 53343420Smjacob smi_wr.s.dat = val; 53443420Smjacob cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); 53543420Smjacob 53664087Smjacob smi_cmd.u64 = 0; 53739235Sgibbs smi_cmd.s.phy_op = MDIO_CLAUSE_45_WRITE; 53870490Smjacob smi_cmd.s.phy_adr = phy_id; 53970490Smjacob smi_cmd.s.reg_adr = device; 54070490Smjacob cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); 54170490Smjacob 54264087Smjacob do 54370490Smjacob { 54470490Smjacob cvmx_wait(1000); 54564087Smjacob smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); 54664087Smjacob } while (smi_wr.s.pending && --timeout); 54764087Smjacob if (timeout <= 0) 54864087Smjacob return -1; 54964087Smjacob 55064087Smjacob return 0; 55164087Smjacob} 55264087Smjacob 55364087Smjacob 55464087Smjacob#ifdef __cplusplus 55564087Smjacob} 55664087Smjacob#endif 55739235Sgibbs 55864087Smjacob#endif 55964087Smjacob 56064087Smjacob