Merge tag 'gpio-updates-for-v6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / net / mdio / mdio-cavium.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2009-2016 Cavium, Inc.
4  */
5
6 #include <linux/delay.h>
7 #include <linux/io.h>
8 #include <linux/module.h>
9 #include <linux/phy.h>
10
11 #include "mdio-cavium.h"
12
13 static void cavium_mdiobus_set_mode(struct cavium_mdiobus *p,
14                                     enum cavium_mdiobus_mode m)
15 {
16         union cvmx_smix_clk smi_clk;
17
18         if (m == p->mode)
19                 return;
20
21         smi_clk.u64 = oct_mdio_readq(p->register_base + SMI_CLK);
22         smi_clk.s.mode = (m == C45) ? 1 : 0;
23         smi_clk.s.preamble = 1;
24         oct_mdio_writeq(smi_clk.u64, p->register_base + SMI_CLK);
25         p->mode = m;
26 }
27
28 static int cavium_mdiobus_c45_addr(struct cavium_mdiobus *p,
29                                    int phy_id, int devad, int regnum)
30 {
31         union cvmx_smix_cmd smi_cmd;
32         union cvmx_smix_wr_dat smi_wr;
33         int timeout = 1000;
34
35         cavium_mdiobus_set_mode(p, C45);
36
37         smi_wr.u64 = 0;
38         smi_wr.s.dat = regnum & 0xffff;
39         oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT);
40
41         smi_cmd.u64 = 0;
42         smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_45_ADDRESS */
43         smi_cmd.s.phy_adr = phy_id;
44         smi_cmd.s.reg_adr = devad;
45         oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
46
47         do {
48                 /* Wait 1000 clocks so we don't saturate the RSL bus
49                  * doing reads.
50                  */
51                 __delay(1000);
52                 smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT);
53         } while (smi_wr.s.pending && --timeout);
54
55         if (timeout <= 0)
56                 return -EIO;
57         return 0;
58 }
59
60 int cavium_mdiobus_read_c22(struct mii_bus *bus, int phy_id, int regnum)
61 {
62         struct cavium_mdiobus *p = bus->priv;
63         union cvmx_smix_cmd smi_cmd;
64         union cvmx_smix_rd_dat smi_rd;
65         int timeout = 1000;
66
67         cavium_mdiobus_set_mode(p, C22);
68
69         smi_cmd.u64 = 0;
70         smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */
71         smi_cmd.s.phy_adr = phy_id;
72         smi_cmd.s.reg_adr = regnum;
73         oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
74
75         do {
76                 /* Wait 1000 clocks so we don't saturate the RSL bus
77                  * doing reads.
78                  */
79                 __delay(1000);
80                 smi_rd.u64 = oct_mdio_readq(p->register_base + SMI_RD_DAT);
81         } while (smi_rd.s.pending && --timeout);
82
83         if (smi_rd.s.val)
84                 return smi_rd.s.dat;
85         else
86                 return -EIO;
87 }
88 EXPORT_SYMBOL(cavium_mdiobus_read_c22);
89
90 int cavium_mdiobus_read_c45(struct mii_bus *bus, int phy_id, int devad,
91                             int regnum)
92 {
93         struct cavium_mdiobus *p = bus->priv;
94         union cvmx_smix_cmd smi_cmd;
95         union cvmx_smix_rd_dat smi_rd;
96         int timeout = 1000;
97         int r;
98
99         r = cavium_mdiobus_c45_addr(p, phy_id, devad, regnum);
100         if (r < 0)
101                 return r;
102
103         smi_cmd.u64 = 0;
104         smi_cmd.s.phy_op = 3; /* MDIO_CLAUSE_45_READ */
105         smi_cmd.s.phy_adr = phy_id;
106         smi_cmd.s.reg_adr = regnum;
107         oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
108
109         do {
110                 /* Wait 1000 clocks so we don't saturate the RSL bus
111                  * doing reads.
112                  */
113                 __delay(1000);
114                 smi_rd.u64 = oct_mdio_readq(p->register_base + SMI_RD_DAT);
115         } while (smi_rd.s.pending && --timeout);
116
117         if (smi_rd.s.val)
118                 return smi_rd.s.dat;
119         else
120                 return -EIO;
121 }
122 EXPORT_SYMBOL(cavium_mdiobus_read_c45);
123
124 int cavium_mdiobus_write_c22(struct mii_bus *bus, int phy_id, int regnum,
125                              u16 val)
126 {
127         struct cavium_mdiobus *p = bus->priv;
128         union cvmx_smix_cmd smi_cmd;
129         union cvmx_smix_wr_dat smi_wr;
130         int timeout = 1000;
131
132         cavium_mdiobus_set_mode(p, C22);
133
134         smi_wr.u64 = 0;
135         smi_wr.s.dat = val;
136         oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT);
137
138         smi_cmd.u64 = 0;
139         smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */
140         smi_cmd.s.phy_adr = phy_id;
141         smi_cmd.s.reg_adr = regnum;
142         oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
143
144         do {
145                 /* Wait 1000 clocks so we don't saturate the RSL bus
146                  * doing reads.
147                  */
148                 __delay(1000);
149                 smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT);
150         } while (smi_wr.s.pending && --timeout);
151
152         if (timeout <= 0)
153                 return -EIO;
154
155         return 0;
156 }
157 EXPORT_SYMBOL(cavium_mdiobus_write_c22);
158
159 int cavium_mdiobus_write_c45(struct mii_bus *bus, int phy_id, int devad,
160                              int regnum, u16 val)
161 {
162         struct cavium_mdiobus *p = bus->priv;
163         union cvmx_smix_cmd smi_cmd;
164         union cvmx_smix_wr_dat smi_wr;
165         int timeout = 1000;
166         int r;
167
168         r = cavium_mdiobus_c45_addr(p, phy_id, devad, regnum);
169         if (r < 0)
170                 return r;
171
172         smi_wr.u64 = 0;
173         smi_wr.s.dat = val;
174         oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT);
175
176         smi_cmd.u64 = 0;
177         smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_45_WRITE */
178         smi_cmd.s.phy_adr = phy_id;
179         smi_cmd.s.reg_adr = devad;
180         oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
181
182         do {
183                 /* Wait 1000 clocks so we don't saturate the RSL bus
184                  * doing reads.
185                  */
186                 __delay(1000);
187                 smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT);
188         } while (smi_wr.s.pending && --timeout);
189
190         if (timeout <= 0)
191                 return -EIO;
192
193         return 0;
194 }
195 EXPORT_SYMBOL(cavium_mdiobus_write_c45);
196
197 MODULE_DESCRIPTION("Common code for OCTEON and Thunder MDIO bus drivers");
198 MODULE_AUTHOR("David Daney");
199 MODULE_LICENSE("GPL v2");