Device Tree Overlay for McASP0 Configuration

Hello Forum,
I’m working on a project with a BeagleBone Black (BBB) where I need to configure the McASP0 unit to acquire data from an array of 64 microphones. The setup involves 4 TDM serial data lines, each handling 16 microphones. Each microphone outputs a 32-bit stream with a 48kHz sampling frequency. The clock is set to 24.576 MHz to manage the TDM stream across these channels.
I’ve been trying to configure the Device Tree Overlay (DTO) for this setup, and I’m encountering persistent issues, particularly around enabling and managing clocks, as well as setting up the McASP unit. Here are the details:

Configuration Requirements

  1. Pins:
    • mcasp0_axr0 to mcasp0_axr3 for the 4 serial data lines.
    • mcasp0_ahclkr for the receive clock at 24.576 MHz.
    • mcasp0_aclkr for synchronization 48kHz (sample frequency).
    • mcasp0_fsr for frame sync at 512Hz (trigger to the first microphone)
  2. Clock Settings:
    • The frame sync (FSR) should operate at 48kHz to match the sample rate of the microphones.
    • need to configure AHCLKR (and potentially AHCLKX if required) to the fixed clock frequency of 24.576 MHz.
  3. Interrupts:
    • TX and RX interrupts for McASP0 should be set up correctly (currently using interrupt numbers 80 and 81).

Challenges

  • Clock Activation: Clocks aren’t enabling; attempts to manually activate result in permission denied errors.
  • IRQ Errors: "IRQ common not found" suggests issues with McASP interrupt setup.
  • config-pin Limitation: config-pin doesn’t work with McASP pin assignments.

Device Tree Overlay Snippet

Here’s the relevant portion of my Device Tree Overlay. I’ve declared the clocks as fixed and set up the necessary serializers and pin configurations:

&mcasp0 {
    status = "okay";

    /* Clock Configuration */
    clocks = <&mcasp0_ahclkx>, <&mcasp0_ahclkr>;
    clock-names = "ahclkx", "ahclkr";

    /* Interrupts */
    interrupt-parent = <&intc>;
    interrupts = <80 81>;  /* TX = 80, RX = 81 */

    /* Serializers */
    serializers = <0 1 2 3>;
    serial-dir = <0 1 1 1>; /* Serializer 0 = TX, Serializers 1-3 = RX */

    /* TDM Slots */
    tdm-slots = <16>;        /* 16 slots for 16 channels */
    op-mode = <0>;           /* TDM mode */

    /* Assigned clocks */
    assigned-clocks = <&mcasp0_ahclkr>;
    assigned-clock-rates = <24576000>;
};

Questions

  1. How can I ensure AHCLKR and AHCLKX are active?
  2. Any alternatives to fixed-clock for better clock management?
  3. Suggestions for resolving "IRQ common not found"?

Thanks for any guidance!

This is conjecture, your device tree is missing the pinmux for that device. If memory is correct that functionality is present but not out of the box. It appears you will have to add mux data for that device to enable the pins you need.

You’re right. I’ve put the pinmux at the begining of the overlay:

        fragment@0 {
                target = <&am33xx_pinmux>;
                __overlay__ {
                        mcasp0_pins: mcasp0_pins {
                                pinctrl-single,pins = <
                                        0x198 0x20      /* mcasp0_axr0,         MODE0 | INPUT */
                                        0x1a8 0x20      /* mcasp0_axr1,         MODE0 | INPUT */
                                        0x19c 0x22      /* mcasp0_axr2,         MODE2 | INPUT */
                                        0x1a4 0x22      /* mcasp0_axr3,         MODE2 | INPUT */
                                        0x0cc 0x0B      /* mcasp0_ahclkr,       MODE3 | OUTPUT*/
                                        0x0d0 0x0B      /* mcasp0_aclkr,        MODE3 | OUTPUT*/
                                        0x0d4 0x0B      /* mcasp0_fsr,          MODE3 | OUTPUT*/
                                >;
                        };
                };
        };

According to the show-pins command, all peripherals are assigned correctly. However, I don’t see the pulse of the clock at the selected pin. Following the McASP guide, Clocks must be configured with the reception mode, that’s why ahclkr, aclkr, fsr.

Silly questions but are you using the pinmux you declared in the overlay ?

Just adding a section in there as you have done, will not actually set the pinmux. It is more of a definition that you then use elsewhere.

