2 Base SMBUS library implementation built upon I/O library.
4 Copyright (c) 2006, Intel Corporation<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 Module Name: SmbusLib.h
19 BaseSmBusLibConstructor (
24 return RETURN_SUCCESS
;
28 // BUGBUG: use PCD to retrieve BUS, DEV, FUNC & OFFSET for SMBUS host BAR
30 #define SMBUS_HOST_BUS 0
31 #define SMBUS_HOST_DEV 31
32 #define SMBUS_HOST_FUNC 3
33 #define SMBUS_HOST_SMB_BASE 0x20
36 // Offsets of registers for SMBUS controller
44 #define R_HOST_BLOCK_DB 7
47 #define R_SLV_DATA 0x0a
48 #define R_AUX_STS 0x0c
49 #define R_AUX_CTL 0x0d
50 #define R_SMLINK_PIN_CTL 0x0e
51 #define R_SMBUS_PIN_CTL 0x0f
52 #define R_SLV_STS 0x10
53 #define R_SLV_CMD 0x11
54 #define R_NOTIFY_DADDR 0x14
55 #define R_NOTIFY_DLOW 0x16
56 #define R_NOTIFY_DHIGH 0x17
61 #define B_HST_STS_DS 0x80
62 #define B_HST_STS_INUSE 0x40
63 #define B_HST_STS_SMBALERT 0x20
64 #define B_HST_STS_FAILED 0x10
65 #define B_HST_STS_BUS_ERR 0x08
66 #define B_HST_STS_DEV_ERR 0x04
67 #define B_HST_STS_INTR 0x02
68 #define B_HST_STS_BUSY 0x01
69 #define B_HST_STS_ERR ( B_HST_STS_BUS_ERR | \
72 #define B_HST_STS_ALL ( B_HST_STS_DS | \
74 B_HST_STS_SMBALERT | \
81 #define B_HST_CNT_PEC 0x80
82 #define B_HST_CNT_START 0x40
83 #define B_HST_CNT_LAST_BYTE 0x20
84 #define B_HST_CNT_SMB_CMD 0x1c
85 #define B_HST_CNT_KILL 0x02
86 #define B_HST_CNT_INTREN 0x01
91 #define B_SMB_CMD_QUICK 0
92 #define B_SMB_CMD_BYTE 1
93 #define B_SMB_CMD_BYTE_DATA 2
94 #define B_SMB_CMD_WORD_DATA 3
95 #define B_SMB_CMD_PROCESS_CALL 4
96 #define B_SMB_CMD_BLOCK 5
97 #define B_SMB_CMD_I2C 6
98 #define B_SMB_CMD_BLOCK_PROCESS 7
103 #define B_AUX_CTL_E32B 0x02
104 #define B_AUX_CTL_AAC 0x01
107 // SMBUS Rd/Wr control
109 #define B_SMBUS_READ 1
110 #define B_SMBUS_WRITE 0
115 GetSmBusIOBaseAddress (
121 SmbusBar
= PciRead32 (
129 ASSERT ((SmbusBar
& 0xffff001f) == 1);
130 return (UINT16
)(SmbusBar
& ~1);
142 HstSts
= IoRead8 (SmBusBase
+ R_HST_STS
);
143 if (HstSts
& B_HST_STS_INUSE
) {
148 // BUGBUG: Dead loop may occur here
150 while (HstSts
& B_HST_STS_BUSY
) {
151 ASSERT (HstSts
& B_HST_STS_INUSE
);
152 HstSts
= IoRead8 (SmBusBase
+ R_HST_STS
);
162 IN UINT8 SmBusProtocol
,
163 IN UINT8 SlaveAddress
166 IoWrite8 (SmBusBase
+ R_XMIT_SLVA
, SlaveAddress
);
168 SmBusBase
+ R_HST_CNT
,
169 IoBitFieldWrite8 (SmBusBase
+ R_HST_CNT
, 2, 4, SmBusProtocol
) |
183 while (((HstSts
= IoRead8 (SmBusBase
+ R_HST_STS
)) & B_HST_STS_INTR
) == 0);
194 IoWrite8 (SmBusBase
+ R_HST_STS
, B_HST_STS_ALL
);
201 IN UINT8 SmBusAddress
204 RETURN_STATUS Status
;
207 SmBusBase
= GetSmBusIOBaseAddress ();
208 if (!SmBusAcquire (SmBusBase
)) {
209 return RETURN_TIMEOUT
;
212 SmBusStart (SmBusAddress
, B_SMB_CMD_QUICK
, SmBusAddress
);
213 if (SmBusWait (SmBusAddress
) & B_HST_STS_ERR
) {
214 Status
= RETURN_DEVICE_ERROR
;
216 Status
= RETURN_SUCCESS
;
219 SmBusCleanup (SmBusAddress
);
226 IN UINTN SmBusAddress
,
227 OUT RETURN_STATUS
*Status
230 RETURN_STATUS RetStatus
;
232 ASSERT ((SmBusAddress
& ~0xfe) == 0);
233 RetStatus
= SmBusQuick ((UINT8
)SmBusAddress
| B_SMBUS_READ
);
242 IN UINTN SmBusAddress
,
243 OUT RETURN_STATUS
*Status
246 RETURN_STATUS RetStatus
;
248 ASSERT ((SmBusAddress
& ~0xfe) == 0);
249 RetStatus
= SmBusQuick ((UINT8
)SmBusAddress
| B_SMBUS_WRITE
);
253 return (BOOLEAN
)!RETURN_ERROR (RetStatus
);
260 IN UINTN SmBusAddress
,
262 IN UINT8 SmBusProtocol
,
263 OUT RETURN_STATUS
*Status
266 RETURN_STATUS RetStatus
;
269 if (Status
== NULL
) {
273 SmBusBase
= GetSmBusIOBaseAddress ();
274 if (!SmBusAcquire (SmBusBase
)) {
275 *Status
= RETURN_TIMEOUT
;
279 IoWrite8 (SmBusBase
+ R_HST_CMD
, (UINT8
)(SmBusAddress
>> 8));
280 IoWrite8 (SmBusBase
+ R_HST_D0
, (UINT8
)Value
);
281 IoWrite8 (SmBusBase
+ R_HST_D1
, (UINT8
)(Value
>> 8));
282 if ((INTN
)SmBusAddress
< 0) {
283 IoOr8 (SmBusBase
+ R_HST_CNT
, B_HST_CNT_PEC
);
284 IoOr8 (SmBusBase
+ R_AUX_CTL
, B_AUX_CTL_AAC
);
286 IoAnd8 (SmBusBase
+ R_HST_CNT
, (UINT8
)~B_HST_CNT_PEC
);
287 IoAnd8 (SmBusBase
+ R_AUX_CTL
, (UINT8
)~B_AUX_CTL_AAC
);
290 SmBusStart (SmBusBase
, SmBusProtocol
, (UINT8
)SmBusAddress
);
292 if (SmBusWait (SmBusBase
) & B_HST_STS_ERR
) {
293 *Status
= RETURN_DEVICE_ERROR
;
295 *Status
= RETURN_SUCCESS
;
296 Value
= IoRead8 (SmBusBase
+ R_HST_D0
);
297 Value
|= (UINT16
)IoRead8 (SmBusBase
+ R_HST_D1
) << 8;
300 SmBusCleanup (SmBusBase
);
307 IN UINTN SmBusAddress
,
308 OUT RETURN_STATUS
*Status
311 ASSERT ((SmBusAddress
& ~(0xfe | MAX_BIT
)) == 0);
312 return (UINT8
)SmBusByteWord (
313 SmBusAddress
| B_SMBUS_READ
,
323 IN UINTN SmBusAddress
,
325 OUT RETURN_STATUS
*Status
328 ASSERT ((SmBusAddress
& ~(0xfe | MAX_BIT
)) == 0);
329 return (UINT8
)SmBusByteWord (
330 SmBusAddress
| B_SMBUS_WRITE
,
340 IN UINTN SmBusAddress
,
341 OUT RETURN_STATUS
*Status
344 ASSERT ((SmBusAddress
& ~(0xfffe | MAX_BIT
)) == 0);
345 return (UINT8
)SmBusByteWord (
346 SmBusAddress
| B_SMBUS_READ
,
356 IN UINTN SmBusAddress
,
358 OUT RETURN_STATUS
*Status
361 ASSERT (((UINT32
)SmBusAddress
& ~(0xfffe | MAX_BIT
)) == 0);
362 return (UINT8
)SmBusByteWord (
363 SmBusAddress
| B_SMBUS_WRITE
,
373 IN UINTN SmBusAddress
,
374 OUT RETURN_STATUS
*Status
377 ASSERT ((SmBusAddress
& ~(0xfffe | MAX_BIT
)) == 0);
378 return SmBusByteWord (
379 SmBusAddress
| B_SMBUS_READ
,
389 IN UINTN SmBusAddress
,
391 OUT RETURN_STATUS
*Status
394 ASSERT ((SmBusAddress
& ~(0xfffe | MAX_BIT
)) == 0);
395 return SmBusByteWord (
396 SmBusAddress
| B_SMBUS_WRITE
,
406 IN UINTN SmBusAddress
,
408 OUT RETURN_STATUS
*Status
411 ASSERT ((SmBusAddress
& ~(0xfffe | MAX_BIT
)) == 0);
412 return SmBusByteWord (
413 SmBusAddress
| B_SMBUS_WRITE
,
415 B_SMB_CMD_PROCESS_CALL
,
424 IN UINTN SmBusAddress
,
425 IN UINT8 SmBusProtocol
,
428 OUT RETURN_STATUS
*Status
431 RETURN_STATUS RetStatus
;
436 BytesCount
= (UINT8
)(SmBusAddress
>> 16);
437 ASSERT (BytesCount
<= 32);
439 if (Status
== NULL
) {
443 SmBusBase
= GetSmBusIOBaseAddress ();
444 if (!SmBusAcquire (SmBusBase
)) {
445 *Status
= RETURN_TIMEOUT
;
449 IoWrite8 (SmBusBase
+ R_HST_CMD
, (UINT8
)(SmBusAddress
>> 8));
450 IoWrite8 (SmBusBase
+ R_HST_D0
, (UINT8
)BytesCount
);
451 if ((INTN
)SmBusAddress
< 0) {
452 IoOr8 (SmBusBase
+ R_HST_CNT
, B_HST_CNT_PEC
);
453 IoOr8 (SmBusBase
+ R_AUX_CTL
, B_AUX_CTL_AAC
);
455 IoAnd8 (SmBusBase
+ R_HST_CNT
, (UINT8
)~B_HST_CNT_PEC
);
456 IoAnd8 (SmBusBase
+ R_AUX_CTL
, (UINT8
)~B_AUX_CTL_AAC
);
460 // BUGBUG: E32B bit does not exist in ICH3 or earlier
462 IoOr8 (SmBusBase
+ R_AUX_CTL
, B_AUX_CTL_E32B
);
463 ASSERT (IoRead8 (SmBusBase
+ R_AUX_CTL
) & B_AUX_CTL_E32B
);
464 for (Index
= 0; InBuffer
!= NULL
&& Index
< BytesCount
; Index
++) {
465 IoWrite8 (SmBusBase
+ R_HOST_BLOCK_DB
, ((UINT8
*)InBuffer
)[Index
]);
468 SmBusStart (SmBusBase
, SmBusProtocol
, (UINT8
)SmBusAddress
);
470 if (SmBusWait (SmBusBase
) & B_HST_STS_ERR
) {
471 *Status
= RETURN_DEVICE_ERROR
;
473 *Status
= RETURN_SUCCESS
;
474 BytesCount
= IoRead8 (SmBusBase
+ R_HST_D0
);
475 for (Index
= 0; OutBuffer
!= NULL
&& Index
< BytesCount
; Index
++) {
476 ((UINT8
*)OutBuffer
)[Index
] = IoRead8 (SmBusBase
+ R_HOST_BLOCK_DB
);
480 SmBusCleanup (SmBusBase
);
487 IN UINTN SmBusAddress
,
489 OUT RETURN_STATUS
*Status
492 ASSERT ((SmBusAddress
& ~(0xfffffe | MAX_BIT
)) == 0);
494 SmBusAddress
| B_SMBUS_READ
,
505 IN UINTN SmBusAddress
,
507 OUT RETURN_STATUS
*Status
510 ASSERT ((SmBusAddress
& ~(0xfffffe | MAX_BIT
)) == 0);
512 SmBusAddress
| B_SMBUS_WRITE
,
522 SmBusBlockProcessCall (
523 IN UINTN SmBusAddress
,
526 OUT RETURN_STATUS
*Status
529 ASSERT ((SmBusAddress
& ~(0xfffffe | MAX_BIT
)) == 0);
531 SmBusAddress
| B_SMBUS_WRITE
,
532 B_SMB_CMD_BLOCK_PROCESS
,
542 IN UINTN SmBusAddress
548 IN UINTN SmBusAddress
,
555 IN UINTN SmBusAddress
,