1 /*
2  * Copyright 2008-2013 Freescale Semiconductor Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *     * Redistributions of source code must retain the above copyright
7  *       notice, this list of conditions and the following disclaimer.
8  *     * Redistributions in binary form must reproduce the above copyright
9  *       notice, this list of conditions and the following disclaimer in the
10  *       documentation and/or other materials provided with the distribution.
11  *     * Neither the name of Freescale Semiconductor nor the
12  *       names of its contributors may be used to endorse or promote products
13  *       derived from this software without specific prior written permission.
14  *
15  *
16  * ALTERNATIVELY, this software may be distributed under the terms of the
17  * GNU General Public License ("GPL") as published by the Free Software
18  * Foundation, either version 2 of that License or (at your option) any
19  * later version.
20  *
21  * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 
34 #include "fsl_fman_memac_mii_acc.h"
35 
36 static void write_phy_reg_10g(struct memac_mii_access_mem_map *mii_regs,
37 	uint8_t phy_addr, uint8_t reg, uint16_t data)
38 {
39 	uint32_t                tmp_reg;
40 
41 	tmp_reg = ioread32be(&mii_regs->mdio_cfg);
42 	/* Leave only MDIO_CLK_DIV bits set on */
43 	tmp_reg &= MDIO_CFG_CLK_DIV_MASK;
44 	/* Set maximum MDIO_HOLD value to allow phy to see
45 	change of data signal */
46 	tmp_reg |= MDIO_CFG_HOLD_MASK;
47 	/* Add 10G interface mode */
48 	tmp_reg |= MDIO_CFG_ENC45;
49 	iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
50 
51 	/* Wait for command completion */
52 	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
53 		udelay(1);
54 
55 	/* Specify phy and register to be accessed */
56 	iowrite32be(phy_addr, &mii_regs->mdio_ctrl);
57 	iowrite32be(reg, &mii_regs->mdio_addr);
58 	wmb();
59 
60 	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
61 		udelay(1);
62 
63 	/* Write data */
64 	iowrite32be(data, &mii_regs->mdio_data);
65 	wmb();
66 
67 	/* Wait for write transaction end */
68 	while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
69 		udelay(1);
70 }
71 
72 static uint32_t read_phy_reg_10g(struct memac_mii_access_mem_map *mii_regs,
73 	uint8_t phy_addr, uint8_t reg, uint16_t *data)
74 {
75 	uint32_t                tmp_reg;
76 
77 	tmp_reg = ioread32be(&mii_regs->mdio_cfg);
78 	/* Leave only MDIO_CLK_DIV bits set on */
79 	tmp_reg &= MDIO_CFG_CLK_DIV_MASK;
80 	/* Set maximum MDIO_HOLD value to allow phy to see
81 	change of data signal */
82 	tmp_reg |= MDIO_CFG_HOLD_MASK;
83 	/* Add 10G interface mode */
84 	tmp_reg |= MDIO_CFG_ENC45;
85 	iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
86 
87 	/* Wait for command completion */
88 	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
89 		udelay(1);
90 
91 	/* Specify phy and register to be accessed */
92 	iowrite32be(phy_addr, &mii_regs->mdio_ctrl);
93 	iowrite32be(reg, &mii_regs->mdio_addr);
94 	wmb();
95 
96 	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
97 		udelay(1);
98 
99 	/* Read cycle */
100 	tmp_reg = phy_addr;
101 	tmp_reg |= MDIO_CTL_READ;
102 	iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
103 	wmb();
104 
105 	/* Wait for data to be available */
106 	while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
107 		udelay(1);
108 
109 	*data =  (uint16_t)ioread32be(&mii_regs->mdio_data);
110 
111 	/* Check if there was an error */
112 	return ioread32be(&mii_regs->mdio_cfg);
113 }
114 
115 static void write_phy_reg_1g(struct memac_mii_access_mem_map *mii_regs,
116 	uint8_t phy_addr, uint8_t reg, uint16_t data)
117 {
118 	uint32_t                tmp_reg;
119 
120 	/* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */
121 	tmp_reg = ioread32be(&mii_regs->mdio_cfg);
122 	tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK);
123 	iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
124 
125 	/* Wait for command completion */
126 	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
127 		udelay(1);
128 
129 	/* Write transaction */
130 	tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT);
131 	tmp_reg |= reg;
132 	iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
133 
134 	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
135 		udelay(1);
136 
137 	iowrite32be(data, &mii_regs->mdio_data);
138 
139 	wmb();
140 
141 	/* Wait for write transaction to end */
142 	while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
143 		udelay(1);
144 }
145 
146 static uint32_t read_phy_reg_1g(struct memac_mii_access_mem_map *mii_regs,
147 	uint8_t phy_addr, uint8_t reg, uint16_t *data)
148 {
149 	uint32_t tmp_reg;
150 
151 	/* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */
152 	tmp_reg = ioread32be(&mii_regs->mdio_cfg);
153 	tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK);
154 	iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
155 
156 	/* Wait for command completion */
157 	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
158 		udelay(1);
159 
160 	/* Read transaction */
161 	tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT);
162 	tmp_reg |= reg;
163 	tmp_reg |= MDIO_CTL_READ;
164 	iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
165 
166 	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
167 		udelay(1);
168 
169 	/* Wait for data to be available */
170 	while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
171 		udelay(1);
172 
173 	*data =  (uint16_t)ioread32be(&mii_regs->mdio_data);
174 
175 	/* Check error */
176 	return ioread32be(&mii_regs->mdio_cfg);
177 }
178 
179 /*****************************************************************************/
180 int fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map *mii_regs,
181 	uint8_t phy_addr, uint8_t reg, uint16_t data,
182 	enum enet_speed enet_speed)
183 {
184 	/* Figure out interface type - 10G vs 1G.
185 	In 10G interface both phy_addr and devAddr present. */
186 	if (enet_speed == E_ENET_SPEED_10000)
187 		write_phy_reg_10g(mii_regs, phy_addr, reg, data);
188 	else
189 		write_phy_reg_1g(mii_regs, phy_addr, reg, data);
190 
191 	return 0;
192 }
193 
194 /*****************************************************************************/
195 int fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map *mii_regs,
196 	uint8_t phy_addr, uint8_t reg, uint16_t *data,
197 	enum enet_speed enet_speed)
198 {
199 	uint32_t ans;
200 	/* Figure out interface type - 10G vs 1G.
201 	In 10G interface both phy_addr and devAddr present. */
202 	if (enet_speed == E_ENET_SPEED_10000)
203 		ans = read_phy_reg_10g(mii_regs, phy_addr, reg, data);
204 	else
205 		ans = read_phy_reg_1g(mii_regs, phy_addr, reg, data);
206 
207 	if (ans & MDIO_CFG_READ_ERR)
208 		return -EINVAL;
209 	return 0;
210 }
211 
212 /* ......................................................................... */
213 
214