sysMpc85xxI2c.c
上传用户:dqzhongke1
上传日期:2022-06-26
资源大小:667k
文件大小:12k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* sysMpc85xxI2c.c - I2C Driver Source Module */
  2. /*
  3.  * Copyright (c) 2005-2006 Wind River Systems, Inc.
  4.  *
  5.  * The right to copy, distribute, modify, or otherwise make use
  6.  * of this software may be licensed only pursuant to the terms
  7.  * of an applicable Wind River license agreement.
  8.  */
  9. /*
  10. modification history
  11. --------------------
  12. 01c,27jan06,dtr  Fix EepromShow and tidyup.
  13. 01b,04apr05,mdo  Documentation fixes for apigen
  14. 01a,28feb05,dtr  created.
  15. */
  16. /*
  17. DESCRIPTION
  18. I2C Driver Source (Low Level Routines) Module
  19. Mpc85xx Memory Controller (PowerPlus Architecture)
  20. Notes:
  21.    1. GREAT care must be made when sending commands to the
  22.       MPC85XX(Mpc85xx).  Several "i2cCycleMpc85xxDelay" calls are made
  23.       in order to not overwhelm the I2C interface.  If commands
  24.       are sent too fast, the I2C interface will lockup and the I2C
  25.       bus may become unusable without a powercycle.  Generally, if
  26.       you cause a I2C bus cycle, you should wait for "a while".
  27.       A possible cause is that the caches were turned on when this
  28.       driver was written.
  29. INCLUDE FILES:   sysMpc85xxI2c.h
  30. */
  31. /* includes */
  32. #include <vxWorks.h>        /* vxWorks generics */
  33. #include "config.h"
  34. #include "sysMotI2c.h"
  35. #include "sysMpc85xxI2c.h"  /* low level definitions, specific */
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <logLib.h>
  39. #include <stdlib.h>
  40. #include <taskLib.h>
  41. #include <arch/ppc/vxPpcLib.h>
  42. /* externals */
  43. IMPORT I2C_DRV_CTRL * pI2cDrvCtrl[2] ;
  44. IMPORT void sysMsDelay(UINT);
  45. /* forward declarations */
  46. void sysMpc85xxMsDelay (UINT mSeconds);
  47. void i2cCycleMpc85xxDelay (int mSeconds);
  48. /* Global flag */
  49. int I2CDoRepeatStart = 0;   /* indicates if a "Repeat Start" is requested */
  50. /******************************************************************************
  51. *
  52. * i2cCycleMpc85xxStart - perform I2C "start" cycle
  53. *
  54. * This function's purpose is to perform an I2C start cycle.
  55. *
  56. * RETURNS:
  57. *   zero        = operation successful
  58. *   non-zero    = operation failed
  59. *
  60. * ERRNO: N/A
  61. */
  62. int i2cCycleMpc85xxStart
  63.     (
  64.     int unit
  65.     )
  66.     {
  67.     unsigned int timeOutCount;
  68.     UINT8 statusReg = 0;
  69.     if (pI2cDrvCtrl[unit] == NULL)
  70.         return -1 ;
  71.     /*
  72.      * if this is a repeat start, then set the required bits and return.
  73.      *
  74.      * NOTE:
  75.      * this driver ONLY supports one repeat start between the start
  76.      * stop and cycles.
  77.      */
  78.     if ( I2CDoRepeatStart == 1 )
  79.         {
  80.         i2cIoctl(I2C_IOCTL_RMW_OR,
  81.                     (UINT32)(pI2cDrvCtrl[unit]->baseAdrs+MPC85XX_I2C_CONTROL_REG),
  82.                     (MPC85XX_I2C_CONTROL_REG_RSTA |
  83.                      MPC85XX_I2C_CONTROL_REG_MSTA |
  84.                      MPC85XX_I2C_CONTROL_REG_MTX),0);
  85.         I2CDoRepeatStart = 0;  /* one repeat start only, so clear this bit */
  86.         return(0);
  87.         }
  88.     /*
  89.      * wait until the I2C bus is free.  if it doesn't become free
  90.      * within a *reasonable* amount of time, exit with an error.
  91.      */
  92.     for ( timeOutCount = 100; timeOutCount; timeOutCount-- )
  93.         {
  94.         statusReg = i2cIoctl(I2C_IOCTL_RD,
  95.                             (UINT32)(pI2cDrvCtrl[unit]->baseAdrs+MPC85XX_I2C_STATUS_REG), 0, 0);
  96.         if ( !(statusReg & MPC85XX_I2C_STATUS_REG_MBB) )
  97.             {
  98.             break;
  99.             }
  100. sysMpc85xxMsDelay(1);
  101.         }
  102.     if ( !timeOutCount )
  103.         {
  104.         return(-1);
  105.         }
  106.     /*
  107.      * since this is the first time through, generate a START(MSTA) and
  108.      * place the I2C interface into a master transmitter mode(MTX).
  109.      */
  110.     i2cIoctl(I2C_IOCTL_RMW_OR,
  111.             (UINT32)(pI2cDrvCtrl[unit]->baseAdrs+MPC85XX_I2C_CONTROL_REG),
  112.             (MPC85XX_I2C_CONTROL_REG_MTX |
  113.              MPC85XX_I2C_CONTROL_REG_MSTA),0);
  114.     /*
  115.      * The first time through, set "I2CDoRepeatStart".  If this function
  116.      * is called again BEFORE a STOP is sent, then we are doing a
  117.      * "dummy write", which sets the devices internal byte pointer
  118.      * to the byte we intend to read.
  119.      */
  120.     I2CDoRepeatStart = 1;
  121.     return(0);
  122.     }
  123. /******************************************************************************
  124. *
  125. * i2cCycleMpc85xxStop - perform I2C "stop" cycle
  126. *
  127. * This function's purpose is to perform an I2C stop cycle.
  128. *
  129. * RETURNS:
  130. *   zero        = operation successful
  131. *   non-zero    = operation failed
  132. *
  133. * ERRNO: N/A
  134. */
  135. int i2cCycleMpc85xxStop
  136.     (
  137.     int unit
  138.     )
  139.     {
  140.     if (pI2cDrvCtrl[unit] == NULL)
  141.         return -1 ;
  142.     /*
  143.      * turn off MSTA bit(which will generate a STOP bus cycle)
  144.      * turn off MTX bit(which places the MPC85XX interface into receive mode
  145.      * turn off TXAK bit(which allows 9th clock cycle acknowledges)
  146.      */
  147.     sysMpc85xxMsDelay(1);
  148.     i2cIoctl(I2C_IOCTL_RMW_AND,
  149.             (UINT32)(pI2cDrvCtrl[unit]->baseAdrs+MPC85XX_I2C_CONTROL_REG),
  150.             ((UINT8)~(MPC85XX_I2C_CONTROL_REG_MTX  |
  151.                MPC85XX_I2C_CONTROL_REG_MSTA |
  152.                MPC85XX_I2C_CONTROL_REG_TXAK)), 0);
  153.     /*
  154.      * Clear the global I2C "Repeat Start" flag.
  155.      */
  156.     I2CDoRepeatStart = 0;
  157.     return(0);
  158.     }
  159. /******************************************************************************
  160. *
  161. * i2cCycleMpc85xxRead - perform I2C "read" cycle
  162. *
  163. * This function's purpose is to perform an I2C read cycle.
  164. *
  165. * RETURNS:
  166. *   zero        = operation successful
  167. *   non-zero    = operation failed
  168. *
  169. * ERRNO: N/A
  170. */
  171. int i2cCycleMpc85xxRead
  172.     (
  173.     int unit,
  174.     unsigned char *pReadDataBuf,    /* pointer to read data buffer */
  175.     int ack    /* 0 = don't ack, 1 = ack */
  176.     )
  177.     {
  178.     unsigned int readData = 0;
  179.     if (pI2cDrvCtrl[unit] == NULL)
  180.         return -1 ;
  181.     /*
  182.      * place the I2C interface into receive mode(MTX=0) and set the interface
  183.      * to NOT acknowledge(TXAK=1) the incoming data on the 9th clock cycle.
  184.      * this is required when doing random reads of a I2C device.
  185.      */
  186.     if (!ack)
  187.         {
  188.         /* Don't send master ack. */
  189.         i2cIoctl(I2C_IOCTL_RMW_AND_OR,
  190.             (UINT32)(pI2cDrvCtrl[unit]->baseAdrs+MPC85XX_I2C_CONTROL_REG),
  191.             ((UINT8)~MPC85XX_I2C_CONTROL_REG_MTX),
  192.               MPC85XX_I2C_CONTROL_REG_TXAK);
  193.         }
  194.     else
  195.         {
  196.         /* Send master ack. */
  197.         i2cIoctl(I2C_IOCTL_RMW_AND_OR,
  198.             (UINT32)(pI2cDrvCtrl[unit]->baseAdrs+MPC85XX_I2C_CONTROL_REG),
  199.             ((UINT8)~(MPC85XX_I2C_CONTROL_REG_MTX|MPC85XX_I2C_CONTROL_REG_TXAK)),
  200.               0);
  201.         }
  202.     sysMpc85xxMsDelay(1);
  203.     /* do a "dummy read".  this latches the data off the bus. */
  204.     i2cIoctl(I2C_IOCTL_RD,
  205.             (UINT32)(pI2cDrvCtrl[unit]->baseAdrs+MPC85XX_I2C_DATA_REG),
  206.             0, 0);
  207.     /* now do the actual read, make this one count */
  208.     sysMpc85xxMsDelay(1);
  209.     readData = i2cIoctl(I2C_IOCTL_RD,
  210.                        (UINT32)(pI2cDrvCtrl[unit]->baseAdrs+MPC85XX_I2C_DATA_REG),
  211.                        0, 0);
  212.     *pReadDataBuf = (unsigned char)readData;
  213.     return(0);
  214.     }
  215. /******************************************************************************
  216. *
  217. * i2cCycleMpc85xxWrite - perform I2C "write" cycle
  218. *
  219. * This function's purpose is to perform an I2C write cycle.
  220. *
  221. * RETURNS:
  222. *   zero        = operation successful
  223. *   non-zero    = operation failed
  224. *
  225. * ERRNO: N/A
  226. */
  227. int i2cCycleMpc85xxWrite
  228.     (
  229.     int             unit,
  230.     unsigned char   writeData   /* character to write */
  231.     )
  232.     {
  233.     if (pI2cDrvCtrl[unit] == NULL)
  234.         return -1 ;
  235.     /*
  236.      * write the requested data to the data register, which will cause
  237.      * it to be transmitted on the I2C bus.
  238.      */
  239.     i2cIoctl(I2C_IOCTL_WR,
  240.             (UINT32)(pI2cDrvCtrl[unit]->baseAdrs+MPC85XX_I2C_DATA_REG),
  241.             (UINT32)writeData, 0);
  242.     return(0);
  243.     }
  244. /******************************************************************************
  245. *
  246. * i2cCycleMpc85xxAckIn - perform I2C "acknowledge-in" cycle
  247. *
  248. * This function's purpose is to perform an I2C acknowledge-in cycle.
  249. *
  250. * RETURNS:
  251. *   zero        = operation successful
  252. *   non-zero    = operation failed
  253. *
  254. * ERRNO: N/A
  255. */
  256. int i2cCycleMpc85xxAckIn
  257.     (
  258.     int unit
  259.     )
  260.     {
  261.     unsigned int statusReg = 0;
  262.     unsigned int timeOutCount;
  263.     if (pI2cDrvCtrl[unit] == NULL)
  264.         return -1 ;
  265.     /*
  266.      * wait until an *internal* device interrupt has been generated, then
  267.      * clear it.  if it is not received, return with an error.
  268.      * we are polling, so NO processor interrupt is generated.
  269.      */
  270.     for ( timeOutCount = 10000; timeOutCount; timeOutCount-- )
  271.         {
  272.         statusReg = i2cIoctl(I2C_IOCTL_RD,
  273.                             (UINT32)(pI2cDrvCtrl[unit]->baseAdrs+MPC85XX_I2C_STATUS_REG), 0, 0);
  274.         if ( statusReg & MPC85XX_I2C_STATUS_REG_MIF )
  275.             {
  276.             i2cIoctl(I2C_IOCTL_RMW_AND,
  277.                     (UINT32)(pI2cDrvCtrl[unit]->baseAdrs+MPC85XX_I2C_STATUS_REG),
  278.                     ((UINT8)~MPC85XX_I2C_STATUS_REG_MIF), 0);
  279.             break;
  280.             }
  281.         }
  282.     if ( !timeOutCount )
  283.         {
  284.         return(-1);
  285.         }
  286.     return(0);
  287.     }
  288. /******************************************************************************
  289. *
  290. * i2cCycleMpc85xxAckOut - perform I2C "acknowledge-out" cycle
  291. *
  292. * This function's purpose is to perform an I2C acknowledge-out cycle.
  293. *
  294. * RETURNS:
  295. *   zero        = operation successful
  296. *   non-zero    = operation failed
  297. *
  298. * ERRNO: N/A
  299. */
  300. int i2cCycleMpc85xxAckOut
  301.     (
  302.     int unit
  303.     )
  304.     {
  305.     if (pI2cDrvCtrl[unit] == NULL)
  306.         return -1 ;
  307.     return(0);
  308.     }
  309. /******************************************************************************
  310. *
  311. * i2cCycleMpc85xxKnownState - initialize the I2C bus to a known state
  312. *
  313. * This function's purpose is to initialize the I2C bus to a known state.
  314. *
  315. * RETURNS:
  316. *   zero        = operation successful
  317. *   non-zero    = operation failed
  318. *
  319. * ERRNO: N/A
  320. */
  321. int i2cCycleMpc85xxKnownState
  322.     (
  323.     int unit
  324.     )
  325.     {
  326.     STATUS status;
  327.     UINT   timeOutCount;
  328.     UINT   statusReg;
  329.     status = OK;
  330.     if (pI2cDrvCtrl[unit] == NULL)
  331.         return ERROR ;
  332.     /*
  333.      * wait until the I2C bus is free.  if it doesn't become free
  334.      * within a *reasonable* amount of time, exit with an error.
  335.      */
  336.     for ( timeOutCount = 1000; timeOutCount; timeOutCount-- )
  337.         {
  338.         statusReg = i2cIoctl(I2C_IOCTL_RD,
  339.                             (UINT32)(pI2cDrvCtrl[unit]->baseAdrs+MPC85XX_I2C_STATUS_REG), 0, 0);
  340.         if ( !(statusReg & MPC85XX_I2C_STATUS_REG_MBB) )
  341.             {
  342.             status = OK;
  343.             break;
  344.             }
  345.         /*
  346.          * re-initialize the I2C if the BUS BUSY does not clear
  347.          * after trying half the *reasonable* amount of reads of the
  348.          * status register.
  349.          */
  350.         if ( !(timeOutCount % 50) )
  351.             {
  352.             status = i2cDrvInit(unit, I2C_DRV_TYPE);
  353.             if ( status == OK )
  354.                 break;
  355.             else
  356.                 return ERROR ;
  357.             }
  358.         }
  359.     if ( !timeOutCount )
  360.         status = ERROR;
  361.     return(status);
  362.     }
  363. /******************************************************************************
  364. *
  365. * i2cCycleMpc85xxDelay - perform interface's I2C delay routine
  366. *
  367. * This function's purpose is to perform whatever delay required for the device.
  368. *
  369. * RETURNS:  N/A
  370. *
  371. * ERRNO: N/A
  372. */
  373. void i2cCycleMpc85xxDelay
  374.     (
  375.     int mSeconds    /* time to delay in milliseconds */
  376.     )
  377.     {
  378.     sysMpc85xxMsDelay(mSeconds);
  379.     }
  380. /******************************************************************************
  381. *
  382. * sysMpc85xxMsDelay - delay for the specified amount of time (MS)
  383. *
  384. * This routine will delay for the specified amount of time by counting
  385. * decrementer ticks.
  386. *
  387. * This routine is not dependent on a particular rollover value for
  388. * the decrementer, it should work no matter what the rollover
  389. * value is.
  390. *
  391. * A small amount of count may be lost at the rollover point resulting in
  392. * the sysMpc85xxMsDelay() causing a slightly longer delay than requested.
  393. *
  394. * This routine will produce incorrect results if the delay time requested
  395. * requires a count larger than 0xffffffff to hold the decrementer
  396. * elapsed tick count.  For a System Bus Speed of 67 MHz this amounts to
  397. * about 258 seconds.
  398. *
  399. * RETURNS: N/A
  400. *
  401. * ERRNO: N/A
  402. */
  403. void sysMpc85xxMsDelay
  404.     (
  405.     UINT        delay            /* length of time in MS to delay */
  406.     )
  407.     {
  408.     sysMsDelay(delay);
  409.     }