]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/ncsw/Peripherals/FM/MAC/fman_memac_mii_acc.c
MFV r362990:
[FreeBSD/FreeBSD.git] / sys / contrib / ncsw / Peripherals / FM / MAC / fman_memac_mii_acc.c
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