xref: /openbmc/u-boot/board/gdsys/a38x/ihs_phys.c (revision cf0bcd7d)
1 #include <common.h>
2 #include <dm.h>
3 #include <miiphy.h>
4 #include <asm-generic/gpio.h>
5 
6 #include "ihs_phys.h"
7 #include "dt_helpers.h"
8 
9 enum {
10 	PORTTYPE_MAIN_CAT,
11 	PORTTYPE_TOP_CAT,
12 	PORTTYPE_16C_16F,
13 	PORTTYPE_UNKNOWN
14 };
15 
16 static struct porttype {
17 	bool phy_invert_in_pol;
18 	bool phy_invert_out_pol;
19 } porttypes[] = {
20 	{ true, false },
21 	{ false, true },
22 	{ false, false },
23 };
24 
25 static void ihs_phy_config(struct phy_device *phydev, bool qinpn, bool qoutpn)
26 {
27 	u16 reg;
28 
29 	phy_config(phydev);
30 
31 	/* enable QSGMII autonegotiation with flow control */
32 	phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0004);
33 	reg = phy_read(phydev, MDIO_DEVAD_NONE, 16);
34 	reg |= (3 << 6);
35 	phy_write(phydev, MDIO_DEVAD_NONE, 16, reg);
36 
37 	/*
38 	 * invert QSGMII Q_INP/N and Q_OUTP/N if required
39 	 * and perform global reset
40 	 */
41 	reg = phy_read(phydev, MDIO_DEVAD_NONE, 26);
42 	if (qinpn)
43 		reg |= (1 << 13);
44 	if (qoutpn)
45 		reg |= (1 << 12);
46 	reg |= (1 << 15);
47 	phy_write(phydev, MDIO_DEVAD_NONE, 26, reg);
48 
49 	/* advertise 1000BASE-T full-duplex only  */
50 	phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000);
51 	reg = phy_read(phydev, MDIO_DEVAD_NONE, 4);
52 	reg &= ~0x1e0;
53 	phy_write(phydev, MDIO_DEVAD_NONE, 4, reg);
54 	reg = phy_read(phydev, MDIO_DEVAD_NONE, 9);
55 	reg = (reg & ~0x300) | 0x200;
56 	phy_write(phydev, MDIO_DEVAD_NONE, 9, reg);
57 
58 	/* copper power up */
59 	reg = phy_read(phydev, MDIO_DEVAD_NONE, 16);
60 	reg &= ~0x0004;
61 	phy_write(phydev, MDIO_DEVAD_NONE, 16, reg);
62 }
63 
64 uint calculate_octo_phy_mask(void)
65 {
66 	uint k;
67 	uint octo_phy_mask = 0;
68 	struct gpio_desc gpio = {};
69 	char gpio_name[64];
70 	static const char * const dev_name[] = {"pca9698@23", "pca9698@21",
71 						"pca9698@24", "pca9698@25",
72 						"pca9698@26"};
73 
74 	/* mark all octo phys that should be present */
75 	for (k = 0; k < 5; ++k) {
76 		snprintf(gpio_name, 64, "cat-gpio-%u", k);
77 
78 		if (request_gpio_by_name(&gpio, dev_name[k], 0x20, gpio_name))
79 			continue;
80 
81 		/* check CAT flag */
82 		if (dm_gpio_get_value(&gpio))
83 			octo_phy_mask |= (1 << (k * 2));
84 		else
85 			/* If CAT == 0, there's no second octo phy -> skip */
86 			continue;
87 
88 		snprintf(gpio_name, 64, "second-octo-gpio-%u", k);
89 
90 		if (request_gpio_by_name(&gpio, dev_name[k], 0x27, gpio_name)) {
91 			/* default: second octo phy is present */
92 			octo_phy_mask |= (1 << (k * 2 + 1));
93 			continue;
94 		}
95 
96 		if (dm_gpio_get_value(&gpio) == 0)
97 			octo_phy_mask |= (1 << (k * 2 + 1));
98 	}
99 
100 	return octo_phy_mask;
101 }
102 
103 int register_miiphy_bus(uint k, struct mii_dev **bus)
104 {
105 	int retval;
106 	struct mii_dev *mdiodev = mdio_alloc();
107 	char *name = bb_miiphy_buses[k].name;
108 
109 	if (!mdiodev)
110 		return -ENOMEM;
111 	strncpy(mdiodev->name,
112 		name,
113 		MDIO_NAME_LEN);
114 	mdiodev->read = bb_miiphy_read;
115 	mdiodev->write = bb_miiphy_write;
116 
117 	retval = mdio_register(mdiodev);
118 	if (retval < 0)
119 		return retval;
120 	*bus = miiphy_get_dev_by_name(name);
121 
122 	return 0;
123 }
124 
125 struct porttype *get_porttype(uint octo_phy_mask, uint k)
126 {
127 	uint octo_index = k * 4;
128 
129 	if (!k) {
130 		if (octo_phy_mask & 0x01)
131 			return &porttypes[PORTTYPE_MAIN_CAT];
132 		else if (!(octo_phy_mask & 0x03))
133 			return &porttypes[PORTTYPE_16C_16F];
134 	} else {
135 		if (octo_phy_mask & (1 << octo_index))
136 			return &porttypes[PORTTYPE_TOP_CAT];
137 	}
138 
139 	return NULL;
140 }
141 
142 int init_single_phy(struct porttype *porttype, struct mii_dev *bus,
143 		    uint bus_idx, uint m, uint phy_idx)
144 {
145 	struct phy_device *phydev = phy_find_by_mask(
146 		bus, 1 << (m * 8 + phy_idx),
147 		PHY_INTERFACE_MODE_MII);
148 
149 	printf(" %u", bus_idx * 32 + m * 8 + phy_idx);
150 
151 	if (!phydev)
152 		puts("!");
153 	else
154 		ihs_phy_config(phydev, porttype->phy_invert_in_pol,
155 			       porttype->phy_invert_out_pol);
156 
157 	return 0;
158 }
159 
160 int init_octo_phys(uint octo_phy_mask)
161 {
162 	uint bus_idx;
163 
164 	/* there are up to four octo-phys on each mdio bus */
165 	for (bus_idx = 0; bus_idx < bb_miiphy_buses_num; ++bus_idx) {
166 		uint m;
167 		uint octo_index = bus_idx * 4;
168 		struct mii_dev *bus = NULL;
169 		struct porttype *porttype = NULL;
170 		int ret;
171 
172 		porttype = get_porttype(octo_phy_mask, bus_idx);
173 
174 		if (!porttype)
175 			continue;
176 
177 		for (m = 0; m < 4; ++m) {
178 			uint phy_idx;
179 
180 			/**
181 			 * Register a bus device if there is at least one phy
182 			 * on the current bus
183 			 */
184 			if (!m && octo_phy_mask & (0xf << octo_index)) {
185 				ret = register_miiphy_bus(bus_idx, &bus);
186 				if (ret)
187 					return ret;
188 			}
189 
190 			if (!(octo_phy_mask & BIT(octo_index + m)))
191 				continue;
192 
193 			for (phy_idx = 0; phy_idx < 8; ++phy_idx)
194 				init_single_phy(porttype, bus, bus_idx, m,
195 						phy_idx);
196 		}
197 	}
198 
199 	return 0;
200 }
201 
202 /*
203  * MII GPIO bitbang implementation
204  * MDC MDIO bus
205  * 13  14   PHY1-4
206  * 25  45   PHY5-8
207  * 46  24   PHY9-10
208  */
209 
210 struct gpio_mii {
211 	int index;
212 	struct gpio_desc mdc_gpio;
213 	struct gpio_desc mdio_gpio;
214 	int mdc_num;
215 	int mdio_num;
216 	int mdio_value;
217 } gpio_mii_set[] = {
218 	{ 0, {}, {}, 13, 14, 1 },
219 	{ 1, {}, {}, 25, 45, 1 },
220 	{ 2, {}, {}, 46, 24, 1 },
221 };
222 
223 static int mii_mdio_init(struct bb_miiphy_bus *bus)
224 {
225 	struct gpio_mii *gpio_mii = bus->priv;
226 	char name[32] = {};
227 	struct udevice *gpio_dev1 = NULL;
228 	struct udevice *gpio_dev2 = NULL;
229 
230 	if (uclass_get_device_by_name(UCLASS_GPIO, "gpio@18100", &gpio_dev1) ||
231 	    uclass_get_device_by_name(UCLASS_GPIO, "gpio@18140", &gpio_dev2)) {
232 		printf("Could not get GPIO device.\n");
233 		return 1;
234 	}
235 
236 	if (gpio_mii->mdc_num > 31) {
237 		gpio_mii->mdc_gpio.dev = gpio_dev2;
238 		gpio_mii->mdc_gpio.offset = gpio_mii->mdc_num - 32;
239 	} else {
240 		gpio_mii->mdc_gpio.dev = gpio_dev1;
241 		gpio_mii->mdc_gpio.offset = gpio_mii->mdc_num;
242 	}
243 	gpio_mii->mdc_gpio.flags = 0;
244 	snprintf(name, 32, "bb_miiphy_bus-%d-mdc", gpio_mii->index);
245 	dm_gpio_request(&gpio_mii->mdc_gpio, name);
246 
247 	if (gpio_mii->mdio_num > 31) {
248 		gpio_mii->mdio_gpio.dev = gpio_dev2;
249 		gpio_mii->mdio_gpio.offset = gpio_mii->mdio_num - 32;
250 	} else {
251 		gpio_mii->mdio_gpio.dev = gpio_dev1;
252 		gpio_mii->mdio_gpio.offset = gpio_mii->mdio_num;
253 	}
254 	gpio_mii->mdio_gpio.flags = 0;
255 	snprintf(name, 32, "bb_miiphy_bus-%d-mdio", gpio_mii->index);
256 	dm_gpio_request(&gpio_mii->mdio_gpio, name);
257 
258 	dm_gpio_set_dir_flags(&gpio_mii->mdc_gpio, GPIOD_IS_OUT);
259 	dm_gpio_set_value(&gpio_mii->mdc_gpio, 1);
260 
261 	return 0;
262 }
263 
264 static int mii_mdio_active(struct bb_miiphy_bus *bus)
265 {
266 	struct gpio_mii *gpio_mii = bus->priv;
267 
268 	dm_gpio_set_value(&gpio_mii->mdc_gpio, gpio_mii->mdio_value);
269 
270 	return 0;
271 }
272 
273 static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
274 {
275 	struct gpio_mii *gpio_mii = bus->priv;
276 
277 	dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN);
278 
279 	return 0;
280 }
281 
282 static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
283 {
284 	struct gpio_mii *gpio_mii = bus->priv;
285 
286 	dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_OUT);
287 	dm_gpio_set_value(&gpio_mii->mdio_gpio, v);
288 	gpio_mii->mdio_value = v;
289 
290 	return 0;
291 }
292 
293 static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
294 {
295 	struct gpio_mii *gpio_mii = bus->priv;
296 
297 	dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN);
298 	*v = (dm_gpio_get_value(&gpio_mii->mdio_gpio));
299 
300 	return 0;
301 }
302 
303 static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
304 {
305 	struct gpio_mii *gpio_mii = bus->priv;
306 
307 	dm_gpio_set_value(&gpio_mii->mdc_gpio, v);
308 
309 	return 0;
310 }
311 
312 static int mii_delay(struct bb_miiphy_bus *bus)
313 {
314 	udelay(1);
315 
316 	return 0;
317 }
318 
319 struct bb_miiphy_bus bb_miiphy_buses[] = {
320 	{
321 		.name = "ihs0",
322 		.init = mii_mdio_init,
323 		.mdio_active = mii_mdio_active,
324 		.mdio_tristate = mii_mdio_tristate,
325 		.set_mdio = mii_set_mdio,
326 		.get_mdio = mii_get_mdio,
327 		.set_mdc = mii_set_mdc,
328 		.delay = mii_delay,
329 		.priv = &gpio_mii_set[0],
330 	},
331 	{
332 		.name = "ihs1",
333 		.init = mii_mdio_init,
334 		.mdio_active = mii_mdio_active,
335 		.mdio_tristate = mii_mdio_tristate,
336 		.set_mdio = mii_set_mdio,
337 		.get_mdio = mii_get_mdio,
338 		.set_mdc = mii_set_mdc,
339 		.delay = mii_delay,
340 		.priv = &gpio_mii_set[1],
341 	},
342 	{
343 		.name = "ihs2",
344 		.init = mii_mdio_init,
345 		.mdio_active = mii_mdio_active,
346 		.mdio_tristate = mii_mdio_tristate,
347 		.set_mdio = mii_set_mdio,
348 		.get_mdio = mii_get_mdio,
349 		.set_mdc = mii_set_mdc,
350 		.delay = mii_delay,
351 		.priv = &gpio_mii_set[2],
352 	},
353 };
354 
355 int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses);
356