2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2009-2016 Cavium, Inc.
9 #include <linux/delay.h>
10 #include <linux/module.h>
11 #include <linux/phy.h>
14 #include "mdio-cavium.h"
16 static void cavium_mdiobus_set_mode(struct cavium_mdiobus
*p
,
17 enum cavium_mdiobus_mode m
)
19 union cvmx_smix_clk smi_clk
;
24 smi_clk
.u64
= oct_mdio_readq(p
->register_base
+ SMI_CLK
);
25 smi_clk
.s
.mode
= (m
== C45
) ? 1 : 0;
26 smi_clk
.s
.preamble
= 1;
27 oct_mdio_writeq(smi_clk
.u64
, p
->register_base
+ SMI_CLK
);
31 static int cavium_mdiobus_c45_addr(struct cavium_mdiobus
*p
,
32 int phy_id
, int regnum
)
34 union cvmx_smix_cmd smi_cmd
;
35 union cvmx_smix_wr_dat smi_wr
;
38 cavium_mdiobus_set_mode(p
, C45
);
41 smi_wr
.s
.dat
= regnum
& 0xffff;
42 oct_mdio_writeq(smi_wr
.u64
, p
->register_base
+ SMI_WR_DAT
);
44 regnum
= (regnum
>> 16) & 0x1f;
47 smi_cmd
.s
.phy_op
= 0; /* MDIO_CLAUSE_45_ADDRESS */
48 smi_cmd
.s
.phy_adr
= phy_id
;
49 smi_cmd
.s
.reg_adr
= regnum
;
50 oct_mdio_writeq(smi_cmd
.u64
, p
->register_base
+ SMI_CMD
);
53 /* Wait 1000 clocks so we don't saturate the RSL bus
57 smi_wr
.u64
= oct_mdio_readq(p
->register_base
+ SMI_WR_DAT
);
58 } while (smi_wr
.s
.pending
&& --timeout
);
65 int cavium_mdiobus_read(struct mii_bus
*bus
, int phy_id
, int regnum
)
67 struct cavium_mdiobus
*p
= bus
->priv
;
68 union cvmx_smix_cmd smi_cmd
;
69 union cvmx_smix_rd_dat smi_rd
;
70 unsigned int op
= 1; /* MDIO_CLAUSE_22_READ */
73 if (regnum
& MII_ADDR_C45
) {
74 int r
= cavium_mdiobus_c45_addr(p
, phy_id
, regnum
);
79 regnum
= (regnum
>> 16) & 0x1f;
80 op
= 3; /* MDIO_CLAUSE_45_READ */
82 cavium_mdiobus_set_mode(p
, C22
);
86 smi_cmd
.s
.phy_op
= op
;
87 smi_cmd
.s
.phy_adr
= phy_id
;
88 smi_cmd
.s
.reg_adr
= regnum
;
89 oct_mdio_writeq(smi_cmd
.u64
, p
->register_base
+ SMI_CMD
);
92 /* Wait 1000 clocks so we don't saturate the RSL bus
96 smi_rd
.u64
= oct_mdio_readq(p
->register_base
+ SMI_RD_DAT
);
97 } while (smi_rd
.s
.pending
&& --timeout
);
104 EXPORT_SYMBOL(cavium_mdiobus_read
);
106 int cavium_mdiobus_write(struct mii_bus
*bus
, int phy_id
, int regnum
, u16 val
)
108 struct cavium_mdiobus
*p
= bus
->priv
;
109 union cvmx_smix_cmd smi_cmd
;
110 union cvmx_smix_wr_dat smi_wr
;
111 unsigned int op
= 0; /* MDIO_CLAUSE_22_WRITE */
114 if (regnum
& MII_ADDR_C45
) {
115 int r
= cavium_mdiobus_c45_addr(p
, phy_id
, regnum
);
120 regnum
= (regnum
>> 16) & 0x1f;
121 op
= 1; /* MDIO_CLAUSE_45_WRITE */
123 cavium_mdiobus_set_mode(p
, C22
);
128 oct_mdio_writeq(smi_wr
.u64
, p
->register_base
+ SMI_WR_DAT
);
131 smi_cmd
.s
.phy_op
= op
;
132 smi_cmd
.s
.phy_adr
= phy_id
;
133 smi_cmd
.s
.reg_adr
= regnum
;
134 oct_mdio_writeq(smi_cmd
.u64
, p
->register_base
+ SMI_CMD
);
137 /* Wait 1000 clocks so we don't saturate the RSL bus
141 smi_wr
.u64
= oct_mdio_readq(p
->register_base
+ SMI_WR_DAT
);
142 } while (smi_wr
.s
.pending
&& --timeout
);
149 EXPORT_SYMBOL(cavium_mdiobus_write
);
151 MODULE_DESCRIPTION("Common code for OCTEON and Thunder MDIO bus drivers");
152 MODULE_AUTHOR("David Daney");
153 MODULE_LICENSE("GPL");