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