xref: /openbmc/u-boot/arch/mips/mach-mscc/phy.c (revision 3098ade2)
1*3098ade2SLars Povlsen // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2*3098ade2SLars Povlsen /*
3*3098ade2SLars Povlsen  * Copyright (c) 2018 Microsemi Corporation
4*3098ade2SLars Povlsen  */
5*3098ade2SLars Povlsen 
6*3098ade2SLars Povlsen #include <common.h>
7*3098ade2SLars Povlsen #include <asm/io.h>
8*3098ade2SLars Povlsen 
9*3098ade2SLars Povlsen int mscc_phy_rd_wr(u8 read,
10*3098ade2SLars Povlsen 		   u32 miimdev,
11*3098ade2SLars Povlsen 		   u8 miim_addr,
12*3098ade2SLars Povlsen 		   u8 addr,
13*3098ade2SLars Povlsen 		   u16 *value)
14*3098ade2SLars Povlsen {
15*3098ade2SLars Povlsen 	u32 data;
16*3098ade2SLars Povlsen 	int i;
17*3098ade2SLars Povlsen 
18*3098ade2SLars Povlsen 	/* Command part */
19*3098ade2SLars Povlsen 	data = (read ? MSCC_F_MII_CMD_MIIM_CMD_OPR_FIELD(2) : /* Read */
20*3098ade2SLars Povlsen 		MSCC_F_MII_CMD_MIIM_CMD_OPR_FIELD(1) | /* Write */
21*3098ade2SLars Povlsen 		MSCC_F_MII_CMD_MIIM_CMD_WRDATA(*value)); /* value */
22*3098ade2SLars Povlsen 
23*3098ade2SLars Povlsen 	/* Addressing part */
24*3098ade2SLars Povlsen 	data |=
25*3098ade2SLars Povlsen 		MSCC_F_MII_CMD_MIIM_CMD_VLD(1) | /* Valid command */
26*3098ade2SLars Povlsen 		MSCC_F_MII_CMD_MIIM_CMD_REGAD(addr) | /* Reg addr */
27*3098ade2SLars Povlsen 		MSCC_F_MII_CMD_MIIM_CMD_PHYAD(miim_addr); /* Miim addr */
28*3098ade2SLars Povlsen 
29*3098ade2SLars Povlsen 	/* Enqueue MIIM operation to be executed */
30*3098ade2SLars Povlsen 	writel(data, BASE_DEVCPU_GCB + MIIM_MII_CMD(miimdev));
31*3098ade2SLars Povlsen 
32*3098ade2SLars Povlsen 	/* Wait for MIIM operation to finish */
33*3098ade2SLars Povlsen 	i = 0;
34*3098ade2SLars Povlsen 	do {
35*3098ade2SLars Povlsen 		if (i++ > 100) {
36*3098ade2SLars Povlsen 			debug("Miim timeout");
37*3098ade2SLars Povlsen 			return -1;
38*3098ade2SLars Povlsen 		}
39*3098ade2SLars Povlsen 		data = readl(BASE_DEVCPU_GCB + MIIM_MII_STATUS(miimdev));
40*3098ade2SLars Povlsen 		debug("Read status miim(%d): 0x%08x\n", miimdev, data);
41*3098ade2SLars Povlsen 	} while (data & MSCC_F_MII_STATUS_MIIM_STAT_BUSY(1));
42*3098ade2SLars Povlsen 
43*3098ade2SLars Povlsen 	if (read) {
44*3098ade2SLars Povlsen 		data = readl(BASE_DEVCPU_GCB + MIIM_MII_DATA(miimdev));
45*3098ade2SLars Povlsen 		if (data & MSCC_M_MII_DATA_MIIM_DATA_SUCCESS) {
46*3098ade2SLars Povlsen 			debug("Read(%d, %d) returned 0x%08x\n",
47*3098ade2SLars Povlsen 			      miim_addr, addr, data);
48*3098ade2SLars Povlsen 			return -1;
49*3098ade2SLars Povlsen 		}
50*3098ade2SLars Povlsen 		*value = MSCC_X_MII_DATA_MIIM_DATA_RDDATA(data);
51*3098ade2SLars Povlsen 	}
52*3098ade2SLars Povlsen 
53*3098ade2SLars Povlsen 	return 0;
54*3098ade2SLars Povlsen }
55*3098ade2SLars Povlsen 
56*3098ade2SLars Povlsen int mscc_phy_rd(u32 miimdev,
57*3098ade2SLars Povlsen 		u8 miim_addr,
58*3098ade2SLars Povlsen 		u8 addr,
59*3098ade2SLars Povlsen 		u16 *value)
60*3098ade2SLars Povlsen {
61*3098ade2SLars Povlsen 	if (mscc_phy_rd_wr(1, miimdev, miim_addr, addr, value) == 0)
62*3098ade2SLars Povlsen 		return 0;
63*3098ade2SLars Povlsen 	debug("Read(%d, %d) returned error\n", miim_addr, addr);
64*3098ade2SLars Povlsen 	return -1;
65*3098ade2SLars Povlsen }
66*3098ade2SLars Povlsen 
67*3098ade2SLars Povlsen int mscc_phy_wr(u32 miimdev,
68*3098ade2SLars Povlsen 		u8 miim_addr,
69*3098ade2SLars Povlsen 		u8 addr,
70*3098ade2SLars Povlsen 		u16 value)
71*3098ade2SLars Povlsen {
72*3098ade2SLars Povlsen 	return mscc_phy_rd_wr(0, miimdev, miim_addr, addr, &value);
73*3098ade2SLars Povlsen }
74