cvmx-mdio.h revision 210284
1/***********************license start***************
2 *  Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
3 *  reserved.
4 *
5 *
6 *  Redistribution and use in source and binary forms, with or without
7 *  modification, are permitted provided that the following conditions are
8 *  met:
9 *
10 *      * Redistributions of source code must retain the above copyright
11 *        notice, this list of conditions and the following disclaimer.
12 *
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.
17 *
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
21 *        permission.
22 *
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.
33 *
34 *
35 *  For any questions regarding licensing please contact marketing@caviumnetworks.com
36 *
37 ***********************license end**************************************/
38
39
40
41
42
43
44/**
45 * @file
46 *
47 * Interface to the SMI/MDIO hardware, including support for both IEEE 802.3
48 * clause 22 and clause 45 operations.
49 *
50 * <hr>$Revision: 41586 $<hr>
51 */
52
53#ifndef __CVMX_MIO_H__
54#define __CVMX_MIO_H__
55
56#ifdef	__cplusplus
57extern "C" {
58#endif
59
60/**
61 * PHY register 0 from the 802.3 spec
62 */
63#define CVMX_MDIO_PHY_REG_CONTROL 0
64typedef union
65{
66    uint16_t u16;
67    struct
68    {
69        uint16_t reset : 1;
70        uint16_t loopback : 1;
71        uint16_t speed_lsb : 1;
72        uint16_t autoneg_enable : 1;
73        uint16_t power_down : 1;
74        uint16_t isolate : 1;
75        uint16_t restart_autoneg : 1;
76        uint16_t duplex : 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;
81    } s;
82} cvmx_mdio_phy_reg_control_t;
83
84/**
85 * PHY register 1 from the 802.3 spec
86 */
87#define CVMX_MDIO_PHY_REG_STATUS 1
88typedef union
89{
90    uint16_t u16;
91    struct
92    {
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;
109
110    } s;
111} cvmx_mdio_phy_reg_status_t;
112
113/**
114 * PHY register 2 from the 802.3 spec
115 */
116#define CVMX_MDIO_PHY_REG_ID1 2
117typedef union
118{
119    uint16_t u16;
120    struct
121    {
122        uint16_t oui_bits_3_18;
123    } s;
124} cvmx_mdio_phy_reg_id1_t;
125
126/**
127 * PHY register 3 from the 802.3 spec
128 */
129#define CVMX_MDIO_PHY_REG_ID2 3
130typedef union
131{
132    uint16_t u16;
133    struct
134    {
135        uint16_t oui_bits_19_24 : 6;
136        uint16_t model : 6;
137        uint16_t revision : 4;
138    } s;
139} cvmx_mdio_phy_reg_id2_t;
140
141/**
142 * PHY register 4 from the 802.3 spec
143 */
144#define CVMX_MDIO_PHY_REG_AUTONEG_ADVER 4
145typedef union
146{
147    uint16_t u16;
148    struct
149    {
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;
155        uint16_t 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;
162    } s;
163} cvmx_mdio_phy_reg_autoneg_adver_t;
164
165/**
166 * PHY register 5 from the 802.3 spec
167 */
168#define CVMX_MDIO_PHY_REG_LINK_PARTNER_ABILITY 5
169typedef union
170{
171    uint16_t u16;
172    struct
173    {
174        uint16_t next_page : 1;
175        uint16_t ack : 1;
176        uint16_t remote_fault : 1;
177        uint16_t reserved_12 : 1;
178        uint16_t asymmetric_pause : 1;
179        uint16_t 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;
186    } s;
187} cvmx_mdio_phy_reg_link_partner_ability_t;
188
189/**
190 * PHY register 6 from the 802.3 spec
191 */
192#define CVMX_MDIO_PHY_REG_AUTONEG_EXPANSION 6
193typedef union
194{
195    uint16_t u16;
196    struct
197    {
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;
204
205    } s;
206} cvmx_mdio_phy_reg_autoneg_expansion_t;
207
208/**
209 * PHY register 9 from the 802.3 spec
210 */
211#define CVMX_MDIO_PHY_REG_CONTROL_1000 9
212typedef union
213{
214    uint16_t u16;
215    struct
216    {
217        uint16_t test_mode : 3;
218        uint16_t manual_master_slave : 1;
219        uint16_t master : 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;
224    } s;
225} cvmx_mdio_phy_reg_control_1000_t;
226
227/**
228 * PHY register 10 from the 802.3 spec
229 */
230#define CVMX_MDIO_PHY_REG_STATUS_1000 10
231typedef union
232{
233    uint16_t u16;
234    struct
235    {
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;
244    } s;
245} cvmx_mdio_phy_reg_status_1000_t;
246
247/**
248 * PHY register 15 from the 802.3 spec
249 */
250#define CVMX_MDIO_PHY_REG_EXTENDED_STATUS 15
251typedef union
252{
253    uint16_t u16;
254    struct
255    {
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;
261    } s;
262} cvmx_mdio_phy_reg_extended_status_t;
263
264
265/**
266 * PHY register 13 from the 802.3 spec
267 */
268#define CVMX_MDIO_PHY_REG_MMD_CONTROL 13
269typedef union
270{
271    uint16_t u16;
272    struct
273    {
274        uint16_t function : 2;
275        uint16_t reserved_5_13 : 9;
276        uint16_t devad : 5;
277    } s;
278} cvmx_mdio_phy_reg_mmd_control_t;
279
280/**
281 * PHY register 14 from the 802.3 spec
282 */
283#define CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA 14
284typedef union
285{
286    uint16_t u16;
287    struct
288    {
289        uint16_t address_data : 16;
290    } s;
291} cvmx_mdio_phy_reg_mmd_address_data_t;
292
293/* Operating request encodings. */
294#define MDIO_CLAUSE_22_WRITE    0
295#define MDIO_CLAUSE_22_READ     1
296
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
301
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
312
313/* Helper function to put MDIO interface into clause 45 mode */
314static inline void __cvmx_mdio_set_clause45_mode(int bus_id)
315{
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));
319    smi_clk.s.mode = 1;
320    smi_clk.s.preamble = 1;
321    cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64);
322}
323/* Helper function to put MDIO interface into clause 22 mode */
324static inline void __cvmx_mdio_set_clause22_mode(int bus_id)
325{
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));
329    smi_clk.s.mode = 0;
330    cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64);
331}
332
333/**
334 * Perform an MII read. This function is used to read PHY
335 * registers controlling auto negotiation.
336 *
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
341 *
342 * @return Result from the read or -1 on failure
343 */
344static inline int cvmx_mdio_read(int bus_id, int phy_id, int location)
345{
346    cvmx_smix_cmd_t smi_cmd;
347    cvmx_smix_rd_dat_t smi_rd;
348    int timeout = 1000;
349
350    if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
351        __cvmx_mdio_set_clause22_mode(bus_id);
352
353    smi_cmd.u64 = 0;
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);
358
359    do
360    {
361        cvmx_wait(1000);
362        smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id));
363    } while (smi_rd.s.pending && timeout--);
364
365    if (smi_rd.s.val)
366        return smi_rd.s.dat;
367    else
368        return -1;
369}
370
371
372/**
373 * Perform an MII write. This function is used to write PHY
374 * registers controlling auto negotiation.
375 *
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
381 *
382 * @return -1 on error
383 *         0 on success
384 */
385static inline int cvmx_mdio_write(int bus_id, int phy_id, int location, int val)
386{
387    cvmx_smix_cmd_t smi_cmd;
388    cvmx_smix_wr_dat_t smi_wr;
389    int timeout = 1000;
390
391    if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
392        __cvmx_mdio_set_clause22_mode(bus_id);
393
394    smi_wr.u64 = 0;
395    smi_wr.s.dat = val;
396    cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
397
398    smi_cmd.u64 = 0;
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);
403
404    do
405    {
406        cvmx_wait(1000);
407        smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
408    } while (smi_wr.s.pending && --timeout);
409    if (timeout <= 0)
410        return -1;
411
412    return 0;
413}
414
415/**
416 * Perform an IEEE 802.3 clause 45 MII read. This function is used to read PHY
417 * registers controlling auto negotiation.
418 *
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
424 *
425 * @return Result from the read or -1 on failure
426 */
427
428static inline int cvmx_mdio_45_read(int bus_id, int phy_id, int device, int location)
429{
430    cvmx_smix_cmd_t smi_cmd;
431    cvmx_smix_rd_dat_t smi_rd;
432    cvmx_smix_wr_dat_t smi_wr;
433    int timeout = 1000;
434
435    if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
436        return -1;
437
438    __cvmx_mdio_set_clause45_mode(bus_id);
439
440    smi_wr.u64 = 0;
441    smi_wr.s.dat = location;
442    cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
443
444    smi_cmd.u64 = 0;
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);
449
450    do
451    {
452        cvmx_wait(1000);
453        smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
454    } while (smi_wr.s.pending && --timeout);
455    if (timeout <= 0)
456    {
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);
458        return -1;
459    }
460
461    smi_cmd.u64 = 0;
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);
466
467    do
468    {
469        cvmx_wait(1000);
470        smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id));
471    } while (smi_rd.s.pending && timeout--);
472
473    if(timeout <= 0)
474    {
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);
476        return -1;
477    }
478
479    if (smi_rd.s.val)
480        return smi_rd.s.dat;
481    else
482    {
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);
484        return -1;
485    }
486}
487
488/**
489 * Perform an IEEE 802.3 clause 45 MII write. This function is used to write PHY
490 * registers controlling auto negotiation.
491 *
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
498 *
499 * @return -1 on error
500 *         0 on success
501 */
502static inline int cvmx_mdio_45_write(int bus_id, int phy_id, int device, int location,
503                                     int val)
504{
505    cvmx_smix_cmd_t smi_cmd;
506    cvmx_smix_wr_dat_t smi_wr;
507    int timeout = 1000;
508
509    if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
510        return -1;
511
512    __cvmx_mdio_set_clause45_mode(bus_id);
513
514    smi_wr.u64 = 0;
515    smi_wr.s.dat = location;
516    cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
517
518    smi_cmd.u64 = 0;
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);
523
524    do
525    {
526        cvmx_wait(1000);
527        smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
528    } while (smi_wr.s.pending && --timeout);
529    if (timeout <= 0)
530        return -1;
531
532    smi_wr.u64 = 0;
533    smi_wr.s.dat = val;
534    cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
535
536    smi_cmd.u64 = 0;
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);
541
542    do
543    {
544        cvmx_wait(1000);
545        smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
546    } while (smi_wr.s.pending && --timeout);
547    if (timeout <= 0)
548        return -1;
549
550    return 0;
551}
552
553
554#ifdef	__cplusplus
555}
556#endif
557
558#endif
559
560