xref: /openbmc/u-boot/board/gdsys/common/ihs_mdio.c (revision 29b103c7)
1 /*
2  * (C) Copyright 2014
3  * Dirk Eibach,  Guntermann & Drunck GmbH, eibach@gdsys.de
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 
10 #include <gdsys_fpga.h>
11 #include <miiphy.h>
12 
13 #include "ihs_mdio.h"
14 
15 static int ihs_mdio_idle(struct mii_dev *bus)
16 {
17 	struct ihs_mdio_info *info = bus->priv;
18 	u16 val;
19 	unsigned int ctr = 0;
20 
21 	do {
22 		FPGA_GET_REG(info->fpga, mdio.control, &val);
23 		udelay(100);
24 		if (ctr++ > 10)
25 			return -1;
26 	} while (!(val & (1 << 12)));
27 
28 	return 0;
29 }
30 
31 static int ihs_mdio_reset(struct mii_dev *bus)
32 {
33 	ihs_mdio_idle(bus);
34 
35 	return 0;
36 }
37 
38 static int ihs_mdio_read(struct mii_dev *bus, int addr, int dev_addr,
39 			 int regnum)
40 {
41 	struct ihs_mdio_info *info = bus->priv;
42 	u16 val;
43 
44 	ihs_mdio_idle(bus);
45 
46 	FPGA_SET_REG(info->fpga, mdio.control,
47 		     ((addr & 0x1f) << 5) | (regnum & 0x1f) | (2 << 10));
48 
49 	/* wait for rx data available */
50 	udelay(100);
51 
52 	FPGA_GET_REG(info->fpga, mdio.rx_data, &val);
53 
54 	return val;
55 }
56 
57 static int ihs_mdio_write(struct mii_dev *bus, int addr, int dev_addr,
58 			  int regnum, u16 value)
59 {
60 	struct ihs_mdio_info *info = bus->priv;
61 
62 	ihs_mdio_idle(bus);
63 
64 	FPGA_SET_REG(info->fpga, mdio.address_data, value);
65 	FPGA_SET_REG(info->fpga, mdio.control,
66 		     ((addr & 0x1f) << 5) | (regnum & 0x1f) | (1 << 10));
67 
68 	return 0;
69 }
70 
71 int ihs_mdio_init(struct ihs_mdio_info *info)
72 {
73 	struct mii_dev *bus = mdio_alloc();
74 
75 	if (!bus) {
76 		printf("Failed to allocate FSL MDIO bus\n");
77 		return -1;
78 	}
79 
80 	bus->read = ihs_mdio_read;
81 	bus->write = ihs_mdio_write;
82 	bus->reset = ihs_mdio_reset;
83 	sprintf(bus->name, info->name);
84 
85 	bus->priv = info;
86 
87 	return mdio_register(bus);
88 }
89