Skip to main content

MMC2 Linux Device Tree Configuration For SD CARD on ARM PART i

Update: 


  • This blog is useful for ARM microprocessors running Linux Kernel versions 4.1.2-ti-r4 to 4.4.0.
  • It could still be relevant for earlier kernel releases but earlier releases have not been tested.
  • If your ARM microprocessor is running kernel's 4.4.16-ti-rt and newer go to part II:

Interfacing a second SD card reader to the Beaglebone Black 

  • I could not find any tutorials or guides in forums on how to interface another SD card to the beaglebone black, so I thought I'd share and show you how I got mine up and running.  I won't explain the device tree bindings in detail but you can use my solution as a reference.


MMC2 PINMUX CONFIGURATION:


Added in file: am335x-bone-common.dtsi

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
mmc3_pins: pinmux_mmc3_pins { 

    pinctrl-single,pins = < 

       0x44 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a1.mmc2_dat0, INPUT_PULLUP | MODE3 */

         0x48 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a2.mmc2_dat1, INPUT_PULLUP | MODE3 */ 

         0x4C (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a3.mmc2_dat2, INPUT_PULLUP | MODE3 */ 

         0x78 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_ben1.mmc2_dat3, INPUT_PULLUP | MODE3 */

         0x88 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_csn3.mmc2_cmd, INPUT_PULLUP | MODE3 */ 

         0x8C (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_clk.mmc2_clk, INPUT_PULLUP | MODE3 */ 

         0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a0.gpio1_16 */ 

         0x74 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* mmc2_sdcd, p9_13, Note: Dont know why but we set card detect pinout to be GPIO */ 

         0x15c (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mmc2_sdwp, p9_17, Note: Write protect is not configured in the device tree settings*/ 

    >; 

};
 

  • Note that the mmc0, mmc1, and mmc2 lines on the beaglebone refer to mmc1, mmc2, and mmc3 in the device tree.


1
2
3
4
         0x88 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_csn3.mmc2_cmd, INPUT_PULLUP | MODE3 */ 
                    ...
                    ...
         0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a0.gpio1_16 */ 

  • You can see that the two lines are connected:





MMC2 DEVICE TREE BINDINGS:




Added in file: am335x-bone-common.dtsi


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
&mmc3 {
      vmmc-supply = <&vmmcsd_fixed>;
      ti,dual-volt;
      ti,needs-special-reset;
      ti,needs-special-hs-handling;
      pinctrl-names = "default";
      pinctrl-0 = <&mmc3_pins>;
      cd-gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>;
      cd-inverted;
      bus-width = <4>;
      max-frequency = <25000000>;
      dmas = <&edma 12
              &edma 13>;
      dma-names = "tx", "rx";
      status = "okay";
};

&edma {
 ti,edma-xbar-event-map = /bits/ 16 <1 12 
                                     2 13>;

};
 


    Comments

    1. I'm getting the following message in the kernel log:
      /ocp/mmc@47810000: could not get #dma-cells for /ocp/l4_wkup@44c00000/prcm@200000/clocks/dpll_disp_ck

      Also I've read somewhere that MMC2 must be enabled in u-boot, I've recompiled u-boot with the corresponding changes, however there is no clock signal on the pin although u-boot does show MMC2 in the list.

      ReplyDelete
      Replies
      1. You should also check your edma settings in am33xx.dtsi. Does #dma-cells = <1> for you?

        Delete
      2. What steps did you take to enable mmc2 in u-boot? Configuring mmc2 in u-boot might not be necessary.
        Also, what are your "mmc3:" settings that is located in am33xx.dtsi? it should look something like:

        mmc3: mmc@47810000 {
        compatible = "ti,omap4-hsmmc";
        ti,hwmods = "mmc3";
        ti,needs-special-reset;
        interrupts = <29>;
        interrupt-parent = <&intc>;
        reg = <0x47810000 0x1000>;
        status = "disabled";
        };

        Delete
    2. This comment has been removed by the author.

      ReplyDelete
      Replies
      1. Regarding the "mmc3" in "am33xx.dtsi": that's exactly what I have, I haven't touched that part.

        In u-boot code I've modified several files and enabled clock. Will provide details later, since it's in my workplace computer. Do you think I could screw up something in u-boot, and that's why your way doesn't work? I'll revert back to the standard u-boot and check.

        Thanks!

        Delete
      2. Regarding the "mmc3" in "am33xx.dtsi": that's exactly what I have, I haven't touched that part.

        In u-boot code I've modified several files and enabled clock. Will provide details later, since it's in my workplace computer. Do you think I could screw up something in u-boot, and that's why your way doesn't work? I'll revert back to the standard u-boot and check.

        Thanks!

        Delete
    3. Below is what I have for edma in am33xx.dtsi:
      ------------------------8<------------------------
      edma: edma@49000000 {
      compatible = "ti,edma3-tpcc";
      ti,hwmods = "tpcc";
      reg = <0x49000000 0x10000>;
      reg-names = "edma3_cc";
      interrupts = <12 13 14>;
      interrupt-names = "edma3_ccint", "emda3_mperr",
      "edma3_ccerrint";
      dma-requests = <64>;
      #dma-cells = <2>;

      ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 5>,
      <&edma_tptc2 0>;
      ti,edma-memcpy-channels = <20 21>;
      };
      ------------------------8<------------------------
      #dma-cells = <2> and assigning 1 or 3 makes it freeze when booting at:
      ------------------------8<------------------------
      Starting kernel ...

      [ 0.001297] clocksource_probe: no matching clocksources found
      [ 1.889323] wkup_m3_ipc 44e11324.wkup_m3_ipc: could not get rproc handle
      [ 2.073446] omap_hsmmc 481d8000.mmc: RX DMA channel request failed
      [ 2.093261] omap_hsmmc 47810000.mmc: RX DMA channel request failed
      [ 2.126905] omap_voltage_late_init: Voltage driver support not added
      [ 2.134621] PM: Cannot get wkup_m3_ipc handle
      [ 2.232672] bone_capemgr bone_capemgr: slot #0: No cape found
      [ 2.276667] bone_capemgr bone_capemgr: slot #1: No cape found
      [ 2.320666] bone_capemgr bone_capemgr: slot #2: No cape found
      [ 2.364666] bone_capemgr bone_capemgr: slot #3: No cape found
      ------------------------8<------------------------

      ReplyDelete
    4. Thomas, I tried your method with the standard u-boot too, but got the same unsuccessful result...

      Here are the changes to u-boot I made, but there is no clock on the pin:

      1) mux.c
      added pins description

      2) board.c:
      added call to
      omap_mmc_init(2, 0, 0, -1, -1);

      3) mmc_host_def.h
      added the base address
      #define OMAP_HSMMC3_BASE 0x47810100

      4) spl.h
      added boot device
      #define BOOT_DEVICE_MMC3 0x10

      5) clock_am33xx.c
      added clock to the array
      clk_modules_explicit_en[]
      ... , &cmper->mmc2clkctrl, ...
      used by:
      do_enable_clocks(clk_domains, clk_modules_explicit_en, 1)

      6) clock_ti814x.c
      added clock control
      writel(PRCM_MOD_EN, &cmalwon->mmchs2clkctrl);
      while (readl(&cmalwon->mmchs2clkctrl) != PRCM_MOD_EN)
      ;

      ReplyDelete
      Replies
      1. Hmmm I see, yeah changing #dma-cells to <1> wouldnt work since eDMA3 needs 2 cells, 1 for the channel controller and the other for the transfer controller.

        I'm curious, what kernel version are you using for your microprocessor?

        Delete
      2. I'm using 4.4.16-ti-rt kernel (before it was 4.4.8-ti-rt).

        Delete
      3. My suggestion would be to first revert back to the standard u-boot then check the mmc3:" settings that is located in am33xx.dtsi to see if anything has changed. Then just interface the SD card to the microprocessor, making sure that the wiring is correct. Next add the pinmux configuration and bindings for mmc3. recompile and reboot and check the kernel log.

        My guess is that you just need to configure the device tree correctly without using u-boot. The only problem would be the edma settings. In my situation my edma was configured to use 1 channel per DMA request, a "DEPRECATED binding" which is stated in this document:

        http://lxr.free-electrons.com/source/Documentation/devicetree/bindings/dma/ti-edma.txt

        I believe to get mmc3 working you need to use the DEPRECATED edma binding in order to have the Crossbar event to channel map property: "ti,edma-xbar-event-map" because mmc3's source modules are crossbar mapped using events 1 and 2.

        One idea i have is to replace your current edma binding in am33xx.dtsi with the DEPRECATED binding (The binding I use):

        edma: edma@49000000 {
        compatible = "ti,edma3";
        ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
        reg = <0x49000000 0x10000>,
        <0x44e10f90 0x40>;
        interrupts = <12 13 14>;
        #dma-cells = <1>;
        };

        then configure mmc3 and edma like i show you in this tutorial.
        ...
        ...
        If you still decide to use uboot, have you tried defining OMAP_HSMMC3_BASE as 0x47810000 instead of 0x47810100 ?


        Delete
      4. Thank you, Thomas!
        I reverted back to the standard u-boot and changed the edma configuration to deprecated binding. Now I have both mmc0 and mmc2 DMA channels errors and boot process stops at:

        [ 2.356078] omap_hsmmc 48060000.mmc: RX DMA channel request failed
        [ 2.381924] omap_hsmmc 47810000.mmc: RX DMA channel request failed
        [ 2.400342] omap_hsmmc 48060000.mmc: RX DMA channel request failed
        [ 2.418247] omap_hsmmc 47810000.mmc: RX DMA channel request failed

        ...Regarding u-boot OMAP_HSMMC3_BASE: I just followed existing definitions in arch-am33xx/mmc_host_def.h, they all use that 0x100 offset:

        #define OMAP_HSMMC1_BASE 0x48060100
        #define OMAP_HSMMC2_BASE 0x481D8100
        #define OMAP_HSMMC3_BASE 0x47810100

        However, if you were able to make mmc2 work without messing with u-boot, I'd prefer your way.

        Delete
      5. I was able to make it work by adding:
        #address-cells = <1>;
        #size-cells = <0>;

        &mmc3 {
        vmmc-supply = <&vmmcsd_fixed>;
        ti,dual-volt;
        ti,needs-special-reset;
        ti,needs-special-hs-handling;
        pinctrl-names = "default";
        pinctrl-0 = <&mmc3_pins>;
        cd-gpios = <&gpio3 16 GPIO_ACTIVE_LOW>;
        bus-width = <4>;
        max-frequency = <25000000>;

        dmas = <&edma_xbar 12 0 1
        &edma_xbar 13 0 2>;

        #address-cells = <1>;
        #size-cells = <0>;

        dma-names = "tx", "rx";
        status = "okay";
        };

        Thank you for advices and directions, Thomas!

        Delete
      6. Great Sergey, that's good to hear! I see that there was a recent patch for the edma3 bindings for edma_xbar.

        Did you get mmc3 to work with the original u-boot configuration and original edma settings that's configured in am33xx.dtsi?

        Delete
      7. Yes, I used the original u-boot and original edma settings. Also I DID NOT need edma events map:

        &edma {
        ti,edma-xbar-event-map = /bits/ 16 <1 12 2 13>;
        };

        Delete
      8. Okay thanks for letting my know. I'm gonna have to update my blog now haha

        Delete
    5. This comment has been removed by the author.

      ReplyDelete

    Post a Comment

    Popular posts from this blog

    Howto: Design and Code a Music Visualizer

    Just here for code? Look no further.
    What is a Music Visualizer? A generation of visuals based on the music. demo



    How to Implement a Music Visualizer?
    Processing the audio file and run a Fourier transformation on audio data to get information about the original sound wave (amplitude and frequency)Store this data Output a visual based on the stored data when music is played
    Things to Think About Before CodingHow to play the sound?How to implement Fourier transformation?How to interpret information from the Fourier transformation?How to sync visual with music?What does the data in an audio file represent? 
    How I Implemented my Music Visualization Software

    I wrote my visualization software in c and used the SDL2 sound API to play an audio WAV file.  To compute the Fourier Transformation I used FFTW, a C routine library known for efficiently computing Discrete Fourier (DFT) Transformations.  My visuals (power spectrum from selected frequencies) is outputted to the Linux Terminal.



    Using DFT Res…

    MMC2 Linux Device Tree Configuration For SD CARD on ARM PART ii

    This blog entry is useful for ARM microprocessors running Kernel versions 4.4.16-ti-rt and newer. For configuring mmc2 on earlier kernel versions go to part I of this topic: MMC2 Linux Device Tree Configuration For ARM PART i

    What has changed since earlier kernel releases?There has been a recent changes (end of last year) to the dt bindings for eDMA3.  Older kernels used DEPRECATED binding for DTS files.  The old bindings were ti,edma3-tpcc/ti,edma3-tptc.  And to get mmc2 (labeled mmc3 in dts files) to work properly you must use theti,edma-xbar-event-map property for edma:
    &mmc3 { vmmc-supply = <&vmmcsd_fixed>; ti,dual-volt; ti,needs-special-reset; ti,needs-special-hs-handling; pinctrl-names = "default"; pinctrl-0 = <&mmc3_pins>; cd-gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>; cd-inverted; bus-width = <4>; max-frequency = <25000000>; dmas = <&edma 12 &…