1 /*
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
4  * for more details.
5  *
6  * Copyright (C) 2009-2012 Cavium, Inc.
7  */
8 
9 #include <linux/platform_device.h>
10 #include <linux/of_address.h>
11 #include <linux/of_mdio.h>
12 #include <linux/delay.h>
13 #include <linux/module.h>
14 #include <linux/gfp.h>
15 #include <linux/phy.h>
16 #include <linux/io.h>
17 
18 #ifdef CONFIG_CAVIUM_OCTEON_SOC
19 #include <asm/octeon/octeon.h>
20 #endif
21 
22 #define DRV_VERSION "1.1"
23 #define DRV_DESCRIPTION "Cavium Networks Octeon/ThunderX SMI/MDIO driver"
24 
25 #define SMI_CMD		0x0
26 #define SMI_WR_DAT	0x8
27 #define SMI_RD_DAT	0x10
28 #define SMI_CLK		0x18
29 #define SMI_EN		0x20
30 
31 #ifdef __BIG_ENDIAN_BITFIELD
32 #define OCT_MDIO_BITFIELD_FIELD(field, more)	\
33 	field;					\
34 	more
35 
36 #else
37 #define OCT_MDIO_BITFIELD_FIELD(field, more)	\
38 	more					\
39 	field;
40 
41 #endif
42 
43 union cvmx_smix_clk {
44 	u64 u64;
45 	struct cvmx_smix_clk_s {
46 	  OCT_MDIO_BITFIELD_FIELD(u64 reserved_25_63:39,
47 	  OCT_MDIO_BITFIELD_FIELD(u64 mode:1,
48 	  OCT_MDIO_BITFIELD_FIELD(u64 reserved_21_23:3,
49 	  OCT_MDIO_BITFIELD_FIELD(u64 sample_hi:5,
50 	  OCT_MDIO_BITFIELD_FIELD(u64 sample_mode:1,
51 	  OCT_MDIO_BITFIELD_FIELD(u64 reserved_14_14:1,
52 	  OCT_MDIO_BITFIELD_FIELD(u64 clk_idle:1,
53 	  OCT_MDIO_BITFIELD_FIELD(u64 preamble:1,
54 	  OCT_MDIO_BITFIELD_FIELD(u64 sample:4,
55 	  OCT_MDIO_BITFIELD_FIELD(u64 phase:8,
56 	  ;))))))))))
57 	} s;
58 };
59 
60 union cvmx_smix_cmd {
61 	u64 u64;
62 	struct cvmx_smix_cmd_s {
63 	  OCT_MDIO_BITFIELD_FIELD(u64 reserved_18_63:46,
64 	  OCT_MDIO_BITFIELD_FIELD(u64 phy_op:2,
65 	  OCT_MDIO_BITFIELD_FIELD(u64 reserved_13_15:3,
66 	  OCT_MDIO_BITFIELD_FIELD(u64 phy_adr:5,
67 	  OCT_MDIO_BITFIELD_FIELD(u64 reserved_5_7:3,
68 	  OCT_MDIO_BITFIELD_FIELD(u64 reg_adr:5,
69 	  ;))))))
70 	} s;
71 };
72 
73 union cvmx_smix_en {
74 	u64 u64;
75 	struct cvmx_smix_en_s {
76 	  OCT_MDIO_BITFIELD_FIELD(u64 reserved_1_63:63,
77 	  OCT_MDIO_BITFIELD_FIELD(u64 en:1,
78 	  ;))
79 	} s;
80 };
81 
82 union cvmx_smix_rd_dat {
83 	u64 u64;
84 	struct cvmx_smix_rd_dat_s {
85 	  OCT_MDIO_BITFIELD_FIELD(u64 reserved_18_63:46,
86 	  OCT_MDIO_BITFIELD_FIELD(u64 pending:1,
87 	  OCT_MDIO_BITFIELD_FIELD(u64 val:1,
88 	  OCT_MDIO_BITFIELD_FIELD(u64 dat:16,
89 	  ;))))
90 	} s;
91 };
92 
93 union cvmx_smix_wr_dat {
94 	u64 u64;
95 	struct cvmx_smix_wr_dat_s {
96 	  OCT_MDIO_BITFIELD_FIELD(u64 reserved_18_63:46,
97 	  OCT_MDIO_BITFIELD_FIELD(u64 pending:1,
98 	  OCT_MDIO_BITFIELD_FIELD(u64 val:1,
99 	  OCT_MDIO_BITFIELD_FIELD(u64 dat:16,
100 	  ;))))
101 	} s;
102 };
103 
104 enum octeon_mdiobus_mode {
105 	UNINIT = 0,
106 	C22,
107 	C45
108 };
109 
110 struct octeon_mdiobus {
111 	struct mii_bus *mii_bus;
112 	u64 register_base;
113 	resource_size_t mdio_phys;
114 	resource_size_t regsize;
115 	enum octeon_mdiobus_mode mode;
116 	int phy_irq[PHY_MAX_ADDR];
117 };
118 
119 #ifdef CONFIG_CAVIUM_OCTEON_SOC
oct_mdio_writeq(u64 val,u64 addr)120 static void oct_mdio_writeq(u64 val, u64 addr)
121 {
122 	cvmx_write_csr(addr, val);
123 }
124 
oct_mdio_readq(u64 addr)125 static u64 oct_mdio_readq(u64 addr)
126 {
127 	return cvmx_read_csr(addr);
128 }
129 #else
130 #define oct_mdio_writeq(val, addr)	writeq_relaxed(val, (void *)addr)
131 #define oct_mdio_readq(addr)		readq_relaxed((void *)addr)
132 #endif
133 
octeon_mdiobus_set_mode(struct octeon_mdiobus * p,enum octeon_mdiobus_mode m)134 static void octeon_mdiobus_set_mode(struct octeon_mdiobus *p,
135 				    enum octeon_mdiobus_mode m)
136 {
137 	union cvmx_smix_clk smi_clk;
138 
139 	if (m == p->mode)
140 		return;
141 
142 	smi_clk.u64 = oct_mdio_readq(p->register_base + SMI_CLK);
143 	smi_clk.s.mode = (m == C45) ? 1 : 0;
144 	smi_clk.s.preamble = 1;
145 	oct_mdio_writeq(smi_clk.u64, p->register_base + SMI_CLK);
146 	p->mode = m;
147 }
148 
octeon_mdiobus_c45_addr(struct octeon_mdiobus * p,int phy_id,int regnum)149 static int octeon_mdiobus_c45_addr(struct octeon_mdiobus *p,
150 				   int phy_id, int regnum)
151 {
152 	union cvmx_smix_cmd smi_cmd;
153 	union cvmx_smix_wr_dat smi_wr;
154 	int timeout = 1000;
155 
156 	octeon_mdiobus_set_mode(p, C45);
157 
158 	smi_wr.u64 = 0;
159 	smi_wr.s.dat = regnum & 0xffff;
160 	oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT);
161 
162 	regnum = (regnum >> 16) & 0x1f;
163 
164 	smi_cmd.u64 = 0;
165 	smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_45_ADDRESS */
166 	smi_cmd.s.phy_adr = phy_id;
167 	smi_cmd.s.reg_adr = regnum;
168 	oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
169 
170 	do {
171 		/* Wait 1000 clocks so we don't saturate the RSL bus
172 		 * doing reads.
173 		 */
174 		__delay(1000);
175 		smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT);
176 	} while (smi_wr.s.pending && --timeout);
177 
178 	if (timeout <= 0)
179 		return -EIO;
180 	return 0;
181 }
182 
octeon_mdiobus_read(struct mii_bus * bus,int phy_id,int regnum)183 static int octeon_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum)
184 {
185 	struct octeon_mdiobus *p = bus->priv;
186 	union cvmx_smix_cmd smi_cmd;
187 	union cvmx_smix_rd_dat smi_rd;
188 	unsigned int op = 1; /* MDIO_CLAUSE_22_READ */
189 	int timeout = 1000;
190 
191 	if (regnum & MII_ADDR_C45) {
192 		int r = octeon_mdiobus_c45_addr(p, phy_id, regnum);
193 		if (r < 0)
194 			return r;
195 
196 		regnum = (regnum >> 16) & 0x1f;
197 		op = 3; /* MDIO_CLAUSE_45_READ */
198 	} else {
199 		octeon_mdiobus_set_mode(p, C22);
200 	}
201 
202 
203 	smi_cmd.u64 = 0;
204 	smi_cmd.s.phy_op = op;
205 	smi_cmd.s.phy_adr = phy_id;
206 	smi_cmd.s.reg_adr = regnum;
207 	oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
208 
209 	do {
210 		/* Wait 1000 clocks so we don't saturate the RSL bus
211 		 * doing reads.
212 		 */
213 		__delay(1000);
214 		smi_rd.u64 = oct_mdio_readq(p->register_base + SMI_RD_DAT);
215 	} while (smi_rd.s.pending && --timeout);
216 
217 	if (smi_rd.s.val)
218 		return smi_rd.s.dat;
219 	else
220 		return -EIO;
221 }
222 
octeon_mdiobus_write(struct mii_bus * bus,int phy_id,int regnum,u16 val)223 static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
224 				int regnum, u16 val)
225 {
226 	struct octeon_mdiobus *p = bus->priv;
227 	union cvmx_smix_cmd smi_cmd;
228 	union cvmx_smix_wr_dat smi_wr;
229 	unsigned int op = 0; /* MDIO_CLAUSE_22_WRITE */
230 	int timeout = 1000;
231 
232 
233 	if (regnum & MII_ADDR_C45) {
234 		int r = octeon_mdiobus_c45_addr(p, phy_id, regnum);
235 		if (r < 0)
236 			return r;
237 
238 		regnum = (regnum >> 16) & 0x1f;
239 		op = 1; /* MDIO_CLAUSE_45_WRITE */
240 	} else {
241 		octeon_mdiobus_set_mode(p, C22);
242 	}
243 
244 	smi_wr.u64 = 0;
245 	smi_wr.s.dat = val;
246 	oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT);
247 
248 	smi_cmd.u64 = 0;
249 	smi_cmd.s.phy_op = op;
250 	smi_cmd.s.phy_adr = phy_id;
251 	smi_cmd.s.reg_adr = regnum;
252 	oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD);
253 
254 	do {
255 		/* Wait 1000 clocks so we don't saturate the RSL bus
256 		 * doing reads.
257 		 */
258 		__delay(1000);
259 		smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT);
260 	} while (smi_wr.s.pending && --timeout);
261 
262 	if (timeout <= 0)
263 		return -EIO;
264 
265 	return 0;
266 }
267 
octeon_mdiobus_probe(struct platform_device * pdev)268 static int octeon_mdiobus_probe(struct platform_device *pdev)
269 {
270 	struct octeon_mdiobus *bus;
271 	struct resource *res_mem;
272 	union cvmx_smix_en smi_en;
273 	int err = -ENOENT;
274 
275 	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
276 	if (!bus)
277 		return -ENOMEM;
278 
279 	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
280 	if (res_mem == NULL) {
281 		dev_err(&pdev->dev, "found no memory resource\n");
282 		return -ENXIO;
283 	}
284 
285 	bus->mdio_phys = res_mem->start;
286 	bus->regsize = resource_size(res_mem);
287 
288 	if (!devm_request_mem_region(&pdev->dev, bus->mdio_phys, bus->regsize,
289 				     res_mem->name)) {
290 		dev_err(&pdev->dev, "request_mem_region failed\n");
291 		return -ENXIO;
292 	}
293 
294 	bus->register_base =
295 		(u64)devm_ioremap(&pdev->dev, bus->mdio_phys, bus->regsize);
296 	if (!bus->register_base) {
297 		dev_err(&pdev->dev, "dev_ioremap failed\n");
298 		return -ENOMEM;
299 	}
300 
301 	bus->mii_bus = mdiobus_alloc();
302 	if (!bus->mii_bus)
303 		goto fail;
304 
305 	smi_en.u64 = 0;
306 	smi_en.s.en = 1;
307 	oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
308 
309 	bus->mii_bus->priv = bus;
310 	bus->mii_bus->irq = bus->phy_irq;
311 	bus->mii_bus->name = "mdio-octeon";
312 	snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%llx", bus->register_base);
313 	bus->mii_bus->parent = &pdev->dev;
314 
315 	bus->mii_bus->read = octeon_mdiobus_read;
316 	bus->mii_bus->write = octeon_mdiobus_write;
317 
318 	platform_set_drvdata(pdev, bus);
319 
320 	err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node);
321 	if (err)
322 		goto fail_register;
323 
324 	dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
325 
326 	return 0;
327 fail_register:
328 	mdiobus_free(bus->mii_bus);
329 fail:
330 	smi_en.u64 = 0;
331 	oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
332 	return err;
333 }
334 
octeon_mdiobus_remove(struct platform_device * pdev)335 static int octeon_mdiobus_remove(struct platform_device *pdev)
336 {
337 	struct octeon_mdiobus *bus;
338 	union cvmx_smix_en smi_en;
339 
340 	bus = platform_get_drvdata(pdev);
341 
342 	mdiobus_unregister(bus->mii_bus);
343 	mdiobus_free(bus->mii_bus);
344 	smi_en.u64 = 0;
345 	oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
346 	return 0;
347 }
348 
349 static const struct of_device_id octeon_mdiobus_match[] = {
350 	{
351 		.compatible = "cavium,octeon-3860-mdio",
352 	},
353 	{},
354 };
355 MODULE_DEVICE_TABLE(of, octeon_mdiobus_match);
356 
357 static struct platform_driver octeon_mdiobus_driver = {
358 	.driver = {
359 		.name		= "mdio-octeon",
360 		.of_match_table = octeon_mdiobus_match,
361 	},
362 	.probe		= octeon_mdiobus_probe,
363 	.remove		= octeon_mdiobus_remove,
364 };
365 
octeon_mdiobus_force_mod_depencency(void)366 void octeon_mdiobus_force_mod_depencency(void)
367 {
368 	/* Let ethernet drivers force us to be loaded.  */
369 }
370 EXPORT_SYMBOL(octeon_mdiobus_force_mod_depencency);
371 
372 module_platform_driver(octeon_mdiobus_driver);
373 
374 MODULE_DESCRIPTION(DRV_DESCRIPTION);
375 MODULE_VERSION(DRV_VERSION);
376 MODULE_AUTHOR("David Daney");
377 MODULE_LICENSE("GPL");
378