peci.c 32 KB

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