Commit 3d0f511dfa873c8d4dc09dd6fe33a1bad5192ed1

Authored by Sukumar Ghorai
Committed by Hebbar, Gururaja
1 parent 23409519e1
Exists in master

omap3:nand: bch ecc support added

bch error correction (t=4 and t=8) for 512 bytes support added.
Tested in omap-3630 es-1.1 silicon.

Need to select the bch-ecc from board file. E.g.
arch/arm/mach-omap2/board-flash.c: board_nand_init()
board_nand_data.ecc_opt = OMAP_ECC_BCH4_CODE_HW

This patch has dependency on -
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg42658.html

Signed-off-by: Parth Mauria Saxena <parth.saxena@ti.com>
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Sriramakrishnan A G <srk@ti.com>
Signed-off-by: Abhilash K V <abhilash.kv@ti.com>
Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>

Showing 5 changed files with 561 additions and 56 deletions Side-by-side Diff

arch/arm/mach-omap2/gpmc.c
... ... @@ -49,6 +49,7 @@
49 49 #define GPMC_ECC_CONTROL 0x1f8
50 50 #define GPMC_ECC_SIZE_CONFIG 0x1fc
51 51 #define GPMC_ECC1_RESULT 0x200
  52 +#define GPMC_ECC_BCH_RESULT_0 0x240
52 53  
53 54 #define GPMC_CS0_OFFSET 0x60
54 55 #define GPMC_CS_SIZE 0x30
... ... @@ -95,7 +96,6 @@
95 96 static struct resource gpmc_cs_mem[GPMC_CS_NUM];
96 97 static DEFINE_SPINLOCK(gpmc_mem_lock);
97 98 static unsigned int gpmc_cs_map; /* flag for cs which are initialized */
98   -static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */
99 99  
100 100 static void __iomem *gpmc_base;
101 101  
102 102  
103 103  
104 104  
105 105  
106 106  
107 107  
108 108  
109 109  
110 110  
111 111  
112 112  
... ... @@ -844,53 +844,78 @@
844 844  
845 845 /**
846 846 * gpmc_enable_hwecc - enable hardware ecc functionality
  847 + * @ecc_type: ecc type e.g. Hamming, BCH
847 848 * @cs: chip select number
848 849 * @mode: read/write mode
849 850 * @dev_width: device bus width(1 for x16, 0 for x8)
850 851 * @ecc_size: bytes for which ECC will be generated
851 852 */
852   -int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size)
  853 +int gpmc_enable_hwecc(int ecc_type, int cs, int mode,
  854 + int dev_width, int ecc_size)
853 855 {
854   - unsigned int val;
  856 + unsigned int bch_mod = 0, bch_wrapmode = 0, eccsize1 = 0, eccsize0 = 0;
  857 + unsigned int ecc_conf_val = 0, ecc_size_conf_val = 0;
855 858  
856   - /* check if ecc module is in used */
857   - if (gpmc_ecc_used != -EINVAL)
858   - return -EINVAL;
859   -
860   - gpmc_ecc_used = cs;
861   -
862   - /* clear ecc and enable bits */
863   - val = ((0x00000001<<8) | 0x00000001);
864   - gpmc_write_reg(GPMC_ECC_CONTROL, val);
865   -
866   - /* program ecc and result sizes */
867   - val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
868   - gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
869   -
870 859 switch (mode) {
871 860 case GPMC_ECC_READ:
872   - gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
  861 + if (ecc_type == OMAP_ECC_BCH4_CODE_HW) {
  862 + eccsize1 = 0xD; eccsize0 = 0x48;
  863 + bch_mod = 0;
  864 + bch_wrapmode = 0x09;
  865 + } else if (ecc_type == OMAP_ECC_BCH8_CODE_HW) {
  866 + eccsize1 = 0x1A; eccsize0 = 0x18;
  867 + bch_mod = 1;
  868 + bch_wrapmode = 0x04;
  869 + } else
  870 + eccsize1 = ((ecc_size >> 1) - 1);
873 871 break;
  872 +
874 873 case GPMC_ECC_READSYN:
875   - gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
876 874 break;
  875 +
877 876 case GPMC_ECC_WRITE:
878   - gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
  877 + if (ecc_type == OMAP_ECC_BCH4_CODE_HW) {
  878 + eccsize1 = 0x20; eccsize0 = 0x00;
  879 + bch_mod = 0;
  880 + bch_wrapmode = 0x06;
  881 + } else if (ecc_type == OMAP_ECC_BCH8_CODE_HW) {
  882 + eccsize1 = 0x20; eccsize0 = 0x00;
  883 + bch_mod = 1;
  884 + bch_wrapmode = 0x06;
  885 + } else
  886 + eccsize1 = ((ecc_size >> 1) - 1);
879 887 break;
  888 +
880 889 default:
881 890 printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
882 891 break;
883 892 }
884 893  
885   - /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
886   - val = (dev_width << 7) | (cs << 1) | (0x1);
887   - gpmc_write_reg(GPMC_ECC_CONFIG, val);
  894 + /* clear ecc and enable bits */
  895 + if ((ecc_type == OMAP_ECC_BCH4_CODE_HW) ||
  896 + (ecc_type == OMAP_ECC_BCH8_CODE_HW)) {
  897 + gpmc_write_reg(GPMC_ECC_CONTROL, 0x00000001);
  898 + ecc_size_conf_val = (eccsize1 << 22) | (eccsize0 << 12);
  899 + ecc_conf_val = ((0x01 << 16) | (bch_mod << 12)
  900 + | (bch_wrapmode << 8) | (dev_width << 7)
  901 + | (0x03 << 4) | (cs << 1) | (0x1));
  902 + } else {
  903 + gpmc_write_reg(GPMC_ECC_CONTROL, 0x00000101);
  904 + ecc_size_conf_val = (eccsize1 << 22) | 0x0000000F;
  905 + ecc_conf_val = (dev_width << 7) | (cs << 1) | (0x1);
  906 + }
  907 +
  908 + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, ecc_size_conf_val);
  909 + gpmc_write_reg(GPMC_ECC_CONFIG, ecc_conf_val);
  910 + gpmc_write_reg(GPMC_ECC_CONTROL, 0x00000101);
  911 +
