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