AnsweredAssumed Answered

Identification of Karo TX53-1331 vs TX53-8030 from U-boot initialization

Question asked by Chris Wyse on Sep 26, 2014
Latest reply on Sep 27, 2014 by Fabio Estevam

Hi,

 

I’m trying to distinguish the difference between the Karo TX53-1331 (IMX535) and the Karo Tx53-8030 (IMX537) module at boot time (U-boot).  I’d like to use a single U-boot image for both modules, and dynamically set the speed and configuration based on the board. 

 

My first thought was to read the chip identification register, but I can’t find any means to distinguish between the two chips.  The identification tells me that they are both IMX53 chips, but not whether they are 535 vs 537.  

 

At a board level, the 1331 has 1 GB of external memory, and the 8030 has 512 MB.  Additionally, we’re getting a new TX53 module with 2 GB of memory.  It would be nice to use a memory size test to determine which board I’m using.  I’ve struggled quite a bit with this task, due to the lack on an emulator and unfamiliarity the the ARM boot process, exception handling, and assembly language.  My premise is to execute code prior to enabling the MMU, referencing the physical address of the RAM.  Ideally, I’d want the data abort exception disabled, then write to the start of the second memory bank at PHYS_SDRAM_2 (0xB0000000).  I’d read from the same location, and compare it with a known value.  If the value matched, then I have the 1331 module with 1 GB of memory (forget about the 2 GB module for now), otherwise it’s the 8030 module.  I didn’t see a way to specifically disable the data abort exception, so I tried to add a handler that just returned to the statement after the exception.  That resulted in no output to the display (initialization failed).

 

Assuming that maybe I was getting a different exception, I tried installing the same handler to all the exception vectors, with some modification based on the exception mode and where the exception address is saved.  This produced the same result.

 

I’ve tried many different approaches, but can’t seem to get them to do what I want.  Additionally, the simplistic approach given above needs to be enhanced to handle recognition of a module with 2 GB of memory.

 

I also attempted to use the get_ram_size() routine used by some other Arm processors for the same problem.  It would be nice to be able to call this during early initialization so that I could set the processor speed/type based on the result. 

 

The lack of an emulator really complicates things, since I have no way of stepping through the code and evaluating registers other than rebuilding the image with instrumentation.  The instrumentation is limited as well, since I’m in the early bootup, and don’t have print capabilities.

 

The test_memory macro (below) is called from lowlevel_init.S, immediately after the call to sdram_init.  Of note is the fact that for karo modules, the sdram_init routine is not used.  Instead, the initialization is done inside flash_header.S, using hardcoded register offsets (which made it difficult for me to find).  I modified that code to always initialize with the assumption that there are two banks of memory.

 

FYI…  In support of the changes to test memory, I modified several configuration macros related to memory size and CPU speed, changing them to global variables.  I modified all code that referenced them to use the variables instead.

 

My questions are:

 

  1. What’s a good approach to resolve this problem? 
  2. What exception occurs if I access memory that isn’t present?
  3. How do I ignore/disable data aborts, or create a handler that returns to the instruction following the exception?
  4. If I turn on the bank 2 chip select when there is no memory present, how is the CS1_RDY bit affected?  Will it always be not ready?
  5. Are there any ramifications of always specifying two elements on the bi_dram field of bd_info (in u-boot.h), even if only one is present?
  6. The Karo module specifies a supported speed of 1200 MHz for the TX53-1331, yet Freescale limits the IMX535 to 1000 MHz.  Should the 1331 be limited to 1000 MHz?

 

Miscellaneous coding:

 

Data abort handler

 

data_abort:

subs   pc, lr, #4           // Return to location after abort

 

Test memory

 

.macro _test_memory

#if BANK_READY_TEST

ldr  r3, =ESDCTL_BASE_ADDR

ldr  r0, [r3, #0x10] //ESDMISC

adrls r1, PHYS_SDRAM_2_SIZE   //  Load address of PHYS_SDRAM_2_SIZE into r1

// Test the CSD1_RDY bit to see if there is another RAM Bank

tst r0, #0x40000000

beq  cfg1Gigabyte

b cfg512Megabyte

#endif

ldr r0, =PHYS_SDRAM_2         // Load physical address of second memory bank into r0 (0xB0000000)

adrls r1, PHYS_SDRAM_2_SIZE   //  Load address of PHYS_SDRAM_2_SIZE into r1

 

ldr r2, =0xABCDABCD        //  Load 0xABCDABCD into r2

ldr r3, =0xDBCADBCA        //  Load 0xDBCADBCA into r3

str  r2, [r0] //  Store 0xABCDABCD at location PHYS_SDRAM_2

ldr  r3, [r0] //  Load r3 with contents of location PHYS_SDRAM_2

cmp  r3, r2 //  Compare the content of PHYS_SDRAM_2 with 0xABCDABCD

beq  cfg1Gigabyte         // If we were able to read the value back successfully, we have two memory banks

cfg512Megabyte:

ldr r2, =0x00000000        // Total Memory: 512 Megabytes

strls r2, [r1] // Load 0 Megabytes into PHYS_SDRAM_2_SIZE

#if BANK_READY_TEST

ldr  r3, =ESDCTL_BASE_ADDR

ldr  r0, [r3, #0x0] //ESDCTL

// Turn off enable for bank 2

and r0, r0, #0xBFFFFFFF

str r0, [r3, #0x0]

#endif

 

b cfgDone

cfg1Gigabyte:

ldr r2, =0x20000000 // Total Memory: 1 Gigabyte

strls r2, [r1]      // Load 512 Megabytes into PHYS_SDRAM_2_SIZE

 

cfgDone:

.endm @ _test_memory

Outcomes