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