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