888 912 return 0;
889 913 }
890 914 EXPORT_SYMBOL(gpmc_enable_hwecc);
891 915  
892 916 /**
893 917 * gpmc_calculate_ecc - generate non-inverted ecc bytes
  918 + * @ecc_type: ecc type e.g. Hamming, BCH
894 919 * @cs: chip select number
895 920 * @dat: data pointer over which ecc is computed
896 921 * @ecc_code: ecc code buffer
897 922  
898 923  
899 924  
900 925  
... ... @@ -901,21 +926,52 @@
901 926 * an erased page will produce an ECC mismatch between generated and read
902 927 * ECC bytes that has to be dealt with separately.
903 928 */
904   -int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
  929 +int gpmc_calculate_ecc(int ecc_type, int cs,
  930 + const u_char *dat, u_char *ecc_code)
905 931 {
906   - unsigned int val = 0x0;
  932 + unsigned int reg;
  933 + unsigned int val1 = 0x0, val2 = 0x0;
  934 + unsigned int val3 = 0x0, val4 = 0x0;
  935 + int i;
907 936  
908   - if (gpmc_ecc_used != cs)
909   - return -EINVAL;
  937 + if ((ecc_type == OMAP_ECC_BCH4_CODE_HW) ||
  938 + (ecc_type == OMAP_ECC_BCH8_CODE_HW)) {
  939 + for (i = 0; i < 4; i++) {
  940 + /*
  941 + * Reading HW ECC_BCH_Results
  942 + * 0x240-0x24C, 0x250-0x25C, 0x260-0x26C, 0x270-0x27C
  943 + */
  944 + reg = GPMC_ECC_BCH_RESULT_0 + (0x10 * i);
  945 + val1 = gpmc_read_reg(reg);
  946 + val2 = gpmc_read_reg(reg + 4);
  947 + if (ecc_type == OMAP_ECC_BCH8_CODE_HW) {
  948 + val3 = gpmc_read_reg(reg + 8);
  949 + val4 = gpmc_read_reg(reg + 12);
910 950  
911   - /* read ecc result */
912   - val = gpmc_read_reg(GPMC_ECC1_RESULT);
913   - *ecc_code++ = val; /* P128e, ..., P1e */
914   - *ecc_code++ = val >> 16; /* P128o, ..., P1o */
915   - /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
916   - *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
  951 + *ecc_code++ = (val4 & 0xFF);
  952 + *ecc_code++ = ((val3 >> 24) & 0xFF);
  953 + *ecc_code++ = ((val3 >> 16) & 0xFF);
  954 + *ecc_code++ = ((val3 >> 8) & 0xFF);
  955 + *ecc_code++ = (val3 & 0xFF);
  956 + *ecc_code++ = ((val2 >> 24) & 0xFF);
  957 + }
  958 + *ecc_code++ = ((val2 >> 16) & 0xFF);
  959 + *ecc_code++ = ((val2 >> 8) & 0xFF);
  960 + *ecc_code++ = (val2 & 0xFF);
  961 + *ecc_code++ = ((val1 >> 24) & 0xFF);
  962 + *ecc_code++ = ((val1 >> 16) & 0xFF);
  963 + *ecc_code++ = ((val1 >> 8) & 0xFF);
  964 + *ecc_code++ = (val1 & 0xFF);
  965 + }
  966 + } else {
  967 + /* read ecc result */
  968 + val1 = gpmc_read_reg(GPMC_ECC1_RESULT);
  969 + *ecc_code++ = val1; /* P128e, ..., P1e */
  970 + *ecc_code++ = val1 >> 16; /* P128o, ..., P1o */
  971 + /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
  972 + *ecc_code++ = ((val1 >> 8) & 0x0f) | ((val1 >> 20) & 0xf0);
  973 + }
917 974  
918   - gpmc_ecc_used = -EINVAL;
919 975 return 0;
920 976 }
921 977 EXPORT_SYMBOL(gpmc_calculate_ecc);
arch/arm/plat-omap/include/plat/gpmc.h
... ... @@ -92,6 +92,8 @@
92 92 OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */
93 93 /* 1-bit ecc: stored at beginning of spare area as romcode */
94 94 OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */
  95 + OMAP_ECC_BCH4_CODE_HW, /* gpmc bch detection & s/w method correction */
  96 + OMAP_ECC_BCH8_CODE_HW, /* gpmc bch detection & s/w method correction */
