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