On Sat, 05 Apr 2014 17:58:11 +0200
Jens Kuske <jensku...@gmail.com> wrote:

> On 03/04/14 07:49, Siarhei Siamashka wrote:
> >
> > I would guess that the .tpr settings, bundled with .cas=6, are likely
> > assuming 400MHz memory clock speed. Which also agrees with the tRFC
> > hardcoded values as you mentioned above. And also with the A10
> > and A20 user manuals, which specify 0~400MHz range for SDRAM_clk.
> >
> > The .cas=9 style sets of timings are likely very conservative and
> > assuming memory clock speeds up to 667MHz if we take the cas value
> > as a hint. If we are running dram at around 480MHz, these settings
> > may unnecessarily sacrifice some performance.
> 
> I found some documentation for TPR registers in the rk30xx manual from
> radxa. Their dram controller is pretty much different, but comparing the
> default values and settable bits of the TPR registers makes it likely
> that at least these registers have nearly the same bitfields.
> 
> This makes the .cas=6 set look like:
> tMRD = 2, tRTP = 4, tWTR = 4, tRP = 6, tRCD = 6,
> tRAS = 18, tRRD = 4, tRC = 24, tCCD = 0
> tAOND_tAOFD = 0, tRTW = 0, tFAW = 18, tMOD = 0, tRTODT = 0
> tXS = 200, tXP = 8, tCKE = 3
> 
> Assuming this is valid, we can do some trail and error again and try to
> figure out the original timings.
> 
> As it turns out, your guess was pretty good. The settings *exactly*
> match DDR2(!)-800E speed bin at 400MHz. Its DDR2 again, as with tRFC.
> Interesting part is, if we assume DDR3-1333H chips (as on cubieboard)
> many parameters are still in spec up to 480MHz (not all however, tFAW,
> tXS and what else I missed not).
> 
> And for the .cas=9 set, most settings match DDR3-1333H speed bin at
> 667MHz. But some settings, like tFAW and tXP are too low,
> they only fit for ~420MHz.
> 
> tMRD = 3, tRTP = 5, tWTR = 5, tRP = 9, tRCD = 9,
> tRAS = 24, tRRD = 6, tRC = 33, tCCD = 0
> tAOND_tAOFD = 0, tRTW = 0, tFAW = 18, tMOD = 0, tRTODT = 0
> tXS = 512, tXP = 10, tCKE = 4

That's a very nice catch. Thanks! Looks like this is a stepping stone
in the memory controller reverse engineering.

However things would have been surely much easier if all of this was
properly documented by Allwinner.

> I tried to calculate the correct parameters for 480MHz on cubietruck,
> and currently lima-memtester is running without any errors till now. I
> first accidentally kept the clock at 432MHz and only changed the tprs,
> and even that gave a ~150MB/s boost at tinymembench compared to the
> original values.
> This is highly experimental, but if somebody wants to try (only
> cubietruck, other dram chips need different timings):
> .clock = 480
> .cas = 7
> .tpr0 = 0x30b27790
> .tpr1 = 0x0000a078
> .tpr2 = 0x0001b200
> 
> These timings are calculated by hand, but maybe this could lead to some
> program or even function in u-boot that calculates matching parameters
> for given dram chip type and speed.

Well, not a big surprise, but my "lucky" Cubietruck fails
lima-memtester tests with these settings too:

Kernel driver is version 14
Detected 1 Mali-400 GP Cores.
Detected 2 Mali-400 PP Cores.
FB: 1280x720@32bpp at 0x51001000 (0x00A8C000)
Using dual buffered direct rendering to FB.

memtester version 4.3.0 (32-bit)
Copyright (C) 2001-2012 Charles Cazabon.
Licensed under the GNU General Public License version 2 (only).

pagesize is 4096
pagesizemask is 0xfffff000
want 300MB (314572800 bytes)
got  300MB (314572800 bytes), trying mlock ...locked.
Loop 1:
  Stuck Address       : ok         
  Random Value        : ok
  Compare XOR         : ok
  Compare SUB         : ok
  Compare MUL         : ok
  Compare DIV         : ok
  Compare OR          : ok
  Compare AND         : ok
  Sequential Increment: ok
  Solid Bits          : ok         
  Block Sequential    : ok         
  Checkerboard        : ok         
  Bit Spread          : ok         
  Bit Flip            : testing 221FAILURE: 0xf7ffffff != 0xf7ffff00 at offset 
0x03e041fc.
FAILURE: 0x08000000 != 0x0800000c at offset 0x03e04200.
FAILURE: 0xf7ffffff != 0xf7ffff06 at offset 0x03e04204.
  Walking Ones        : ok         
  Walking Zeroes      : ok         

Loop 2:
  Stuck Address       : ok         
  Random Value        : ok
  Compare XOR         : ok
  Compare SUB         : ok
  Compare MUL         : ok
  Compare DIV         : ok
  Compare OR          : ok
  Compare AND         : ok
  Sequential Increment: ok
  Solid Bits          : ok         
  Block Sequential    : ok         
  Checkerboard        : ok         
  Bit Spread          : ok         
  Bit Flip            : testing 213FAILURE: 0xfbffffff != 0xfbffff00 at offset 
