issue using sram through eim with torizon

Hi,
I’m trying to configure a torizoncore image to make a fpga accessible as sram using eim.

I have recompiled the os with only a few changes: I allowed GONFIG_MTD_ROM, CONFIG_MTD_RAM and CONFIG_MTD_PHYSMAP using menuconfig. I have now the following configuration:

apalis-imx6-10571917:/dev$ zcat /proc/config.gz | grep MTD
CONFIG_MTD=y
# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_AR7_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_OF_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_OOPS=y
# CONFIG_MTD_SWAP is not set
# CONFIG_MTD_PARTITIONED_MASTER is not set
CONFIG_MTD_CFI=y
CONFIG_MTD_JEDECPROBE=y
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_CFI_STAA=y
CONFIG_MTD_CFI_UTIL=y
CONFIG_MTD_RAM=y
CONFIG_MTD_ROM=y
CONFIG_MTD_ABSENT=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_COMPAT=y
CONFIG_MTD_PHYSMAP_START=0x8000000
CONFIG_MTD_PHYSMAP_LEN=0
CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_PHYSMAP_OF is not set
# CONFIG_MTD_IMPA7 is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
CONFIG_MTD_PLATRAM=y
# Self-contained MTD device drivers
# CONFIG_MTD_PMC551 is not set
CONFIG_MTD_DATAFLASH=y
# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
# CONFIG_MTD_DATAFLASH_OTP is not set
# CONFIG_MTD_MCHP23K256 is not set
CONFIG_MTD_SST25L=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_BLOCK2MTD is not set
# CONFIG_MTD_DOCG3 is not set
# end of Self-contained MTD device drivers
CONFIG_MTD_NAND_CORE=y
# CONFIG_MTD_ONENAND is not set
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
# CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC is not set
CONFIG_MTD_RAW_NAND=y
# CONFIG_MTD_NAND_ECC_SW_BCH is not set
# CONFIG_MTD_NAND_DENALI_PCI is not set
# CONFIG_MTD_NAND_DENALI_DT is not set
# CONFIG_MTD_NAND_CAFE is not set
# CONFIG_MTD_NAND_BRCMNAND is not set
CONFIG_MTD_NAND_GPMI_NAND=y
# CONFIG_MTD_NAND_MXC is not set
# CONFIG_MTD_NAND_MXIC is not set
# CONFIG_MTD_NAND_GPIO is not set
# CONFIG_MTD_NAND_PLATFORM is not set
# CONFIG_MTD_NAND_NANDSIM is not set
# CONFIG_MTD_NAND_RICOH is not set
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_SPI_NAND is not set
# CONFIG_MTD_LPDDR is not set
# CONFIG_MTD_LPDDR2_NVM is not set
CONFIG_MTD_SPI_NOR=y
CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_MTD_UBI_BEB_LIMIT=20
CONFIG_MTD_UBI_FASTMAP=y
# CONFIG_MTD_UBI_GLUEBI is not set
CONFIG_MTD_UBI_BLOCK=y
# CONFIG_MTD_HYPERBUS is not set
CONFIG_LEDS_TRIGGER_MTD=y

I also applied a device tree overlay that enable eim and specify a sram device:

// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
 * Copyright 2020-2021 Toradex
 */

// Enable the LVDS interface on the Apalis iMX6Q. Make sure to also select a valid display configuration.

/dts-v1/;
/plugin/;

/ {
	compatible = "toradex,apalis_imx6q";
};




/* gpio */


&gpio6 {
   gpio6 {
   gpio-hog;
   gpios = <9 5>;
   output-high;
   };
};


&gpio1 {
   gpio7 {
   gpio-hog;
   gpios = <2 0>;
   output-high;
   };
   
gpio8 {
   gpio-hog;
   gpios = <6 0>;
   output-high;
   };
};




&ecspi1 {
	/* pin conflict with weim */
	status = "disabled";
};

&ecspi2 {
	/* pin conflict with weim */
	status = "disabled";
};

&can2 {
	/* max7310_c on i2c3 is gone */
	status = "disabled";
};

