Merge tag 'mips-pull-2019-11-16' of git://git.denx.de/u-boot-mips
[oweals/u-boot.git] / arch / mips / mach-mscc / phy.c
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
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
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
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 }