Cannot write to EIM of the i.MX6 via Linux

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Cannot write to EIM of the i.MX6 via Linux

Jump to solution
5,816 Views
GerrySimmons
Contributor II

I am still struggling to figure out why I can't write to the EIM  or the EIM registers on the i.mx6 under Linux.  Any help would be much appreciated.  I am at the end of things to even try next.

We are trying to test a IRQ and EIM based interface.  Currently I am having difficulty accessing the EIM bus.  I can read the EIM registers but can't write to them (value never changes).  I can't read or write to the EIM CS0 address block.

However I have discovered that from u-boot I can read/write to the EIM - CS0 (0x0800_0000) address range.  I am not sure if this is indeed making it out to the EIM pins but the board doesn't hang.  I can also read/write to the EIM registers (AIPS2->CSnGCR1-2,CSnRCR1-2,CSnWCR1-2).

Here is output from test of writing to CS0GCR1 register (0x021b8000). 

The original values match the default values from Processor Reference.

MX6Q SABRELITE U-Boot > md.l 0x021b8000 6

021b8000: 00610089 00001002 1c022000 00000000    ..a...... ......

021b8010: 1c092480 00000000    .$......

MX6Q SABRELITE U-Boot > mw.l 0x021b8000 0x00E100B9 1 MX6Q SABRELITE U-Boot > md.l 0x021b8000 6

021b8000: 00e100b9 00001002 1c022000 00000000    ......... ......

021b8010: 1c092480 00000000    .$......

Here is output from reading the EIM CS0 address block (0x08000000). The values change slightly with every read.  But that makes sense as nothing is currently hooked up to the EIM bus.

MX6Q SABRELITE U-Boot > md.l 0x08000000 16

08000000: 00010000 00030002 00050004 00070006 ................

08000010: 00090008 000b000a 000d000c 000f000e ................

08000020: 00110010 00130012 00150014 00170016 ................

08000030: 00190018 001b001a 001d001c 001f001e ................

08000040: 00210020 00230022 00250024 00270026 .!.".#.$.%.&.'.

08000050: 00290028 002b002a    (.).*.+.

I can write to it without apparent issues.

MX6Q SABRELITE U-Boot > mw.l 0x08000000 0xdeadbeaf 10 MX6Q SABRELITE U-Boot > md.l 0x08000000 16

08000000: 00010001 00030003 00050005 00070006 ................

08000010: 00090009 000b000a 000d000d 000f000f ................

08000020: 00110011 00130012 00150015 00170017 ................

08000030: 00190018 001b001a 001d001d 001f001e ................

08000040: 00210021 00230022 00250024 00270027 !.!.".#.$.%.'.'.

08000050: 00290028 002b002b    (.).+.+.

In my Linux Kernel module I can read from the EIM control registers.  I have set up a debugfs output to display the values. These values match what I expect to see as defaults.  Also they are the same values that I see in U-Boot.

EIM_WCR: 0x20

EIM_WIAR: 0x10

EIM_EAR: 0x0

EIM_CSOGCR1: 0x610089

EIM_CSOGCR2: 0x1002

EIM_CSORCR1: 0x1c022000

EIM_CSORCR2: 0x0

EIM_CSOWCR1: 0x1c092480

EIM_CSOWCR2: 0x0

EIM_CS1GCR1: 0x10080

EIM_CS1GCR2: 0x1000

EIM_CS1RCR1: 0x0

EIM_CS1RCR2: 0x0

EIM_CS1WCR1: 0x0

EIM_CS1WCR2: 0x0

EIM_CS2GCR1: 0x10080

EIM_CS2GCR2: 0x1000

EIM_CS2RCR1: 0x0

EIM_CS2RCR2: 0x0

EIM_CS2WCR1: 0x0

EIM_CS2WCR2: 0x0

EIM_CS3GCR1: 0x10080

EIM_CS3GCR2: 0x1000

EIM_CS3RCR1: 0x0

EIM_CS3RCR2: 0x0

EIM_CS3WCR1: 0x0

EIM_CS3WCR2: 0x0

EIM_CSOGCR1:

However in the code I try to set the value for the EIM_CSOGCR1 register and it doesn't change when I read it back.  Here are the read and write code lines.

#define EIM_CS0_OFFSET (0xb8000)

#define EIM_CSnGCR1 (0x00)

#define PERIPBASE_VIRT            0xF2000000

#define AIPS2_ARB_BASE_ADDR        0x02100000

#define AIPS2_BASE_ADDR_VIRT        (PERIPBASE_VIRT + AIPS2_ARB_BASE_ADDR)

__raw_readl(AIPS2_BASE_ADDR_VIRT+EIM_CS0_OFFSET+EIM_CSnGCR1)

__raw_writel(0x00E100B9,AIPS2_BASE_ADDR_VIRT+EIM_CS0_OFFSET+EIM_CSnGCR1)