In &mcasp0 {
you would need to add
pinctrl-0 = <mcasp0_pins>;

Maybe you have this already in which case ignore what I have said.

I used a second fragment to configure the McASP unit. There are some commented lines that I found they can be useful but not effective so far. What’s your opinion about those?

        fragment@2 {
                target = <&mcasp0>;
                __overlay__ {

                        pinctrl-names = "default";
                        pinctrl-0 = <&mcasp0_pins>;

                        status = "okay";

/*                      compatible = "ti,am33xx-mcasp-audio", "ti,am33xx-mcasp-serial", "ti,no-idle"; */

                        interrupt-parent = <&intc>;             /* Points to the interrupt controller */
                        interrupts = <80 81>;                   /* The IRQ number for McASP */
                        interrupt-names = "tx", "rx";


/*                      reg = <0x48038000 0x2000>, <0x48038000 0x3000>; */
/*                      clocks = <&mcasp0_ahclkx>, <&mcasp0_ahclkr>; */
/*                      clock-names = "ahclkx", "ahclkr"; */
                        clocks = <&mcasp0_ahclkr>;
                        clock-names = "ahclkr";

                        op-mode = <0>;          /* MCASP_IIS_MODE */
                        tdm-slots = <16>;
/*                      num-serializer = <4>; */
                        serializers = <0 1 2 3>;
                        serial-dir = <2 2 2 2>; /* 0: INACTIVE, 1: TX, 2: RX */
                        /* tx-num-evt = <4>; */
                        rx-num-evt = <4>;
                };
        };

Regarding to mcasp0_ahclkr, this clock is compiled as follows:

        fragment@1 {
                target-path = "/";
                __overlay__ {
                        clocks {
                                mcasp0_ahclkr: mcasp0_ahclkr {
                                        status = "okay";
                                        compatible = "fixed-clock";
                                        clock-frequency = <24576000>;  /* Example: 24.576 MHz */
                                        #clock-cells = <0>;
                                };
                        };
                };
        };

This clock is present in the kernel debug clock summary, but it is’n active nor prepared. To check this, I used this command cat /sys/kernel/debug/clk/clk_summary

It has been many years since I last tried to setup some audio devices under Linux. I seem to recall it being pretty tough to get going, mostly due to lack of documentation.

Besides the pinmux and mcasp0 overlays have you changed anything else ? Is this for a stock Debian kernel or are you rolling your own ?

From memory you also need a sound section in the devicetree. This could be why you don’t have any clocks.

I always find it a good idea to check other devicetree for sound configuration and see what they are doing. Obviously not a BBB but is has a Sound section which might give you a few pointers.

Found this in am335x-myirtech-myd.dts overlay.

        sound: sound {
                compatible = "simple-audio-card";
                simple-audio-card,format = "i2s";
                simple-audio-card,bitclock-master = <&master_codec>;
                simple-audio-card,frame-master = <&master_codec>;
        
                simple-audio-card,cpu {
                        sound-dai = <&mcasp0>;
                };

                master_codec: simple-audio-card,codec@1 {
                        sound-dai = <&sgtl5000>;
                };
                
                simple-audio-card,codec@2 {
                        sound-dai = <&tda9988>;
                };
        };      

Hi Benedict. Thank you for your reply.

Most of the sound card examples I reviewed use an external codec, such as the one you refer (tda9988) that apparently is used for the HDMI unit. I’ve found the pcm5102a dummy codec configuration in this TI Application Report. Is that the only way to enable a sound card to use the McASP unit? So far, I’ve been using the Device Tree Compiler (dtc) in the command window. In the /boot/uEnv.txt file, I added the address of the .dtbo file, which rests in the /lib/firmware folder.

Here is a third fragment where I declare the clock that I’ll be using as AUXCLK/AHCKLR. However, it’s still not clear for me if I can select 24.576MHz, or should I take an existing clock like the sys_clk that runs at 24MHz. Following the McASP reference manual, I expect to declare the division within this node to define the bit clock (ACLKR) and frame sync (FSR). Does that make sense?

fragment@3 {
	target-path = "/";
	__overlay__ {
		clocks {
			mcasp0_ahclkr: mcasp0_ahclkr {
				compatible = "fixed-clock";
				clock-frequency = <24576000>;
				#clock-cells = <0>;
			};
			clk_mcasp1: clk_mcasp1 {
				#clock-cells = <0>;
				compatible = "gpio-gate-clock";
				clocks = <&mcasp0_ahclkr>;
				enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
			};
		};
		pcm5102a: pcm5102a {
			#sound-dai-cells = <0>;
			compatible = "ti,pcm5102a";
			status = "okay";
		};
		sound {
			compatible = "simple-audio-card";
			simple-audio-card,name = "TDM_16mics";
			simple-audio-card,format = "i2s";
			simple-audio-card,bitclock-master = <&sound1_master>;
			simple-audio-card,frame-master = <&sound1_master>;
			simple-audio-card,bitclock-inversion;
			simple-audio-card,cpu {
				sound-dai = <&mcasp0>;
				#sound-dai-cells = <0>;
				system-clock-direction = "out";
				system-clock-frequency = <24576000>;
				clocks = <&clk_mcasp1>;
			};
			simple-audio-card,codec {
				sound-dai = <&pcm5102a>;
				#sound-dai-cells = <0>;
			};
		};
        };
};

Drawbacks

  • Sound cards are not detected.
  • I’m still getting a warning that says “IRQ common not found”, and this is why I declare tx and rx interrupts from the <&intc> node.
  • Pin assignation seems to be alright, but the assigned clock pin does not show any signal.