95 97 };
96 98  
97 99 /*
... ... @@ -155,7 +157,7 @@
155 157 extern int gpmc_nand_read(int cs, int cmd);
156 158 extern int gpmc_nand_write(int cs, int cmd, int wval);
157 159  
158   -int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size);
159   -int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
  160 +int gpmc_enable_hwecc(int ecc, int cs, int mode, int dev_width, int ecc_size);
  161 +int gpmc_calculate_ecc(int ecc, int cs, const u_char *dat, u_char *ecc_code);
160 162 #endif
drivers/mtd/nand/Makefile
... ... @@ -30,6 +30,7 @@
30 30 obj-$(CONFIG_MTD_NAND_ATMEL) += atmel_nand.o
31 31 obj-$(CONFIG_MTD_NAND_GPIO) += gpio.o
32 32 obj-$(CONFIG_MTD_NAND_OMAP2) += omap2.o
  33 +obj-$(CONFIG_MTD_NAND_OMAP2) += omap_bch_decoder.o
33 34 obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o
34 35 obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o
35 36 obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o
drivers/mtd/nand/omap2.c
... ... @@ -99,6 +99,8 @@
99 99  
100 100 static const char *part_probes[] = { "cmdlinepart", NULL };
101 101  
  102 +int decode_bch(int select_4_8, unsigned char *ecc, unsigned int *err_loc);
  103 +
102 104 /* oob info generated runtime depending on ecc algorithm and layout selected */
103 105 static struct nand_ecclayout omap_oobinfo;
104 106 /* Define some generic bad / good block scan pattern which are used
... ... @@ -131,7 +133,8 @@
131 133 OMAP_NAND_IO_WRITE, /* write */
132 134 } iomode;
133 135 u_char *buf;
134   - int buf_len;
  136 + int buf_len;
  137 + int ecc_opt;
