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