]> git.proxmox.com Git - mirror_edk2.git/blob - Vlv2TbltDevicePkg/Library/SmbusLib/SmbusLib.c
Vlv2TbltDevicePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / Vlv2TbltDevicePkg / Library / SmbusLib / SmbusLib.c
1 /** @file
2 Intel ICH9 SMBUS library implementation built upon I/O library.
3
4 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8
9
10 **/
11
12 #include "CommonHeader.h"
13
14 /**
15 Gets Io port base address of Smbus Host Controller.
16
17 This internal function depends on a feature flag named PcdIchSmbusFixedIoPortBaseAddress
18 to retrieve Smbus Io port base. If that feature flag is true, it will get Smbus Io port base
19 address from a preset Pcd entry named PcdIchSmbusIoPortBaseAddress; otherwise, it will always
20 read Pci configuration space to get that value in each Smbus bus transaction.
21
22 @return The Io port base address of Smbus host controller.
23
24 **/
25 UINTN
26 InternalGetSmbusIoPortBaseAddress (
27 VOID
28 )
29 {
30 UINTN IoPortBaseAddress;
31
32 IoPortBaseAddress = (UINTN) MmioRead32 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SMBUS, PCI_FUNCTION_NUMBER_PCH_SMBUS, R_PCH_SMBUS_BASE)) & B_PCH_SMBUS_BASE_BAR;
33
34 //
35 // Make sure that the IO port base address has been properly set.
36 //
37 ASSERT (IoPortBaseAddress != 0);
38
39 return IoPortBaseAddress;
40 }
41
42 /**
43 Acquires the ownership of SMBUS.
44
45 This internal function reads the host state register.
46 If the SMBUS is not available, RETURN_TIMEOUT is returned;
47 Otherwise, it performs some basic initializations and returns
48 RETURN_SUCCESS.
49
50 @param IoPortBaseAddress The Io port base address of Smbus Host controller.
51
52 @retval RETURN_SUCCESS The SMBUS command was executed successfully.
53 @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command.
54
55 **/
56 RETURN_STATUS
57 InternalSmBusAcquire (
58 UINTN IoPortBaseAddress
59 )
60 {
61 UINT8 HostStatus;
62
63 HostStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS);
64 if ((HostStatus & B_PCH_SMBUS_IUS) != 0) {
65 return RETURN_TIMEOUT;
66 } else if ((HostStatus & B_PCH_SMBUS_HBSY) != 0) {
67 //
68 // Clear host status register and exit.
69 //
70 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
71 return RETURN_TIMEOUT;
72 }
73 //
74 // Clear out any odd status information (Will Not Clear In Use).
75 //
76 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, HostStatus);
77
78 return RETURN_SUCCESS;
79 }
80
81 /**
82 Starts the SMBUS transaction and waits until the end.
83
84 This internal function start the SMBUS transaction and waits until the transaction
85 of SMBUS is over by polling the INTR bit of Host status register.
86 If the SMBUS is not available, RETURN_TIMEOUT is returned;
87 Otherwise, it performs some basic initializations and returns
88 RETURN_SUCCESS.
89
90 @param IoPortBaseAddress The Io port base address of Smbus Host controller.
91 @param HostControl The Host control command to start SMBUS transaction.
92
93 @retval RETURN_SUCCESS The SMBUS command was executed successfully.
94 @retval RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect).
95 @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected
96 in the Host Status Register bit. Device errors are
97 a result of a transaction collision, illegal command field,
98 unclaimed cycle (host initiated), or bus errors (collisions).
99
100 **/
101 RETURN_STATUS
102 InternalSmBusStart (
103 IN UINTN IoPortBaseAddress,
104 IN UINT8 HostControl
105 )
106 {
107 UINT8 HostStatus;
108 UINT8 AuxiliaryStatus;
109
110 //
111 // Set Host Control Register (Initiate Operation, Interrupt disabled).
112 //
113 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCTL, (UINT8)(HostControl + B_PCH_SMBUS_START));
114
115 do {
116 //
117 // Poll INTR bit of Host Status Register.
118 //
119 HostStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS);
120 } while ((HostStatus & (B_PCH_SMBUS_INTR | B_PCH_SMBUS_ERRORS | B_PCH_SMBUS_BYTE_DONE_STS)) == 0);
121
122 if ((HostStatus & B_PCH_SMBUS_ERRORS) == 0) {
123 return RETURN_SUCCESS;
124 }
125
126 //
127 // Clear error bits of Host Status Register.
128 //
129 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_ERRORS);
130
131 //
132 // Read Auxiliary Status Register to judge CRC error.
133 //
134 AuxiliaryStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS);
135 if ((AuxiliaryStatus & B_PCH_SMBUS_CRCE) != 0) {
136 return RETURN_CRC_ERROR;
137 }
138
139 return RETURN_DEVICE_ERROR;
140 }
141
142 /**
143 Executes an SMBUS quick, byte or word command.
144
145 This internal function executes an SMBUS quick, byte or word commond.
146 If Status is not NULL, then the status of the executed command is returned in Status.
147
148 @param HostControl The value of Host Control Register to set.
149 @param SmBusAddress Address that encodes the SMBUS Slave Address,
150 SMBUS Command, SMBUS Data Length, and PEC.
151 @param Value The byte/word write to the SMBUS.
152 @param Status Return status for the executed command.
153 This is an optional parameter and may be NULL.
154
155 @return The byte/word read from the SMBUS.
156
157 **/
158 UINT16
159 InternalSmBusNonBlock (
160 IN UINT8 HostControl,
161 IN UINTN SmBusAddress,
162 IN UINT16 Value,
163 OUT RETURN_STATUS *Status
164 )
165 {
166 RETURN_STATUS ReturnStatus;
167 UINTN IoPortBaseAddress;
168 UINT8 AuxiliaryControl;
169
170 IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
171
172 //
173 // Try to acquire the ownership of ICH SMBUS.
174 //
175 ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
176 if (RETURN_ERROR (ReturnStatus)) {
177 goto Done;
178 }
179
180 //
181 // Set the appropriate Host Control Register and auxiliary Control Register.
182 //
183 AuxiliaryControl = 0;
184 if (SMBUS_LIB_PEC (SmBusAddress)) {
185 AuxiliaryControl |= B_PCH_SMBUS_AAC;
186 HostControl |= B_PCH_SMBUS_PEC_EN;
187 }
188
189 //
190 // Set Host Command Register.
191 //
192 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
193
194 //
195 // Write value to Host Data 0 and Host Data 1 Registers.
196 //
197 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD0, (UINT8) Value);
198 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD1, (UINT8) (Value >> 8));
199
200 //
201 // Set Auxiliary Control Register.
202 //
203 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXC, AuxiliaryControl);
204
205 //
206 // Set SMBUS slave address for the device to send/receive from.
207 //
208 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_TSA, (UINT8) SmBusAddress);
209
210 //
211 // Start the SMBUS transaction and wait for the end.
212 //
213 ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
214
215 //
216 // Read value from Host Data 0 and Host Data 1 Registers.
217 //
218 Value = (UINT16)(IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD1) << 8);
219 Value = (UINT16)(Value | IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD0));
220
221 //
222 // Clear Host Status Register and Auxiliary Status Register.
223 //
224 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
225 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
226
227 Done:
228 if (Status != NULL) {
229 *Status = ReturnStatus;
230 }
231
232 return Value;
233 }
234
235 /**
236 Executes an SMBUS quick read command.
237
238 Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress.
239 Only the SMBUS slave address field of SmBusAddress is required.
240 If Status is not NULL, then the status of the executed command is returned in Status.
241 If PEC is set in SmBusAddress, then ASSERT().
242 If Command in SmBusAddress is not zero, then ASSERT().
243 If Length in SmBusAddress is not zero, then ASSERT().
244 If any reserved bits of SmBusAddress are set, then ASSERT().
245
246 @param SmBusAddress Address that encodes the SMBUS Slave Address,
247 SMBUS Command, SMBUS Data Length, and PEC.
248 @param Status Return status for the executed command.
249 This is an optional parameter and may be NULL.
250
251 **/
252 VOID
253 EFIAPI
254 SmBusQuickRead (
255 IN UINTN SmBusAddress,
256 OUT RETURN_STATUS *Status OPTIONAL
257 )
258 {
259 ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
260 ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
261 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
262 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
263
264 InternalSmBusNonBlock (
265 V_PCH_SMBUS_SMB_CMD_QUICK,
266 SmBusAddress | B_PCH_SMBUS_RW_SEL_READ,
267 0,
268 Status
269 );
270 }
271
272 /**
273 Executes an SMBUS quick write command.
274
275 Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress.
276 Only the SMBUS slave address field of SmBusAddress is required.
277 If Status is not NULL, then the status of the executed command is returned in Status.
278 If PEC is set in SmBusAddress, then ASSERT().
279 If Command in SmBusAddress is not zero, then ASSERT().
280 If Length in SmBusAddress is not zero, then ASSERT().
281 If any reserved bits of SmBusAddress are set, then ASSERT().
282
283 @param SmBusAddress Address that encodes the SMBUS Slave Address,
284 SMBUS Command, SMBUS Data Length, and PEC.
285 @param Status Return status for the executed command.
286 This is an optional parameter and may be NULL.
287
288 **/
289 VOID
290 EFIAPI
291 SmBusQuickWrite (
292 IN UINTN SmBusAddress,
293 OUT RETURN_STATUS *Status OPTIONAL
294 )
295 {
296 ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
297 ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
298 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
299 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
300
301 InternalSmBusNonBlock (
302 V_PCH_SMBUS_SMB_CMD_QUICK,
303 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
304 0,
305 Status
306 );
307 }
308
309 /**
310 Executes an SMBUS receive byte command.
311
312 Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress.
313 Only the SMBUS slave address field of SmBusAddress is required.
314 The byte received from the SMBUS is returned.
315 If Status is not NULL, then the status of the executed command is returned in Status.
316 If Command in SmBusAddress is not zero, then ASSERT().
317 If Length in SmBusAddress is not zero, then ASSERT().
318 If any reserved bits of SmBusAddress are set, then ASSERT().
319
320 @param SmBusAddress Address that encodes the SMBUS Slave Address,
321 SMBUS Command, SMBUS Data Length, and PEC.
322 @param Status Return status for the executed command.
323 This is an optional parameter and may be NULL.
324
325 @return The byte received from the SMBUS.
326
327 **/
328 UINT8
329 EFIAPI
330 SmBusReceiveByte (
331 IN UINTN SmBusAddress,
332 OUT RETURN_STATUS *Status OPTIONAL
333 )
334 {
335 UINT8 ValueReturn = 0;
336
337 ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
338 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
339 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
340
341 ValueReturn = (UINT8) InternalSmBusNonBlock (
342 V_PCH_SMBUS_SMB_CMD_BYTE,
343 SmBusAddress | B_PCH_SMBUS_RW_SEL_READ,
344 0,
345 Status
346 );
347 return ValueReturn;
348
349 }
350
351 /**
352 Executes an SMBUS send byte command.
353
354 Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress.
355 The byte specified by Value is sent.
356 Only the SMBUS slave address field of SmBusAddress is required. Value is returned.
357 If Status is not NULL, then the status of the executed command is returned in Status.
358 If Command in SmBusAddress is not zero, then ASSERT().
359 If Length in SmBusAddress is not zero, then ASSERT().
360 If any reserved bits of SmBusAddress are set, then ASSERT().
361
362 @param SmBusAddress Address that encodes the SMBUS Slave Address,
363 SMBUS Command, SMBUS Data Length, and PEC.
364 @param Value The 8-bit value to send.
365 @param Status Return status for the executed command.
366 This is an optional parameter and may be NULL.
367
368 @return The parameter of Value.
369
370 **/
371 UINT8
372 EFIAPI
373 SmBusSendByte (
374 IN UINTN SmBusAddress,
375 IN UINT8 Value,
376 OUT RETURN_STATUS *Status OPTIONAL
377 )
378 {
379 UINT8 ValueReturn = 0;
380
381 ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
382 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
383 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
384
385 ValueReturn = (UINT8) InternalSmBusNonBlock (
386 V_PCH_SMBUS_SMB_CMD_BYTE,
387 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
388 Value,
389 Status
390 );
391 return ValueReturn;
392
393 }
394
395 /**
396 Executes an SMBUS read data byte command.
397
398 Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress.
399 Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
400 The 8-bit value read from the SMBUS is returned.
401 If Status is not NULL, then the status of the executed command is returned in Status.
402 If Length in SmBusAddress is not zero, then ASSERT().
403 If any reserved bits of SmBusAddress are set, then ASSERT().
404
405 @param SmBusAddress Address that encodes the SMBUS Slave Address,
406 SMBUS Command, SMBUS Data Length, and PEC.
407 @param Status Return status for the executed command.
408 This is an optional parameter and may be NULL.
409
410 @return The byte read from the SMBUS.
411
412 **/
413 UINT8
414 EFIAPI
415 SmBusReadDataByte (
416 IN UINTN SmBusAddress,
417 OUT RETURN_STATUS *Status OPTIONAL
418 )
419 {
420 UINT8 ValueReturn = 0;
421
422 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
423 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
424 ValueReturn = (UINT8) InternalSmBusNonBlock (
425 V_PCH_SMBUS_SMB_CMD_BYTE_DATA,
426 SmBusAddress | B_PCH_SMBUS_RW_SEL_READ,
427 0,
428 Status
429 );
430 return ValueReturn;
431 }
432
433 /**
434 Executes an SMBUS write data byte command.
435
436 Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress.
437 The 8-bit value specified by Value is written.
438 Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
439 Value is returned.
440 If Status is not NULL, then the status of the executed command is returned in Status.
441 If Length in SmBusAddress is not zero, then ASSERT().
442 If any reserved bits of SmBusAddress are set, then ASSERT().
443
444 @param SmBusAddress Address that encodes the SMBUS Slave Address,
445 SMBUS Command, SMBUS Data Length, and PEC.
446 @param Value The 8-bit value to write.
447 @param Status Return status for the executed command.
448 This is an optional parameter and may be NULL.
449
450 @return The parameter of Value.
451
452 **/
453 UINT8
454 EFIAPI
455 SmBusWriteDataByte (
456 IN UINTN SmBusAddress,
457 IN UINT8 Value,
458 OUT RETURN_STATUS *Status OPTIONAL
459 )
460 {
461 UINT8 ValueReturn = 0;
462
463 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
464 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
465
466 ValueReturn = (UINT8) InternalSmBusNonBlock (
467 V_PCH_SMBUS_SMB_CMD_BYTE_DATA,
468 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
469 Value,
470 Status
471 );
472 return ValueReturn;
473
474 }
475
476 /**
477 Executes an SMBUS read data word command.
478
479 Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress.
480 Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
481 The 16-bit value read from the SMBUS is returned.
482 If Status is not NULL, then the status of the executed command is returned in Status.
483 If Length in SmBusAddress is not zero, then ASSERT().
484 If any reserved bits of SmBusAddress are set, then ASSERT().
485
486 @param SmBusAddress Address that encodes the SMBUS Slave Address,
487 SMBUS Command, SMBUS Data Length, and PEC.
488 @param Status Return status for the executed command.
489 This is an optional parameter and may be NULL.
490
491 @return The byte read from the SMBUS.
492
493 **/
494 UINT16
495 EFIAPI
496 SmBusReadDataWord (
497 IN UINTN SmBusAddress,
498 OUT RETURN_STATUS *Status OPTIONAL
499 )
500 {
501 UINT16 ValueReturn = 0;
502 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
503 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
504
505 ValueReturn = InternalSmBusNonBlock (
506 V_PCH_SMBUS_SMB_CMD_WORD_DATA,
507 SmBusAddress | B_PCH_SMBUS_RW_SEL_READ,
508 0,
509 Status
510 );
511 return ValueReturn;
512
513 }
514
515 /**
516 Executes an SMBUS write data word command.
517
518 Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress.
519 The 16-bit value specified by Value is written.
520 Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
521 Value is returned.
522 If Status is not NULL, then the status of the executed command is returned in Status.
523 If Length in SmBusAddress is not zero, then ASSERT().
524 If any reserved bits of SmBusAddress are set, then ASSERT().
525
526 @param SmBusAddress Address that encodes the SMBUS Slave Address,
527 SMBUS Command, SMBUS Data Length, and PEC.
528 @param Value The 16-bit value to write.
529 @param Status Return status for the executed command.
530 This is an optional parameter and may be NULL.
531
532 @return The parameter of Value.
533
534 **/
535 UINT16
536 EFIAPI
537 SmBusWriteDataWord (
538 IN UINTN SmBusAddress,
539 IN UINT16 Value,
540 OUT RETURN_STATUS *Status OPTIONAL
541 )
542 {
543 UINT16 ValueReturn = 0;
544 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
545 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
546
547 ValueReturn = InternalSmBusNonBlock (
548 V_PCH_SMBUS_SMB_CMD_WORD_DATA,
549 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
550 Value,
551 Status
552 );
553 return ValueReturn;
554 }
555
556 /**
557 Executes an SMBUS process call command.
558
559 Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress.
560 The 16-bit value specified by Value is written.
561 Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
562 The 16-bit value returned by the process call command is returned.
563 If Status is not NULL, then the status of the executed command is returned in Status.
564 If Length in SmBusAddress is not zero, then ASSERT().
565 If any reserved bits of SmBusAddress are set, then ASSERT().
566
567 @param SmBusAddress Address that encodes the SMBUS Slave Address,
568 SMBUS Command, SMBUS Data Length, and PEC.
569 @param Value The 16-bit value to write.
570 @param Status Return status for the executed command.
571 This is an optional parameter and may be NULL.
572
573 @return The 16-bit value returned by the process call command.
574
575 **/
576 UINT16
577 EFIAPI
578 SmBusProcessCall (
579 IN UINTN SmBusAddress,
580 IN UINT16 Value,
581 OUT RETURN_STATUS *Status OPTIONAL
582 )
583 {
584 UINT16 ValueReturn = 0;
585 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
586 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
587
588 ValueReturn = InternalSmBusNonBlock (
589 V_PCH_SMBUS_SMB_CMD_PROCESS_CALL,
590 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
591 Value,
592 Status
593 );
594 return ValueReturn;
595 }
596
597 /**
598 Executes an SMBUS block command.
599
600 Executes an SMBUS block read, block write and block write-block read command
601 on the SMBUS device specified by SmBusAddress.
602 Bytes are read from the SMBUS and stored in Buffer.
603 The number of bytes read is returned, and will never return a value larger than 32-bytes.
604 If Status is not NULL, then the status of the executed command is returned in Status.
605 It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
606 SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
607
608 @param HostControl The value of Host Control Register to set.
609 @param SmBusAddress Address that encodes the SMBUS Slave Address,
610 SMBUS Command, SMBUS Data Length, and PEC.
611 @param WriteBuffer Pointer to the buffer of bytes to write to the SMBUS.
612 @param ReadBuffer Pointer to the buffer of bytes to read from the SMBUS.
613 @param Status Return status for the executed command.
614 This is an optional parameter and may be NULL.
615
616 @return The number of bytes read from the SMBUS.
617
618 **/
619 UINTN
620 InternalSmBusBlock (
621 IN UINT8 HostControl,
622 IN UINTN SmBusAddress,
623 IN UINT8 *WriteBuffer,
624 OUT UINT8 *ReadBuffer,
625 OUT RETURN_STATUS *Status
626 )
627 {
628 RETURN_STATUS ReturnStatus;
629 UINTN Index;
630 UINTN BytesCount;
631 UINTN IoPortBaseAddress;
632 UINT8 AuxiliaryControl;
633
634 IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
635
636 BytesCount = SMBUS_LIB_LENGTH (SmBusAddress);
637
638 //
639 // Try to acquire the ownership of ICH SMBUS.
640 //
641 ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
642 if (RETURN_ERROR (ReturnStatus)) {
643 goto Done;
644 }
645
646 //
647 // Set the appropriate Host Control Register and auxiliary Control Register.
648 //
649 AuxiliaryControl = B_PCH_SMBUS_E32B;
650 if (SMBUS_LIB_PEC (SmBusAddress)) {
651 AuxiliaryControl |= B_PCH_SMBUS_AAC;
652 HostControl |= B_PCH_SMBUS_PEC_EN;
653 }
654
655 //
656 // Set Host Command Register.
657 //
658 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
659
660 //
661 // Set Auxiliary Control Regiester.
662 //
663 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXC, AuxiliaryControl);
664
665 //
666 // Clear byte pointer of 32-byte buffer.
667 //
668 IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HCTL);
669
670 if (WriteBuffer != NULL) {
671 //
672 // Write the number of block to Host Block Data Byte Register.
673 //
674 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD0, (UINT8) BytesCount);
675
676 //
677 // Write data block to Host Block Data Register.
678 //
679 for (Index = 0; Index < BytesCount; Index++) {
680 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HBD, WriteBuffer[Index]);
681 }
682 }
683
684 //
685 // Set SMBUS slave address for the device to send/receive from.
686 //
687 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_TSA, (UINT8) SmBusAddress);
688
689 //
690 // Start the SMBUS transaction and wait for the end.
691 //
692 ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
693 if (RETURN_ERROR (ReturnStatus)) {
694 goto Done;
695 }
696
697 if (ReadBuffer != NULL) {
698 //
699 // Read the number of block from host block data byte register.
700 //
701 BytesCount = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD0);
702
703 //
704 // Write data block from Host Block Data Register.
705 //
706 for (Index = 0; Index < BytesCount; Index++) {
707 ReadBuffer[Index] = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HBD);
708 }
709 }
710
711 Done:
712 //
713 // Clear Host Status Register and Auxiliary Status Register.
714 //
715 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
716 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
717
718 if (Status != NULL) {
719 *Status = ReturnStatus;
720 }
721
722 return BytesCount;
723 }
724
725 /**
726 Executes an SMBUS read block command.
727
728 Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress.
729 Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
730 Bytes are read from the SMBUS and stored in Buffer.
731 The number of bytes read is returned, and will never return a value larger than 32-bytes.
732 If Status is not NULL, then the status of the executed command is returned in Status.
733 It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
734 SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
735 If Length in SmBusAddress is not zero, then ASSERT().
736 If Buffer is NULL, then ASSERT().
737 If any reserved bits of SmBusAddress are set, then ASSERT().
738
739 @param SmBusAddress Address that encodes the SMBUS Slave Address,
740 SMBUS Command, SMBUS Data Length, and PEC.
741 @param Buffer Pointer to the buffer to store the bytes read from the SMBUS.
742 @param Status Return status for the executed command.
743 This is an optional parameter and may be NULL.
744
745 @return The number of bytes read.
746
747 **/
748 UINTN
749 EFIAPI
750 SmBusReadBlock (
751 IN UINTN SmBusAddress,
752 OUT VOID *Buffer,
753 OUT RETURN_STATUS *Status OPTIONAL
754 )
755 {
756 UINTN BytesCount = 0;
757
758 ASSERT (Buffer != NULL);
759 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
760 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
761
762
763 BytesCount = InternalSmBusBlock (
764 V_PCH_SMBUS_SMB_CMD_BLOCK,
765 SmBusAddress | B_PCH_SMBUS_RW_SEL_READ,
766 NULL,
767 Buffer,
768 Status
769 );
770 return BytesCount;
771
772 }
773
774 /**
775 Executes an SMBUS write block command.
776
777 Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress.
778 The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.
779 Bytes are written to the SMBUS from Buffer.
780 The number of bytes written is returned, and will never return a value larger than 32-bytes.
781 If Status is not NULL, then the status of the executed command is returned in Status.
782 If Length in SmBusAddress is zero or greater than 32, then ASSERT().
783 If Buffer is NULL, then ASSERT().
784 If any reserved bits of SmBusAddress are set, then ASSERT().
785
786 @param SmBusAddress Address that encodes the SMBUS Slave Address,
787 SMBUS Command, SMBUS Data Length, and PEC.
788 @param Buffer Pointer to the buffer to store the bytes read from the SMBUS.
789 @param Status Return status for the executed command.
790 This is an optional parameter and may be NULL.
791
792 @return The number of bytes written.
793
794 **/
795 UINTN
796 EFIAPI
797 SmBusWriteBlock (
798 IN UINTN SmBusAddress,
799 OUT VOID *Buffer,
800 OUT RETURN_STATUS *Status OPTIONAL
801 )
802 {
803 UINTN BytesCount = 0;
804
805 ASSERT (Buffer != NULL);
806 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
807 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
808 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
809
810
811 BytesCount = InternalSmBusBlock (
812
813 V_PCH_SMBUS_SMB_CMD_BLOCK,
814 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
815 Buffer,
816 NULL,
817 Status
818 );
819
820 return BytesCount;
821 }
822
823 /**
824 Executes an SMBUS block process call command.
825
826 Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress.
827 The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.
828 Bytes are written to the SMBUS from WriteBuffer. Bytes are then read from the SMBUS into ReadBuffer.
829 If Status is not NULL, then the status of the executed command is returned in Status.
830 It is the caller's responsibility to make sure ReadBuffer is large enough for the total number of bytes read.
831 SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
832 If Length in SmBusAddress is zero or greater than 32, then ASSERT().
833 If WriteBuffer is NULL, then ASSERT().
834 If ReadBuffer is NULL, then ASSERT().
835 If any reserved bits of SmBusAddress are set, then ASSERT().
836
837 @param SmBusAddress Address that encodes the SMBUS Slave Address,
838 SMBUS Command, SMBUS Data Length, and PEC.
839 @param WriteBuffer Pointer to the buffer of bytes to write to the SMBUS.
840 @param ReadBuffer Pointer to the buffer of bytes to read from the SMBUS.
841 @param Status Return status for the executed command.
842 This is an optional parameter and may be NULL.
843
844 @return The number of bytes written.
845
846 **/
847 UINTN
848 EFIAPI
849 SmBusBlockProcessCall (
850 IN UINTN SmBusAddress,
851 IN VOID *WriteBuffer,
852 OUT VOID *ReadBuffer,
853 OUT RETURN_STATUS *Status OPTIONAL
854 )
855 {
856 UINTN BytesCount = 0;
857
858 ASSERT (WriteBuffer != NULL);
859 ASSERT (ReadBuffer != NULL);
860 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
861 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
862 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
863
864 BytesCount = InternalSmBusBlock (
865 V_PCH_SMBUS_SMB_CMD_BLOCK_PROCESS,
866 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
867 WriteBuffer,
868 ReadBuffer,
869 Status
870 );
871 return BytesCount;
872
873 }