This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/AM3358: gpio-leds triggers and mmc renumbering

Part Number: AM3358

Tool/software: Linux

In Linux, what is the correct way of linking an indicator LED to activity on a given mmc interface? Naively I would assume you just setup the device tree to use triggers with the gpio-led driver. Something like the following:

mmc1-led {
    pinctrl-names = "default";
    pinctrl-0 = <&mmc1_led_pins>;
    compatible = "gpio-leds";

    mmc1-led@0 {
        label = "mmc1:activity";
        gpios = <&gpioX YY GPIO_ACTIVE_LOW>;
        linux,default-trigger = "mmc1";
        default-state = "off";
    };
};

However the device names given by the kernel don't always line up with the physical interface. Obviously this is annoying as the triggers driving the indicator lights are now displaying the wrong information. Just as an example I have the following mmc devices:

sd card on mmc0 is named mmc1
emmc on mmc1 is named mmc2
wifi on mmc2 is named mmc0

However on a board variant without wifi the device names match the correct bus.

sd card on mmc0 is named mmc0
emmc on mmc1 is named mmc1

From what I have read the kernel dynamically assigns the mmc device names based on the order they are discovered. So the scenario where the device names match the physical interface may just be luck. Is there a way to force the device name to match the physical bus a device is attached to? Is the discovery order based on something predictable I can work with like ascending addresses within the memory map? Or is the answer a workaround like an init script to figure out what the devices were named to set the appropriate LED triggers? Any pointers on how to solve this would be appreciated.

  • Hi Andrew,

    The assignment of mmc modules in Linux is based on the entries in am33xx.dtsi (see the below image). In the context of the device tree, mmc1 is always mmc1 because it is assigned to the specific memory address where that instance of the module resides. The confusion comes from the hardware numbering which starts at 1 but in Linux the "/dev/mmcblk" value starts at 0. So only in Linux does the SD Card on MMC1 change to be "mmcblk0" and eMMC on MMC2 => mmcblk1. 

    Does this information help you with setting up the gpio-led? You can always use other board dts files as reference.

  • According to the TRM the IP blocks are zero based and the AM335x physically has mmc[0-2]. The device tree (am33xx.dtsi) names the modules using one based indexing and provides mmc[1-3]. As you mentioned, Linux also uses zero based numbering (So why are the mmc entries in the device tree one based?). So yes there is a difference but I don't think this is my problem.

    on the board with wifi:

    physical mmc0 registers as mmcblk1 (matches expected mmc1 device tree name)
    physical mmc1 registers as mmcblk2 (matches expected mmc2 device tree name)
    physical mmc2 (no mmcblk device as this is wifi, but dmesg shows a message for mmc0)

    on the board without wifi

    physical mmc0 registers as mmcblk0 (does not match expected mmc1 device tree name)
    physical mmc1 registers as mmcblk1 (does not match expected mmc2 device tree name)

    So a core device tree shared between both boards defining an led with a mmc1 trigger behaves differently. This is my problem.
  • Hi Andrew,

    I'm not able to find out why WiLink gets assigned to MMC0 in Linux. So I've assigned this thread to our software team for comment.
  • Andrew,

    I believe this is tied to how the devices probe. Wifi probably probes first and takes the MMC0 "trigger". I will try to get more information on this to confirm, but in the interim there are two possible workarounds I can think of:

    1. Build wifi as a module and have it come up after the other two.
    2. Use sysfs to go change the trigger for the led on the system where it is not working.

    Hopefully one of these two will meet your needs in the near term.

    Thanks.
  • As an experiment I modified the device tree to run all possible MMC combinations. Based on the results it looks like the MMC probe consistently starts at the module with the lowest physical address and then increments (for AM335x memory map mmc2 < mmc0 < mmc1). To keep things short I didn't include all the results, but the log messages below show the general trend.

    device tree: SD + EMMC + WIFI enabled
    # dmesg | grep mmc[012]
    [    1.438306] mmc0: new high speed SDIO card at address 0001
    [    1.719685] mmc1: host does not support reading read-only switch, assuming write-enable
    [    1.727845] mmc1: new high speed SDHC card at address aaaa
    [    1.734150] mmcblk1: mmc1:aaaa SL16G 14.8 GiB
    [    1.758374] mmc2: new high speed MMC card at address 0001
    [    1.764454] mmcblk2: mmc2:0001 W52532 28.5 GiB
    [    1.769241] mmcblk2boot0: mmc2:0001 W52532 partition 1 4.00 MiB
    [    1.775472] mmcblk2boot1: mmc2:0001 W52532 partition 2 4.00 MiB

    device tree: SD + EMMC enabled
    # dmesg | grep mmc[012]
    [    3.650171] mmc0: host does not support reading read-only switch, assuming write-enable
    [    3.664153] mmc0: new high speed SDHC card at address aaaa
    [    3.670343] mmcblk0: mmc0:aaaa SL16G 14.8 GiB
    [    3.680171] mmc1: new high speed MMC card at address 0001
    [    3.690132] mmcblk1: mmc1:0001 W52532 28.5 GiB
    [    3.694911] mmcblk1boot0: mmc1:0001 W52532 partition 1 4.00 MiB
    [    3.701155] mmcblk1boot1: mmc1:0001 W52532 partition 2 4.00 MiB

    device tree: EMMC enabled
    # dmesg | grep mmc[012]
    [    3.618187] mmc0: new high speed MMC card at address 0001
    [    3.624309] mmcblk0: mmc0:0001 W52532 28.5 GiB
    [    3.629151] mmcblk0boot0: mmc0:0001 W52532 partition 1 4.00 MiB
    [    3.635308] mmcblk0boot1: mmc0:0001 W52532 partition 2 4.00 MiB

    I think the rules determining the name that will be assigned to a device are predictable. So I can just redefine my LED triggers in the device tree file that supplies the WIFI bindings. It's just a shame the assigned name has nothing to do with the physical interface. At least serial ports don't behave this way...

    Thank you Ron and Ahmad.