1/**@file
2  Provide the SMBUS ASL methods for BIOS usage.
3  Note the code requested here illegally consumes PCI IO resources and
4  collides with some runtime SMBUS driver.
5  The only valid solution is to retire this code and provide native SMBUS
6  driver with SMBUS operation region support implemented for ACPI usage.
7
8Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
9SPDX-License-Identifier: BSD-2-Clause-Patent
10
11**/
12
13//
14// Define various SMBus PCI Configuration Space Registers.
15//
16OperationRegion(SMBP, PCI_Config, 0x0, 0xC0)
17Field(SMBP,DWordAcc,NoLock,Preserve)
18{
19  Offset(0x20),  // SMBus Base Address
20      , 5,
21  SBAR, 11,
22  Offset(0x40), // Host Configuration
23      , 2,
24  I2CE, 1,      // I2C_EN
25}
26
27//
28// Define various SMBus IO Mapped Registers.
29//
30OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10)
31Field(SMBI,ByteAcc,NoLock,Preserve)
32{
33  HSTS, 8,  // 0 - Host Status Register
34  Offset(0x02),
35  HCON, 8,  // 2 - Host Control
36  HCOM, 8,  // 3 - Host Command
37  TXSA, 8,  // 4 - Transmit Slave Address
38  DAT0, 8,  // 5 - Host Data 0
39  DAT1, 8,  // 6 - Host Data 1
40  HBDR, 8,  // 7 - Host Block Data
41  PECR, 8,  // 8 - Packer Error Check
42  RXSA, 8,  // 9 - Receive Slave Address
43  SDAT, 16, // A - Slave Data
44}
45
46// SMBus Send Byte - This function will write a single byte of
47// data to a specific Slave Device per SMBus Send Byte Protocol.
48//  Arg0 = Address
49//  Arg1 = Data
50//  Return: Success = 1
51//          Failure = 0
52Method(SSXB,2,Serialized)
53{
54  // Step 1:  Confirm the ICHx SMBus is ready to perform
55  // communication.
56
57  If(STRT())
58  {
59    Return(0)
60  }
61
62  // Step 2:  Initiate a Send Byte.
63  Store(0,I2CE)       // Ensure SMbus Mode.
64  Store(0xBF,HSTS)    // Clear all but INUSE_STS.
65  Store(Arg0,TXSA)    // Write Address in TXSA.
66  Store(Arg1,HCOM)    // Data in HCOM.
67
68  // Set the SMBus Host control register to 0x48.
69  //   Bit 7:    =  0  = reserved
70  //   Bit 6:    =  1  = start
71  //   Bit 5:    =  0  = disregard, I2C related bit
72  //   Bits 4:2: = 001 = Byte Protocol
73  //   Bit 1:    =  0  = Normal Function
74  //   Bit 0:    =  0  = Disable interrupt generation
75  Store(0x48,HCON)
76
77  // Step 3:  Exit the Method correctly.
78  If(COMP)
79  {
80    Or(HSTS,0xFF,HSTS)    // Clear INUSE_STS and others..
81    Return(1)             // Return Success.
82  }
83
84  Return(0)
85}
86
87// SMBus Receive Byte - This function will write a single byte
88// of data to a specific Slave Device per SMBus Receive Byte
89// Protocol.
90//  Arg0 = Address
91//  Return: Success = Byte-Size Value
92//          Failure = Word-Size Value = FFFFh.
93Method(SRXB,1,Serialized)
94{
95  // Step 1:  Confirm the ICHx SMBus is ready to perform
96  // communication.
97  If(STRT())
98  {
99    Return(0xFFFF)
100  }
101
102  // Step 2:  Initiate a Receive Byte.
103  Store(0,I2CE)             // Ensure SMbus Mode.
104  Store(0xBF,HSTS)          // Clear all but INUSE_STS.
105  Store(Or(Arg0,1),TXSA)    // Read Address in TXSA.
106
107  // Set the SMBus Host control register to 0x48.
108  //   Bit 7:    =  0  = reserved
109  //   Bit 6:    =  1  = start
110  //   Bit 5:    =  0  = disregard, I2C related bit
111  //   Bits 4:2: = 001 = Byte Protocol
112  //   Bit 1:    =  0  = Normal Function
113  //   Bit 0:    =  0  = Disable interrupt generation
114  Store(0x44,HCON)
115
116  // Step 3:  Exit the Method correctly.
117  If(COMP)
118  {
119    Or(HSTS,0xFF,HSTS)    // Clear INUSE_STS and others
120    Return(DAT0)          // Return Success.
121  }
122
123  Return(0xFFFF)        // Return Failure.
124}
125
126// SMBus Write Byte - This function will write a single byte
127// of data to a specific Slave Device per SMBus Write Byte
128// Protocol.
129//  Arg0 = Address
130//  Arg1 = Command
131//  Arg2 = Data
132//  Return: Success = 1
133//          Failure = 0
134Method(SWRB,3,Serialized)
135{
136  // Step 1:  Confirm the ICHx SMBus is ready to perform communication.
137  If(STRT())
138  {
139    Return(0)
140  }
141
142  // Step 2:  Initiate a Write Byte.
143  Store(0,I2CE)       // Ensure SMbus Mode.
144  Store(0xBF,HSTS)    // Clear all but INUSE_STS.
145  Store(Arg0,TXSA)    // Write Address in TXSA.
146  Store(Arg1,HCOM)    // Command in HCOM.
147  Store(Arg2,DAT0)    // Data in DAT0.
148
149  // Set the SMBus Host control register to 0x48.
150  //   Bit 7:    =  0  = reserved
151  //   Bit 6:    =  1  = start
152  //   Bit 5:    =  0  = disregard, I2C related bit
153  //   Bits 4:2: = 010 = Byte Data Protocol
154  //   Bit 1:    =  0  = Normal Function
155  //   Bit 0:    =  0  = Disable interrupt generation
156  Store(0x48,HCON)
157
158  // Step 3:  Exit the Method correctly.
159  If(COMP)
160  {
161    Or(HSTS,0xFF,HSTS)    // Clear INUSE_STS and others..
162    Return(1)             // Return Success.
163  }
164
165  Return(0)    // Return Failure.
166}
167
168// SMBus Read Byte - This function will read a single byte of data
169// from a specific slave device per SMBus Read Byte Protocol.
170//  Arg0 = Address
171//  Arg1 = Command
172//  Return: Success = Byte-Size Value
173//          Failure = Word-Size Value
174Method(SRDB,2,Serialized)
175{
176  // Step 1:  Confirm the ICHx SMBus is ready to perform communication.
177  If(STRT())
178  {
179  Return(0xFFFF)
180  }
181
182  // Step 2:  Initiate a Read Byte.
183  Store(0,I2CE)             // Ensure SMbus Mode.
184  Store(0xBF,HSTS)          // Clear all but INUSE_STS.
185  Store(Or(Arg0,1),TXSA)    // Read Address in TXSA.
186  Store(Arg1,HCOM)          // Command in HCOM.
187
188  // Set the SMBus Host control register to 0x48.
189  //   Bit 7:    =  0  = reserved
190  //   Bit 6:    =  1  = start
191  //   Bit 5:    =  0  = disregard, I2C related bit
192  //   Bits 4:2: = 010 = Byte Data Protocol
193  //   Bit 1:    =  0  = Normal Function
194  //   Bit 0:    =  0  = Disable interrupt generation
195  Store(0x48,HCON)
196
197  // Step 3:  Exit the Method correctly.
198  If(COMP)
199  {
200    Or(HSTS,0xFF,HSTS)    // Clear INUSE_STS and others..
201    Return(DAT0)          // Return Success.
202  }
203
204  Return(0xFFFF)    // Return Failure.
205}
206
207// SMBus Write Word - This function will write a single word
208// of data to a specific Slave Device per SMBus Write Word
209// Protocol.
210//  Arg0 = Address
211//  Arg1 = Command
212//  Arg2 = Data (16 bits in size)
213//  Return: Success = 1
214//          Failure = 0
215Method(SWRW,3,Serialized)
216{
217  // Step 1:  Confirm the ICHx SMBus is ready to perform communication.
218  If(STRT())
219  {
220    Return(0)
221  }
222
223  // Step 2:  Initiate a Write Word.
224  Store(0,I2CE)                        // Ensure SMbus Mode.
225  Store(0xBF,HSTS)                     // Clear all but INUSE_STS.
226  Store(Arg0,TXSA)                     // Write Address in TXSA.
227  Store(Arg1,HCOM)                     // Command in HCOM.
228  And(Arg2,0xFF,DAT1)                  // Low byte Data in DAT1.
229  And(ShiftRight(Arg2,8),0xFF,DAT0)    // High byte Data in DAT0.
230
231  // Set the SMBus Host control register to 0x4C.
232  //   Bit 7:    =  0  = reserved
233  //   Bit 6:    =  1  = start
234  //   Bit 5:    =  0  = disregard, I2C related bit
235  //   Bits 4:2: = 011 = Word Data Protocol
236  //   Bit 1:    =  0  = Normal Function
237  //   Bit 0:    =  0  = Disable interrupt generation
238  Store(0x4C,HCON)
239
240  // Step 3:  Exit the Method correctly.
241  If(COMP())
242  {
243    Or(HSTS,0xFF,HSTS)    // Clear INUSE_STS and others.
244    Return(1)             // Return Success.
245  }
246
247  Return(0)    // Return Failure.
248}
249
250// SMBus Read Word - This function will read a single byte of data
251// from a specific slave device per SMBus Read Word Protocol.
252//  Arg0 = Address
253//  Arg1 = Command
254//  Return: Success = Word-Size Value
255//          Failure = Dword-Size Value
256Method(SRDW,2,Serialized)
257{
258  // Step 1:  Confirm the ICHx SMBus is ready to perform communication.
259  If(STRT())
260  {
261  Return(0xFFFF)
262  }
263
264  // Step 2:  Initiate a Read Word.
265  Store(0,I2CE)             // Ensure SMbus Mode.
266  Store(0xBF,HSTS)          // Clear all but INUSE_STS.
267  Store(Or(Arg0,1),TXSA)    // Read Address in TXSA.
268  Store(Arg1,HCOM)          // Command in HCOM.
269
270  // Set the SMBus Host control register to 0x4C.
271  //   Bit 7:    =  0  = reserved
272  //   Bit 6:    =  1  = start
273  //   Bit 5:    =  0  = disregard, I2C related bit
274  //   Bits 4:2: = 011 = Word Data Protocol
275  //   Bit 1:    =  0  = Normal Function
276  //   Bit 0:    =  0  = Disable interrupt generation
277  Store(0x4C,HCON)
278
279  // Step 3:  Exit the Method correctly.
280  If(COMP())
281  {
282    Or(HSTS,0xFF,HSTS)                    // Clear INUSE_STS and others.
283    Return(Or(ShiftLeft(DAT0,8),DAT1))    // Return Success.
284  }
285
286  Return(0xFFFFFFFF)    // Return Failure.
287}
288
289// SMBus Block Write - This function will write an entire block of data
290// to a  specific slave device per SMBus Block Write Protocol.
291//  Arg0 = Address
292//  Arg1 = Command
293//  Arg2 = Buffer of Data to Write
294//  Arg3 = 1 = I2C Block Write, 0 = SMBus Block Write
295//  Return:  Success = 1
296//    Failure = 0
297Method(SBLW,4,Serialized)
298{
299  // Step 1:  Confirm the ICHx SMBus is ready to perform communication.
300  If(STRT())
301  {
302    Return(0)
303  }
304
305  // Step 2:  Initiate a Block Write.
306  Store(Arg3,I2CE)                      // Select the proper protocol.
307  Store(0xBF,HSTS)                      // Clear all but INUSE_STS.
308  Store(Arg0,TXSA)                      // Write Address in TXSA.
309  Store(Arg1,HCOM)                      // Command in HCOM.
310  Store(Sizeof(Arg2),DAT0)              // Count in DAT0.
311  Store(0,Local1)                       // Init Pointer to Buffer.
312  Store(DerefOf(Index(Arg2,0)),HBDR)    // First Byte in HBD Register.
313
314  // Set the SMBus Host control register to 0x48.
315  //   Bit 7:    =  0  = reserved
316  //   Bit 6:    =  1  = start
317  //   Bit 5:    =  0  = disregard, I2C related bit
318  //   Bits 4:2: = 101 = Block Protocol
319  //   Bit 1:    =  0  = Normal Function
320  //   Bit 0:    =  0  = Disable interrupt generation
321  Store(0x54,HCON)
322
323  // Step 3:  Send the entire Block of Data.
324  While(LGreater(Sizeof(Arg2),Local1))
325  {
326    // Wait up to 200ms for Host Status to get set.
327    Store(4000,Local0)    // 4000 * 50us = 200ms.
328
329    While(LAnd(LNot(And(HSTS,0x80)),Local0))
330    {
331      Decrement(Local0)  // Decrement Count.
332      Stall(50)          // Delay = 50us.
333    }
334
335    If(LNot(Local0))    // Timeout?
336    {
337      KILL()       // Yes.  Kill Communication.
338      Return(0)    // Return failure.
339    }
340
341    Store(0x80,HSTS)     // Clear Host Status.
342    Increment(Local1)    // Point to Next Byte.
343
344    // Place next byte in HBDR if last byte has not been sent.
345    If(LGreater(Sizeof(Arg2),Local1))
346    {
347      Store(DerefOf(Index(Arg2,Local1)),HBDR)
348    }
349  }
350
351  // Step 4:  Exit the Method correctly.
352  If(COMP())
353  {
354    Or(HSTS,0xFF,HSTS)    // Clear all status bits.
355    Return(1)             // Return Success.
356  }
357
358  Return(0)    // Return Failure.
359}
360
361// SMBus Block Read - This function will read a block of data from
362// a specific slave device per SMBus Block Read Protocol.
363//  Arg0 = Address
364//  Arg1 = Command
365//  Arg2 = 1 = I2C Block Write, 0 = SMBus Block Write
366//  Return: Success = Data Buffer (First Byte = length)
367//          Failure = 0
368Method(SBLR,3,Serialized)
369{
370  Name(TBUF, Buffer(256) {})
371
372  // Step 1:  Confirm the ICHx SMBus is ready to perform communication.
373  If(STRT())
374  {
375    Return(0)
376  }
377
378  // Step 2:  Initiate a Block Read.
379  Store(Arg2,I2CE)          // Select the proper protocol.
380  Store(0xBF,HSTS)          // Clear all but INUSE_STS.
381  Store(Or(Arg0,1),TXSA)    // Read Address in TXSA.
382  Store(Arg1,HCOM)          // Command in HCOM.
383
384  // Set the SMBus Host control register to 0x48.
385  //   Bit 7:    =  0  = reserved
386  //   Bit 6:    =  1  = start
387  //   Bit 5:    =  0  = disregard, I2C related bit
388  //   Bits 4:2: = 101 = Block Protocol
389  //   Bit 1:    =  0  = Normal Function
390  //   Bit 0:    =  0  = Disable interrupt generation
391  Store(0x54,HCON)
392
393  // Step 3:  Wait up to 200ms to get the Data Count.
394  Store(4000,Local0)     // 4000 * 50us = 200ms.
395
396  While(LAnd(LNot(And(HSTS,0x80)),Local0))
397  {
398    Decrement(Local0)    // Decrement Count.
399    Stall(50)            // Delay = 50us.
400  }
401
402  If(LNot(Local0))      // Timeout?
403  {
404    KILL()       // Yes. Kill Communication.
405    Return(0)    // Return failure.
406  }
407
408  Store(DAT0,Index(TBUF,0))    // Get the Data Count.
409  Store(0x80,HSTS)             // Clear Host Status.
410  Store(1,Local1)              // Local1 = Buffer Pointer.
411
412  // Step 4:  Get the Block Data and store it.
413  While(LLess(Local1,DerefOf(Index(TBUF,0))))
414  {
415    // Wait up to 200ms for Host Status to get set.
416    Store(4000,Local0)    // 4000 * 50us = 200ms.
417
418    While(LAnd(LNot(And(HSTS,0x80)),Local0))
419    {
420      Decrement(Local0)  // Decrement Count.
421      Stall(50)          // Delay = 50us.
422    }
423
424    If(LNot(Local0))     // Timeout?
425    {
426      KILL()       // Yes. Kill Communication.
427      Return(0)    // Return failure.
428    }
429
430    Store(HBDR,Index(TBUF,Local1))  // Place into Buffer.
431    Store(0x80,HSTS)                // Clear Host Status.
432    Increment(Local1)
433  }
434
435  // Step 5:  Exit the Method correctly.
436  If(COMP())
437  {
438    Or(HSTS,0xFF,HSTS)    // Clear INUSE_STS and others.
439    Return(TBUF)          // Return Success.
440  }
441
442  Return(0)    // Return Failure.
443}
444
445
446// SMBus Start Check
447//  Return:  Success = 0
448//    Failure = 1
449Method(STRT,0,Serialized)
450{
451  // Wait up to 200ms to confirm the SMBus Semaphore has been
452  // released (In Use Status = 0).  Note that the Sleep time may take
453  // longer as the This function will yield the Processor such that it
454  // may perform different tasks during the delay.
455  Store(200,Local0)      // 200 * 1ms = 200ms.
456
457  While(Local0)
458  {
459    If(And(HSTS,0x40))      // In Use Set?
460    {
461      Decrement(Local0)     // Yes.  Decrement Count.
462      Sleep(1)              // Delay = 1ms.
463      If(LEqual(Local0,0))  // Count = 0?
464      {
465        Return(1)  // Return failure.
466      }
467    }
468    Else
469    {
470      Store(0,Local0)    // In Use Clear.  Continue.
471    }
472  }
473
474  // In Use Status = 0 during last read, which will make subsequent
475  // reads return In Use Status = 1 until software clears it.  All
476  // software using ICHx SMBus should check this bit before initiating
477  // any SMBus communication.
478
479  // Wait up to 200ms to confirm the Host Interface is
480  // not processing a command.
481  Store(4000,Local0)      // 4000 * 50us = 200ms.
482
483  While(Local0)
484  {
485    If(And(HSTS,0x01))    // Host Busy Set?
486    {
487      Decrement(Local0)       // Decrement Count.
488      Stall(50)               // Delay = 50us.
489      If(LEqual(Local0,0))    // Count = 0?
490      {
491        KILL()    // Yes. Kill Communication.
492      }
493    }
494    Else
495    {
496      Return(0)
497    }
498  }
499
500  Return(1)    // Timeout. Return failure.
501}
502
503// SMBus Completion Check
504//  Return:  Success = 1
505//    Failure = 0
506Method(COMP,0,Serialized)
507{
508  // Wait for up to 200ms for the Completion Command
509  // Status to get set.
510  Store(4000,Local0)      // 4000 * 50us = 200ms.
511
512  While(Local0)
513  {
514    If(And(HSTS,0x02))    // Completion Status Set?
515    {
516      Return(1)    // Yes. We are done.
517    }
518    Else
519    {
520      Decrement(Local0)       // Decrement Count.
521      Stall(50)               // Delay 50us.
522      If(LEqual(Local0,0))    // Count = 0?
523      {
524        KILL()    // Yes. Kill Communication.
525      }
526    }
527  }
528
529  Return(0)    // Timeout.  Return Failure.
530}
531
532// SMBus Kill Command
533Method(KILL,0,Serialized)
534{
535  Or(HCON,0x02,HCON)    // Yes. Send Kill command.
536  Or(HSTS,0xFF,HSTS)    // Clear all status.
537}
538