135 138 };
136 139  
137 140 /**
... ... @@ -528,7 +531,6 @@
528 531 struct omap_nand_info *info = container_of(mtd,
529 532 struct omap_nand_info, mtd);
530 533 int ret = 0;
531   -
532 534 if (len <= mtd->oobsize) {
533 535 omap_read_buf_pref(mtd, buf, len);
534 536 return;
... ... @@ -808,6 +810,8 @@
808 810 mtd);
809 811 int blockCnt = 0, i = 0, ret = 0;
810 812 int stat = 0;
  813 + int j, eccsize, eccflag, count;
  814 + unsigned int err_loc[8];
811 815  
812 816 /* Ex NAND_ECC_HW12_2048 */
813 817 if ((info->nand.ecc.mode == NAND_ECC_HW) &&
814 818  
... ... @@ -816,17 +820,59 @@
816 820 else
817 821 blockCnt = 1;
818 822  
819   - for (i = 0; i < blockCnt; i++) {
820   - if (memcmp(read_ecc, calc_ecc, 3) != 0) {
821   - ret = omap_compare_ecc(read_ecc, calc_ecc, dat);
822   - if (ret < 0)
823   - return ret;
824   - /* keep track of the number of corrected errors */
825   - stat += ret;
  823 + switch (info->ecc_opt) {
  824 + case OMAP_ECC_HAMMING_CODE_HW:
  825 + case OMAP_ECC_HAMMING_CODE_HW_ROMCODE:
  826 + for (i = 0; i < blockCnt; i++) {
  827 + if (memcmp(read_ecc, calc_ecc, 3) != 0) {
  828 + ret = omap_compare_ecc(read_ecc, calc_ecc, dat);
  829 + if (ret < 0)
  830 + return ret;
  831 +
  832 + /* keep track of number of corrected errors */
  833 + stat += ret;
  834 + }
  835 + read_ecc += 3;
  836 + calc_ecc += 3;
  837 + dat += 512;
826 838 }
827   - read_ecc += 3;
828   - calc_ecc += 3;
829   - dat += 512;
  839 + break;
  840 +
  841 + case OMAP_ECC_BCH4_CODE_HW:
  842 + eccsize = 7;
  843 + gpmc_calculate_ecc(info->ecc_opt, info->gpmc_cs, dat, calc_ecc);
  844 + for (i = 0; i < blockCnt; i++) {
  845 + /* check if any ecc error */
  846 + eccflag = 0;
  847 + for (j = 0; (j < eccsize) && (eccflag == 0); j++)
  848 + if (calc_ecc[j] != 0)
  849 + eccflag = 1;
  850 +
  851 + if (eccflag == 1) {
  852 + eccflag = 0;
  853 + for (j = 0; (j < eccsize) &&
  854 + (eccflag == 0); j++)
  855 + if (read_ecc[j] != 0xFF)
  856 + eccflag = 1;
  857 + }
  858 +
  859 + count = 0;
  860 + if (eccflag == 1)
  861 + count = decode_bch(0, calc_ecc, err_loc);
  862 +
  863 + for (j = 0; j < count; j++) {
  864 + if (err_loc[j] < 4096)
  865 + dat[err_loc[j] >> 3] ^=
  866 + 1 << (err_loc[j] & 7);
  867 + /* else, not interested to correct ecc */
  868 + }
  869 +
  870 + stat += count;
  871 + calc_ecc = calc_ecc + eccsize;
  872 + read_ecc = read_ecc + eccsize;
  873 + dat += 512;
  874 + }
  875 + break;
830 876 }
831 877 return stat;
832 878 }
... ... @@ -848,7 +894,7 @@
848 894 {
849 895 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
850 896 mtd);
851   - return gpmc_calculate_ecc(info->gpmc_cs, dat, ecc_code);
  897 + return gpmc_calculate_ecc(info->ecc_opt, info->gpmc_cs, dat, ecc_code);
852 898 }
853 899  
854 900 /**
... ... @@ -863,7 +909,8 @@
863 909 struct nand_chip *chip = mtd->priv;
864 910 unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
865 911  
866   - gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size);
  912 + gpmc_enable_hwecc(info->ecc_opt, info->gpmc_cs, mode,
  913 + dev_width, info->nand.ecc.size);
867 914 }
868 915  
869 916 /**
... ... @@ -960,6 +1007,7 @@
960 1007 info->mtd.priv = &info->nand;
961 1008 info->mtd.name = dev_name(&pdev->dev);
962 1009 info->mtd.owner = THIS_MODULE;
  1010 + info->ecc_opt = pdata->ecc_opt;
963 1011  
964 1012 info->nand.options = pdata->devsize;
965 1013 info->nand.options |= NAND_SKIP_BBTSCAN;
... ... @@ -998,7 +1046,6 @@
998 1046 info->nand.waitfunc = omap_wait;
999 1047 info->nand.chip_delay = 50;
1000 1048 }
1001   -
1002 1049 switch (pdata->xfer_type) {
1003 1050 case NAND_OMAP_PREFETCH_POLLED:
1004 1051 info->nand.read_buf = omap_read_buf_pref;
... ... @@ -1059,10 +1106,17 @@
1059 1106 /* selsect the ecc type */
1060 1107 if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_DEFAULT)
1061 1108 info->nand.ecc.mode = NAND_ECC_SOFT;
1062   - else if ((pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW) ||
1063   - (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE)) {
1064   - info->nand.ecc.bytes = 3;
1065   - info->nand.ecc.size = 512;
  1109 + else {
  1110 + if (pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) {
  1111 + info->nand.ecc.bytes = 4*7;
  1112 + info->nand.ecc.size = 4*512;
  1113 + } else if (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW) {
  1114 + info->nand.ecc.bytes = 13;
  1115 + info->nand.ecc.size = 4*512;
  1116 + } else {
  1117 + info->nand.ecc.bytes = 3;
  1118 + info->nand.ecc.size = 512;
  1119 + }
1066 1120 info->nand.ecc.calculate = omap_calculate_ecc;
1067 1121 info->nand.ecc.hwctl = omap_enable_hwecc;
1068 1122 info->nand.ecc.correct = omap_correct_data;
drivers/mtd/nand/omap_bch_decoder.c
  1 +/*
  2 + * drivers/mtd/nand/omap_omap_bch_decoder.c
  3 + *
  4 + * Whole BCH ECC Decoder (Post hardware generated syndrome decoding)
  5 + *
  6 + * Copyright (c) 2007 Texas Instruments
  7 + *
  8 + * Author: Sukumar Ghorai <s-ghorai@ti.com
  9 + * Michael Fillinger <m-fillinger@ti.com>
  10 + *
  11 + * This program is free software; you can redistribute it and/or modify
  12 + * it under the terms of the GNU General Public License version 2 as
  13 + * published by the Free Software Foundation.
  14 + */
  15 +#undef DEBUG
  16 +
  17 +#include <linux/kernel.h>
  18 +#include <linux/module.h>
  19 +
  20 +#define mm 13
  21 +#define kk_shorten 4096
  22 +#define nn 8191 /* Length of codeword, n = 2**mm - 1 */
  23 +
  24 +#define PPP 0x201B /* Primary Polynomial : x^13 + x^4 + x^3 + x + 1 */
  25 +#define P 0x001B /* With omitted x^13 */
  26 +#define POLY 12 /* degree of the primary Polynomial less one */
  27 +
  28 +/**
  29 + * mpy_mod_gf - GALOIS field multiplier
  30 + * Input : A(x), B(x)
  31 + * Output : A(x)*B(x) mod P(x)
  32 + */
  33 +static unsigned int mpy_mod_gf(unsigned int a, unsigned int b)
  34 +{
  35 + unsigned int R = 0;
  36 + unsigned int R1 = 0;
  37 + unsigned int k = 0;
  38 +
  39 + for (k = 0; k < mm; k++) {
  40 +
  41 + R = (R << 1) & 0x1FFE;
  42 + if (R1 == 1)
  43 + R ^= P;
  44 +
  45 + if (((a >> (POLY - k)) & 1) == 1)
  46 + R ^= b;
  47 +
  48 + if (k < POLY)
  49 + R1 = (R >> POLY) & 1;
  50 + }
  51 + return R;
  52 +}
  53 +
  54 +/**
  55 + * chien - CHIEN search
  56 + *
  57 + * @location - Error location vector pointer
  58 + *
  59 + * Inputs : ELP(z)
  60 + * No. of found errors
  61 + * Size of input codeword
  62 + * Outputs : Up to 8 locations
  63 + * No. of errors
  64 + */
  65 +static int chien(unsigned int select_4_8, int err_nums,
  66 + unsigned int err[], unsigned int *location)
  67 +{
  68 + int i, count; /* Number of dectected errors */
  69 + /* Contains accumulation of evaluation at x^i (i:1->8) */
  70 + unsigned int gammas[8] = {0};
  71 + unsigned int alpha;
  72 + unsigned int bit, ecc_bits;
  73 + unsigned int elp_sum;
  74 +
  75 + ecc_bits = (select_4_8 == 0) ? 52 : 104;
  76 +
  77 + /* Start evaluation at Alpha**8192 and decreasing */
  78 + for (i = 0; i < 8; i++)
  79 + gammas[i] = err[i];
  80 +
  81 + count = 0;
  82 + for (i = 1; (i <= nn) && (count < err_nums); i++) {
  83 +
  84 + /* Result of evaluation at root */
  85 + elp_sum = 1 ^ gammas[0] ^ gammas[1] ^
  86 + gammas[2] ^ gammas[3] ^
  87 + gammas[4] ^ gammas[5] ^
  88 + gammas[6] ^ gammas[7];
  89 +
  90 + alpha = PPP >> 1;
  91 + gammas[0] = mpy_mod_gf(gammas[0], alpha);
  92 + alpha = mpy_mod_gf(alpha, (PPP >> 1)); /* x alphha^-2 */
  93 + gammas[1] = mpy_mod_gf(gammas[1], alpha);
  94 + alpha = mpy_mod_gf(alpha, (PPP >> 1)); /* x alphha^-2 */
  95 + gammas[2] = mpy_mod_gf(gammas[2], alpha);
  96 + alpha = mpy_mod_gf(alpha, (PPP >> 1)); /* x alphha^-3 */
  97 + gammas[3] = mpy_mod_gf(gammas[3], alpha);
  98 + alpha = mpy_mod_gf(alpha, (PPP >> 1)); /* x alphha^-4 */
  99 + gammas[4] = mpy_mod_gf(gammas[4], alpha);
  100 + alpha = mpy_mod_gf(alpha, (PPP >> 1)); /* x alphha^-5 */
  101 + gammas[5] = mpy_mod_gf(gammas[5], alpha);
  102 + alpha = mpy_mod_gf(alpha, (PPP >> 1)); /* x alphha^-6 */
  103 + gammas[6] = mpy_mod_gf(gammas[6], alpha);
  104 + alpha = mpy_mod_gf(alpha, (PPP >> 1)); /* x alphha^-7 */
  105 + gammas[7] = mpy_mod_gf(gammas[7], alpha);
  106 +
  107 + if (elp_sum == 0) {
  108 + /* calculate bit position in main data area */
  109 + bit = ((i-1) & ~7)|(7-((i-1) & 7));
  110 + if (i >= 2 * ecc_bits)
  111 + location[count++] =
  112 + kk_shorten - (bit - 2 * ecc_bits) - 1;
  113 + }
  114 + }
  115 +
  116 + /* Failure: No. of detected errors != No. or corrected errors */
  117 + if (count != err_nums) {
  118 + count = -1;
  119 + printk(KERN_ERR "BCH decoding failed\n");
  120 + }
  121 + for (i = 0; i < count; i++)
  122 + pr_debug("%d ", location[i]);
  123 +
  124 + return count;
  125 +}
  126 +
  127 +/* synd : 16 Syndromes
  128 + * return: gamaas - Coefficients to the error polynomial
  129 + * return: : Number of detected errors
  130 +*/
  131 +static unsigned int berlekamp(unsigned int select_4_8,
  132 + unsigned int synd[], unsigned int err[])
  133 +{
  134 + int loop, iteration;
  135 + unsigned int LL = 0; /* Detected errors */
  136 + unsigned int d = 0; /* Distance between Syndromes and ELP[n](z) */
  137 + unsigned int invd = 0; /* Inverse of d */
  138 + /* Intermediate ELP[n](z).
  139 + * Final ELP[n](z) is Error Location Polynomial
  140 + */
  141 + unsigned int gammas[16] = {0};
  142 + /* Intermediate normalized ELP[n](z) : D[n](z) */
  143 + unsigned int D[16] = {0};
  144 + /* Temporary value that holds an ELP[n](z) coefficient */
  145 + unsigned int next_gamma = 0;
  146 +
  147 + int e = 0;
  148 + unsigned int sign = 0;
  149 + unsigned int u = 0;
  150 + unsigned int v = 0;
  151 + unsigned int C1 = 0, C2 = 0;
  152 + unsigned int ss = 0;
  153 + unsigned int tmp_v = 0, tmp_s = 0;
  154 + unsigned int tmp_poly;
  155 +
  156 + /*-------------- Step 0 ------------------*/
  157 + for (loop = 0; loop < 16; loop++)
  158 + gammas[loop] = 0;
  159 + gammas[0] = 1;
  160 + D[1] = 1;
  161 +
  162 + iteration = 0;
  163 + LL = 0;
  164 + while ((iteration < ((select_4_8+1)*2*4)) &&
  165 + (LL <= ((select_4_8+1)*4))) {
  166 +
  167 + pr_debug("\nIteration.............%d\n", iteration);
  168 + d = 0;
  169 + /* Step: 0 */
  170 + for (loop = 0; loop <= LL; loop++) {
  171 + tmp_poly = mpy_mod_gf(
  172 + gammas[loop], synd[iteration - loop]);
  173 + d ^= tmp_poly;
  174 + pr_debug("%02d. s=0 LL=%x poly %x\n",
  175 + loop, LL, tmp_poly);
  176 + }
  177 +
  178 + /* Step 1: 1 cycle only to perform inversion */
  179 + v = d << 1;
  180 + e = -1;
  181 + sign = 1;
  182 + ss = 0x2000;
  183 + invd = 0;
  184 + u = PPP;
  185 + for (loop = 0; (d != 0) && (loop <= (2 * POLY)); loop++) {
  186 + pr_debug("%02d. s=1 LL=%x poly NULL\n",
  187 + loop, LL);
  188 + C1 = (v >> 13) & 1;
  189 + C2 = C1 & sign;
  190 +
  191 + sign ^= C2 ^ (e == 0);
  192 +
  193 + tmp_v = v;
  194 + tmp_s = ss;
  195 +
  196 + if (C1 == 1) {
  197 + v ^= u;
  198 + ss ^= invd;
  199 + }
  200 + v = (v << 1) & 0x3FFF;
  201 + if (C2 == 1) {
  202 + u = tmp_v;
  203 + invd = tmp_s;
  204 + e = -e;
  205 + }
  206 + invd >>= 1;
  207 + e--;
  208 + }
  209 +
  210 + for (loop = 0; (d != 0) && (loop <= (iteration + 1)); loop++) {
  211 + /* Step 2
  212 + * Interleaved with Step 3, if L<(n-k)
  213 + * invd: Update of ELP[n](z) = ELP[n-1](z) - d.D[n-1](z)
  214 + */
  215 +
  216 + /* Holds value of ELP coefficient until precedent
  217 + * value does not have to be used anymore
  218 + */
  219 + tmp_poly = mpy_mod_gf(d, D[loop]);
  220 + pr_debug("%02d. s=2 LL=%x poly %x\n",
  221 + loop, LL, tmp_poly);
  222 +
  223 + next_gamma = gammas[loop] ^ tmp_poly;
  224 + if ((2 * LL) < (iteration + 1)) {
  225 + /* Interleaving with Step 3
  226 + * for parallelized update of ELP(z) and D(z)
  227 + */
  228 + } else {
  229 + /* Update of ELP(z) only -> stay in Step 2 */
  230 + gammas[loop] = next_gamma;
  231 + if (loop == (iteration + 1)) {
  232 + /* to step 4 */
  233 + break;
  234 + }
  235 + }
  236 +
  237 + /* Step 3
  238 + * Always interleaved with Step 2 (case when L<(n-k))
  239 + * Update of D[n-1](z) = ELP[n-1](z)/d
  240 + */
  241 + D[loop] = mpy_mod_gf(gammas[loop], invd);
  242 + pr_debug("%02d. s=3 LL=%x poly %x\n",
  243 + loop, LL, D[loop]);
  244 +
  245 + /* Can safely update ELP[n](z) */
  246 + gammas[loop] = next_gamma;
  247 +
  248 + if (loop == (iteration + 1)) {
  249 + /* If update finished */
  250 + LL = iteration - LL + 1;
  251 + /* to step 4 */
  252 + break;
  253 + }
  254 + /* Else, interleaving to step 2*/
  255 + }
  256 +
  257 + /* Step 4: Update D(z): i:0->L */
  258 + /* Final update of D[n](z) = D[n](z).z*/
  259 + for (loop = 0; loop < 15; loop++) /* Left Shift */
  260 + D[15 - loop] = D[14 - loop];
  261 +
  262 + D[0] = 0;
  263 +
  264 + iteration++;
  265 + } /* while */
  266 +
  267 + /* Processing finished, copy ELP to final registers : 0->2t-1*/
  268 + for (loop = 0; loop < 8; loop++)
  269 + err[loop] = gammas[loop+1];
  270 +
  271 + pr_debug("\n Err poly:");
  272 + for (loop = 0; loop < 8; loop++)
  273 + pr_debug("0x%x ", err[loop]);
  274 +
  275 + return LL;
  276 +}
  277 +
  278 +/*
  279 + * syndrome - Generate syndrome components from hw generate syndrome
  280 + * r(x) = c(x) + e(x)
  281 + * s(x) = c(x) mod g(x) + e(x) mod g(x) = e(x) mod g(x)
  282 + * so receiver checks if the syndrome s(x) = r(x) mod g(x) is equal to zero.
  283 + * unsigned int s[16]; - Syndromes
  284 + */
  285 +static void syndrome(unsigned int select_4_8,
  286 + unsigned char *ecc, unsigned int syn[])
  287 +{
  288 + unsigned int k, l, t;
  289 + unsigned int alpha_bit, R_bit;
  290 + int ecc_pos, ecc_min;
  291 +
  292 + /* 2t-1 = 15 (for t=8) minimal polynomials of the first 15 powers of a
  293 + * primitive elemmants of GF(m); Even powers minimal polynomials are
  294 + * duplicate of odd powers' minimal polynomials.
  295 + * Odd powers of alpha (1 to 15)
  296 + */
  297 + unsigned int pow_alpha[8] = {0x0002, 0x0008, 0x0020, 0x0080,
  298 + 0x0200, 0x0800, 0x001B, 0x006C};
  299 +
  300 + pr_debug("\n ECC[0..n]: ");
  301 + for (k = 0; k < 13; k++)
  302 + pr_debug("0x%x ", ecc[k]);
  303 +
  304 + if (select_4_8 == 0) {
  305 + t = 4;
  306 + ecc_pos = 55; /* bits(52-bits): 55->4 */
  307 + ecc_min = 4;
  308 + } else {
  309 + t = 8;
  310 + ecc_pos = 103; /* bits: 103->0 */
  311 + ecc_min = 0;
  312 + }
  313 +
  314 + /* total numbber of syndrom to be used is 2t */
  315 + /* Step1: calculate the odd syndrome(s) */
  316 + R_bit = ((ecc[ecc_pos/8] >> (7 - ecc_pos%8)) & 1);
  317 + ecc_pos--;
  318 + for (k = 0; k < t; k++)
  319 + syn[2 * k] = R_bit;
  320 +
  321 + while (ecc_pos >= ecc_min) {
  322 + R_bit = ((ecc[ecc_pos/8] >> (7 - ecc_pos%8)) & 1);
  323 + ecc_pos--;
  324 +
  325 + for (k = 0; k < t; k++) {
  326 + /* Accumulate value of x^i at alpha^(2k+1) */
  327 + if (R_bit == 1)
  328 + syn[2*k] ^= pow_alpha[k];
  329 +
  330 + /* Compute a**(2k+1), using LSFR */
  331 + for (l = 0; l < (2 * k + 1); l++) {
  332 + alpha_bit = (pow_alpha[k] >> POLY) & 1;
  333 + pow_alpha[k] = (pow_alpha[k] << 1) & 0x1FFF;
  334 + if (alpha_bit == 1)
  335 + pow_alpha[k] ^= P;
  336 + }
  337 + }
  338 + }
  339 +
  340 + /* Step2: calculate the even syndrome(s)
  341 + * Compute S(a), where a is an even power of alpha
  342 + * Evenry even power of primitive element has the same minimal
  343 + * polynomial as some odd power of elemets.
  344 + * And based on S(a^2) = S^2(a)
  345 + */
  346 + for (k = 0; k < t; k++)
  347 + syn[2*k+1] = mpy_mod_gf(syn[k], syn[k]);
  348 +
  349 + pr_debug("\n Syndromes: ");
  350 + for (k = 0; k < 16; k++)
  351 + pr_debug("0x%x ", syn[k]);
  352 +}
  353 +
  354 +/**
  355 + * decode_bch - BCH decoder for 4- and 8-bit error correction
  356 + *
  357 + * @ecc - ECC syndrome generated by hw BCH engine
  358 + * @err_loc - pointer to error location array
  359 + *
  360 + * This function does post sydrome generation (hw generated) decoding
  361 + * for:-
  362 + * Dimension of Galoise Field: m = 13
  363 + * Length of codeword: n = 2**m - 1
  364 + * Number of errors that can be corrected: 4- or 8-bits
  365 + * Length of information bit: kk = nn - rr
  366 + */
  367 +int decode_bch(int select_4_8, unsigned char *ecc, unsigned int *err_loc)
  368 +{
  369 + int no_of_err;
  370 + unsigned int syn[16] = {0,}; /* 16 Syndromes */
  371 + unsigned int err_poly[8] = {0,};
  372 + /* Coefficients to the error polynomial
  373 + * ELP(x) = 1 + err0.x + err1.x^2 + ... + err7.x^8
  374 + */
  375 +
  376 + /* Decoting involes three steps
  377 + * 1. Compute the syndrom from teh received codeword,
  378 + * 2. Find the error location polynomial from a set of equations
  379 + * derived from the syndrome,
  380 + * 3. Use the error location polynomial to identify errants bits,
  381 + *
  382 + * And correcttion done by bit flips using error locaiton and expected
  383 + * to be outseide of this implementation.
  384 + */
  385 + syndrome(select_4_8, ecc, syn);
  386 + no_of_err = berlekamp(select_4_8, syn, err_poly);
  387 + if (no_of_err <= (4 << select_4_8))
  388 + no_of_err = chien(select_4_8, no_of_err, err_poly, err_loc);
  389 +
  390 + return no_of_err;
  391 +}
  392 +EXPORT_SYMBOL(decode_bch);