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
write_phy_reg_10g(struct memac_mii_access_mem_map * mii_regs,uint8_t phy_addr,uint8_t reg,uint16_t data)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
read_phy_reg_10g(struct memac_mii_access_mem_map * mii_regs,uint8_t phy_addr,uint8_t reg,uint16_t * data)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
write_phy_reg_1g(struct memac_mii_access_mem_map * mii_regs,uint8_t phy_addr,uint8_t reg,uint16_t data)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
read_phy_reg_1g(struct memac_mii_access_mem_map * mii_regs,uint8_t phy_addr,uint8_t reg,uint16_t * data)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 /*****************************************************************************/
fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map * mii_regs,uint8_t phy_addr,uint8_t reg,uint16_t data,enum enet_speed enet_speed)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 /*****************************************************************************/
fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map * mii_regs,uint8_t phy_addr,uint8_t reg,uint16_t * data,enum enet_speed enet_speed)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