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