Current Hacks

Recent site activity

correctly configuring uboot after a ram upgrade

Setting up BWSCON/BANKCFG for ram upgrades on a df3120

This tutorial will attempt to describe how to configure the bankcfg register so that u-boot can see the correct amount of ram after an upgrade.

We will need to refer to the s3c2412 datasheet, page 80, and also to lowlevel_init.S in uboot/board/df3120 in the minifs sources.


Things you will need
----------------------------

1. s3c2412 datasheet
2. datasheet for the upgraded ram chip
3. scientific calculator that can convert hex to binary and vice versa

Things I didn't have
1. The datasheet for my upgraded ram chip
2. much of a clue about what I was attempting to do

Getting started
-------------------

I upgraded my parrot photoframe with 64MB of ram, unfortunately at the time of writing this tutorial, we only have the ram settings for 8MB (stock ram) and a 32MB stick that Claude upgraded his frame with.  The only thing I know about this ram is that it's pc133, it only has one set of markings on the chip, 32Mx16, that's all, no part number :(  However, the frame does boot with the ram chip installed in place of the stock 8MB chip, so as long as we get the bits correct in the bankcfg register described on page 80 of the datasheet, we should in theory be able to see all 64MB.  As luck would have it testing uboot with Claudes 32MB bankcfg values in lowlevel_init.S worked and I now have 32MB of ram showing on my system :)  So really I just need to deconstruct the 2 values (8MB value and 32MB value) and see roughly what's changed and poke some values and see what happens :)

So, if we read the datasheet, we can see that BANKCFG is at address 0x48000000, it's also 4bytes wide, so 32bits.  If you look at line 43 in lowlevel_init.S you will see the following:
  #define BWSCON 0x48000000

so to be clear, BWSCON in our uboot code = the address of our BANKCFG register from page 80 in the datasheet.

So, we're still looking at lowlevel_init.S, search for 0x48000000 until you see (line 67):

 mov r0,#0x48000000
 ldr r1,=0x24001
 /*ldr r1,=0x44801  */ /* 32mb ? */

We are interested in the 2 lines with ldr r1,= in them, one is commented out.  These 2 values are what we know so far, the value on the uncommented line is for configuring the stock ram, 0x24001, the trouble is it's in hexadecimal, which is a bit of a pain when you're trying to decipher registers,  so open up your calculator, set it into hex mode and enter the value (the part after the 0x, 24001), now hit the binary button and we'll see it represented in 'bits', you can think of these 'bit's as switches, and when you compare these bits to the 'bit' column on page 80 of the datasheet you can see which properties in the bankcfg register are being switched on or off.

if you look at the binary value for (hex) 0x24001 in your calculator, the right most value is bit 0, which is BW at the bottom of page 80, bit one is the 'reserved' bit above it, and so on.
bit 31 ----> 0000000000000 01 0 01 0 00 0 00 00 00 00 0 1  <---- bit zero

I've added the first 14 bits myself, as the standard windows caluculator doesn't show them, they're the last 13bits which are reserved and bit 18 of RASBW0, if I hadn't you wouldn't see the full 32bits and it would've been confusing :)

If we break this down from top to bottom (bit 31 to 0 = 32bits total) we should see:
RESERVED [31:19] = 13bits, set to zero as they're reserved :
0000 0000 0000 0

RASBW0     [18:17] = 2bits:
01 = 12bit

RESERVED [16] = 1bit:
0

RASBW1     [15:14] = 2bits:
01 = 12bit

RESERVED [13] = 1bit:
0

CASBW0 [12:11] = 2bits:
00 = 8bit

RESERVED [10] = 1bit:
0

CASBW0 [9:8] = 2bits:
00 = 8bit

ADDRCFG0 [7:6] = 2bits:
00 = BA,RAS,CAS

ADDRCFG1 [5:4] = 2bits:
00 = BA,RAS,CAS

MEMCFG [3:2] = 2bits:
00 = SDR

Reserved [1] = 1bit:
0

BW [0] = 1bit:
1 = 16bit

Lets break down our second value and then see what's similar and what we know about my ram:

0000000000000 10 0 01 0 01 0 00  00 00 00 0 1

RESERVED [31:19] = 13bits, set to zero as they're reserved?:
0000 0000 0000 0 (same)

RASBW0     [18:17] = 2bits:
10 = 13bit (changed, was 01, 12bit)

RESERVED [16] = 1bit:
0

RASBW1     [15:14] = 2bits:
01 = 12bit (same)

RESERVED [13] = 1bit:
0

CASBW0 [12:11] = 2bits:
01 = 9bit (changed, was 00, 8bit)

RESERVED [10] = 1bit:
0

CASBW0 [9:8] = 2bits:
00 = 8bit (same)

ADDRCFG0 [7:6] = 2bits:
00 = BA,RAS,CAS  (same)

