diff options
author | Mike J. Chen <mjchen@google.com> | 2012-03-01 13:49:38 -0800 |
---|---|---|
committer | Mike J. Chen <mjchen@google.com> | 2012-03-07 10:01:13 -0800 |
commit | b2a35767def33998341a33eb7c62be2a1dafbeb5 (patch) | |
tree | 4298cea4baa5983478101541eab4b7b9529c68a1 | |
parent | b93c6cbffaf30afbb47c59b710e70e2735a33108 (diff) | |
download | uboot-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/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap4/bch.c | 301 | ||||
-rw-r--r-- | common/Makefile | 3 | ||||
-rw-r--r-- | common/cmd_cpfrom.c | 134 |
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); |