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