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