1 //*****************************************************************************
2 //
3 // peci.c - Driver for the Platform Environment Control Interface (PECI)
4 // module.
5 //
6 // Copyright (c) 2010-2011 Texas Instruments Incorporated. All rights reserved.
7 // Software License Agreement
8 //
9 // Texas Instruments (TI) is supplying this software for use solely and
10 // exclusively on TI's microcontroller products. The software is owned by
11 // TI and/or its suppliers, and is protected under applicable copyright
12 // laws. You may not combine this software with "viral" open-source
13 // software in order to form a larger program.
14 //
15 // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
16 // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
17 // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
19 // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
20 // DAMAGES, FOR ANY REASON WHATSOEVER.
21 //
22 // This is part of revision 8264 of the Stellaris Peripheral Driver Library.
23 //
24 //*****************************************************************************
25
26 //*****************************************************************************
27 //
28 //! \addtogroup peci_api
29 //! @{
30 //
31 //*****************************************************************************
32
33 #include "inc/hw_ints.h"
34 #include "inc/hw_memmap.h"
35 #include "inc/hw_peci.h"
36 #include "inc/hw_sysctl.h"
37 #include "inc/hw_types.h"
38 #include "driverlib/debug.h"
39 #include "driverlib/interrupt.h"
40 #include "driverlib/peci.h"
41
42 //*****************************************************************************
43 //
44 // The following defines provide characteristics of the PECI module that are
45 // important to the driver but which can not be gleaned from the register
46 // definitions.
47 //
48 //*****************************************************************************
49 #define PECI_MAX_BAUD 2000000 // Maximum baud rate
50 #define PECI_MIN_BAUD 2000 // Minimum baud rate
51 #define PECI_MIN_RATIO 8 // Minimum baud rate divider
52 #define PECI_MAX_RATIO 65535 // Maximum baud rate divider
53 #define PECI_POLL_PRESCALE 4096 // Polling timer prescaler
54 #define PECI_MIN_POLL 2 // Minimum polling interval (ms)
55 #define PECI_MAX_POLL 1000 // Maximum polling interval (ms)
56
57 //*****************************************************************************
58 //
59 //! \internal
60 //! Checks a PECI domain.
61 //!
62 //! \param ulDomain is the PECI domain identifier.
63 //!
64 //! This function determines if a domain identifier is valid.
65 //!
66 //! \return Returns \b true if the domain identifier is valid and \b false
67 //! otherwise.
68 //
69 //*****************************************************************************
70 #ifdef DEBUG
71 static tBoolean
PECIDomainValid(unsigned long ulDomain)72 PECIDomainValid(unsigned long ulDomain)
73 {
74 return((ulDomain == PECI_DOMAIN_M0D0) ||
75 (ulDomain == PECI_DOMAIN_M0D1) ||
76 (ulDomain == PECI_DOMAIN_M1D0) ||
77 (ulDomain == PECI_DOMAIN_M1D1));
78 }
79 #endif
80
81 //*****************************************************************************
82 //
83 //! Sets the configuration of the PECI module.
84 //!
85 //! \param ulBase is the base address of the PECI module.
86 //! \param ulPECIClk is the rate of the clock supplied to the PECI module.
87 //! \param ulBaud is the bit rate that should be used for the PECI transfers.
88 //! \param ulPoll is the polling rate, in ms, that should be used for the
89 //! time between PECI polls.
90 //! \param ulOffset is the offset to be applied to all temperature values to
91 //! convert from relative to absolute.
92 //! \param ulRetry is the number of retry attempts for a PECI transaction.
93 //!
94 //! This function initializes operation of the PECI block. It programs the bit
95 //! rate, polling rate and retry counts for PECI transactions. It also
96 //! programs the offset value to be used to translate relative temperature
97 //! values from PECI transactions to absolute values. At the end of this
98 //! function, no host/domain combinations are enabled. Each desired
99 //! host/domain combination can be configured/enabled with a call to
100 //! PECIDomainEnable().
101 //!
102 //! The peripheral clock is the same as the processor clock. This value is
103 //! returned by SysCtlClockGet(), or it can be explicitly hard coded if it is
104 //! constant and known (to save the code/execution overhead of a call to
105 //! SysCtlClockGet()).
106 //!
107 //! The \e ulBaud parameter defines the bit rate for the PECI transactions.
108 //! This value is used to calculate a divisor value based on the specified
109 //! \e ulPECIClk. If the exact baud rate cannot be achieved (due to rounding),
110 //! the baud rate is programmed to the nearest value that is less than the
111 //! specified value.
112 //!
113 //! The \e ulPoll parameter defines the polling rate, in milliseconds, used
114 //! for PECI transactions. For generation of the polling rate, the \e
115 //! ulPECIClk is pre-divided by \b 4096. A value of 0 disables the polling
116 //! feature. If the exact polling rate cannot be achieved (due to rounding),
117 //! the polling rate is programmed to the nearest value that is greater than
118 //! the specified value.
119 //!
120 //! The \e ulRetry parameter defines the number of PECI transactions that are
121 //! attempted before indicating an error condition.
122 //!
123 //! \return None.
124 //
125 //*****************************************************************************
126 void
PECIConfigSet(unsigned long ulBase,unsigned long ulPECIClk,unsigned long ulBaud,unsigned long ulPoll,unsigned long ulOffset,unsigned long ulRetry)127 PECIConfigSet(unsigned long ulBase, unsigned long ulPECIClk,
128 unsigned long ulBaud, unsigned long ulPoll,
129 unsigned long ulOffset, unsigned long ulRetry)
130 {
131 unsigned long ulTemp, ulDiv;
132
133 //
134 // Check the arguments.
135 //
136 ASSERT(ulBase == PECI0_BASE);
137 ASSERT(ulPECIClk != 0);
138 ASSERT((ulBaud != 0) && (ulBaud <= PECI_MAX_BAUD) &&
139 (ulBaud >= PECI_MIN_BAUD) &&
140 ((ulBaud * 4 * PECI_MIN_RATIO) < ulPECIClk));
141 ASSERT((ulPoll == 0) ||
142 ((ulPoll >= PECI_MIN_POLL) && (ulPoll <= PECI_MAX_POLL)));
143
144 //
145 // Generate value for the PECI Control Register.
146 //
147 ulTemp = ((ulOffset << PECI_CTL_OFFSET_S) & PECI_CTL_OFFSET_M);
148 ulTemp |= ((ulRetry << PECI_CTL_CRETRY_S) & PECI_CTL_CRETRY_M);
149 HWREG(ulBase + PECI_O_CTL) = ulTemp;
150
151 //
152 // Compute the divisor for the PECI baud rate clock.
153 // Round up, to ensure programmed baud rate is <= specified rate.
154 // Ensure that proper ratio is maintained for clock:baud.
155 //
156 ulDiv = (ulPECIClk + (4 * ulBaud) - 1) / (4 * ulBaud);
157 ulDiv = (ulDiv < PECI_MIN_RATIO) ? PECI_MIN_RATIO : ulDiv;
158 ulDiv = (ulDiv > PECI_MAX_RATIO) ? PECI_MAX_RATIO : ulDiv;
159 ulTemp = ((ulDiv << PECI_DIV_BAUD_S) & PECI_DIV_BAUD_M);
160
161 //
162 // Compute the divisor for the PECI polling rate.
163 // Round up, to ensure programmed polling rate is >= specified rate.
164 //
165 ulDiv = ((ulPoll == 0) ? 0 : ((((ulPECIClk * ulPoll) / 1000) +
166 (PECI_POLL_PRESCALE - 1)) /
167 PECI_POLL_PRESCALE));
168 ulTemp |= ((ulDiv << PECI_DIV_POLL_S) & PECI_DIV_POLL_M);;
169 HWREG(ulBase + PECI_O_DIV) = ulTemp;
170 }
171
172 //*****************************************************************************
173 //
174 //! Gets the current configuration of the PECI module.
175 //!
176 //! \param ulBase is the base address of the PECI module.
177 //! \param ulPECIClk is the rate of the clock supplied to the PECI module.
178 //! \param pulBaud is a pointer to storage for the bit rate.
179 //! \param pulPoll is a pointer to storage for the polling rate.
180 //! \param pulOffset is a pointer to stoarage for the offset.
181 //! \param pulRetry is a pointer to storage for the retry count.
182 //!
183 //! The baud rate and poll rate for the PECI module are determined, given an
184 //! explicitly provided peripheral clock. The returned rates are the actual
185 //! rates being used; they may not be the same as the requested rates, due to
186 //! rounding in the calculations.
187 //!
188 //! The peripheral clock is the same as the processor clock. This value is
189 //! returned by SysCtlClockGet(), or it can be explicitly hard coded if it is
190 //! constant and known (to save the code/execution overhead of a call to
191 //! SysCtlClockGet()).
192 //!
193 //! \return None.
194 //
195 //*****************************************************************************
196 void
PECIConfigGet(unsigned long ulBase,unsigned long ulPECIClk,unsigned long * pulBaud,unsigned long * pulPoll,unsigned long * pulOffset,unsigned long * pulRetry)197 PECIConfigGet(unsigned long ulBase, unsigned long ulPECIClk,
198 unsigned long *pulBaud, unsigned long *pulPoll,
199 unsigned long *pulOffset, unsigned long *pulRetry)
200 {
201 unsigned long ulTemp;
202
203 //
204 // Check the arguments.
205 //
206 ASSERT(ulBase == PECI0_BASE);
207 ASSERT(ulPECIClk != 0);
208 ASSERT(*pulBaud != 0);
209 ASSERT(*pulPoll != 0);
210 ASSERT(*pulOffset != 0);
211 ASSERT(*pulRetry != 0);
212
213 //
214 // Retrieve the Offset and Retry values
215 //
216 ulTemp = HWREG(ulBase + PECI_O_CTL);
217 *pulOffset = ((ulTemp & PECI_CTL_OFFSET_M) >> PECI_CTL_OFFSET_S);
218 *pulRetry = ((ulTemp & PECI_CTL_CRETRY_M) >> PECI_CTL_CRETRY_S);
219
220 //
221 // Calculate the baud rate.
222 //
223 ulTemp = HWREG(ulBase + PECI_O_DIV);
224 *pulBaud = ulPECIClk / ((ulTemp & PECI_DIV_BAUD_M) >> PECI_DIV_BAUD_S);
225
226 //
227 // Compute the divisor for the PECI polling rate.
228 // Round up, to ensure programmed polling rate is >= specified rate.
229 //
230 *pulPoll = ((((ulTemp & PECI_DIV_POLL_M) >> PECI_DIV_POLL_S) * 1000) /
231 (ulPECIClk / PECI_POLL_PRESCALE));
232 }
233
234 //*****************************************************************************
235 //
236 //! Enables bypassing of negotiation errors.
237 //!
238 //! \param ulBase is the base address of the PECI module.
239 //!
240 //! This function enables bypassing of negotiation errors that might occur
241 //! during a PECI transaction. When enabled, negotiation errors are ignored.
242 //!
243 //! \return None.
244 //
245 //*****************************************************************************
246 void
PECIBypassEnable(unsigned long ulBase)247 PECIBypassEnable(unsigned long ulBase)
248 {
249 //
250 // Check the arguments.
251 //
252 ASSERT(ulBase == PECI0_BASE);
253
254 //
255 // Enable bypass.
256 //
257 HWREG(ulBase + PECI_O_CTL) |= PECI_CTL_BYERR;
258 }
259
260 //*****************************************************************************
261 //
262 //! Disables bypassing of negotiation errors.
263 //!
264 //! \param ulBase is the base address of the PECI module.
265 //!
266 //! This function disables bypassing of negotiation errors that might occur
267 //! during a PECI transaction. When disabled, negotiation errors are reported
268 //! and the remainder of the transaction is aborted.
269 //!
270 //! \return None.
271 //
272 //*****************************************************************************
273 void
PECIBypassDisable(unsigned long ulBase)274 PECIBypassDisable(unsigned long ulBase)
275 {
276 //
277 // Check the arguments.
278 //
279 ASSERT(ulBase == PECI0_BASE);
280
281 //
282 // Disable bypass.
283 //
284 HWREG(ulBase + PECI_O_CTL) &= ~PECI_CTL_BYERR;
285 }
286
287 //*****************************************************************************
288 //
289 //! Sets the configuration of the specified PECI domain.
290 //!
291 //! \param ulBase is the base address of the PECI module.
292 //! \param ulDomain is the PECI domain that should be configured.
293 //! \param ulHigh is the high temperature threshold value.
294 //! \param ulLow is the low temperature threshold value.
295 //!
296 //! This function configures the specified PECI domain for temperature
297 //! monitoring operations. The values for \e ulHigh and \e ulLow can be
298 //! specified as values relative to the maximum temperature allowed, or they
299 //! can be specified as absolute temperatures if an offset was programmed
300 //! in the PECIConfigSet() function.
301 //!
302 //! The \e ulDomain parameter can be one of the following values:
303 //! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
304 //! \b PECI_DOMAIN_M1D1.
305 //!
306 //! \return None.
307 //
308 //*****************************************************************************
309 void
PECIDomainConfigSet(unsigned long ulBase,unsigned long ulDomain,unsigned long ulHigh,unsigned long ulLow)310 PECIDomainConfigSet(unsigned long ulBase, unsigned long ulDomain,
311 unsigned long ulHigh, unsigned long ulLow)
312 {
313 //
314 // Check the arguments.
315 //
316 ASSERT(ulBase == PECI0_BASE);
317 ASSERT(PECIDomainValid(ulDomain));
318 ASSERT(ulHigh <= 0xFFFF);
319 ASSERT(ulLow <= 0xFFFF);
320 ASSERT(ulHigh > ulLow);
321
322 //
323 // Set the HTHRESH and LTHRESH fields in the domain control/status
324 // register.
325 //
326 HWREG(ulBase + PECI_O_M0D0C + (ulDomain * 4)) =
327 (((ulHigh << PECI_M0D0C_HITHR_S) & PECI_M0D0C_HITHR_M) |
328 ((ulLow << PECI_M0D0C_LOTHR_S) & PECI_M0D0C_LOTHR_M));
329 }
330
331 //*****************************************************************************
332 //
333 //! Gets the configuration of the specified PECI domain.
334 //!
335 //! \param ulBase is the base address of the PECI module.
336 //! \param ulDomain is the PECI domain that should be configured.
337 //! \param pulHigh is a pointer to storage for the high threshold.
338 //! \param pulLow is a pointer to storage for the low threshold.
339 //!
340 //! This function configures the specified PECI domain for temperature
341 //! monitoring operations. The values for \e ulHigh and \e ulLow can be
342 //! specified as values relative to the maximum temperature allowed, or they
343 //! can be specified as absolute temperatures if an offset was programmed
344 //! in the PECIConfigSet() function.
345 //!
346 //! The \e ulDomain parameter can be one of the following values:
347 //! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
348 //! \b PECI_DOMAIN_M1D1.
349 //!
350 //! \return None.
351 //
352 //*****************************************************************************
353 void
PECIDomainConfigGet(unsigned long ulBase,unsigned long ulDomain,unsigned long * pulHigh,unsigned long * pulLow)354 PECIDomainConfigGet(unsigned long ulBase, unsigned long ulDomain,
355 unsigned long *pulHigh, unsigned long *pulLow)
356 {
357 unsigned long ulTemp;
358
359 //
360 // Check the arguments.
361 //
362 ASSERT(ulBase == PECI0_BASE);
363 ASSERT(PECIDomainValid(ulDomain));
364 ASSERT(pulHigh != 0);
365 ASSERT(pulLow != 0);
366
367 //
368 // Get the HTHRESH and LTHRESH fields in the domain control/status
369 // register.
370 //
371 ulTemp = HWREG(ulBase + PECI_O_M0D0C + (ulDomain * 4));
372 *pulHigh = ((ulTemp && PECI_M0D0C_HITHR_M) >> PECI_M0D0C_HITHR_S);
373 *pulLow = ((ulTemp && PECI_M0D0C_LOTHR_M) >> PECI_M0D0C_LOTHR_S);
374 }
375
376 //*****************************************************************************
377 //
378 //! Enables a domain within the PECI module.
379 //!
380 //! \param ulBase is the base address of the PECI module.
381 //! \param ulDomain is the PECI domain that should be enabled.
382 //!
383 //! This function enables the specified PECI domain for temperature monitoring
384 //! operations.
385 //!
386 //! The \e ulDomain parameter can be one of the following values:
387 //! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
388 //! \b PECI_DOMAIN_M1D1.
389 //!
390 //! \return None.
391 //
392 //*****************************************************************************
393 void
PECIDomainEnable(unsigned long ulBase,unsigned long ulDomain)394 PECIDomainEnable(unsigned long ulBase, unsigned long ulDomain)
395 {
396 //
397 // Check the arguments.
398 //
399 ASSERT(ulBase == PECI0_BASE);
400 ASSERT(PECIDomainValid(ulDomain));
401
402 //
403 // Enable the specified domain.
404 //
405 HWREG(ulBase + PECI_O_CTL) |= (1 << ulDomain);
406 }
407
408 //*****************************************************************************
409 //
410 //! Disables a domain within the PECI module.
411 //!
412 //! \param ulBase is the base address of the PECI module.
413 //! \param ulDomain is the PECI domain that should be disabled.
414 //!
415 //! This function disables the specified PECI domain.
416 //!
417 //! The \e ulDomain parameter can be one of the following values:
418 //! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
419 //! \b PECI_DOMAIN_M1D1.
420 //!
421 //! \return None.
422 //
423 //*****************************************************************************
424 void
PECIDomainDisable(unsigned long ulBase,unsigned long ulDomain)425 PECIDomainDisable(unsigned long ulBase, unsigned long ulDomain)
426 {
427 //
428 // Check the arguments.
429 //
430 ASSERT(ulBase == PECI0_BASE);
431 ASSERT(PECIDomainValid(ulDomain));
432
433 //
434 // Disable the specified domain.
435 //
436 HWREG(ulBase + PECI_O_CTL) &= ~(1 << ulDomain);
437 }
438
439 //*****************************************************************************
440 //
441 //! Reads the current temperature value for the specified domain.
442 //!
443 //! \param ulBase is the base address of the PECI module.
444 //! \param ulDomain is the PECI domain that should be disabled.
445 //!
446 //! This function returns the most recently read temperature value from the
447 //! specified domain.
448 //!
449 //! The \e ulDomain parameter can be one of the following values:
450 //! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
451 //! \b PECI_DOMAIN_M1D1.
452 //!
453 //! \return None.
454 //
455 //*****************************************************************************
456 unsigned long
PECIDomainValueGet(unsigned long ulBase,unsigned long ulDomain)457 PECIDomainValueGet(unsigned long ulBase, unsigned long ulDomain)
458 {
459 //
460 // Check the arguments.
461 //
462 ASSERT(ulBase == PECI0_BASE);
463 ASSERT(PECIDomainValid(ulDomain));
464
465 //
466 // Return the most recently polled temperature value
467 //
468 return(((HWREG(ulBase + PECI_O_M0D0 + (ulDomain * 4)) &
469 PECI_M0D0_VALUE_M)));
470 }
471
472 //*****************************************************************************
473 //
474 //! Reads the maximum/error value for the specified domain.
475 //!
476 //! \param ulBase is the base address of the PECI module.
477 //! \param ulDomain is the PECI domain that should be disabled.
478 //!
479 //! This function returns the maximum temperature value for the specified
480 //! domain.
481 //!
482 //! The \e ulDomain parameter can be one of the following values:
483 //! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
484 //! \b PECI_DOMAIN_M1D1.
485 //!
486 //! \return None.
487 //
488 //*****************************************************************************
489 unsigned long
PECIDomainMaxReadGet(unsigned long ulBase,unsigned long ulDomain)490 PECIDomainMaxReadGet(unsigned long ulBase, unsigned long ulDomain)
491 {
492 //
493 // Check the arguments.
494 //
495 ASSERT(ulBase == PECI0_BASE);
496 ASSERT(PECIDomainValid(ulDomain));
497
498 //
499 // Return the most recently polled temperature value
500 //
501 return(((HWREG(ulBase + PECI_O_M0D0 + (ulDomain * 4)) &
502 PECI_M0D0_MAXREAD_M) >> PECI_M0D0_MAXREAD_S));
503 }
504
505 //*****************************************************************************
506 //
507 //! Clears the current temperature value for the specified domain.
508 //!
509 //! \param ulBase is the base address of the PECI module.
510 //! \param ulDomain is the PECI domain that should be disabled.
511 //!
512 //! This function clears the current and maximum values for the specified
513 //! domain.
514 //!
515 //! The \e ulDomain parameter can be one of the following values:
516 //! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
517 //! \b PECI_DOMAIN_M1D1.
518 //!
519 //! \return None.
520 //
521 //*****************************************************************************
522 void
PECIDomainValueClear(unsigned long ulBase,unsigned long ulDomain)523 PECIDomainValueClear(unsigned long ulBase, unsigned long ulDomain)
524 {
525 //
526 // Check the arguments.
527 //
528 ASSERT(ulBase == PECI0_BASE);
529 ASSERT(PECIDomainValid(ulDomain));
530
531 //
532 // Clear the temperature value.
533 //
534 HWREG(ulBase + PECI_O_M0D0 + (ulDomain * 4) ) &= ~PECI_M0D0_VALUE_M;
535 }
536
537 //*****************************************************************************
538 //
539 //! Clears the maximum/error value for the specified domain.
540 //!
541 //! \param ulBase is the base address of the PECI module.
542 //! \param ulDomain is the PECI domain that should be disabled.
543 //!
544 //! This function clears the current and maximum values for the specified
545 //! domain.
546 //!
547 //! The \e ulDomain parameter can be one of the following values:
548 //! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
549 //! \b PECI_DOMAIN_M1D1.
550 //!
551 //! \return None.
552 //
553 //*****************************************************************************
554 void
PECIDomainMaxReadClear(unsigned long ulBase,unsigned long ulDomain)555 PECIDomainMaxReadClear(unsigned long ulBase, unsigned long ulDomain)
556 {
557 //
558 // Check the arguments.
559 //
560 ASSERT(ulBase == PECI0_BASE);
561 ASSERT(PECIDomainValid(ulDomain));
562
563 //
564 // Clear the maximum/error value.
565 //
566 HWREG(ulBase + PECI_O_M0D0 + (ulDomain * 4) ) &= ~PECI_M0D0_MAXREAD_M;
567 }
568
569 //*****************************************************************************
570 //
571 //! Registers an interrupt handler for the PECI module.
572 //!
573 //! \param ulBase specifies the PECI module base address.
574 //! \param pfnHandler is a pointer to the function to be called when the
575 //! PECI interrupt occurs.
576 //!
577 //! This function registers the handler to be called when an PECI interrupt
578 //! occurs. This function enables the global interrupt in the interrupt
579 //! controller; specific PECI interrupts must be enabled via PECIIntEnable().
580 //! If necessary, it is the interrupt handler's responsibility to clear the
581 //! interrupt source via PECIIntClear().
582 //!
583 //! \sa IntRegister() for important information about registering interrupt
584 //! handlers.
585 //!
586 //! \return None.
587 //
588 //*****************************************************************************
589 void
PECIIntRegister(unsigned long ulBase,void (* pfnHandler)(void))590 PECIIntRegister(unsigned long ulBase, void (*pfnHandler)(void))
591 {
592 //
593 // Check the arguments.
594 //
595 ASSERT(ulBase == PECI0_BASE);
596 ASSERT(pfnHandler != 0);
597
598 //
599 // Register the interrupt handler.
600 //
601 IntRegister(INT_PECI0, pfnHandler);
602
603 //
604 // Enable the PECI interrupt.
605 //
606 IntEnable(INT_PECI0);
607 }
608
609 //*****************************************************************************
610 //
611 //! Unregisters an interrupt handler for the PECI module.
612 //!
613 //! \param ulBase specifies the PECI module base address.
614 //!
615 //! This function unregisters the handler to be called when a PECI interrupt
616 //! occurs. This function also masks off the interrupt in the interrupt
617 //! controller so that the interrupt handler no longer is called.
618 //!
619 //! \sa IntRegister() for important information about registering interrupt
620 //! handlers.
621 //!
622 //! \return None.
623 //
624 //*****************************************************************************
625 void
PECIIntUnregister(unsigned long ulBase)626 PECIIntUnregister(unsigned long ulBase)
627 {
628 //
629 // Check the arguments.
630 //
631 ASSERT(ulBase == PECI0_BASE);
632
633 //
634 // Disable the PECI interrupt.
635 //
636 IntDisable(INT_PECI0);
637
638 //
639 // Unregister the interrupt handler.
640 //
641 IntUnregister(INT_PECI0);
642 }
643
644 //*****************************************************************************
645 //
646 //! Enables individual PECI interrupt sources.
647 //!
648 //! \param ulBase specifies the PECI module base address.
649 //! \param ulIntFlags is a bit mask of the interrupt sources to be enabled.
650 //! \param ulIntMode is the mode for the PECI domain interrupts.
651 //!
652 //! This function enables the indicated PECI interrupt sources. Only the
653 //! sources that are enabled can be reflected to the processor interrupt;
654 //! disabled sources have no effect on the processor.
655 //!
656 //! The \e ulIntFlags parameter can be any of the following values:
657 //! \b PECI_READ, \b PECI_ERR, \b PECI_AC, \b PECI_M0D0, \b PECI_M0D1,
658 //! \b PECI_M1D0, or \b PECI_M1D1.
659 //!
660 //! The \e ulIntMode parameter is used to configure the interrupt mode for
661 //! the corresponding \b PECI_DOMAIN_MnDm field, and can be any of the
662 //! following values: \b PECI_M0D0_MODE1, \b PECI_M0D0_MODE2,
663 //! \b PECI_M0D0_MODE3, \b PECI_M0D1_MODE1, \b PECI_M0D1_MODE2,
664 //! \b PECI_M0D1_MODE3. \b PECI_M1D0_MODE1, \b PECI_M1D0_MODE2,
665 //! \b PECI_M1D0_MODE3, \b PECI_M1D1_MODE1, \b PECI_M1D1_MODE2, or
666 //! \b PECI_M1D1_MODE3.
667 //!
668 //! \return None.
669 //
670 //*****************************************************************************
671 void
PECIIntEnable(unsigned long ulBase,unsigned long ulIntFlags,unsigned long ulIntMode)672 PECIIntEnable(unsigned long ulBase, unsigned long ulIntFlags,
673 unsigned long ulIntMode)
674 {
675 unsigned long ulTemp;
676
677 //
678 // Check the arguments.
679 //
680 ASSERT(ulBase == PECI0_BASE);
681
682 //
683 // Get the current mask value.
684 //
685 ulTemp = HWREG(ulBase + PECI_O_IM);
686
687 //
688 // Clear the bit/bit-fields that are configured, based on the value
689 // in the flags parameter.
690 //
691 ulTemp &= ~ulIntFlags;
692
693 //
694 // Set/Enable the bit/bit-fields based on the value in the flags and mode
695 // parameter. The flags parameter alters the bits in the lower half
696 // of the mask, while the mode alters the bit fields in the upper
697 // half of the mask.
698 //
699 ulTemp |= (0x0000FFFF & ulIntFlags);
700 ulTemp |= (0xFFFF0000 & ulIntMode);
701 HWREG(ulBase + PECI_O_IM) = ulTemp;
702 }
703
704 //*****************************************************************************
705 //
706 //! Disables individual PECI interrupt sources.
707 //!
708 //! \param ulBase specifies the PECI module base address.
709 //! \param ulIntFlags is a bit mask of the interrupt sources to be disabled.
710 //!
711 //! This function disables the indicated PECI interrupt sources. Only the
712 //! sources that are enabled can be reflected to the processor interrupt;
713 //! disabled sources have no effect on the processor.
714 //!
715 //! The \e ulIntFlags parameter can be any of the following values:
716 //! \b PECI_READ, \b PECI_ERR, \b PECI_AC, \b PECI_M0D0, \b PECI_M0D1,
717 //! \b PECI_M1D0, or \b PECI_M1D1.
718 //!
719 //! \return None.
720 //
721 //*****************************************************************************
722 void
PECIIntDisable(unsigned long ulBase,unsigned long ulIntFlags)723 PECIIntDisable(unsigned long ulBase, unsigned long ulIntFlags)
724 {
725 //
726 // Check the arguments.
727 //
728 ASSERT(ulBase == PECI0_BASE);
729
730 //
731 // Disable the specified interrupts.
732 //
733 HWREG(ulBase + PECI_O_IM) &= ~ulIntFlags;
734 }
735
736 //*****************************************************************************
737 //
738 //! Gets the current interrupt status.
739 //!
740 //! \param ulBase specifies the PECI module base address.
741 //! \param bMasked is \b false if the raw interrupt status is required or
742 //! \b true if the masked interrupt status is required.
743 //!
744 //! This function returns the interrupt status for the PECI module. Either the
745 //! raw interrupt status or the status of interrupts that are allowed to
746 //! reflect to the processor can be returned.
747 //!
748 //! The interpretation of the PECI_DOMAIN_MnDm fields vary based on the mode
749 //! value programed using the PECIIntEnable() function for the field. Each
750 //! field may take on one of the following values:
751 //! \b PECI_MnDm_MODE1_HIGH, \b PECI_MnDm_MODE2_MID, \b PECI_MnDm_MODE2_HIGH,
752 //! \b PECI_MnDm_MODE3_LOW, \b PECI_MnDm_MODE3_MID, or \b PECI_MnDm_MODE3_HIGH.
753 //!
754 //! \return The current interrupt status, enumerated as a bit field of
755 //! \b PECI_READ, \b PECI_ERR, \b PECI_AC, \b PECI_M0D0, \b PECI_M0D1,
756 //! \b PECI_M1D0, or \b PECI_M1D1.
757 //
758 //*****************************************************************************
759 unsigned long
PECIIntStatus(unsigned long ulBase,tBoolean bMasked)760 PECIIntStatus(unsigned long ulBase, tBoolean bMasked)
761 {
762 //
763 // Check the arguments.
764 //
765 ASSERT(ulBase == PECI0_BASE);
766
767 //
768 // Return either the interrupt status or the raw interrupt status as
769 // requested.
770 //
771 if(bMasked)
772 {
773 return(HWREG(ulBase + PECI_O_MIS));
774 }
775 else
776 {
777 return(HWREG(ulBase + PECI_O_RIS));
778 }
779 }
780
781 //*****************************************************************************
782 //
783 //! Clears PECI interrupt sources.
784 //!
785 //! \param ulBase specifies the PECI module base address.
786 //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared.
787 //!
788 //! This function clears the specified PECI interrupt sources so that they no
789 //! longer assert. This function must be called in the interrupt handler to
790 //! keep the interrupts from being recognized again immediately upon exit.
791 //! The \e ulIntFlags parameter can consist of any combination of the
792 //! \b PECI_READ, \b PECI_ERR, \b PECI_AC, \b PECI_M0D0, \b PECI_M0D1,
793 //! \b PECI_M1D0, or \b PECI_M1D1 values.
794 //!
795 //! \note Because there is a write buffer in the Cortex-M processor, it may
796 //! take several clock cycles before the interrupt source is actually cleared.
797 //! Therefore, it is recommended that the interrupt source be cleared early in
798 //! the interrupt handler (as opposed to the very last action) to avoid
799 //! returning from the interrupt handler before the interrupt source is
800 //! actually cleared. Failure to do so may result in the interrupt handler
801 //! being immediately reentered (because the interrupt controller still sees
802 //! the interrupt source asserted).
803 //!
804 //! \return None.
805 //
806 //*****************************************************************************
807 void
PECIIntClear(unsigned long ulBase,unsigned long ulIntFlags)808 PECIIntClear(unsigned long ulBase, unsigned long ulIntFlags)
809 {
810 //
811 // Check the arguments.
812 //
813 ASSERT(ulBase == PECI0_BASE);
814
815 //
816 // Clear the requested interrupt sources.
817 //
818 HWREG(ulBase + PECI_O_IC) = ulIntFlags;
819 }
820
821 //*****************************************************************************
822 //
823 //! Sends a PECI Advanced Command.
824 //!
825 //! \param ulBase specifies the PECI module base address.
826 //!
827 //! This function sends a PECI Advanced Command. If the interface is not IDLE,
828 //! it waits for the interface to become IDLE then sends the command. The
829 //! function parameters are used to populate the message control fields before
830 //! activating the command.
831 //!
832 //! \return None.
833 //
834 //*****************************************************************************
835 void
PECIAdvCmdSend(unsigned long ulBase,unsigned char ucCmd,unsigned char ucHidRe,unsigned char ucDomain,unsigned char ucProcAdd,unsigned long ulArg,unsigned char ucSize,unsigned long ulData0,unsigned long ulData1)836 PECIAdvCmdSend(unsigned long ulBase, unsigned char ucCmd,
837 unsigned char ucHidRe, unsigned char ucDomain,
838 unsigned char ucProcAdd, unsigned long ulArg,
839 unsigned char ucSize, unsigned long ulData0,
840 unsigned long ulData1)
841 {
842 //
843 // Check the arguments.
844 //
845 ASSERT(ulBase == PECI0_BASE);
846
847 //
848 // Wait for the interface to be idle.
849 //
850 while(HWREG(ulBase + PECI_O_ACCODE) == 0xFFFFFFFF)
851 {
852 }
853
854 //
855 // Fill in the registers for the advanced command.
856 //
857 HWREG(ulBase + PECI_O_ACARG) = ulArg;
858 HWREG(ulBase + PECI_O_ACRDWR0) = ulData0;
859 HWREG(ulBase + PECI_O_ACRDWR1) = ulData1;
860 HWREG(ulBase + PECI_O_ACADDR) = (ucHidRe << 24) |
861 (ucSize << 16) |
862 (ucDomain << 8) |
863 (ucProcAdd << 0);
864
865 //
866 // Now, issue the command.
867 //
868 HWREG(ulBase + PECI_O_ACCMD) = ucCmd;
869 }
870
871 //*****************************************************************************
872 //
873 //! Sends a PECI Advanced Command (non blocking).
874 //!
875 //! \param ulBase specifies the PECI module base address.
876 //!
877 //! This function sends a PECI Advanced Command. If the interface is not IDLE,
878 //! it returns immediately. Otherwise, it sends the the command. The function
879 //! paramters are used to populate the message control fields before activating
880 //! the command.
881 //!
882 //! \return None.
883 //
884 //*****************************************************************************
885 unsigned long
PECIAdvCmdSendNonBlocking(unsigned long ulBase,unsigned char ucCmd,unsigned char ucHidRe,unsigned char ucDomain,unsigned char ucProcAdd,unsigned long ulArg,unsigned char ucSize,unsigned long ulData0,unsigned long ulData1)886 PECIAdvCmdSendNonBlocking(unsigned long ulBase, unsigned char ucCmd,
887 unsigned char ucHidRe, unsigned char ucDomain,
888 unsigned char ucProcAdd, unsigned long ulArg,
889 unsigned char ucSize, unsigned long ulData0,
890 unsigned long ulData1)
891 {
892 //
893 // Check the arguments.
894 //
895 ASSERT(ulBase == PECI0_BASE);
896
897 //
898 // Check for the interface to be idle.
899 // If not, return immediately.
900 //
901 if(HWREG(ulBase + PECI_O_ACCODE) == 0xFFFFFFFF)
902 {
903 return(0);
904 }
905
906 //
907 // Send the command.
908 //
909 PECIAdvCmdSend(ulBase, ucCmd, ucHidRe, ucDomain, ucProcAdd, ulArg,
910 ucSize, ulData0, ulData1);
911
912 //
913 // Return, indicating that the command has been issued.
914 //
915 return(1);
916 }
917
918 //*****************************************************************************
919 //
920 //! Obtains status of previous PECI Advanced Command.
921 //!
922 //! \param ulBase specifies the PECI module base address.
923 //!
924 //! This function gets the status of a previously issued PECI Advanced Command.
925 //! If the command has completed, and the data pointers are non-zero, the data
926 //! registers are read and saved.
927 //!
928 //! \return -1 if command has not yet been completed, otherwise, the return
929 //! code associated with the Advanced Command.
930 //
931 //*****************************************************************************
932 unsigned long
PECIAdvCmdStatusGet(unsigned long ulBase,unsigned long * pulData0,unsigned long * pulData1)933 PECIAdvCmdStatusGet(unsigned long ulBase, unsigned long *pulData0,
934 unsigned long *pulData1)
935 {
936 unsigned long ulCode;
937
938 //
939 // Check the arguments.
940 //
941 ASSERT(ulBase == PECI0_BASE);
942
943 //
944 // If the command has completed, optionally read and save the data
945 // registers.
946 //
947 ulCode = HWREG(ulBase + PECI_O_ACCODE);
948 if(ulCode != 0xFFFFFFFF)
949 {
950 if(pulData0 != (void *)0)
951 {
952 *pulData0 = HWREG(ulBase + PECI_O_ACRDWR0);
953 }
954 if(pulData1 != (void *)0)
955 {
956 *pulData1 = HWREG(ulBase + PECI_O_ACRDWR1);
957 }
958 }
959
960 //
961 // Return the command code from the most recently completed command.
962 //
963 return(ulCode);
964 }
965
966 //*****************************************************************************
967 //
968 // Close the Doxygen group.
969 //! @}
970 //
971 //*****************************************************************************
972