]> git.proxmox.com Git - mirror_edk2.git/blame - Omap35xxPkg/SmbusDxe/Smbus.c
ARM Packages: Removed trailing spaces
[mirror_edk2.git] / Omap35xxPkg / SmbusDxe / Smbus.c
CommitLineData
1e57a462 1/** @file\r
2\r
3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
3402aac7 4\r
1e57a462 5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <Uefi.h>\r
16#include <Omap3530/Omap3530.h>\r
17\r
18#include <Library/DebugLib.h>\r
19#include <Library/IoLib.h>\r
20#include <Library/UefiBootServicesTableLib.h>\r
21\r
22#include <Protocol/SmbusHc.h>\r
23\r
24#define MAX_RETRY 1000\r
25\r
26//\r
27// Internal Functions\r
28//\r
29STATIC\r
30EFI_STATUS\r
31WaitForBusBusy (\r
32 VOID\r
33 )\r
34{\r
35 UINTN Retry = 0;\r
36\r
37 while (++Retry < MAX_RETRY && (MmioRead16(I2C_STAT) & BB) == 0x1);\r
38\r
39 if (Retry == MAX_RETRY) {\r
40 return EFI_TIMEOUT;\r
41 }\r
42\r
43 return EFI_SUCCESS;\r
44}\r
45\r
46STATIC\r
47EFI_STATUS\r
48PollForStatus(\r
49 UINT16 StatusBit\r
50 )\r
51{\r
52 UINTN Retry = 0;\r
53\r
54 while(Retry < MAX_RETRY) {\r
55 if (MmioRead16(I2C_STAT) & StatusBit) {\r
56 //Clear particular status bit from Status register.\r
57 MmioOr16(I2C_STAT, StatusBit);\r
58 break;\r
59 }\r
60 Retry++;\r
61 }\r
62\r
63 if (Retry == MAX_RETRY) {\r
64 return EFI_TIMEOUT;\r
65 }\r
66\r
67 return EFI_SUCCESS;\r
68}\r
69\r
70STATIC\r
71EFI_STATUS\r
72ConfigureI2c (\r
73 VOID\r
74 )\r
75{\r
76 //Program prescaler to obtain 12-MHz clock\r
77 MmioWrite16(I2C_PSC, 0x0000);\r
78\r
3402aac7
RC
79 //Program SCLL and SCLH\r
80 //NOTE: Following values are the register dump after U-Boot code executed.\r
1e57a462 81 //We need to figure out how its calculated based on the I2C functional clock and I2C_PSC.\r
82 MmioWrite16(I2C_SCLL, 0x0035);\r
83 MmioWrite16(I2C_SCLH, 0x0035);\r
84\r
85 //Take the I2C controller out of reset.\r
86 MmioOr16(I2C_CON, I2C_EN);\r
87\r
88 //Initialize the I2C controller.\r
89\r
90 //Set I2C controller in Master mode.\r
91 MmioOr16(I2C_CON, MST);\r
92\r
93 //Enable interrupts for receive/transmit mode.\r
94 MmioOr16(I2C_IE, (XRDY_IE | RRDY_IE | ARDY_IE | NACK_IE));\r
95\r
96 return EFI_SUCCESS;\r
97}\r
98\r
99STATIC\r
100EFI_STATUS\r
101I2CReadOneByte (\r
102 UINT8 *Data\r
103 )\r
104{\r
105 EFI_STATUS Status;\r
106\r
107 //I2C bus status checking\r
108 Status = WaitForBusBusy();\r
109 if (EFI_ERROR(Status)) {\r
110 return Status;\r
111 }\r
112\r
113 //Poll till Receive ready bit is set.\r
114 Status = PollForStatus(RRDY);\r
115 if (EFI_ERROR(Status)) {\r
116 return Status;\r
117 }\r
118\r
119 *Data = MmioRead8(I2C_DATA);\r
120\r
121 return EFI_SUCCESS;\r
122}\r
123\r
124STATIC\r
125EFI_STATUS\r
126I2CWriteOneByte (\r
3402aac7 127 UINT8 Data\r
1e57a462 128 )\r
129{\r
130 EFI_STATUS Status;\r
131\r
132 //I2C bus status checking\r
133 Status = WaitForBusBusy();\r
134 if (EFI_ERROR(Status)) {\r
135 return Status;\r
136 }\r
137\r
138 //Data transfer\r
139 //Poll till Transmit ready bit is set\r
140 Status = PollForStatus(XRDY);\r
141 if (EFI_ERROR(Status)) {\r
142 return Status;\r
143 }\r
144\r
145 MmioWrite8(I2C_DATA, Data);\r
146\r
147 //Wait and check if the NACK is not set.\r
148 gBS->Stall(1000);\r
149 if (MmioRead16(I2C_STAT) & NACK) {\r
150 return EFI_DEVICE_ERROR;\r
151 }\r
152\r
153 return EFI_SUCCESS;\r
154}\r
155\r
156STATIC\r
157EFI_STATUS\r
158SmbusBlockRead (\r
159 OUT UINT8 *Buffer,\r
160 IN UINTN Length\r
161 )\r
162{\r
163 UINTN Index = 0;\r
164 EFI_STATUS Status = EFI_SUCCESS;\r
165\r
166 //Transfer configuration for receiving data.\r
167 MmioWrite16(I2C_CNT, Length);\r
168 //Need stop bit before sending data.\r
169 MmioWrite16(I2C_CON, (I2C_EN | MST | STP | STT));\r
170\r
171 while (Index < Length) {\r
172 //Read a byte\r
173 Status = I2CReadOneByte(&Buffer[Index++]);\r
174 if (EFI_ERROR(Status)) {\r
175 return Status;\r
176 }\r
177 }\r
178\r
179 //Transfer completion\r
180 Status = PollForStatus(ARDY);\r
181 if (EFI_ERROR(Status)) {\r
182 return Status;\r
183 }\r
184\r
185 return Status;\r
186}\r
187\r
188STATIC\r
189EFI_STATUS\r
190SmbusBlockWrite (\r
191 IN UINT8 *Buffer,\r
192 IN UINTN Length\r
193 )\r
194{\r
195 UINTN Index = 0;\r
196 EFI_STATUS Status = EFI_SUCCESS;\r
197\r
198 //Transfer configuration for transmitting data\r
199 MmioWrite16(I2C_CNT, Length);\r
200 MmioWrite16(I2C_CON, (I2C_EN | TRX | MST | STT | STP));\r
201\r
202 while (Index < Length) {\r
203 //Send a byte\r
204 Status = I2CWriteOneByte(Buffer[Index++]);\r
205 if (EFI_ERROR(Status)) {\r
206 return Status;\r
207 }\r
208 }\r
209\r
210 //Transfer completion\r
211 Status = PollForStatus(ARDY);\r
212 if (EFI_ERROR(Status)) {\r
213 return Status;\r
214 }\r
215\r
216 return Status;\r
217}\r
218\r
219//\r
220// Public Functions.\r
221//\r
222EFI_STATUS\r
223EFIAPI\r
224SmbusExecute (\r
225 IN CONST EFI_SMBUS_HC_PROTOCOL *This,\r
226 IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,\r
227 IN CONST EFI_SMBUS_DEVICE_COMMAND Command,\r
228 IN CONST EFI_SMBUS_OPERATION Operation,\r
229 IN CONST BOOLEAN PecCheck,\r
230 IN OUT UINTN *Length,\r
231 IN OUT VOID *Buffer\r
232 )\r
233{\r
234 UINT8 *ByteBuffer = Buffer;\r
235 EFI_STATUS Status = EFI_SUCCESS;\r
236 UINT8 SlaveAddr = (UINT8)(SlaveAddress.SmbusDeviceAddress);\r
237\r
238 if (PecCheck) {\r
239 return EFI_UNSUPPORTED;\r
240 }\r
241\r
242 if ((Operation != EfiSmbusWriteBlock) && (Operation != EfiSmbusReadBlock)) {\r
243 return EFI_UNSUPPORTED;\r
244 }\r
245\r
246 //Set the Slave address.\r
247 MmioWrite16(I2C_SA, SlaveAddr);\r
248\r
249 if (Operation == EfiSmbusReadBlock) {\r
250 Status = SmbusBlockRead(ByteBuffer, *Length);\r
251 } else if (Operation == EfiSmbusWriteBlock) {\r
252 Status = SmbusBlockWrite(ByteBuffer, *Length);\r
253 }\r
254\r
255 return Status;\r
256}\r
257\r
258EFI_STATUS\r
259EFIAPI\r
260SmbusArpDevice (\r
261 IN CONST EFI_SMBUS_HC_PROTOCOL *This,\r
262 IN BOOLEAN ArpAll,\r
263 IN EFI_SMBUS_UDID *SmbusUdid OPTIONAL,\r
264 IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL\r
265 )\r
266{\r
267 return EFI_UNSUPPORTED;\r
268}\r
269\r
270\r
271EFI_STATUS\r
272EFIAPI\r
273SmbusGetArpMap (\r
274 IN CONST EFI_SMBUS_HC_PROTOCOL *This,\r
275 IN OUT UINTN *Length,\r
276 IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap\r
277 )\r
278{\r
279 return EFI_UNSUPPORTED;\r
280}\r
281\r
282\r
283EFI_STATUS\r
284EFIAPI\r
285SmbusNotify (\r
286 IN CONST EFI_SMBUS_HC_PROTOCOL *This,\r
287 IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,\r
288 IN CONST UINTN Data,\r
289 IN CONST EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction\r
290 )\r
291{\r
292 return EFI_UNSUPPORTED;\r
293}\r
294\r
295EFI_SMBUS_HC_PROTOCOL SmbusProtocol =\r
296{\r
297 SmbusExecute,\r
298 SmbusArpDevice,\r
299 SmbusGetArpMap,\r
300 SmbusNotify\r
301};\r
302\r
303EFI_STATUS\r
304InitializeSmbus (\r
305 IN EFI_HANDLE ImageHandle,\r
306 IN EFI_SYSTEM_TABLE *SystemTable\r
307 )\r
308{\r
309 EFI_HANDLE Handle = NULL;\r
310 EFI_STATUS Status;\r
311\r
312 //Configure I2C controller.\r
313 Status = ConfigureI2c();\r
314 if (EFI_ERROR(Status)) {\r
315 DEBUG ((EFI_D_ERROR, "InitializeI2c fails.\n"));\r
316 return Status;\r
317 }\r
318\r
319 // Install the SMBUS interface\r
320 Status = gBS->InstallMultipleProtocolInterfaces(&Handle, &gEfiSmbusHcProtocolGuid, &SmbusProtocol, NULL);\r
321 ASSERT_EFI_ERROR(Status);\r
3402aac7 322\r
1e57a462 323 return Status;\r
324}\r
325\r