xref: /openbmc/u-boot/drivers/net/fm/memac_phy.c (revision 00caae6d)
1 /*
2  * Copyright 2012 Freescale Semiconductor, Inc.
3  *	Andy Fleming <afleming@gmail.com>
4  *	Roy Zang <tie-fei.zang@freescale.com>
5  *
6  * SPDX-License-Identifier:	GPL-2.0+
7  * Some part is taken from tsec.c
8  */
9 #include <common.h>
10 #include <miiphy.h>
11 #include <phy.h>
12 #include <asm/io.h>
13 #include <fsl_memac.h>
14 #include <fm_eth.h>
15 
16 #ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
17 #define memac_out_32(a, v)	out_le32(a, v)
18 #define memac_clrbits_32(a, v)	clrbits_le32(a, v)
19 #define memac_setbits_32(a, v)	setbits_le32(a, v)
20 #else
21 #define memac_out_32(a, v)	out_be32(a, v)
22 #define memac_clrbits_32(a, v)	clrbits_be32(a, v)
23 #define memac_setbits_32(a, v)	setbits_be32(a, v)
24 #endif
25 
26 static u32 memac_in_32(u32 *reg)
27 {
28 #ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
29 	return in_le32(reg);
30 #else
31 	return in_be32(reg);
32 #endif
33 }
34 
35 /*
36  * Write value to the PHY for this device to the register at regnum, waiting
37  * until the write is done before it returns.  All PHY configuration has to be
38  * done through the TSEC1 MIIM regs
39  */
40 int memac_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
41 			int regnum, u16 value)
42 {
43 	u32 mdio_ctl;
44 	struct memac_mdio_controller *regs = bus->priv;
45 	u32 c45 = 1; /* Default to 10G interface */
46 
47 	if (dev_addr == MDIO_DEVAD_NONE) {
48 		c45 = 0; /* clause 22 */
49 		dev_addr = regnum & 0x1f;
50 		memac_clrbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
51 	} else
52 		memac_setbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
53 
54 	/* Wait till the bus is free */
55 	while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
56 		;
57 
58 	/* Set the port and dev addr */
59 	mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
60 	memac_out_32(&regs->mdio_ctl, mdio_ctl);
61 
62 	/* Set the register address */
63 	if (c45)
64 		memac_out_32(&regs->mdio_addr, regnum & 0xffff);
65 
66 	/* Wait till the bus is free */
67 	while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
68 		;
69 
70 	/* Write the value to the register */
71 	memac_out_32(&regs->mdio_data, MDIO_DATA(value));
72 
73 	/* Wait till the MDIO write is complete */
74 	while ((memac_in_32(&regs->mdio_data)) & MDIO_DATA_BSY)
75 		;
76 
77 	return 0;
78 }
79 
80 /*
81  * Reads from register regnum in the PHY for device dev, returning the value.
82  * Clears miimcom first.  All PHY configuration has to be done through the
83  * TSEC1 MIIM regs
84  */
85 int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
86 			int regnum)
87 {
88 	u32 mdio_ctl;
89 	struct memac_mdio_controller *regs = bus->priv;
90 	u32 c45 = 1;
91 
92 	if (dev_addr == MDIO_DEVAD_NONE) {
93 		if (!strcmp(bus->name, DEFAULT_FM_TGEC_MDIO_NAME))
94 			return 0xffff;
95 		c45 = 0; /* clause 22 */
96 		dev_addr = regnum & 0x1f;
97 		memac_clrbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
98 	} else
99 		memac_setbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
100 
101 	/* Wait till the bus is free */
102 	while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
103 		;
104 
105 	/* Set the Port and Device Addrs */
106 	mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
107 	memac_out_32(&regs->mdio_ctl, mdio_ctl);
108 
109 	/* Set the register address */
110 	if (c45)
111 		memac_out_32(&regs->mdio_addr, regnum & 0xffff);
112 
113 	/* Wait till the bus is free */
114 	while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
115 		;
116 
117 	/* Initiate the read */
118 	mdio_ctl |= MDIO_CTL_READ;
119 	memac_out_32(&regs->mdio_ctl, mdio_ctl);
120 
121 	/* Wait till the MDIO write is complete */
122 	while ((memac_in_32(&regs->mdio_data)) & MDIO_DATA_BSY)
123 		;
124 
125 	/* Return all Fs if nothing was there */
126 	if (memac_in_32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
127 		return 0xffff;
128 
129 	return memac_in_32(&regs->mdio_data) & 0xffff;
130 }
131 
132 int memac_mdio_reset(struct mii_dev *bus)
133 {
134 	return 0;
135 }
136 
137 int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info)
138 {
139 	struct mii_dev *bus = mdio_alloc();
140 
141 	if (!bus) {
142 		printf("Failed to allocate FM TGEC MDIO bus\n");
143 		return -1;
144 	}
145 
146 	bus->read = memac_mdio_read;
147 	bus->write = memac_mdio_write;
148 	bus->reset = memac_mdio_reset;
149 	strcpy(bus->name, info->name);
150 
151 	bus->priv = info->regs;
152 
153 	/*
154 	 * On some platforms like B4860, default value of MDIO_CLK_DIV bits
155 	 * in mdio_stat(mdio_cfg) register generates MDIO clock too high
156 	 * (much higher than 2.5MHz), violating the IEEE specs.
157 	 * On other platforms like T1040, default value of MDIO_CLK_DIV bits
158 	 * is zero, so MDIO clock is disabled.
159 	 * So, for proper functioning of MDIO, MDIO_CLK_DIV bits needs to
160 	 * be properly initialized.
161 	 * NEG bit default should be '1' as per FMAN-v3 RM, but on platform
162 	 * like T2080QDS, this bit default is '0', which leads to MDIO failure
163 	 * on XAUI PHY, so set this bit definitely.
164 	 */
165 	memac_setbits_32(
166 		&((struct memac_mdio_controller *)info->regs)->mdio_stat,
167 		MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG);
168 
169 	return mdio_register(bus);
170 }
171