0x038051bc.
FAILURE: 0x04000000 != 0x040000ff at offset 0x038051c0.
FAILURE: 0xfbffffff != 0xfbffff00 at offset 0x038051c4.
FAILURE: 0x04000000 != 0x040000ff at offset 0x038051c8.
FAILURE: 0xfbffffff != 0xfbffff00 at offset 0x038051cc.
FAILURE: 0x04000000 != 0x040000ff at offset 0x038051d0.
FAILURE: 0xfbffffff != 0xfbffff00 at offset 0x038051d4.
FAILURE: 0x04000000 != 0x040000ff at offset 0x038051d8.
FAILURE: 0xfbffffff != 0xfbffff00 at offset 0x038051dc.
FAILURE: 0x04000000 != 0x040000ff at offset 0x038051e0.
FAILURE: 0xfbffffff != 0xfbffff00 at offset 0x038051e4.
FAILURE: 0x04000000 != 0x040000ff at offset 0x038051e8.
FAILURE: 0xfbffffff != 0xfbffff00 at offset 0x038051ec.
FAILURE: 0x04000000 != 0x040000ff at offset 0x038051f0.
FAILURE: 0xfbffffff != 0xfbffff00 at offset 0x038051f4.
FAILURE: 0x04000000 != 0x040000ff at offset 0x038051f8.
  Walking Ones        : ok         
  Walking Zeroes      : ok         


> Last warning, all numbers were juggled around many times and I did never
> check them again, so they could easily be wrong. But the overall idea
> should be correct.

Thanks for spotting all of this. The rk30xx manual is indeed a good
reference. BTW, I'm playing with the following ruby script right now:

#!/usr/bin/env ruby

# Bitfields for DDR_PHYCTL_DTPR0, DDR_PHYCTL_DTPR1, DDR_PHYCTL_DTPR2 from
# RK30xx manual represented as [highest bit, lowest bit, add constant, name]
$tpr_bitfields = [
    [ # .tpr0
        [31, 31,  0, "tCCD"],
        [30, 25,  0, "tRC"],
        [24, 21,  0, "tRRD"],
        [20, 16,  0, "tRAS"],
        [15, 12,  0, "tRCD"],
        [11,  8,  0, "tRP"],
        [ 7,  5,  0, "tWTR"],
        [ 4,  2,  0, "tRTP"],
        [ 1,  0,  4, "tMRD"],
    ],
    [ # .tpr1
        [23, 16,  0, "tRFC"],
        [15, 12,  0, "reserved"],
        [11, 11,  0, "tRTODT"],
        [10,  9, 12, "tMOD"],
        [ 8,  3,  0, "tFAW"],
        [ 2,  2,  0, "tTRW"],
    ],
    [ # .tpr2
        [28, 19,  0, "tDLLK"],
        [18, 15,  0, "tCKE"],
        [14, 10,  0, "tXP"],
        [ 9,  0,  0, "tXS"],
    ]
]

# Convert an array with 3 magic constants to a key->value hash
def convert_from_tpr(tpr)
    result = {}
    tpr.each_index {|i|
        $tpr_bitfields[i].each {|v|
            maxbit = v[0]
            minbit = v[1]
            x = (tpr[i] >> minbit) & ((1 << (maxbit - minbit + 1)) - 1)
            result[v[3]] = x + v[2]
        }
    }
    return result
end

# Convert from a key->value hash back to an array with 3 magic constants
def convert_to_tpr(a)
    result = [0, 0, 0]
    tmp_hash = {}
    $tpr_bitfields.each_index {|i|
        $tpr_bitfields[i].each {|v|
            tmp_hash[v[3]] = [i, v[1], v[2]]
        }
    }
    a.each {|k, v|
        result[tmp_hash[k][0]] |= (v - tmp_hash[k][2]) << tmp_hash[k][1]
    }
    return result
end

# Format 3 magic tpr constants as dram_para stuct in u-boot sources
def print_tpr(comment, dram_clock, tpr)

    # A sanity check: ensure that the roundtrip conversion to the
    # key->value hash and back to three 32-bit magic constants does
    # not introduce any errors
    new_tpr = convert_to_tpr(convert_from_tpr(tpr))
    raise "Roundtrip conversion failed" unless new_tpr[0] == tpr[0] &&
                                               new_tpr[1] == tpr[1] &&
                                               new_tpr[2] == tpr[2]

    printf("\n%s\n", comment)

    tmp = convert_from_tpr(tpr)
    used_keys = {}

    printf("\t/*\n")
    # Show the most interesting values in a special sorting order
    ["tRCD", "tRC", "tRAS", "tRP", "tFAW", "tRRD", "tRFC"].each {|k|
        used_keys[k] = 1
        printf("\t * %8s = %8.2f ns (%d)\n", k,
               tmp[k].to_f * 1000 / dram_clock, tmp[k])
    }
    # Show the rest of the values in any order
    tmp.each {|k, v|
        next if used_keys[k]
        printf("\t * %8s = %8.2f ns (%d)\n", k,
               tmp[k].to_f * 1000 / dram_clock, tmp[k])
    }
    printf("\t */\n")

    printf("\t.clock = %d\n", dram_clock)
    printf("\t.tpr0 = 0x%x,\n\t.tpr1 = 0x%x,\n\t.tpr2 = 0x%x,\n",
           tpr[0], tpr[1], tpr[2])
end

# Define interesting sets of tpr magic values

tpr_cas6 = [0x30926692, 0x1090, 0x1a0c8]
tpr_cas9 = [0x42d899b7, 0xa090, 0x22a00]

tpr_jemk_cas7 = [0x30b27790, 0x0000a078, 0x0001b200]

# And print more details about them

print_tpr("/* the original .cas=6 set at 400MHz */",
          400, tpr_cas6)
print_tpr("/* the original .cas=9 set at 667MHz */",
          667, tpr_cas9)
print_tpr("/* the experimental .cas=7 set from jemk */",
          480, tpr_jemk_cas7)

# Tweak .cas=9 set to modify the tFAW bitfield value

tmp = convert_from_tpr(tpr_cas9)
tmp["tFAW"] = 35
print_tpr("/* .cas=9 set with tFAW changed to 35 */",
          480, convert_to_tpr(tmp))

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to