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 } 74