External EIM Bus CS1

Dear Toradexteam,

currently we have a SRAM mapped in the EIM - CS0 area 128MB. It works well.
Now we like to split the area in 2 regions with CS0 and CS1.
I used CS0 Registers and values as a template and as documented in the toradex knowledge-base.
It looks simple, but I had done something wrong.
If I read form CS1 area I got the data form CS0 area. I guess there is a register value not defined.
Please can you assist me, to find the error.

// EIM clock root and clock gate registers
#define CCM_BASE_ADDRESS      0x30380000
#define CCM_CCGR22            0x30384160
#define CCM_TARGET_ROOT83     0x3038A980
#define IOMUXC_GPR1           0x30340004

clkRegs = (DWORD*)Map_MapMemory(CCM_BASE_ADDRESS, 0x10000);
targetAddr = clkRegs + (CCM_CCGR22 - CCM_BASE_ADDRESS) / 4;          // CCM_CCGR22 
*targetAddr &= ~0xFFFFFFFF;                                           //CLR all

targetAddr = clkRegs + (CCM_TARGET_ROOT83 - CCM_BASE_ADDRESS) / 4;   //TARGETROOT83
*targetAddr |= 0x10000000;				  // 0x10000000 -> clock root is on

targetAddr = clkRegs + (CCM_CCGR22 - CCM_BASE_ADDRESS) / 4;          // CCM_CCGR22 
*targetAddr |= 0x33;     //SETTING for domain 0: 3 (Domain clocks needed all the time

pRegister = (DWORD*)Map_OALPAtoVA(IOMUXC_GPR1, 1);
*pRegister |= 0x1B;       // WEIM_ACT_CS0 32MB    WEIM_ACT_CS1 32MB

pWEIM = (ptCSP_WEIM_REGS)Map_MapMemory(0x30bc0000, 0x1000);
pWEIM->CS0GCR1 |= 0x0000009;    // CS0 enable und MUX mode
pWEIM->CS1GCR1 |= 0x0000009;    // CS1 enable und MUX mode

pWEIM->CS0GCR2 = 0x00001002; 	                             
pWEIM->CS1GCR2 = 0x00001002;  
                             
pWEIM->CS0RD1 = 0x1E626430;  // timing between ADV OE CS,...
pWEIM->CS1RD1 = 0x1E626430;    

pWEIM->CS0RD2 = 0x0000002A;  // timing BE beginn read,...
pWEIM->CS1RD2 = 0x0000002A;   

pWEIM->CS0WR1 &= 0x00000000;   //clr WADVA 
pWEIM->CS0WR1 = 0x1F6FFFD3;    //ALE 

pWEIM->CS1WR1 &= 0x00000000;    
pWEIM->CS1WR1 = 0x1F6FFFD3;     

Test: I write to area extBus (0x28…) and then I read from extBusAB(0x2A…)
and I got the same data written to extBus reading from extBusAB

volatile DWORD *extBus;
volatile DWORD *extBusAB;

HANDLE hMap;

hMap = Map_Init();
extBus = (DWORD*)Map_MapMemory(0x28000000, 0x100000);
*extBus = 0x3333;

extBusAB = (DWORD*)Map_MapMemory(0x2A000000, 0x100000);
*extBusAB = 0x99AA;

for (int i = 0; i < 10; i++)
{
	printf("\n SRam=%x  AB=%x", *extBus, *extBusAB);
	extBus++;
	*extBus = i;
	extBusAB++;
}
Map_UnMapMemory(pWEIM);
Map_UnMapMemory(clkRegs);
Map_Deinit(hMap);

Could you share a part pf your schematic related to mentioned SRAM?

I will send you a schematic, but with my settings I see only the CS0 WE OE signals therefore it is normal to get
SRAM data all the time.
With my settings there is no CS1 signal activ. I think the problem is not the hardware (schematic) but my register definitions.
Please can you have a look at it, or an example. The lines 17 to 21 above I tried to split the EIM Bus
0x2800_0000 - 0x2FFF_FFFF in 32MB (0x1B), I tried also 0x1D (2* 64MB) without success…

best regards

Dear @maha

Background

The documentation of the register IOMUXC_GPR_GPR1 in NXP’s reference manual is not fully clear. There’s a definition in a source file on github (gprvals), which seems to be correct. Attention, the numbers are octal !

If I get it correctly, the values for the WEIM_ADDRSx fields are

00 =  32MB address space  
01 =  64MB address space  
10 =  128MB address space  
11 =  never used

Edit: I had a wrong interpretation of the values in my original answer (see below)
( 00 = no address space )
( 01 = 32MB address space )
( 10 = 64MB address space )
( 11 = 128MB address space )

and there’s a statement
The address space of the
first active chip select must be the biggest one, the following active chip select address spaces may be
equal or lower.

Your Code

The default value of the register IOMUXC_GPR_GPR1 is 0x0F40_0005.
Your statement …

*pRegister |= 0x1B;

…modifies this to 0x00F40_001F, which means

  • CS0 = invalid setting
  • CS1 = 64MB (overlapping the range of CS0)

I assume replacing it by the following statement should fix the issue

*pRegister = (*pRegister & ~0x3F) | 0x1B;  
// I edited my original post, where I had missed the ~ operator.

It would be nice to get your feedback whether this helped.

Regards, Andy

Hello Andy ,
thank you for the proposal. I change first to

*pRegister = (*pRegister & 0x3F) | 0x2D;     //(0x1B are 32 MB  and 0x2D are 2*64MB)

and then to

*pRegister = (*pRegister & 0xFFFFFF00) | 0x2D;

read IOMUXC_GPR_GPR1: 4f402005 <–Value after start
new IOMUXC_GPR_GPR1: 4f40202d <–Change see above
pWEIM->CS0GCR1: 00610089
pWEIM->CS0GCR2: 00001002
pWEIM->CS0WR1: 1f6fffd3
IOMUXC_GPR1: 4f40202d
pWEIM->CS1GCR1: 00010089
pWEIM->CS1GCR2: 00001002
pWEIM->CS1WR1: 1f6fffd3

but the CS1 is not active.
best regards

Dear @maha

I implemented the code on my system to verify the functionality. Attached to this comment you find a source code which worked for me:

A write and a read on each chip select looks as follows:

1137-cs0-cs1.png
CH1: CS0 (SODIMM 105)
CH2: CS1 (SODIMM 107)

I assume the major error in your code was the value of IOMUXC_GPR_GPR1. The low 12 bits of this register must be configured to 0x01b (instead of 0x02d). I adjusted my previous answer accordingly.

Regards, Andy

Dear Andy,
thank you so much for the example.
I works fine. Now I see CS0 and CS1.
You helped me a lot.

Best regards, maha