1*2fff4a9bSHoratiu Vultur // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2*2fff4a9bSHoratiu Vultur /*
3*2fff4a9bSHoratiu Vultur  * Copyright (c) 2018 Microsemi Corporation
4*2fff4a9bSHoratiu Vultur  */
5*2fff4a9bSHoratiu Vultur 
6*2fff4a9bSHoratiu Vultur #include <miiphy.h>
7*2fff4a9bSHoratiu Vultur #include <wait_bit.h>
8*2fff4a9bSHoratiu Vultur #include "mscc_miim.h"
9*2fff4a9bSHoratiu Vultur 
10*2fff4a9bSHoratiu Vultur #define MIIM_STATUS			0x0
11*2fff4a9bSHoratiu Vultur #define		MIIM_STAT_BUSY			BIT(3)
12*2fff4a9bSHoratiu Vultur #define MIIM_CMD			0x8
13*2fff4a9bSHoratiu Vultur #define		MIIM_CMD_SCAN		BIT(0)
14*2fff4a9bSHoratiu Vultur #define		MIIM_CMD_OPR_WRITE	BIT(1)
15*2fff4a9bSHoratiu Vultur #define		MIIM_CMD_OPR_READ	BIT(2)
16*2fff4a9bSHoratiu Vultur #define		MIIM_CMD_SINGLE_SCAN	BIT(3)
17*2fff4a9bSHoratiu Vultur #define		MIIM_CMD_WRDATA(x)	((x) << 4)
18*2fff4a9bSHoratiu Vultur #define		MIIM_CMD_REGAD(x)	((x) << 20)
19*2fff4a9bSHoratiu Vultur #define		MIIM_CMD_PHYAD(x)	((x) << 25)
20*2fff4a9bSHoratiu Vultur #define		MIIM_CMD_VLD		BIT(31)
21*2fff4a9bSHoratiu Vultur #define MIIM_DATA			0xC
22*2fff4a9bSHoratiu Vultur #define		MIIM_DATA_ERROR		(0x2 << 16)
23*2fff4a9bSHoratiu Vultur 
mscc_miim_wait_ready(struct mscc_miim_dev * miim)24*2fff4a9bSHoratiu Vultur static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
25*2fff4a9bSHoratiu Vultur {
26*2fff4a9bSHoratiu Vultur 	return wait_for_bit_le32(miim->regs + MIIM_STATUS, MIIM_STAT_BUSY,
27*2fff4a9bSHoratiu Vultur 				 false, 250, false);
28*2fff4a9bSHoratiu Vultur }
29*2fff4a9bSHoratiu Vultur 
mscc_miim_read(struct mii_dev * bus,int addr,int devad,int reg)30*2fff4a9bSHoratiu Vultur int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
31*2fff4a9bSHoratiu Vultur {
32*2fff4a9bSHoratiu Vultur 	struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
33*2fff4a9bSHoratiu Vultur 	u32 val;
34*2fff4a9bSHoratiu Vultur 	int ret;
35*2fff4a9bSHoratiu Vultur 
36*2fff4a9bSHoratiu Vultur 	ret = mscc_miim_wait_ready(miim);
37*2fff4a9bSHoratiu Vultur 	if (ret)
38*2fff4a9bSHoratiu Vultur 		goto out;
39*2fff4a9bSHoratiu Vultur 
40*2fff4a9bSHoratiu Vultur 	writel(MIIM_CMD_VLD | MIIM_CMD_PHYAD(addr) |
41*2fff4a9bSHoratiu Vultur 	       MIIM_CMD_REGAD(reg) | MIIM_CMD_OPR_READ,
42*2fff4a9bSHoratiu Vultur 	       miim->regs + MIIM_CMD);
43*2fff4a9bSHoratiu Vultur 
44*2fff4a9bSHoratiu Vultur 	ret = mscc_miim_wait_ready(miim);
45*2fff4a9bSHoratiu Vultur 	if (ret)
46*2fff4a9bSHoratiu Vultur 		goto out;
47*2fff4a9bSHoratiu Vultur 
48*2fff4a9bSHoratiu Vultur 	val = readl(miim->regs + MIIM_DATA);
49*2fff4a9bSHoratiu Vultur 	if (val & MIIM_DATA_ERROR) {
50*2fff4a9bSHoratiu Vultur 		ret = -EIO;
51*2fff4a9bSHoratiu Vultur 		goto out;
52*2fff4a9bSHoratiu Vultur 	}
53*2fff4a9bSHoratiu Vultur 
54*2fff4a9bSHoratiu Vultur 	ret = val & 0xFFFF;
55*2fff4a9bSHoratiu Vultur  out:
56*2fff4a9bSHoratiu Vultur 	return ret;
57*2fff4a9bSHoratiu Vultur }
58*2fff4a9bSHoratiu Vultur 
mscc_miim_write(struct mii_dev * bus,int addr,int devad,int reg,u16 val)59*2fff4a9bSHoratiu Vultur int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
60*2fff4a9bSHoratiu Vultur 		    u16 val)
61*2fff4a9bSHoratiu Vultur {
62*2fff4a9bSHoratiu Vultur 	struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
63*2fff4a9bSHoratiu Vultur 	int ret;
64*2fff4a9bSHoratiu Vultur 
65*2fff4a9bSHoratiu Vultur 	ret = mscc_miim_wait_ready(miim);
66*2fff4a9bSHoratiu Vultur 	if (ret < 0)
67*2fff4a9bSHoratiu Vultur 		goto out;
68*2fff4a9bSHoratiu Vultur 
69*2fff4a9bSHoratiu Vultur 	writel(MIIM_CMD_VLD | MIIM_CMD_PHYAD(addr) |
70*2fff4a9bSHoratiu Vultur 	       MIIM_CMD_REGAD(reg) | MIIM_CMD_WRDATA(val) |
71*2fff4a9bSHoratiu Vultur 	       MIIM_CMD_OPR_WRITE, miim->regs + MIIM_CMD);
72*2fff4a9bSHoratiu Vultur  out:
73*2fff4a9bSHoratiu Vultur 	return ret;
74*2fff4a9bSHoratiu Vultur }
75