ADDRCFG1 [5:4] = 2bits:
00 = BA,RAS,CAS  (same)

MEMCFG [3:2] = 2bits:
00 = SDR         (same)

Reserved [1] = 1bit:
0

BW [0] = 1bit:
1 = 16bit        (same)

so, as we can see, there are really only 2 changed values, these are the RASBW0 and CASBW0 bits, not sure why they've both increased by one bit for each value but those 2 values changing are consistent with us only having a single ram chip, if we had 2 and had swapped them out for 2x 32MB chips, we would expect the RASBW1 and CASBW1 values to have changed too :)  If you have the datasheet for your ram it should be a very simple case of changing the RASBW0/CASBW0 values to match your chips values.

So what now?  Well, my ram appears to be working as 32MB, even though it's 64MB, so I obviously need to adjust those values, it would appear that they need to go up, possibly both of them it seems and by 1, if I only had 16MB on the board, I would expect to decrease 1 of the values?  Possibly RASBW?

so, looking at the values we get if we count up 12bits x 8bits we get:
4095x255=1044225

and for 13bits x 9bits we get:
8191x511=4185601
 4194304
For each of the values, use your calculator in binary mode and press 1 for each of the bits, so for 13 bits enter 13 1s on the keypad, do the same for each to get the values.

So, from 8MB to 32MB is 4x the ram and we can see a correlation between 1044225 and 4185601, it's about 4x, curiously right now not exactly 4x though!! probably something slightly fundamental that I'm missing, anyway, it's close enough for me to take a stab in the dark and guess that for me to go from 32MB to 64MB is 2x the value I got for multiplying the bit widths.  So, how to get to that value? lets do the maths again, now I thought that I'd need to increase both values, but looking at it I only want a 2 fold increase, not 4 fold, which is what changing both values gives us, so I now think I only need to change 1 bit width value, lets see what happens, Changing RASBW0 to 14bit?

14bit = 16383
9bit = 511
16383x511 = 8361493
 8388608
now lets see what happens if we just change CASBW0 to 10bit

13bit = 8191
10bit = 1023
8191x1023 = 8379393

Both are pretty close to what I think I need, so my only choice here is to try them both.

If we do the math for a 16MB ram chip, I suspect that we will find exactly the same thing, that it will be one or the other bit (RASBW0/CASBW0) in the register that needs changing.

I'm not sure if I'm clutching at straws here, I don't know enough of the internal make up of my chip but looking at the 32MB chip that has already been done might shed some light on the correlation between values and I might get a more definitive answer as to which way is correct.

Looking at a datasheet for the HYB39S256160CTL 32MB ram stick, we know that it's 16Mx16bit ram, which is described as 8192x512x16bit, 13/9/2 addressing, looks like I was off by 1 on each value, should I count bit zero too? :D  Anyway, there's my fundamental flaw but adjusting the values and everything pretty much falls into place if we add the number of banks into the equation, which is 13bitsx9bitsx4banksx2 (16bits = 2x8bit bytes?) or (8192x512)x4 x2 = 33554432 which gives us the number of bytes of ram we expect to see in total in a 32MB chip, huzzah.

Had a little google for datasheets for 32Mx16 to see how they have rasbw/casbw values set and it appears that it's RAS 13bits wide x CAS 10bits wide in 4banks, so I'm going to go with a hunch and try that value first and see how I get on :D

So, for my 64MB of ram I think I need to change the CASBW0 bits from 01 to 10, which gives me a hex value of 0x45001

So going back to lowlevel_init.S we need to change it so that it looks like this:

 mov r0,#0x48000000
 /* ldr r1,=0x24001 */ /* 8mb  */
 /* ldr r1,=0x44801 */ /* 32mb ? */
 ldr r1,=0x45001 /* 64MB ? */

Now save lowlevel_init.S and recompile uboot and get ready with openocd to jtag it to the frame, or if you're brave, just put it on your SD card and burn it to your nand, bear in mind that you could brick your frame doing this and you will need jtag to recover it :D

I suspect if we were looking at a 16MB chip, we would have to check a few datasheets to see whether there's a common combination of bit settings for rasbw0/casbw0, I need to check more datasheets for 32Mx16 pc133 chips to be certain that they're all 13bitx10bits ras/cas, if so then we know that for 8, 16,32,64MB chips there can only be one value that we will have to poke into the bankcfg/bwscon address for each chip, hopefully we can squeeze a check into u-boot to make a universal loader, if we can't do it in code, we can certainly do it with a compile time switch/define I think.  Of course this all assumes that I've researched things properly and worked out the correct bankcfg value.  If not the only thing to try will be to use only other value it could be, 14bitx9bit. 16384x512.

Something else to note, if you have the datasheet then you should check whether you've got the bankcon2 settings (thanks to doragasu for the information) correct for the timing of your chip.  If in doubt start with the slowest timings and tweak them as necessary if you're unsure.

Comments