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