aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike J. Chen <mjchen@google.com>2012-03-01 13:49:38 -0800
committerMike J. Chen <mjchen@google.com>2012-03-07 10:01:13 -0800
commitb2a35767def33998341a33eb7c62be2a1dafbeb5 (patch)
tree4298cea4baa5983478101541eab4b7b9529c68a1
parentb93c6cbffaf30afbb47c59b710e70e2735a33108 (diff)
downloaduboot-b2a35767def33998341a33eb7c62be2a1dafbeb5.tar.gz
OMAP4: Add command to call PPAL HAL CPFROM APIs
PPA HAL CPFROM APIs are used to configure the CPFROM module and program eFuses. Change-Id: I33ba8a12f5bb1d51c6fbd47795a5f9491a4a1cf1 Signed-off-by: Carlos Leija <cileija@ti.com> Signed-off-by: Mike J. Chen <mjchen@google.com>
-rw-r--r--arch/arm/cpu/armv7/omap4/Makefile1
-rw-r--r--arch/arm/cpu/armv7/omap4/bch.c301
-rw-r--r--common/Makefile3
-rw-r--r--common/cmd_cpfrom.c134
4 files changed, 439 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv7/omap4/Makefile b/arch/arm/cpu/armv7/omap4/Makefile
index 567596bb0..cad1071d2 100644
--- a/arch/arm/cpu/armv7/omap4/Makefile
+++ b/arch/arm/cpu/armv7/omap4/Makefile
@@ -36,6 +36,7 @@ ifndef CONFIG_SPL_BUILD
COBJS += mem.o
COBJS += sys_info.o
COBJS-$(CONFIG_OMAP_SECURE_HAL) += hal_services.o
+COBJS-$(CONFIG_OMAP_CPFROM) += bch.o
COBJS += $(COBJS-y)
endif
diff --git a/arch/arm/cpu/armv7/omap4/bch.c b/arch/arm/cpu/armv7/omap4/bch.c
new file mode 100644
index 000000000..605244caa
--- /dev/null
+++ b/arch/arm/cpu/armv7/omap4/bch.c
@@ -0,0 +1,301 @@
+/* ____________________________________________________________________________
+*
+* Filename : bch.c
+*______________________________________________________________________________
+*
+* History:
+* 24 Apr 2008 : Creation
+*____________________________________________________________________________*/
+
+/*_______________________________ Include Files _____________________________*/
+#include <common.h>
+#include <asm/arch/omap4_hal.h>
+/*________________________________ Local Types ______________________________*/
+
+/*______________________________ Local Constants ____________________________*/
+
+#define mm_max 8 /* Dimension of Galois Field */
+#define nn_max 256 /* Length of codeword, n = 2**m - 1 */
+#define tt_max 2 /* Number of errors that can be corrected */
+#define kk_max 256 /* Length of information bit, kk = nn - rr */
+#define rr_max 32 /* Number of parity checks, rr = deg[g(x)] */
+#define parallel_max 8 /* Number of parallel encoding/syndrome computations */
+
+/*______________________________ Local Variables ____________________________*/
+int i, j;
+int gen_roots[nn_max + 1], gen_roots_true[nn_max + 1] ; // Roots of generator polynomial
+int iii, jjj, Temp ;
+int bb_temp[rr_max] ;
+int loop_count ;
+int mask ; // Register states
+
+int mm, nn, kk, tt, rr; // BCH code parameters
+int nn_shorten, kk_shorten; // Shortened BCH code
+int Parallel ; // Parallel processing
+int p[mm_max + 1], alpha_to[nn_max], index_of[nn_max] ; // Galois field
+int gg[rr_max] ; // Generator polynomial
+int bb[rr_max] ; // Parity checks
+int T_G[rr_max][rr_max], T_G_R[rr_max][rr_max]; // Parallel lookahead table
+int T_G_R_Temp[rr_max][rr_max] ;
+int data[kk_max], data_p[parallel_max][kk_max]; // Information data and received data
+/*______________________________ Local Functions Declarations _______________*/
+
+/*______________________________ Global Functions ___________________________*/
+
+U32 hexStringtoInteger(const char* hexString, U32* result)
+{
+ int iL;
+ int temp;
+ int factor;
+ int length;
+
+ length = strlen(hexString);
+ if ((length == 0) || (length>8))
+ return 1;
+ *result = 0;
+ factor = 1;
+ /* Convert the characters to hex number */
+ for(iL=length-1; iL>=0 ;iL--)
+ {
+ if (*(hexString+iL)>=97){
+ temp = ( *(hexString+iL) - 97) + 10;
+ }else if ( *(hexString+iL) >= 65){
+ temp = (*(hexString+iL) - 65) + 10;
+ }else{
+ temp = *(hexString+iL) - 48;
+ }
+ *result += (temp * factor);
+ factor *= 16;
+ }
+ return 0;
+}
+
+U32 cpfrom_bit_reverse32(U32 value)
+{
+ U32 value_i;
+ U32 value_o;
+ U32 itr;
+
+ value_i=value;
+ value_o=value_i & 1;
+
+ for(itr=0; itr<31; itr++)
+ {
+ value_o = value_o<<1;
+ value_i = value_i>>1;
+ value_o = value_o | (value_i & 1);
+ }
+ return value_o;
+}
+
+U32 cpfrom_byte_reverse32(U32 value)
+{
+ U32 value_i;
+ U32 value_o;
+ U32 itr;
+
+ value_i=value;
+ value_o=value_i & 0xFF;
+
+ for(itr=0; itr<3; itr++)
+ {
+ value_o = value_o<<8;
+ value_i = value_i>>8;
+ value_o = value_o | (value_i & 0xFF);
+ }
+ return value_o;
+}
+
+U32 bch_enc(U8 index, U32 in_v[])
+{
+ U32 out_v;
+
+ if (index == 1){
+ kk_shorten = 32;
+ mm = 6;
+ }
+ else if (index == 4){
+ kk_shorten = 128;
+ mm = 8;
+ }
+ else
+ return 0xFFFFFFFF;
+
+ tt = 2;
+ Parallel = 8;
+
+// nn = (int)pow(2, mm) - 1 ;
+ nn = 1; /* nn = (int)pow(2, mm) - 1 ; */
+ for (j = 0 ; j < mm ; j++) /* nn = (int)pow(2, mm) - 1 ; */
+ nn = nn * 2; /* nn = (int)pow(2, mm) - 1 ; */
+ nn = nn - 1; /* nn = (int)pow(2, mm) - 1 ; */
+
+// INPUT
+ for (j = 0 ; j < index ; j++)
+ { for (i = 0 ; i < 32 ; i++)
+ { if (0x1 & (in_v[j] >> i))
+ data[32*(j+1)-i-1] = 1 ;
+ else
+ data[32*(j+1)-i-1] = 0 ;
+ }
+ }
+
+// generate the Galois Field GF(2**mm)
+ // Primitive polynomials
+ for (i = 1; i < mm; i++)
+ p[i] = 0;
+ p[0] = p[mm] = 1;
+ if (mm == 6) p[1] = 1;
+ else if (mm == 8) p[4] = p[5] = p[6] = 1;
+
+ // Galois field implementation with shift registers
+ mask = 1 ;
+ alpha_to[mm] = 0 ;
+ for (i = 0; i < mm; i++)
+ { alpha_to[i] = mask ;
+ index_of[alpha_to[i]] = i ;
+ if (p[i] != 0)
+ alpha_to[mm] ^= mask ;
+
+ mask <<= 1 ;
+ }
+
+ index_of[alpha_to[mm]] = mm ;
+ mask >>= 1 ;
+ for (i = mm + 1; i < nn; i++)
+ { if (alpha_to[i-1] >= mask)
+ alpha_to[i] = alpha_to[mm] ^ ((alpha_to[i-1] ^ mask) << 1) ;
+ else alpha_to[i] = alpha_to[i-1] << 1 ;
+
+ index_of[alpha_to[i]] = i ;
+ }
+ index_of[0] = -1 ;
+
+// Compute the generator polynomial and lookahead matrix for BCH code
+ // Initialization of gen_roots
+ for (i = 0; i <= nn; i++)
+ { gen_roots_true[i] = 0;
+ gen_roots[i] = 0;
+ }
+
+ // Cyclotomic cosets of gen_roots
+ for (i = 1; i <= 2*tt ; i++)
+ {
+ for (j = 0; j < mm; j++)
+ {
+// Temp = ((int)pow(2, j) * i) % nn;
+ Temp = 1; /* Temp = ((int)pow(2, j) * i); */
+ for(jjj=0; jjj<j; jjj++) /* Temp = ((int)pow(2, j) * i); */
+ Temp = Temp * 2; /* Temp = ((int)pow(2, j) * i); */
+// Temp = fmod((double)(Temp * i), (double)nn);
+ Temp = (Temp * i) % nn; /* Temp = ((int)pow(2, j) * i) % nn; */
+ gen_roots_true[Temp] = 1;
+ }
+ }
+
+ rr = 0; // Count the number of parity check bits
+ for (i = 0; i < nn; i++)
+ { if (gen_roots_true[i] == 1)
+ { rr++;
+ gen_roots[rr] = i;
+ }
+ }
+ kk = nn - rr;
+
+ // Compute generator polynomial based on its roots
+ gg[0] = 2 ; // g(x) = (X + alpha) initially
+ gg[1] = 1 ;
+ for (i = 2; i <= rr; i++)
+ { gg[i] = 1 ;
+ for (j = i - 1; j > 0; j--)
+ {
+ if (gg[j] != 0)
+// gg[j] = gg[j-1]^ alpha_to[fmod((double)(index_of[gg[j]] + index_of[alpha_to[gen_roots[i]]]), (double)nn)] ;
+ gg[j] = gg[j-1]^ alpha_to[(index_of[gg[j]] + index_of[alpha_to[gen_roots[i]]]) % nn] ;
+ else
+ gg[j] = gg[j-1] ;
+ }
+// gg[0] = alpha_to[fmod((double)(index_of[gg[0]] + index_of[alpha_to[gen_roots[i]]]), (double)nn)] ;
+ gg[0] = alpha_to[(index_of[gg[0]] + index_of[alpha_to[gen_roots[i]]]) % nn] ;
+ }
+
+ // for parallel encoding and syndrome computation
+ // Max parallalism is rr
+ if (Parallel > rr)
+ Parallel = rr ;
+
+ // Construct parallel lookahead matrix T_g, and T_g**r from gg(x)
+ for (i = 0; i < rr; i++)
+ { for (j = 0; j < rr; j++)
+ T_G[i][j] = 0;
+ }
+ for (i = 1; i < rr; i++)
+ T_G[i][i-1] = 1 ;
+ for (i = 0; i < rr; i++)
+ T_G[i][rr - 1] = gg[i] ;
+ for (i = 0; i < rr; i++)
+ { for (j = 0; j < rr; j++)
+ T_G_R[i][j] = T_G[i][j];
+ }
+
+ // Compute T_G**R Matrix
+ for (iii = 1; iii < Parallel; iii++)
+ { for (i = 0; i < rr; i++)
+ { for (j = 0; j < rr; j++)
+ { Temp = 0;
+ for (jjj = 0; jjj < rr; jjj++)
+ Temp = Temp ^ T_G_R[i][jjj] * T_G[jjj][j];
+ T_G_R_Temp[i][j] = Temp;
+ }
+ }
+ for (i = 0; i < rr; i++)
+ { for (j = 0; j < rr; j++)
+ T_G_R[i][j] = T_G_R_Temp[i][j];
+ }
+ }
+
+ nn_shorten = kk_shorten + rr ;
+
+// Parallel BCH Encode
+ // Determine the number of loops required for parallelism.
+// loop_count = ceil(kk_shorten / (double)Parallel) ;
+ loop_count = kk_shorten / Parallel ;
+
+ // Serial to parallel data conversion
+ for (i = 0; i < Parallel; i++)
+ { for (j = 0; j < loop_count; j++)
+ { if (i + j * Parallel < kk_shorten)
+ data_p[i][j] = data[i + j * Parallel];
+ else
+ data_p[i][j] = 0;
+ }
+ }
+
+ // Initialize the parity bits.
+ for (i = 0; i < rr; i++)
+ bb[i] = 0;
+
+ // Compute parity checks
+ // S(t) = T_G_R [ S(t-1) + M(t) ]
+ for (iii = loop_count - 1; iii >= 0; iii--)
+ {
+ for (i = 0; i < rr; i++)
+ bb_temp[i] = bb[i] ;
+ for (i = Parallel - 1; i >= 0; i--)
+ bb_temp[rr - Parallel + i] = bb_temp[rr - Parallel + i] ^ data_p[i][iii];
+
+ for (i = 0; i < rr; i++)
+ { Temp = 0;
+ for (j = 0; j < rr; j++)
+ Temp = Temp ^ (bb_temp[j] * T_G_R[i][j]);
+ bb[i] = Temp;
+ }
+ }
+
+// OUTPUT
+ out_v = 0;
+ for (i = 0 ; i < rr ; i++)
+ out_v = ( out_v << 1) | bb[i] ;
+ return out_v;
+}
+/*------------------------------- End OF File --------------------------------*/
diff --git a/common/Makefile b/common/Makefile
index bc39ea263..ceb8d117c 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -176,6 +176,9 @@ COBJS-$(CONFIG_LYNXKDI) += lynxkdi.o
COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o
COBJS-$(CONFIG_UPDATE_TFTP) += update.o
COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
+
+COBJS-$(CONFIG_OMAP_CPFROM) += cmd_cpfrom.o
+
endif
COBJS-y += console.o
diff --git a/common/cmd_cpfrom.c b/common/cmd_cpfrom.c
new file mode 100644
index 000000000..12799d2f6
--- /dev/null
+++ b/common/cmd_cpfrom.c
@@ -0,0 +1,134 @@
+/*
+ * (C) Copyright 2012
+ * Texas Instruments, <www.ti.com>
+ * Carlos Leija <cileija@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Test CPFROM APIs
+ */
+#include <common.h>
+#include <command.h>
+#include <i2c.h>
+
+// HS defines
+#include <asm/arch/omap4_hal.h>
+
+#define SYS_CLK_38_4 0x0
+
+#define PPA_SERV_HAL_CPAUTOLOAD 0x3A
+#define PPA_SERV_HAL_CPINIT 0x3B
+#define PPA_SERV_HAL_CPMSV 0x3D
+
+void issueAutld(void)
+{
+ printf(" Issuing Autoload\n");
+ if ( (SEC_ENTRY_Std_Ppa_Call (PPA_SERV_HAL_CPAUTOLOAD, 0)) == 0 )
+ printf(" ... [cpfrom autoload] done\n\n");
+ else
+ printf("[ERROR] [cpfrom autoload] Failed!\n\n");
+}
+
+int do_cpfrom (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ U32 value;
+ U32 VAL_BCH[5];
+
+ char *cmd = argv[1];
+ unsigned char cLdata=0;
+
+ if (argc < 2) {
+ printf("Not enough ARGS!!\n");
+ goto cpfrom_cmd_usage;
+ } else if (argc > 4) {
+ printf("Too many ARGS!!\n");
+ goto cpfrom_cmd_usage;
+ } else if (argc == 2) {
+ if (strcmp(cmd,"autoload") == 0) {
+ printf(" Calling CPFROM AutoLoad\n");
+ issueAutld();
+ } else if (strcmp(cmd,"init") == 0) {
+ cLdata = '0';
+ printf(" Initializing CPFROM \n");
+ printf(" Turning Phoenix VPP resource\n");
+ cLdata = 0x1;
+ i2c_set_bus_num(0);
+ i2c_write(0x48, 0x9c, 1, &cLdata, 1); // VPP_CFG_GRP
+ cLdata = 0x3;
+ i2c_write(0x48, 0x9d, 1, &cLdata, 1); // VPP_CFG_TRANS
+ cLdata = 0x21;
+ i2c_write(0x48, 0x9e, 1, &cLdata, 1); // VPP_CFG_STATE
+ printf (" Setting voltage : ");
+ cLdata = 0x8;
+ i2c_write(0x48, 0x9f, 1, &cLdata, 1); // VPP_CFG_VOLTAGE
+ printf(" ... done\n\n");
+ printf( " Note: In SDP, C60 reads +0.06V of selected voltage\n\n");
+
+ printf(" -----------------------------------------\n");
+ printf(" Using default platform clock speed 38.4 MHz\n");
+ printf(" Calling CPFROM_Init\n");
+ if ( (SEC_ENTRY_Std_Ppa_Call (PPA_SERV_HAL_CPINIT, 1, SYS_CLK_38_4 )) == 0 ){
+ printf(" ... [cpfrom %s] done\n\n", cmd);
+ issueAutld();
+ } else
+ printf("[ERROR] [cpfrom %s] Failed!\n\n", cmd);
+ }
+ } else {
+ /* 3 or 4 arguments */
+ if (strcmp(cmd,"msv") == 0) {
+ hexStringtoInteger(argv[2],&value);
+ VAL_BCH[0] = cpfrom_byte_reverse32(value);
+ VAL_BCH[1] = bch_enc(1, VAL_BCH);
+
+ VAL_BCH[0] = value;
+
+ printf(" Input:\n");
+ printf(" MSV Hex value : %x\n", value);
+
+ printf(" Passing:\n");
+ printf(" MSV_ECC : %x\n", VAL_BCH[1]);
+
+ if (argc > 3) {
+ value = simple_strtoul(argv[3], NULL, 16);
+ if (value == 5){
+ printf(" Calling MSV function\n");
+ if ( (SEC_ENTRY_Std_Ppa_Call (PPA_SERV_HAL_CPMSV, 2, VAL_BCH[0], VAL_BCH[1])) == 0 ){
+ printf(" ... [cpfrom %s] done\n\n", cmd);
+ issueAutld();
+ } else
+ printf("[ERROR] [cpfrom %s] Failed!\n\n", cmd);
+ } else
+ printf(" This is a dryrun only\n");
+ } else
+ printf(" This is a dryrun only\n");
+ } else {
+ printf(" Command [cpfrom %s] not supported!\n\n", cmd);
+ goto cpfrom_cmd_usage;
+ }
+ }
+ return 0;
+
+cpfrom_cmd_usage:
+ printf("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+}
+
+U_BOOT_CMD(cpfrom, 4, 1, do_cpfrom,
+ " cpfrom init\n"
+ " cpfrom autoload\n"
+ " cpfrom msv <MSV_hex_no_0x> 5<--- add to program\n",
+ NULL);