&i2c1 {
	/* pin conflict with weim */
	status = "disabled";
};

&i2c3 {
	/* pin conflict with weim */
	status = "disabled";
};

&uart3 {
	/* pin conflict with gpmi and weim */
	status = "disabled";
};

&uart1 {
	/* pin conflict with gpmi and weim */
	status = "disabled";
};

&usbh1 {
	/* max7310_b on i2c3 is gone */
	status = "disabled";
};




&weim {
    compatible = "fsl,syctrl-eim-driver";
	pinctrl-names = "default";	

	fsl,weim-cs-gpr = <&gpr>;
	status = "okay";

	ranges = <0 0 0x08000000 0x08000000>;
	/* FPGA on CS0 */

	sram@0,0 {
		compatible = "mtd-ram";
		reg = <0 0x00000000 0x00040000>;
		bank-width = <2>;
		        fsl,weim-cs-timing = <0x00610001 0x00000000 0x0E022000
                 0x00000000 0x1c092480 0x00000000>;
		#address-cells = <1>;
		#size-cells = <1>;
	};
};

Thanks to this overlay I can access correct values from my fpga by mmaping /dev/mem and reading values from 0x08000000 with devmem2.

But I would like to make this memory appearing as a separate device from the /dev/ folder, like /dev/sram for example.

It don’t seems to work with my actual config. what do you advise me to do to achieve this?

Best regards
rfonck

Greetings @rfonck,

I don’t personally know of any such method to map a memory address to a separate /dev entry. After some research I couldn’t really find any answers as well. In general brand new /dev entries are generated from that device’s respective driver. There’s not really a way go generate a new /dev entry from user space. There are some tricks with udev rules. But usually udev rules operate on already existing /dev entries.

Is this a blocker for you? Or just more of a convenience change?

Best Regards,
Jeremias

Hi,
The issue is that to communicate with the fpga using /dev/mem interface, I must use super user privileges.

However the application I want to run don’t have these privileges.

I tought that by creating a specific/dev/“sram” device and configuring it, it could be possible to access my data directly without special privileges by mmaping the /dev/“sram” device.

Do you think it is not possible to create this using “mtd-ram” driver ?

How do you think I can run a non privileged application accessing this data ?

Best regards,
rfonck

Well assuming your running your application n a container one thing you might try is cgroups. When you run a container you can pass crgoups arguments that give access to certain devices, at least in that specific container.

See more about this here: Torizon Best Practices Guide | Toradex Developer Center

Looking at the kernel documentation here: linux/devices.txt at master · torvalds/linux · GitHub

I can see that /dev/mem is a device that can be specified with cgroups, so perhaps this is worth a try.

Best Regards,
Jeremias

Hi,

thanks a lot for your reply.

I created a container in order to test the access to the /dev/mem device.

I used the following dockerfile:

FROM --platform=linux/arm torizon/debian:2-bullseye
 
RUN apt update && apt install nano -y

And I ran it using this command line:

docker run --rm -it  -v /dev/mem:/dev/mem --device-cgroup-rule='c 1:1 rwm'  rfonck/gs-torizon

But once I’m in the container, I can’t access /dev/mem device.

root@100e48afcc07:/home/torizon/devmem2# ./devmem2 0x08000000
Error at line 79, file readMem.c (1) [Operation not permitted]

It’s obvious that I missconfigured something in the permissions but I don’t really understand where I can specify that my container can access the /dev/mem device without any super user permission.

If you have any indication to give to me or liks that explain how to deal with these permissions I will be very grateful.

Best regards,
rfonck

After looking at some docker forums it seems this argument is also needed --cap-add SYS_RAWIO.

So the full run command would be something like:

docker run --rm -it --device /dev/mem:/dev/mem --device-cgroup-rule='c 1:1 rwm' --cap-add SYS_RAWIO

This seems to work on my side and I can run devmem without sudo/privileged permissions.

Best Regards,
Jeremias

Thanks a lot.

It match what I was looking for on this topic.

Best regards
rfonck

Perfect! Glad we were able to work this out.