xref: /openbmc/u-boot/drivers/net/ti/cpsw_mdio.c (revision 6f443330)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * CPSW MDIO generic driver for TI AMxx/K2x/EMAC devices.
4  *
5  * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
6  */
7 
8 #include <common.h>
9 #include <asm/io.h>
10 #include <miiphy.h>
11 #include <wait_bit.h>
12 
13 struct cpsw_mdio_regs {
14 	u32	version;
15 	u32	control;
16 #define CONTROL_IDLE		BIT(31)
17 #define CONTROL_ENABLE		BIT(30)
18 #define CONTROL_FAULT		BIT(19)
19 #define CONTROL_FAULT_ENABLE	BIT(18)
20 #define CONTROL_DIV_MASK	GENMASK(15, 0)
21 
22 	u32	alive;
23 	u32	link;
24 	u32	linkintraw;
25 	u32	linkintmasked;
26 	u32	__reserved_0[2];
27 	u32	userintraw;
28 	u32	userintmasked;
29 	u32	userintmaskset;
30 	u32	userintmaskclr;
31 	u32	__reserved_1[20];
32 
33 	struct {
34 		u32		access;
35 		u32		physel;
36 #define USERACCESS_GO		BIT(31)
37 #define USERACCESS_WRITE	BIT(30)
38 #define USERACCESS_ACK		BIT(29)
39 #define USERACCESS_READ		(0)
40 #define USERACCESS_PHY_REG_SHIFT	(21)
41 #define USERACCESS_PHY_ADDR_SHIFT	(16)
42 #define USERACCESS_DATA		GENMASK(15, 0)
43 	} user[0];
44 };
45 
46 #define CPSW_MDIO_DIV_DEF	0xff
47 #define PHY_REG_MASK		0x1f
48 #define PHY_ID_MASK		0x1f
49 
50 /*
51  * This timeout definition is a worst-case ultra defensive measure against
52  * unexpected controller lock ups.  Ideally, we should never ever hit this
53  * scenario in practice.
54  */
55 #define CPSW_MDIO_TIMEOUT            100 /* msecs */
56 
57 struct cpsw_mdio {
58 	struct cpsw_mdio_regs *regs;
59 	struct mii_dev *bus;
60 	int div;
61 };
62 
63 /* wait until hardware is ready for another user access */
cpsw_mdio_wait_for_user_access(struct cpsw_mdio * mdio)64 static int cpsw_mdio_wait_for_user_access(struct cpsw_mdio *mdio)
65 {
66 	return wait_for_bit_le32(&mdio->regs->user[0].access,
67 				 USERACCESS_GO, false,
68 				 CPSW_MDIO_TIMEOUT, false);
69 }
70 
cpsw_mdio_read(struct mii_dev * bus,int phy_id,int dev_addr,int phy_reg)71 static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
72 			  int dev_addr, int phy_reg)
73 {
74 	struct cpsw_mdio *mdio = bus->priv;
75 	int data, ret;
76 	u32 reg;
77 
78 	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
79 		return -EINVAL;
80 
81 	ret = cpsw_mdio_wait_for_user_access(mdio);
82 	if (ret)
83 		return ret;
84 	reg = (USERACCESS_GO | USERACCESS_READ |
85 	       (phy_reg << USERACCESS_PHY_REG_SHIFT) |
86 	       (phy_id << USERACCESS_PHY_ADDR_SHIFT));
87 	writel(reg, &mdio->regs->user[0].access);
88 	ret = cpsw_mdio_wait_for_user_access(mdio);
89 	if (ret)
90 		return ret;
91 
92 	reg = readl(&mdio->regs->user[0].access);
93 	data = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -1;
94 	return data;
95 }
96 
cpsw_mdio_write(struct mii_dev * bus,int phy_id,int dev_addr,int phy_reg,u16 data)97 static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr,
98 			   int phy_reg, u16 data)
99 {
100 	struct cpsw_mdio *mdio = bus->priv;
101 	u32 reg;
102 	int ret;
103 
104 	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
105 		return -EINVAL;
106 
107 	ret = cpsw_mdio_wait_for_user_access(mdio);
108 	if (ret)
109 		return ret;
110 	reg = (USERACCESS_GO | USERACCESS_WRITE |
111 	       (phy_reg << USERACCESS_PHY_REG_SHIFT) |
112 	       (phy_id << USERACCESS_PHY_ADDR_SHIFT) |
113 	       (data & USERACCESS_DATA));
114 	writel(reg, &mdio->regs->user[0].access);
115 
116 	return cpsw_mdio_wait_for_user_access(mdio);
117 }
118 
cpsw_mdio_get_alive(struct mii_dev * bus)119 u32 cpsw_mdio_get_alive(struct mii_dev *bus)
120 {
121 	struct cpsw_mdio *mdio = bus->priv;
122 	u32 val;
123 
124 	val = readl(&mdio->regs->control);
125 	return val & GENMASK(15, 0);
126 }
127 
cpsw_mdio_init(const char * name,u32 mdio_base,u32 bus_freq,int fck_freq)128 struct mii_dev *cpsw_mdio_init(const char *name, u32 mdio_base,
129 			       u32 bus_freq, int fck_freq)
130 {
131 	struct cpsw_mdio *cpsw_mdio;
132 	int ret;
133 
134 	cpsw_mdio = calloc(1, sizeof(*cpsw_mdio));
135 	if (!cpsw_mdio) {
136 		debug("failed to alloc cpsw_mdio\n");
137 		return NULL;
138 	}
139 
140 	cpsw_mdio->bus = mdio_alloc();
141 	if (!cpsw_mdio->bus) {
142 		debug("failed to alloc mii bus\n");
143 		free(cpsw_mdio);
144 		return NULL;
145 	}
146 
147 	cpsw_mdio->regs = (struct cpsw_mdio_regs *)mdio_base;
148 
149 	if (!bus_freq || !fck_freq)
150 		cpsw_mdio->div = CPSW_MDIO_DIV_DEF;
151 	else
152 		cpsw_mdio->div = (fck_freq / bus_freq) - 1;
153 	cpsw_mdio->div &= CONTROL_DIV_MASK;
154 
155 	/* set enable and clock divider */
156 	writel(cpsw_mdio->div | CONTROL_ENABLE | CONTROL_FAULT |
157 	       CONTROL_FAULT_ENABLE, &cpsw_mdio->regs->control);
158 	wait_for_bit_le32(&cpsw_mdio->regs->control,
159 			  CONTROL_IDLE, false, CPSW_MDIO_TIMEOUT, true);
160 
161 	/*
162 	 * wait for scan logic to settle:
163 	 * the scan time consists of (a) a large fixed component, and (b) a
164 	 * small component that varies with the mii bus frequency.  These
165 	 * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
166 	 * silicon.  Since the effect of (b) was found to be largely
167 	 * negligible, we keep things simple here.
168 	 */
169 	mdelay(1);
170 
171 	cpsw_mdio->bus->read = cpsw_mdio_read;
172 	cpsw_mdio->bus->write = cpsw_mdio_write;
173 	cpsw_mdio->bus->priv = cpsw_mdio;
174 	snprintf(cpsw_mdio->bus->name, sizeof(cpsw_mdio->bus->name), name);
175 
176 	ret = mdio_register(cpsw_mdio->bus);
177 	if (ret < 0) {
178 		debug("failed to register mii bus\n");
179 		goto free_bus;
180 	}
181 
182 	return cpsw_mdio->bus;
183 
184 free_bus:
185 	mdio_free(cpsw_mdio->bus);
186 	free(cpsw_mdio);
187 	return NULL;
188 }
189 
cpsw_mdio_free(struct mii_dev * bus)190 void cpsw_mdio_free(struct mii_dev *bus)
191 {
192 	struct cpsw_mdio *mdio = bus->priv;
193 	u32 reg;
194 
195 	/* disable mdio */
196 	reg = readl(&mdio->regs->control);
197 	reg &= ~CONTROL_ENABLE;
198 	writel(reg, &mdio->regs->control);
199 
200 	mdio_unregister(bus);
201 	mdio_free(bus);
202 	free(mdio);
203 }
204