]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseSmbusLib/SmbusLib.c
Convert to unix format.
[mirror_edk2.git] / MdePkg / Library / BaseSmbusLib / SmbusLib.c
CommitLineData
878ddf1f 1/** @file\r
2 Base SMBUS library implementation built upon I/O library.\r
3\r
4 Copyright (c) 2006, Intel Corporation<BR>\r
5 All rights reserved. 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 Module Name: SmbusLib.h\r
14\r
15**/\r
16\r
17RETURN_STATUS\r
18EFIAPI\r
19BaseSmBusLibConstructor (\r
20 IN VOID *Param1,\r
21 IN VOID *Param2\r
22 )\r
23{\r
24 return RETURN_SUCCESS;\r
25}\r
26\r
27//\r
28// BUGBUG: use PCD to retrieve BUS, DEV, FUNC & OFFSET for SMBUS host BAR\r
29//\r
30#define SMBUS_HOST_BUS 0\r
31#define SMBUS_HOST_DEV 31\r
32#define SMBUS_HOST_FUNC 3\r
33#define SMBUS_HOST_SMB_BASE 0x20\r
34\r
35//\r
36// Offsets of registers for SMBUS controller\r
37//\r
38#define R_HST_STS 0\r
39#define R_HST_CNT 2\r
40#define R_HST_CMD 3\r
41#define R_XMIT_SLVA 4\r
42#define R_HST_D0 5\r
43#define R_HST_D1 6\r
44#define R_HOST_BLOCK_DB 7\r
45#define R_PEC 8\r
46#define R_RCV_SLVA 9\r
47#define R_SLV_DATA 0x0a\r
48#define R_AUX_STS 0x0c\r
49#define R_AUX_CTL 0x0d\r
50#define R_SMLINK_PIN_CTL 0x0e\r
51#define R_SMBUS_PIN_CTL 0x0f\r
52#define R_SLV_STS 0x10\r
53#define R_SLV_CMD 0x11\r
54#define R_NOTIFY_DADDR 0x14\r
55#define R_NOTIFY_DLOW 0x16\r
56#define R_NOTIFY_DHIGH 0x17\r
57\r
58//\r
59// Bits in HST_STS\r
60//\r
61#define B_HST_STS_DS 0x80\r
62#define B_HST_STS_INUSE 0x40\r
63#define B_HST_STS_SMBALERT 0x20\r
64#define B_HST_STS_FAILED 0x10\r
65#define B_HST_STS_BUS_ERR 0x08\r
66#define B_HST_STS_DEV_ERR 0x04\r
67#define B_HST_STS_INTR 0x02\r
68#define B_HST_STS_BUSY 0x01\r
69#define B_HST_STS_ERR ( B_HST_STS_BUS_ERR | \\r
70 B_HST_STS_DEV_ERR | \\r
71 B_HST_STS_FAILED )\r
72#define B_HST_STS_ALL ( B_HST_STS_DS | \\r
73 B_HST_STS_INUSE | \\r
74 B_HST_STS_SMBALERT | \\r
75 B_HST_STS_ERR | \\r
76 B_HST_STS_INTR )\r
77\r
78//\r
79// Bits in HST_CNT\r
80//\r
81#define B_HST_CNT_PEC 0x80\r
82#define B_HST_CNT_START 0x40\r
83#define B_HST_CNT_LAST_BYTE 0x20\r
84#define B_HST_CNT_SMB_CMD 0x1c\r
85#define B_HST_CNT_KILL 0x02\r
86#define B_HST_CNT_INTREN 0x01\r
87\r
88//\r
89// SMBUS Protocols\r
90//\r
91#define B_SMB_CMD_QUICK 0\r
92#define B_SMB_CMD_BYTE 1\r
93#define B_SMB_CMD_BYTE_DATA 2\r
94#define B_SMB_CMD_WORD_DATA 3\r
95#define B_SMB_CMD_PROCESS_CALL 4\r
96#define B_SMB_CMD_BLOCK 5\r
97#define B_SMB_CMD_I2C 6\r
98#define B_SMB_CMD_BLOCK_PROCESS 7\r
99\r
100//\r
101// Bits in AUX_CTL\r
102//\r
103#define B_AUX_CTL_E32B 0x02\r
104#define B_AUX_CTL_AAC 0x01\r
105\r
106//\r
107// SMBUS Rd/Wr control\r
108//\r
109#define B_SMBUS_READ 1\r
110#define B_SMBUS_WRITE 0\r
111\r
112static\r
113UINT16\r
114EFIAPI\r
115GetSmBusIOBaseAddress (\r
116 VOID\r
117 )\r
118{\r
119 UINT32 SmbusBar;\r
120\r
121 SmbusBar = PciRead32 (\r
122 PCI_LIB_ADDRESS (\r
123 SMBUS_HOST_BUS,\r
124 SMBUS_HOST_DEV,\r
125 SMBUS_HOST_FUNC,\r
126 SMBUS_HOST_SMB_BASE\r
127 )\r
128 );\r
129 ASSERT ((SmbusBar & 0xffff001f) == 1);\r
130 return (UINT16)(SmbusBar & ~1);\r
131}\r
132\r
133static\r
134BOOLEAN\r
135EFIAPI\r
136SmBusAcquire (\r
137 IN UINT16 SmBusBase\r
138 )\r
139{\r
140 UINT8 HstSts;\r
141\r
142 HstSts = IoRead8 (SmBusBase + R_HST_STS);\r
143 if (HstSts & B_HST_STS_INUSE) {\r
144 return FALSE;\r
145 }\r
146\r
147 //\r
148 // BUGBUG: Dead loop may occur here\r
149 //\r
150 while (HstSts & B_HST_STS_BUSY) {\r
151 ASSERT (HstSts & B_HST_STS_INUSE);\r
152 HstSts = IoRead8 (SmBusBase + R_HST_STS);\r
153 }\r
154 return TRUE;\r
155}\r
156\r
157static\r
158VOID\r
159EFIAPI\r
160SmBusStart (\r
161 IN UINT16 SmBusBase,\r
162 IN UINT8 SmBusProtocol,\r
163 IN UINT8 SlaveAddress\r
164 )\r
165{\r
166 IoWrite8 (SmBusBase + R_XMIT_SLVA, SlaveAddress);\r
167 IoWrite8 (\r
168 SmBusBase + R_HST_CNT,\r
169 IoBitFieldWrite8 (SmBusBase + R_HST_CNT, 2, 4, SmBusProtocol) |\r
170 B_HST_CNT_START\r
171 );\r
172}\r
173\r
174static\r
175UINT8\r
176EFIAPI\r
177SmBusWait (\r
178 IN UINT16 SmBusBase\r
179 )\r
180{\r
181 UINT8 HstSts;\r
182\r
183 while (((HstSts = IoRead8 (SmBusBase + R_HST_STS)) & B_HST_STS_INTR) == 0);\r
184 return HstSts;\r
185}\r
186\r
187static\r
188VOID\r
189EFIAPI\r
190SmBusCleanup (\r
191 IN UINT16 SmBusBase\r
192 )\r
193{\r
194 IoWrite8 (SmBusBase + R_HST_STS, B_HST_STS_ALL);\r
195}\r
196\r
197static\r
198RETURN_STATUS\r
199EFIAPI\r
200SmBusQuick (\r
201 IN UINT8 SmBusAddress\r
202 )\r
203{\r
204 RETURN_STATUS Status;\r
205 UINT16 SmBusBase;\r
206\r
207 SmBusBase = GetSmBusIOBaseAddress ();\r
208 if (!SmBusAcquire (SmBusBase)) {\r
209 return RETURN_TIMEOUT;\r
210 }\r
211\r
212 SmBusStart (SmBusAddress, B_SMB_CMD_QUICK, SmBusAddress);\r
213 if (SmBusWait (SmBusAddress) & B_HST_STS_ERR) {\r
214 Status = RETURN_DEVICE_ERROR;\r
215 } else {\r
216 Status = RETURN_SUCCESS;\r
217 }\r
218\r
219 SmBusCleanup (SmBusAddress);\r
220 return Status;\r
221}\r
222\r
223VOID\r
224EFIAPI\r
225SmBusQuickRead (\r
226 IN UINTN SmBusAddress,\r
227 OUT RETURN_STATUS *Status\r
228 )\r
229{\r
230 RETURN_STATUS RetStatus;\r
231\r
232 ASSERT ((SmBusAddress & ~0xfe) == 0);\r
233 RetStatus = SmBusQuick ((UINT8)SmBusAddress | B_SMBUS_READ);\r
234 if (Status) {\r
235 *Status = RetStatus;\r
236 }\r
237}\r
238\r
239BOOLEAN\r
240EFIAPI\r
241SmBusQuickWrite (\r
242 IN UINTN SmBusAddress,\r
243 OUT RETURN_STATUS *Status\r
244 )\r
245{\r
246 RETURN_STATUS RetStatus;\r
247\r
248 ASSERT ((SmBusAddress & ~0xfe) == 0);\r
249 RetStatus = SmBusQuick ((UINT8)SmBusAddress | B_SMBUS_WRITE);\r
250 if (Status) {\r
251 *Status = RetStatus;\r
252 }\r
253 return (BOOLEAN)!RETURN_ERROR (RetStatus);\r
254}\r
255\r
256static\r
257UINT16\r
258EFIAPI\r
259SmBusByteWord (\r
260 IN UINTN SmBusAddress,\r
261 IN UINT16 Value,\r
262 IN UINT8 SmBusProtocol,\r
263 OUT RETURN_STATUS *Status\r
264 )\r
265{\r
266 RETURN_STATUS RetStatus;\r
267 UINT16 SmBusBase;\r
268\r
269 if (Status == NULL) {\r
270 Status = &RetStatus;\r
271 }\r
272\r
273 SmBusBase = GetSmBusIOBaseAddress ();\r
274 if (!SmBusAcquire (SmBusBase)) {\r
275 *Status = RETURN_TIMEOUT;\r
276 return Value;\r
277 }\r
278\r
279 IoWrite8 (SmBusBase + R_HST_CMD, (UINT8)(SmBusAddress >> 8));\r
280 IoWrite8 (SmBusBase + R_HST_D0, (UINT8)Value);\r
281 IoWrite8 (SmBusBase + R_HST_D1, (UINT8)(Value >> 8));\r
282 if ((INTN)SmBusAddress < 0) {\r
283 IoOr8 (SmBusBase + R_HST_CNT, B_HST_CNT_PEC);\r
284 IoOr8 (SmBusBase + R_AUX_CTL, B_AUX_CTL_AAC);\r
285 } else {\r
286 IoAnd8 (SmBusBase + R_HST_CNT, (UINT8)~B_HST_CNT_PEC);\r
287 IoAnd8 (SmBusBase + R_AUX_CTL, (UINT8)~B_AUX_CTL_AAC);\r
288 }\r
289\r
290 SmBusStart (SmBusBase, SmBusProtocol, (UINT8)SmBusAddress);\r
291\r
292 if (SmBusWait (SmBusBase) & B_HST_STS_ERR) {\r
293 *Status = RETURN_DEVICE_ERROR;\r
294 } else {\r
295 *Status = RETURN_SUCCESS;\r
296 Value = IoRead8 (SmBusBase + R_HST_D0);\r
297 Value |= (UINT16)IoRead8 (SmBusBase + R_HST_D1) << 8;\r
298 }\r
299\r
300 SmBusCleanup (SmBusBase);\r
301 return Value;\r
302}\r
303\r
304UINT8\r
305EFIAPI\r
306SmBusReceiveByte (\r
307 IN UINTN SmBusAddress,\r
308 OUT RETURN_STATUS *Status\r
309 )\r
310{\r
311 ASSERT ((SmBusAddress & ~(0xfe | MAX_BIT)) == 0);\r
312 return (UINT8)SmBusByteWord (\r
313 SmBusAddress | B_SMBUS_READ,\r
314 0,\r
315 B_SMB_CMD_BYTE,\r
316 Status\r
317 );\r
318}\r
319\r
320UINT8\r
321EFIAPI\r
322SmBusSendByte (\r
323 IN UINTN SmBusAddress,\r
324 IN UINT8 Value,\r
325 OUT RETURN_STATUS *Status\r
326 )\r
327{\r
328 ASSERT ((SmBusAddress & ~(0xfe | MAX_BIT)) == 0);\r
329 return (UINT8)SmBusByteWord (\r
330 SmBusAddress | B_SMBUS_WRITE,\r
331 Value,\r
332 B_SMB_CMD_BYTE,\r
333 Status\r
334 );\r
335}\r
336\r
337UINT8\r
338EFIAPI\r
339SmBusReadDataByte (\r
340 IN UINTN SmBusAddress,\r
341 OUT RETURN_STATUS *Status\r
342 )\r
343{\r
344 ASSERT ((SmBusAddress & ~(0xfffe | MAX_BIT)) == 0);\r
345 return (UINT8)SmBusByteWord (\r
346 SmBusAddress | B_SMBUS_READ,\r
347 0,\r
348 B_SMB_CMD_BYTE_DATA,\r
349 Status\r
350 );\r
351}\r
352\r
353UINT8\r
354EFIAPI\r
355SmBusWriteDataByte (\r
356 IN UINTN SmBusAddress,\r
357 IN UINT8 Value,\r
358 OUT RETURN_STATUS *Status\r
359 )\r
360{\r
361 ASSERT (((UINT32)SmBusAddress & ~(0xfffe | MAX_BIT)) == 0);\r
362 return (UINT8)SmBusByteWord (\r
363 SmBusAddress | B_SMBUS_WRITE,\r
364 Value,\r
365 B_SMB_CMD_BYTE_DATA,\r
366 Status\r
367 );\r
368}\r
369\r
370UINT16\r
371EFIAPI\r
372SmBusReadDataWord (\r
373 IN UINTN SmBusAddress,\r
374 OUT RETURN_STATUS *Status\r
375 )\r
376{\r
377 ASSERT ((SmBusAddress & ~(0xfffe | MAX_BIT)) == 0);\r
378 return SmBusByteWord (\r
379 SmBusAddress | B_SMBUS_READ,\r
380 0,\r
381 B_SMB_CMD_WORD_DATA,\r
382 Status\r
383 );\r
384}\r
385\r
386UINT16\r
387EFIAPI\r
388SmBusWriteDataWord (\r
389 IN UINTN SmBusAddress,\r
390 IN UINT16 Value,\r
391 OUT RETURN_STATUS *Status\r
392 )\r
393{\r
394 ASSERT ((SmBusAddress & ~(0xfffe | MAX_BIT)) == 0);\r
395 return SmBusByteWord (\r
396 SmBusAddress | B_SMBUS_WRITE,\r
397 Value,\r
398 B_SMB_CMD_WORD_DATA,\r
399 Status\r
400 );\r
401}\r
402\r
403UINT16\r
404EFIAPI\r
405SmBusProcessCall (\r
406 IN UINTN SmBusAddress,\r
407 IN UINT16 Value,\r
408 OUT RETURN_STATUS *Status\r
409 )\r
410{\r
411 ASSERT ((SmBusAddress & ~(0xfffe | MAX_BIT)) == 0);\r
412 return SmBusByteWord (\r
413 SmBusAddress | B_SMBUS_WRITE,\r
414 Value,\r
415 B_SMB_CMD_PROCESS_CALL,\r
416 Status\r
417 );\r
418}\r
419\r
420static\r
421UINTN\r
422EFIAPI\r
423SmBusBlock (\r
424 IN UINTN SmBusAddress,\r
425 IN UINT8 SmBusProtocol,\r
426 IN VOID *InBuffer,\r
427 OUT VOID *OutBuffer,\r
428 OUT RETURN_STATUS *Status\r
429 )\r
430{\r
431 RETURN_STATUS RetStatus;\r
432 UINT16 SmBusBase;\r
433 UINTN Index;\r
434 UINTN BytesCount;\r
435\r
436 BytesCount = (UINT8)(SmBusAddress >> 16);\r
437 ASSERT (BytesCount <= 32);\r
438\r
439 if (Status == NULL) {\r
440 Status = &RetStatus;\r
441 }\r
442\r
443 SmBusBase = GetSmBusIOBaseAddress ();\r
444 if (!SmBusAcquire (SmBusBase)) {\r
445 *Status = RETURN_TIMEOUT;\r
446 return 0;\r
447 }\r
448\r
449 IoWrite8 (SmBusBase + R_HST_CMD, (UINT8)(SmBusAddress >> 8));\r
450 IoWrite8 (SmBusBase + R_HST_D0, (UINT8)BytesCount);\r
451 if ((INTN)SmBusAddress < 0) {\r
452 IoOr8 (SmBusBase + R_HST_CNT, B_HST_CNT_PEC);\r
453 IoOr8 (SmBusBase + R_AUX_CTL, B_AUX_CTL_AAC);\r
454 } else {\r
455 IoAnd8 (SmBusBase + R_HST_CNT, (UINT8)~B_HST_CNT_PEC);\r
456 IoAnd8 (SmBusBase + R_AUX_CTL, (UINT8)~B_AUX_CTL_AAC);\r
457 }\r
458\r
459 //\r
460 // BUGBUG: E32B bit does not exist in ICH3 or earlier\r
461 //\r
462 IoOr8 (SmBusBase + R_AUX_CTL, B_AUX_CTL_E32B);\r
463 ASSERT (IoRead8 (SmBusBase + R_AUX_CTL) & B_AUX_CTL_E32B);\r
464 for (Index = 0; InBuffer != NULL && Index < BytesCount; Index++) {\r
465 IoWrite8 (SmBusBase + R_HOST_BLOCK_DB, ((UINT8*)InBuffer)[Index]);\r
466 }\r
467\r
468 SmBusStart (SmBusBase, SmBusProtocol, (UINT8)SmBusAddress);\r
469\r
470 if (SmBusWait (SmBusBase) & B_HST_STS_ERR) {\r
471 *Status = RETURN_DEVICE_ERROR;\r
472 } else {\r
473 *Status = RETURN_SUCCESS;\r
474 BytesCount = IoRead8 (SmBusBase + R_HST_D0);\r
475 for (Index = 0; OutBuffer != NULL && Index < BytesCount; Index++) {\r
476 ((UINT8*)OutBuffer)[Index] = IoRead8 (SmBusBase + R_HOST_BLOCK_DB);\r
477 }\r
478 }\r
479\r
480 SmBusCleanup (SmBusBase);\r
481 return BytesCount;\r
482}\r
483\r
484UINTN\r
485EFIAPI\r
486SmBusReadBlock (\r
487 IN UINTN SmBusAddress,\r
488 OUT VOID *Buffer,\r
489 OUT RETURN_STATUS *Status\r
490 )\r
491{\r
492 ASSERT ((SmBusAddress & ~(0xfffffe | MAX_BIT)) == 0);\r
493 return SmBusBlock (\r
494 SmBusAddress | B_SMBUS_READ,\r
495 B_SMB_CMD_BLOCK,\r
496 NULL,\r
497 Buffer,\r
498 Status\r
499 );\r
500}\r
501\r
502UINTN\r
503EFIAPI\r
504SmBusWriteBlock (\r
505 IN UINTN SmBusAddress,\r
506 OUT VOID *Buffer,\r
507 OUT RETURN_STATUS *Status\r
508 )\r
509{\r
510 ASSERT ((SmBusAddress & ~(0xfffffe | MAX_BIT)) == 0);\r
511 return SmBusBlock (\r
512 SmBusAddress | B_SMBUS_WRITE,\r
513 B_SMB_CMD_BLOCK,\r
514 Buffer,\r
515 NULL,\r
516 Status\r
517 );\r
518}\r
519\r
520UINTN\r
521EFIAPI\r
522SmBusBlockProcessCall (\r
523 IN UINTN SmBusAddress,\r
524 IN VOID *OutBuffer,\r
525 OUT VOID *InBuffer,\r
526 OUT RETURN_STATUS *Status\r
527 )\r
528{\r
529 ASSERT ((SmBusAddress & ~(0xfffffe | MAX_BIT)) == 0);\r
530 return SmBusBlock (\r
531 SmBusAddress | B_SMBUS_WRITE,\r
532 B_SMB_CMD_BLOCK_PROCESS,\r
533 OutBuffer,\r
534 InBuffer,\r
535 Status\r
536 );\r
537}\r
538\r
539RETURN_STATUS\r
540EFIAPI\r
541SmBusArpAll (\r
542 IN UINTN SmBusAddress\r
543 );\r
544\r
545RETURN_STATUS\r
546EFIAPI\r
547SmBusArpDevice (\r
548 IN UINTN SmBusAddress,\r
549 IN CONST GUID *Uuid\r
550 );\r
551\r
552RETURN_STATUS\r
553EFIAPI\r
554SmBusGetUuid (\r
555 IN UINTN SmBusAddress,\r
556 OUT GUID *Uuid\r
557 );\r