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