[U-Boot] [PATCH 1/3] atmel_nand: if don't have gf table in rom code we will build it runtime

Josh Wu josh.wu at atmel.com
Mon Oct 27 04:31:52 CET 2014


Hi, Andreas, Bo

On 10/27/2014 9:47 AM, Bo Shen wrote:
> Hi Andreas,
>
> On 10/25/2014 06:22 AM, Andreas Bießmann wrote:
>> Hi Bo,
>>
>> before diving into that code I have a question. What will be the boot
>> mode for devices without integrated PMECC table? Can the first stage
>> loader be read with PMECC mode?
>> The question arises while thinking about this patch. We have generally
>> two options here:
>>   a) pre-generated PMECC table included in u-boot
>>   b) runtime generated PMECC table in RAM (this solution)
>>
>> While a) will bloat the u-boot binary b) will require some RAM to hold
>> the table. If I understood correctly we will malloc at most 128 KiB for
>> the PMECC table ... Ok option a) is not an option ;)
>> Here my question arises, how can the ROM loader allocate 128 KiB? Do
>> these devices have so many SRAM? Or am I wrong?

Does your ROM loader means the ROM code?
As the ROM code has a pre-generated PMECC table included. ROM code and 
the pre-generated PMECC table are both in the embedded readonly ROM. So 
that's not in the SRAM.

>
>   On SAMA5D4 SoC, the PMECC table is only seen by the ROM loader. So, 
> for atbootstrap, we also need to generate the PMECC table and put it 
> in DDR2 SDRAM.
>   We can use the PMECC generate by atbootstrap, however we must to 
> maintain the address where to put the PMECC table, it will easily 
> cause issues, so we try to regenerate the PMECC table also in u-boot.
>
>> On 16.09.14 09:57, Bo Shen wrote:
>>> From: Josh Wu <josh.wu at atmel.com>
>>>
>>> Add a macro NO_GALOIS_TABLE_IN_ROM. If it is defined we will build a
>>> runtime pmecc galois table.
>>>
>>> Signed-off-by: Josh Wu <josh.wu at atmel.com>
>>> Signed-off-by: Bo Shen <voice.shen at atmel.com>
>>> ---
>>>
>>>   drivers/mtd/nand/atmel_nand.c | 127 
>>> +++++++++++++++++++++++++++++++++++++++++-
>>>   1 file changed, 126 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/mtd/nand/atmel_nand.c 
>>> b/drivers/mtd/nand/atmel_nand.c
>>> index e73834d..7cf7b39 100644
>>> --- a/drivers/mtd/nand/atmel_nand.c
>>> +++ b/drivers/mtd/nand/atmel_nand.c
>>> @@ -761,6 +761,108 @@ static int pmecc_choose_ecc(struct 
>>> atmel_nand_host *host,
>>>   }
>>>   #endif
>>>
>>> +#if defined(NO_GALOIS_TABLE_IN_ROM)
>>> +static uint16_t *pmecc_galois_table;
>>> +static int pmecc_build_galois_table(unsigned int mm,
>>> +        int16_t *index_of, int16_t *alpha_to)
>>> +{
>>> +    unsigned int i, mask, nn;
>>> +    unsigned int p[15];
>>> +
>>> +    nn = (1 << mm) - 1;
>>> +    /* set default value */
>>> +    for (i = 1; i < mm; i++)
>>> +        p[i] = 0;
>>
>> memset(p[1], 0, mm-1); // or even the whole field?
>
> OK. I will change it.
>
>>> +
>>> +    /* 1 + X^mm */
>>> +    p[0]  = 1;
>>> +    p[mm] = 1;
>>> +
>>> +    /* others  */
>>> +    switch (mm) {
>>> +    case 3:
>>> +    case 4:
>>> +    case 6:
>>> +    case 15:
>>> +        p[1] = 1;
>>> +        break;
>>> +    case 5:
>>> +    case 11:
>>> +        p[2] = 1;
>>> +        break;
>>> +    case 7:
>>> +    case 10:
>>> +        p[3] = 1;
>>> +        break;
>>> +    case 8:
>>> +        p[2] = 1;
>>> +        p[3] = 1;
>>> +        p[4] = 1;
>>> +        break;
>>> +    case 9:
>>> +        p[4] = 1;
>>> +        break;
>>> +    case 12:
>>> +        p[1] = 1;
>>> +        p[4] = 1;
>>> +        p[6] = 1;
>>> +        break;
>>> +    case 13:
>>> +        p[1] = 1;
>>> +        p[3] = 1;
>>> +        p[4] = 1;
>>> +        break;
>>> +    case 14:
>>> +        p[1] = 1;
>>> +        p[6] = 1;
>>> +        p[10] = 1;
>>> +        break;
>>> +    default:
>>> +        /* Error */
>>> +        return -EINVAL;
>>> +    }
>>> +
>>> +    /* Build alpha ^ mm it will help to generate the field 
>>> (primitiv) */
>>> +    alpha_to[mm] = 0;
>>> +    for (i = 0; i < mm; i++)
>>> +        if (p[i])
>>> +            alpha_to[mm] |= 1 << i;
>>
>> In fact p[] is a bit-field which is then copied to alpha_to[mm], why not
>> use alpha_to[mm] in the switch-case and eliminate p[]?
>
> I will consider that.
>
>>> +
>>> +    /*
>>> +     * Then build elements from 0 to mm - 1. As degree is less than mm
>>> +     * so it is just a logical shift.
>>> +     */
>>> +    mask = 1;
>>> +    for (i = 0; i < mm; i++) {
>>> +        alpha_to[i] = mask;
>>> +        index_of[alpha_to[i]] = i;
>>> +        mask <<= 1;
>>> +    }
>>> +
>>> +    index_of[alpha_to[mm]] = mm;
>>> +
>>> +    /* use a mask to select the MSB bit of the LFSR */
>>> +    mask >>= 1;
>>> +
>>> +    /* then finish the building */
>>> +    for (i = mm + 1; i <= nn; i++) {
>>> +        /* check if the msb bit of the lfsr is set */
>>> +        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 % nn;
>>> +    }
>>> +
>>> +    /* index of 0 is undefined in a multiplicative field */
>>> +    index_of[0] = -1;
>>> +
>>> +    return 0;
>>
>> The whole function is so longish and complicated ... I don't really like
>> it. Maybe eliminating p[] makes it better?
>
> I will try to check the table would be usable in BCH library code.

I already submitted a patch to the kernel: 
http://patchwork.ozlabs.org/patch/398827/
In that patch, this function is rewritten according to BCH code.
So I think maybe after that patch is accepted by kernel, then, we can 
resend new version patch to u-boot.

Best Regards,
Josh Wu




More information about the U-Boot mailing list