Fabrizio,

 

It looks like the mux_sys_init uses the RESOURCE macro,

 

#define RESOURCE(op, id) ps_io_map(&(op->io_mapper),  (uintptr_t) id##_PADDR, id##_SIZE, 0, PS_MEM_NORMAL)

 

So you should just have to change the IMX6_IOMUXC_SIZE in imx6/mux.c to 0x4000 to map the four pages the mux should need.

 

In the setup_iomux_enet function you could add a check to see if io_ops->mux_sys->priv == NULL, then use the RESOURCE macro. Else, just set base to equal to already mapped address.

 

-    void *base = RESOURCE(&io_ops->io_mapper, IOMUXC);

+    void *base;

+

+    if (io_ops->mux_sys_priv != NULL) {

+        base = io_ops->mux_sys_priv;

+    }

+    else  {

+        base = RESOURCE(&io_ops->io_mapper, IOMUXC);

+    }

 

I haven’t tested that, but it’s the logic that you should apply to your code.

 

I’ll let Data61 respond to why the mux stuff was added.

 

DornerWorks helped get the imx6 Ethernet drivers functional. We have an http server application that we host on our Github page that runs on seL4 7.0. You could give that a try as a reference.

 

https://github.com/dornerworks/dw-camkes-manifests

 

Let me know if you need any more help.

 

Chris Guikema

 

From: Devel [mailto:devel-bounces@sel4.systems] On Behalf Of Fabrizio Bertocci
Sent: Monday, June 25, 2018 9:12 PM
To: devel@sel4.systems
Subject: [seL4] IOMUX on iMX6 conflict with libethdrivers

 

Hi,

I need your help in trying to understand what is the best way to implement a permanent fix I can push on the seL4 repository regarding the incompatibility issues between the libethdriver and MUX interface of the platsupport.

 

This apply to the iMX6 ethernet driver. I'm not sure about other platforms.

 

In short, the problem is that platsupport takes ownership of the entire MUX (maps the I/O) when the io_ops are initialized:

Repo: seL4/seL4_libs

File: libsel4platsupport/src/io.c

Function: sel4platsupport_new_io_ops

  ...

  mux_sys_init(io_ops, get_mux_dependencies(), &io_ops->mux_sys);

  ...

 

The above call end up calling the platform-specific mux_sys_init that maps only the first 4Kb of IO space from address 0x020e0000 (the base address of the IOMUX controller - note: the IOMUX controller uses 16Kb of address space for its registers, not 4Kb!!!):

Repo: seL4/util_libs

File: libplatsupport/src/plat/imx6/mux.c

Function: mux_sys_init

  ...

  MAP_IF_NULL(io_ops, IMX6_IOMUXC, _mux.iomuxc);

  return imx6_mux_init_common(mux);

 

The pointer "io_ops->mux_sys->priv" should point to the base address of the IOMUX of the SoC (in the virtual memory space of the calling process).

 

The Ethernet driver unfortunately attempts to map the IOMUX again:

Repo: seL4/util_libs

File: libethdrivers/src/plat/imx6/uboot/mx6qsabrelite.c

Function: setup_iomux_enet

  ...

  void *base = RESOURCE(&io_ops->io_mapper, IOMUXC);

  ... 

  // Modify the IOMUX registers, then release the mapped IO:

  ...

  UNRESOURCE(&io_ops->io_mapper, IOMUXC, base);

 

but using a larger size (the full 16Kb from the same base address of the IOMUX controller).

 

So, the ethernet controller attempt to map the IO fails because it is already mapped, and nothing works.

 

Right now in my project I've entirely commented out the initialization of the MUXC from the sel4platsupport_new_io_ops function.

 

I understand that if the io_ops attempt to map the MUX (and leave it mapped) there must be a reason, unfortunately I fail to see it. The structure describing the MUXC register (struct imx6_iomuxc_regs, defined in libplatsupport/src/plat/imx6/mux.c) is private and not accessible outside that file, and the only two interface functions available (mux_feature_enable/mux_feature_disable) are not enough to be usable by the ethernet driver.

 

The ethernet driver could also attempt to reuse the same mapped IOMUX (beside that the size of the mapped area is different and won't work anyway), but that will require using the 'priv' field of the io_ops->mux_sys (beside, even trying to map the whole 16Kb of the IOMUX and have the driver to reuse the same mapped address, for some unknown reasons it doesn't work).

 

So, what is the right approach to fix this problem? 

Why the MUX subsystem maps some IO, never release it and keep it private for most of it?

The IOMUX has been introduced somewhere between version 1.0 and 9.x... and it seems a half-baked job... Can we just comment it out if nobody is using it?

Or if you have some ideas/suggestions on how to expand it in such a way the ethernet driver could use, please let me know. I'll be happy to implement it.

 

Regards,

Fabrizio