]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/ncsw/Peripherals/FM/MAC/fman_dtsec_mii_acc.c
Update edk2 headers to stable202005
[FreeBSD/FreeBSD.git] / sys / contrib / ncsw / Peripherals / FM / MAC / fman_dtsec_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 "common/general.h"
35 #include "fsl_fman_dtsec_mii_acc.h"
36
37
38 /**
39  * dtsec_mii_get_div() - calculates the value of the dtsec mii divider
40  * @dtsec_freq:         dtsec clock frequency (in Mhz)
41  *
42  * This function calculates the dtsec mii clock divider that determines
43  * the MII MDC clock. MII MDC clock will be set to work in the range
44  * of 1.5 to 2.5Mhz
45  * The output of this function is the value of MIIMCFG[MgmtClk] which
46  * implicitly determines the divider value.
47  * Note: the dTSEC system clock is equal to 1/2 of the FMan clock.
48  *
49  * The table below which reflects dtsec_mii_get_div() functionality
50  * shows the relations among dtsec_freq, MgmtClk, actual divider
51  * and the MII frequency:
52  *
53  * dtsec freq   MgmtClk     div        MII freq Mhz
54  * [0.....80]     1      (1/4)(1/8)    [0   to 2.5]
55  * [81...120]     2      (1/6)(1/8)    [1.6 to 2.5]
56  * [121..160]     3      (1/8)(1/8)    [1.8 to 2.5]
57  * [161..200]     4      (1/10)(1/8)   [2.0 to 2.5]
58  * [201..280]     5      (1/14)(1/8)   [1.8 to 2.5]
59  * [281..400]     6      (1/20)(1/8)   [1.1 to 2.5]
60  * [401..560]     7      (1/28)(1/8)   [1.8 to 2.5]
61  * [560..frq]     7      (1/28)(1/8)   [frq/224]
62  *
63  * Returns: the MIIMCFG[MgmtClk] appropriate value
64  */
65
66 static uint8_t dtsec_mii_get_div(uint16_t dtsec_freq)
67 {
68         uint16_t mgmt_clk;
69
70         if (dtsec_freq < 80) mgmt_clk = 1;
71         else if (dtsec_freq < 120) mgmt_clk = 2;
72         else if (dtsec_freq < 160) mgmt_clk = 3;
73         else if (dtsec_freq < 200) mgmt_clk = 4;
74         else if (dtsec_freq < 280) mgmt_clk = 5;
75         else if (dtsec_freq < 400) mgmt_clk = 6;
76         else mgmt_clk = 7;
77
78         return (uint8_t)mgmt_clk;
79 }
80
81 void fman_dtsec_mii_reset(struct dtsec_mii_reg *regs)
82 {
83         /* Reset the management interface */
84         iowrite32be(ioread32be(&regs->miimcfg) | MIIMCFG_RESET_MGMT,
85                         &regs->miimcfg);
86         iowrite32be(ioread32be(&regs->miimcfg) & ~MIIMCFG_RESET_MGMT,
87                         &regs->miimcfg);
88 }
89
90
91 int fman_dtsec_mii_write_reg(struct dtsec_mii_reg *regs, uint8_t addr,
92                 uint8_t reg, uint16_t data, uint16_t dtsec_freq)
93 {
94         uint32_t        tmp;
95
96         /* Setup the MII Mgmt clock speed */
97         iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), &regs->miimcfg);
98         wmb();
99
100         /* Stop the MII management read cycle */
101         iowrite32be(0, &regs->miimcom);
102         /* Dummy read to make sure MIIMCOM is written */
103         tmp = ioread32be(&regs->miimcom);
104         wmb();
105
106         /* Setting up MII Management Address Register */
107         tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg);
108         iowrite32be(tmp, &regs->miimadd);
109         wmb();
110
111         /* Setting up MII Management Control Register with data */
112         iowrite32be((uint32_t)data, &regs->miimcon);
113         /* Dummy read to make sure MIIMCON is written */
114         tmp = ioread32be(&regs->miimcon);
115         wmb();
116
117         /* Wait until MII management write is complete */
118         /* todo: a timeout could be useful here */
119         while ((ioread32be(&regs->miimind)) & MIIMIND_BUSY)
120                 /* busy wait */;
121
122         return 0;
123 }
124
125 int fman_dtsec_mii_read_reg(struct dtsec_mii_reg *regs, uint8_t  addr,
126                 uint8_t reg, uint16_t *data, uint16_t dtsec_freq)
127 {
128         uint32_t        tmp;
129
130         /* Setup the MII Mgmt clock speed */
131         iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), &regs->miimcfg);
132         wmb();
133
134         /* Setting up the MII Management Address Register */
135         tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg);
136         iowrite32be(tmp, &regs->miimadd);
137         wmb();
138
139         /* Perform an MII management read cycle */
140         iowrite32be(MIIMCOM_READ_CYCLE, &regs->miimcom);
141         /* Dummy read to make sure MIIMCOM is written */
142         tmp = ioread32be(&regs->miimcom);
143         wmb();
144
145         /* Wait until MII management read is complete */
146         /* todo: a timeout could be useful here */
147         while ((ioread32be(&regs->miimind)) & MIIMIND_BUSY)
148                 /* busy wait */;
149
150         /* Read MII management status  */
151         *data = (uint16_t)ioread32be(&regs->miimstat);
152         wmb();
153
154         iowrite32be(0, &regs->miimcom);
155         /* Dummy read to make sure MIIMCOM is written */
156         tmp = ioread32be(&regs->miimcom);
157
158         if (*data == 0xffff)
159                 return -ENXIO;
160
161         return 0;
162 }
163