• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /********************************************************************************
2 Copyright (C) 2016 Marvell International Ltd.
3 
4 Marvell BSD License Option
5 
6 If you received this File from Marvell, you may opt to use, redistribute and/or
7 modify this File under the following licensing terms.
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10 
11   * Redistributions of source code must retain the above copyright notice,
12     this list of conditions and the following disclaimer.
13 
14   * Redistributions in binary form must reproduce the above copyright
15     notice, this list of conditions and the following disclaimer in the
16     documentation and/or other materials provided with the distribution.
17 
18   * Neither the name of Marvell nor the names of its contributors may be
19     used to endorse or promote products derived from this software without
20     specific prior written permission.
21 
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
26 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 *******************************************************************************/
34 
35 #include <Protocol/DriverBinding.h>
36 #include <Protocol/Mdio.h>
37 
38 #include <Library/BaseLib.h>
39 #include <Library/BaseMemoryLib.h>
40 #include <Library/DebugLib.h>
41 #include <Library/IoLib.h>
42 #include <Library/MemoryAllocationLib.h>
43 #include <Library/PcdLib.h>
44 #include <Library/UefiBootServicesTableLib.h>
45 #include <Library/UefiLib.h>
46 
47 #include "MvMdioDxe.h"
48 
49 UINT64 MdioBase = 0;
50 
51 STATIC
52 EFI_STATUS
MdioCheckParam(INTN PhyAddr,INTN RegOff)53 MdioCheckParam (
54  INTN PhyAddr,
55  INTN RegOff
56  )
57 {
58   if (PhyAddr > MVEBU_PHY_ADDR_MASK) {
59     DEBUG((DEBUG_ERROR, "Invalid PHY address %d\n", PhyAddr));
60     return EFI_INVALID_PARAMETER;
61   }
62 
63   if (RegOff > MVEBU_PHY_REG_MASK) {
64     DEBUG((DEBUG_ERROR, "Invalid register offset %d\n", RegOff));
65     return EFI_INVALID_PARAMETER;
66   }
67   return EFI_SUCCESS;
68 }
69 
70 STATIC
71 EFI_STATUS
MdioWaitReady(VOID)72 MdioWaitReady (
73   VOID
74   )
75 {
76   UINT32 Timeout = MVEBU_SMI_TIMEOUT;
77   UINT32 MdioReg;
78 
79   /* wait till the SMI is not busy */
80   do {
81     /* read smi register */
82     MdioReg = MmioRead32(MdioBase);
83     if (Timeout-- == 0) {
84       DEBUG((DEBUG_ERROR, "SMI busy Timeout\n"));
85       return EFI_TIMEOUT;
86     }
87   } while (MdioReg & MVEBU_SMI_BUSY);
88 
89   return EFI_SUCCESS;
90 }
91 
92 STATIC
93 EFI_STATUS
MdioWaitValid(VOID)94 MdioWaitValid (
95   VOID
96   )
97 {
98   UINT32 Timeout = MVEBU_SMI_TIMEOUT;
99   UINT32 MdioReg;
100 
101   /* wait till read value is ready */
102   do {
103     /* read smi register */
104     MdioReg = MmioRead32 (MdioBase);
105     if (Timeout-- == 0) {
106       DEBUG((DEBUG_ERROR, "SMI read ready time-out\n"));
107       return EFI_TIMEOUT;
108     }
109   } while (!(MdioReg & MVEBU_SMI_READ_VALID));
110 
111   return EFI_SUCCESS;
112 }
113 
114 STATIC
115 EFI_STATUS
MdioOperation(IN CONST MARVELL_MDIO_PROTOCOL * This,IN UINT32 PhyAddr,IN UINT32 RegOff,IN BOOLEAN Write,IN OUT UINT32 * Data)116 MdioOperation (
117   IN CONST MARVELL_MDIO_PROTOCOL *This,
118   IN UINT32 PhyAddr,
119   IN UINT32 RegOff,
120   IN BOOLEAN Write,
121   IN OUT UINT32 *Data
122   )
123 {
124   UINT32 MdioReg;
125   EFI_STATUS Status;
126 
127   Status = MdioCheckParam (PhyAddr, RegOff);
128   if (EFI_ERROR(Status)) {
129     DEBUG((DEBUG_ERROR, "MdioDxe: wrong parameters\n"));
130     return Status;
131   }
132 
133   /* wait till the SMI is not busy */
134   Status = MdioWaitReady ();
135   if (EFI_ERROR(Status)) {
136     DEBUG((DEBUG_ERROR, "MdioDxe: MdioWaitReady error\n"));
137     return Status;
138   }
139 
140   /* fill the phy addr and reg offset and write opcode and data */
141   MdioReg = (PhyAddr << MVEBU_SMI_DEV_ADDR_OFFS)
142       | (RegOff << MVEBU_SMI_REG_ADDR_OFFS);
143   if (Write) {
144     MdioReg &= ~MVEBU_SMI_OPCODE_READ;
145     MdioReg |= (*Data << MVEBU_SMI_DATA_OFFS);
146   } else {
147     MdioReg |= MVEBU_SMI_OPCODE_READ;
148   }
149 
150   /* write the smi register */
151   MdioRegWrite32 (MdioReg, MdioBase);
152 
153   /* make sure that the write transaction  is over */
154   Status = Write ? MdioWaitReady () : MdioWaitValid ();
155   if (EFI_ERROR(Status)) {
156     DEBUG((DEBUG_ERROR, "MdioDxe: MdioWaitReady error\n"));
157     return Status;
158   }
159 
160   if (!Write) {
161     *Data = MmioRead32 (MdioBase) & MVEBU_SMI_DATA_MASK;
162   }
163 
164   return EFI_SUCCESS;
165 }
166 
167 STATIC
168 EFI_STATUS
MvMdioRead(IN CONST MARVELL_MDIO_PROTOCOL * This,IN UINT32 PhyAddr,IN UINT32 RegOff,IN UINT32 * Data)169 MvMdioRead (
170   IN CONST MARVELL_MDIO_PROTOCOL *This,
171   IN UINT32 PhyAddr,
172   IN UINT32 RegOff,
173   IN UINT32 *Data
174   )
175 {
176   EFI_STATUS Status;
177 
178   Status = MdioOperation (
179             This,
180             PhyAddr,
181             RegOff,
182             FALSE,
183             Data
184             );
185 
186   return Status;
187 }
188 
189 EFI_STATUS
MvMdioWrite(IN CONST MARVELL_MDIO_PROTOCOL * This,IN UINT32 PhyAddr,IN UINT32 RegOff,IN UINT32 Data)190 MvMdioWrite (
191   IN CONST MARVELL_MDIO_PROTOCOL *This,
192   IN UINT32 PhyAddr,
193   IN UINT32 RegOff,
194   IN UINT32 Data
195   )
196 {
197   return MdioOperation (
198             This,
199             PhyAddr,
200             RegOff,
201             TRUE,
202             &Data
203             );
204 }
205 
206 EFI_STATUS
207 EFIAPI
MvMdioDxeInitialise(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)208 MvMdioDxeInitialise (
209   IN EFI_HANDLE  ImageHandle,
210   IN EFI_SYSTEM_TABLE  *SystemTable
211   )
212 {
213   MARVELL_MDIO_PROTOCOL *Mdio;
214   EFI_STATUS Status;
215   EFI_HANDLE Handle = NULL;
216 
217   Mdio = AllocateZeroPool (sizeof (MARVELL_MDIO_PROTOCOL));
218   Mdio->Read = MvMdioRead;
219   Mdio->Write = MvMdioWrite;
220   MdioBase = PcdGet64 (PcdMdioBaseAddress);
221   if (MdioBase == 0) {
222     DEBUG((DEBUG_ERROR, "MdioDxe: PcdMdioBaseAddress not set\n"));
223     return EFI_INVALID_PARAMETER;
224   }
225   Status = gBS->InstallMultipleProtocolInterfaces (
226                   &Handle,
227                   &gMarvellMdioProtocolGuid, Mdio,
228                   NULL
229                   );
230 
231   if (EFI_ERROR(Status)) {
232     DEBUG((DEBUG_ERROR, "Failed to install interfaces\n"));
233     return Status;
234   }
235 
236   return EFI_SUCCESS;
237 }
238