Also if I try to read from the EIM CS0 address range the whole system hangs.

int map_shared_mem(struct itest_device_t * itest_dev_data) {

   /* get access to shared mem*/

   itest_dev_data->eim_addr = ioremap_nocache(EIM_CS0_BASE, SZ_128K);

   printk("itest: EIM memory virt address = 0x%p\n",itest_dev_data->eim_addr);

   if (itest_dev_data->eim_addr == NULL)

   {

     printk("itest:  error mapping EIM memory\n");

     return -ENOMEM;

   }

   return 0;

}

int itest_init(void)

{

.

.

.

map_shared_mem(&itest_device);

test_data = ioread16(itest_device.eim_addr); printk("%d\n",test_data);

}

Here is output from module.  After this nothing else is printed and the system appears to be unresponsive.

root@imx6qsabrelite:~# insmod /itest.ko

init

itest: EIM memory virt address = 0xc0ac0000

I then looked into the AHB to IP Bridge (AIPSTZ) (AIPS_TZ) registers in hopes that some of the access registers were the issue.

However it appears that u-boot sets them up.  Here is code from U-Boot that appears to be setting up the aips registers.

void init_aips(void)

{

         struct aipstz_regs *aips1, *aips2;

         aips1 = (struct aipstz_regs *)AIPS1_BASE_ADDR;

         aips2 = (struct aipstz_regs *)AIPS2_BASE_ADDR;

         /*

          * Set all MPROTx to be non-bufferable, trusted for R/W,

          * not forced to user-mode.

          */

         writel(0x77777777, &aips1->mprot0);

         writel(0x77777777, &aips1->mprot1);

         writel(0x77777777, &aips2->mprot0);

         writel(0x77777777, &aips2->mprot1);

         /*

          * Set all OPACRx to be non-bufferable, not require

          * supervisor privilege level for access,allow for

          * write access and untrusted master access.

          */

         writel(0x00000000, &aips1->opacr0);

         writel(0x00000000, &aips1->opacr1);

         writel(0x00000000, &aips1->opacr2);

         writel(0x00000000, &aips1->opacr3);

         writel(0x00000000, &aips1->opacr4);

         writel(0x00000000, &aips2->opacr0);

         writel(0x00000000, &aips2->opacr1);

         writel(0x00000000, &aips2->opacr2);

         writel(0x00000000, &aips2->opacr3);

         writel(0x00000000, &aips2->opacr4); }

This matches what I see in U-Boot and Linux.

//output from u-boot

MX6Q SABRELITE U-Boot > md.l 0x0207c000 1

0207c000: 77777777    wwww

MX6Q SABRELITE U-Boot > md.l 0x0207c040 5

0207c040: 00000000 00000000 00000000 00000000 ................

0207c050: 00000000    ....

MX6Q SABRELITE U-Boot > md.l 0x0217c000 1

0217c000: 77777777    wwww

MX6Q SABRELITE U-Boot > md.l 0x0217c040 5

0217c040: 00000000 00000000 00000000 00000000 ................

0217c050: 00000000    ....

//output from kernel module

AIPSTZ1_MPR: 0x77777777

AIPSTZ1_OPACR0: 0x0

AIPSTZ1_OPACR1: 0x0

AIPSTZ1_OPACR2: 0x0

AIPSTZ1_OPACR3: 0x0

AIPSTZ1_OPACR4: 0x0

AIPSTZ2_MPR: 0x77777777

AIPSTZ2_OPACR0: 0x0

AIPSTZ2_OPACR1: 0x0

AIPSTZ2_OPACR2: 0x0

AIPSTZ2_OPACR3: 0x0

AIPSTZ2_OPACR4: 0x0

I also looked at the CSU registers but they also seem the same between Linux and U-Boot.

Labels (2)
Tags (1)
1 Solution
1,173 Views
troy_kisky
Contributor II

Try enabling EMI slow clock

CCM_CCGR6 bits 11-10

View solution in original post

3 Replies
1,173 Views
rellimekim
Contributor I

Thank you for this post!  It helped me solve my problem, too.

My team had the exact same symptoms as the OP, but we are running WEC7 on the iMX53.  Access to EIM registers worked in EBOOT, but not from our EIM drivers loaded by the OS.  We have spent several days tracking down the privilege and locking scenarios that might have been preventing access - but this was the problem.

On the iMX53, it is CCM_CCGR5[17:16] that must be set to enable the EIM clock (emi_slow_clk_enable).

CCM info in the iMX53 Reference Manual p.919

EIM info in the iMX53 Reference Manual p.1114

Thanks Troy!

0 Kudos
1,174 Views
troy_kisky
Contributor II

Try enabling EMI slow clock

CCM_CCGR6 bits 11-10

1,173 Views
GerrySimmons
Contributor II

This worked!  Evidently, this turns the EIM interface back on after the Linux driver turns it off. U-boot has the interface on.

0 Kudos