1 /***********************license start***************
2 * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * * Neither the name of Cavium Networks nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
23 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
24 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
25 * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
26 * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
27 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
28 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
29 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
30 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
31 * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
32 * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
35 * For any questions regarding licensing please contact marketing@caviumnetworks.com
37 ***********************license end**************************************/
47 * Interface to the SMI/MDIO hardware, including support for both IEEE 802.3
48 * clause 22 and clause 45 operations.
50 * <hr>$Revision: 41586 $<hr>
53 #ifndef __CVMX_MIO_H__
54 #define __CVMX_MIO_H__
61 * PHY register 0 from the 802.3 spec
63 #define CVMX_MDIO_PHY_REG_CONTROL 0
70 uint16_t loopback : 1;
71 uint16_t speed_lsb : 1;
72 uint16_t autoneg_enable : 1;
73 uint16_t power_down : 1;
75 uint16_t restart_autoneg : 1;
77 uint16_t collision_test : 1;
78 uint16_t speed_msb : 1;
79 uint16_t unidirectional_enable : 1;
80 uint16_t reserved_0_4 : 5;
82 } cvmx_mdio_phy_reg_control_t;
85 * PHY register 1 from the 802.3 spec
87 #define CVMX_MDIO_PHY_REG_STATUS 1
93 uint16_t capable_100base_t4 : 1;
94 uint16_t capable_100base_x_full : 1;
95 uint16_t capable_100base_x_half : 1;
96 uint16_t capable_10_full : 1;
97 uint16_t capable_10_half : 1;
98 uint16_t capable_100base_t2_full : 1;
99 uint16_t capable_100base_t2_half : 1;
100 uint16_t capable_extended_status : 1;
101 uint16_t capable_unidirectional : 1;
102 uint16_t capable_mf_preamble_suppression : 1;
103 uint16_t autoneg_complete : 1;
104 uint16_t remote_fault : 1;
105 uint16_t capable_autoneg : 1;
106 uint16_t link_status : 1;
107 uint16_t jabber_detect : 1;
108 uint16_t capable_extended_registers : 1;
111 } cvmx_mdio_phy_reg_status_t;
114 * PHY register 2 from the 802.3 spec
116 #define CVMX_MDIO_PHY_REG_ID1 2
122 uint16_t oui_bits_3_18;
124 } cvmx_mdio_phy_reg_id1_t;
127 * PHY register 3 from the 802.3 spec
129 #define CVMX_MDIO_PHY_REG_ID2 3
135 uint16_t oui_bits_19_24 : 6;
137 uint16_t revision : 4;
139 } cvmx_mdio_phy_reg_id2_t;
142 * PHY register 4 from the 802.3 spec
144 #define CVMX_MDIO_PHY_REG_AUTONEG_ADVER 4
150 uint16_t next_page : 1;
151 uint16_t reserved_14 : 1;
152 uint16_t remote_fault : 1;
153 uint16_t reserved_12 : 1;
154 uint16_t asymmetric_pause : 1;
156 uint16_t advert_100base_t4 : 1;
157 uint16_t advert_100base_tx_full : 1;
158 uint16_t advert_100base_tx_half : 1;
159 uint16_t advert_10base_tx_full : 1;
160 uint16_t advert_10base_tx_half : 1;
161 uint16_t selector : 5;
163 } cvmx_mdio_phy_reg_autoneg_adver_t;
166 * PHY register 5 from the 802.3 spec
168 #define CVMX_MDIO_PHY_REG_LINK_PARTNER_ABILITY 5
174 uint16_t next_page : 1;
176 uint16_t remote_fault : 1;
177 uint16_t reserved_12 : 1;
178 uint16_t asymmetric_pause : 1;
180 uint16_t advert_100base_t4 : 1;
181 uint16_t advert_100base_tx_full : 1;
182 uint16_t advert_100base_tx_half : 1;
183 uint16_t advert_10base_tx_full : 1;
184 uint16_t advert_10base_tx_half : 1;
185 uint16_t selector : 5;
187 } cvmx_mdio_phy_reg_link_partner_ability_t;
190 * PHY register 6 from the 802.3 spec
192 #define CVMX_MDIO_PHY_REG_AUTONEG_EXPANSION 6
198 uint16_t reserved_5_15 : 11;
199 uint16_t parallel_detection_fault : 1;
200 uint16_t link_partner_next_page_capable : 1;
201 uint16_t local_next_page_capable : 1;
202 uint16_t page_received : 1;
203 uint16_t link_partner_autoneg_capable : 1;
206 } cvmx_mdio_phy_reg_autoneg_expansion_t;
209 * PHY register 9 from the 802.3 spec
211 #define CVMX_MDIO_PHY_REG_CONTROL_1000 9
217 uint16_t test_mode : 3;
218 uint16_t manual_master_slave : 1;
220 uint16_t port_type : 1;
221 uint16_t advert_1000base_t_full : 1;
222 uint16_t advert_1000base_t_half : 1;
223 uint16_t reserved_0_7 : 8;
225 } cvmx_mdio_phy_reg_control_1000_t;
228 * PHY register 10 from the 802.3 spec
230 #define CVMX_MDIO_PHY_REG_STATUS_1000 10
236 uint16_t master_slave_fault : 1;
237 uint16_t is_master : 1;
238 uint16_t local_receiver_ok : 1;
239 uint16_t remote_receiver_ok : 1;
240 uint16_t remote_capable_1000base_t_full : 1;
241 uint16_t remote_capable_1000base_t_half : 1;
242 uint16_t reserved_8_9 : 2;
243 uint16_t idle_error_count : 8;
245 } cvmx_mdio_phy_reg_status_1000_t;
248 * PHY register 15 from the 802.3 spec
250 #define CVMX_MDIO_PHY_REG_EXTENDED_STATUS 15
256 uint16_t capable_1000base_x_full : 1;
257 uint16_t capable_1000base_x_half : 1;
258 uint16_t capable_1000base_t_full : 1;
259 uint16_t capable_1000base_t_half : 1;
260 uint16_t reserved_0_11 : 12;
262 } cvmx_mdio_phy_reg_extended_status_t;
266 * PHY register 13 from the 802.3 spec
268 #define CVMX_MDIO_PHY_REG_MMD_CONTROL 13
274 uint16_t function : 2;
275 uint16_t reserved_5_13 : 9;
278 } cvmx_mdio_phy_reg_mmd_control_t;
281 * PHY register 14 from the 802.3 spec
283 #define CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA 14
289 uint16_t address_data : 16;
291 } cvmx_mdio_phy_reg_mmd_address_data_t;
293 /* Operating request encodings. */
294 #define MDIO_CLAUSE_22_WRITE 0
295 #define MDIO_CLAUSE_22_READ 1
297 #define MDIO_CLAUSE_45_ADDRESS 0
298 #define MDIO_CLAUSE_45_WRITE 1
299 #define MDIO_CLAUSE_45_READ_INC 2
300 #define MDIO_CLAUSE_45_READ 3
302 /* MMD identifiers, mostly for accessing devices withing XENPAK modules. */
303 #define CVMX_MMD_DEVICE_PMA_PMD 1
304 #define CVMX_MMD_DEVICE_WIS 2
305 #define CVMX_MMD_DEVICE_PCS 3
306 #define CVMX_MMD_DEVICE_PHY_XS 4
307 #define CVMX_MMD_DEVICE_DTS_XS 5
308 #define CVMX_MMD_DEVICE_TC 6
309 #define CVMX_MMD_DEVICE_CL22_EXT 29
310 #define CVMX_MMD_DEVICE_VENDOR_1 30
311 #define CVMX_MMD_DEVICE_VENDOR_2 31
313 /* Helper function to put MDIO interface into clause 45 mode */
314 static inline void __cvmx_mdio_set_clause45_mode(int bus_id)
316 cvmx_smix_clk_t smi_clk;
317 /* Put bus into clause 45 mode */
318 smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id));
320 smi_clk.s.preamble = 1;
321 cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64);
323 /* Helper function to put MDIO interface into clause 22 mode */
324 static inline void __cvmx_mdio_set_clause22_mode(int bus_id)
326 cvmx_smix_clk_t smi_clk;
327 /* Put bus into clause 22 mode */
328 smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id));
330 cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64);
334 * Perform an MII read. This function is used to read PHY
335 * registers controlling auto negotiation.
337 * @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
338 * support multiple busses.
339 * @param phy_id The MII phy id
340 * @param location Register location to read
342 * @return Result from the read or -1 on failure
344 static inline int cvmx_mdio_read(int bus_id, int phy_id, int location)
346 cvmx_smix_cmd_t smi_cmd;
347 cvmx_smix_rd_dat_t smi_rd;
350 if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
351 __cvmx_mdio_set_clause22_mode(bus_id);
354 smi_cmd.s.phy_op = MDIO_CLAUSE_22_READ;
355 smi_cmd.s.phy_adr = phy_id;
356 smi_cmd.s.reg_adr = location;
357 cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
362 smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id));
363 } while (smi_rd.s.pending && timeout--);
373 * Perform an MII write. This function is used to write PHY
374 * registers controlling auto negotiation.
376 * @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
377 * support multiple busses.
378 * @param phy_id The MII phy id
379 * @param location Register location to write
380 * @param val Value to write
382 * @return -1 on error
385 static inline int cvmx_mdio_write(int bus_id, int phy_id, int location, int val)
387 cvmx_smix_cmd_t smi_cmd;
388 cvmx_smix_wr_dat_t smi_wr;
391 if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
392 __cvmx_mdio_set_clause22_mode(bus_id);
396 cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
399 smi_cmd.s.phy_op = MDIO_CLAUSE_22_WRITE;
400 smi_cmd.s.phy_adr = phy_id;
401 smi_cmd.s.reg_adr = location;
402 cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
407 smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
408 } while (smi_wr.s.pending && --timeout);
416 * Perform an IEEE 802.3 clause 45 MII read. This function is used to read PHY
417 * registers controlling auto negotiation.
419 * @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
420 * support multiple busses.
421 * @param phy_id The MII phy id
422 * @param device MDIO Managable Device (MMD) id
423 * @param location Register location to read
425 * @return Result from the read or -1 on failure
428 static inline int cvmx_mdio_45_read(int bus_id, int phy_id, int device, int location)
430 cvmx_smix_cmd_t smi_cmd;
431 cvmx_smix_rd_dat_t smi_rd;
432 cvmx_smix_wr_dat_t smi_wr;
435 if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
438 __cvmx_mdio_set_clause45_mode(bus_id);
441 smi_wr.s.dat = location;
442 cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
445 smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS;
446 smi_cmd.s.phy_adr = phy_id;
447 smi_cmd.s.reg_adr = device;
448 cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
453 smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
454 } while (smi_wr.s.pending && --timeout);
457 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);
462 smi_cmd.s.phy_op = MDIO_CLAUSE_45_READ;
463 smi_cmd.s.phy_adr = phy_id;
464 smi_cmd.s.reg_adr = device;
465 cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
470 smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id));
471 } while (smi_rd.s.pending && timeout--);
475 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);
483 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);
489 * Perform an IEEE 802.3 clause 45 MII write. This function is used to write PHY
490 * registers controlling auto negotiation.
492 * @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
493 * support multiple busses.
494 * @param phy_id The MII phy id
495 * @param device MDIO Managable Device (MMD) id
496 * @param location Register location to write
497 * @param val Value to write
499 * @return -1 on error
502 static inline int cvmx_mdio_45_write(int bus_id, int phy_id, int device, int location,
505 cvmx_smix_cmd_t smi_cmd;
506 cvmx_smix_wr_dat_t smi_wr;
509 if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
512 __cvmx_mdio_set_clause45_mode(bus_id);
515 smi_wr.s.dat = location;
516 cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
519 smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS;
520 smi_cmd.s.phy_adr = phy_id;
521 smi_cmd.s.reg_adr = device;
522 cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
527 smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
528 } while (smi_wr.s.pending && --timeout);
534 cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
537 smi_cmd.s.phy_op = MDIO_CLAUSE_45_WRITE;
538 smi_cmd.s.phy_adr = phy_id;
539 smi_cmd.s.reg_adr = device;
540 cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
545 smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
546 } while (smi_wr.s.pending && --timeout);