3228f71417c86fff39c44955ddd83c105ebce19f
[keystone-rtos/ibl.git] / src / util / i2cConfig / i2cparam.c
1 /*
2  *
3  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 
4  * 
5  * 
6  *  Redistribution and use in source and binary forms, with or without 
7  *  modification, are permitted provided that the following conditions 
8  *  are met:
9  *
10  *    Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  *    Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the 
15  *    documentation and/or other materials provided with the   
16  *    distribution.
17  *
18  *    Neither the name of Texas Instruments Incorporated nor the names of
19  *    its contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
23  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
24  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
26  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
27  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
28  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
31  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
32  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34 */
38 /*************************************************************************************
39  * FILE PURPOSE: Write the ibl configuration table to the i2c eeprom
40  *************************************************************************************
41  * @file i2cparam.c
42  *
43  * @brief
44  *        Creates the ibl configuration table and writes to the i2c
45  *
46  *************************************************************************************/
48 #include "types.h" 
49 #include "ibl.h"
50 #include "i2c.h"
51 #include "pllapi.h"
52 #include "iblcfg.h"
53 #include "target.h"
54 #include "string.h"
55 #include <stdlib.h>
56 #include <stdio.h>
58 ibl_t ibl;
60 /* The configAddress must be programmed. On images which support both endians
61  * there can be two seperate configurations, one for big endian, and one for little */
62 unsigned int configBusAddress = I2C_BUS_ADDR;
63 unsigned int configAddress = I2C_MAP_ADDR;
66 /**
67  *  @brief
68  *      Ones complement addition
69  */
70 inline uint16 onesComplementAdd (uint16 value1, uint16 value2)
71 {
72   uint32 result;
74   result = (uint32)value1 + (uint32)value2;
76   result = (result >> 16) + (result & 0xFFFF); /* add in carry   */
77   result += (result >> 16);                    /* maybe one more */
78   return ((uint16)result);
79 }
82 /**
83  *  @brief
84  *      Ones complement checksum computation 
85  */
86 uint16 onesComplementChksum (uint16 * restrict p_data, uint16 len)
87 {
88   uint16 chksum = 0;
90   while (len > 0)
91   {
92     chksum = onesComplementAdd(chksum, *p_data);
93     p_data++;
94     len--;
95   }
96   return (chksum);
97
99 /**
100  *  @brief
101  *     Display the error returned by the i2c driver 
102  */
103 void showI2cError (I2C_RET iret, char *stage)
105     char *ecode;
107     switch (iret)  {
108         case I2C_RET_LOST_ARB:        ecode = "I2C master lost an arbitration battle";
109                                       break;
111         case I2C_RET_NO_ACK:          ecode = "I2C master detected no ack from slave";
112                                       break;
114         case I2C_RET_IDLE_TIMEOUT:    ecode = "I2C timed out";
115                                       break;
117         case I2C_RET_BAD_REQUEST:     ecode = "I2C driver detected a bad data request";
118                                       break;
120         case I2C_RET_CLOCK_STUCK_LOW: ecode = "I2C driver found the bus stuck low";
121                                       break;
123         case I2C_RET_GEN_ERROR:       ecode = "I2C driver reported a general error";
124                                       break;
126     }
128     printf ("Error: %s, reported at stage: %s\n", ecode, stage);
132 /**
133  * @brief
134  *   Group the data into a 64 byte (max) data block aligned on a 64 byte boundary 
135  */
136 Int32 formBlock (UINT8 *base, Int32 dataSize, Int32 *offset, Uint8 *data, Uint32 baseI2cDataAddr)
138     Uint32 currentAddress;
139     Int32  nbytes;
140     Int32  i;
142     /* The I2C eeprom address is the parameter base address plus the current offset
143      * The number of bytes is blocked to end on a 64 byte boundary */
144     currentAddress = baseI2cDataAddr + *offset;
145     nbytes         = 64 - (currentAddress & (64 - 1));
147     /* Only write the bytes in the input array */
148     if (*offset + nbytes > dataSize)
149         nbytes = dataSize - *offset;
151     if (nbytes == 0)
152         return (0);
154     /* The address is placed first */
155     data[0] = (currentAddress >> 8) & 0xff;
156     data[1] = (currentAddress >> 0) & 0xff;
158     /* The data */
159     for (i = 0; i < nbytes; i++)
160         data[i+2] = base[*offset + i];
162     /* Update the offset */
163     *offset += nbytes;
165     /* Return the total number of bytes (including address) to go on the bus */
166     return (nbytes + 2);
172 void main (void)
174     I2C_RET  iret;
175     UINT8    writeBlock[66];
176     char     iline[132];
177     Int32    n; 
178     Int32    currentOffset;
179     uint16   chk; 
181     volatile Int32 i;
183     if (configAddress == 0)  {
184       printf ("Error: The global variable config address must be setup prior to running this program\n");
185       printf ("       This is the address in the I2C eeprom where the parameters live. On configurations\n");
186       printf ("       which support both big and little endian it is possible to configure the IBL to\n");
187       printf ("       usage a different configuration table for each endian, so this program must be run\n");
188       printf ("       twice. The value 0 is invalid for configAddress\n");
189       return;
190     }
192     printf ("Run the GEL for for the device to be configured, press return to program the I2C\n");
193     getchar ();
195     /* Program the main system PLL */
196     hwPllSetPll (MAIN_PLL,      
197                  ibl.pllConfig[ibl_MAIN_PLL].prediv,         /* Pre-divider  */
198                  ibl.pllConfig[ibl_MAIN_PLL].mult,           /* Multiplier   */
199                  ibl.pllConfig[ibl_MAIN_PLL].postdiv);       /* Post-divider */
202     hwI2Cinit (ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz,  /* The CPU frequency during I2C data load */
203                DEVICE_I2C_MODULE_DIVISOR,                  /* The divide down of CPU that drives the i2c */
204                IBL_CFG_I2C_CLK_FREQ_KHZ/8,                 /* The I2C data rate used during table load. Slowed for writes */
205                IBL_CFG_I2C_OWN_ADDR);                      /* The address used by this device on the i2c bus */
208     /* Compute the checksum over the ibl configuration structure */
209     ibl.chkSum = 0;
210     chk = onesComplementChksum ((uint16 *)&ibl, sizeof(ibl_t)/sizeof(uint16));
211     if (ibl.chkSum != 0xffff)
212       ibl.chkSum = ~chk;
214     
216     /* Block the data into 64 byte blocks aligned on 64 byte boundaries for the data write.
217      * The block address is prepended to the data block before writing */
218     currentOffset = 0;
219     do  {
221         n = formBlock ((UINT8 *)&ibl, sizeof(ibl_t), &currentOffset, writeBlock, configAddress);
223         if (n > 0)  {
225             iret = hwI2cMasterWrite (configBusAddress,   /* The I2C bus address of the eeprom */
226                                      writeBlock,         /* The data to write */
227                                      n,                  /* The number of bytes to write */
228                                      I2C_RELEASE_BUS,    /* Release the bus when the write is done */
229                                      FALSE );            /* Bus is not owned at start of operation */
231             if (iret != I2C_RET_OK)  {
232                 sprintf (iline, "Block at offset %d\n", currentOffset);
233                 showI2cError (iret, iline);
234                 return;
235             }
237             /* Need some delay to allow the programming to occur */
238             for (i = 0; i < 600000; i++);
240         }
242     } while (n > 0);
243             
244     
246     printf ("I2c table write complete\n");
252