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.

Proper way of sharing IO resources between ARM and DSP in OMAP-L138 Linux PSP

Other Parts Discussed in Thread: OMAP-L138

What is the proper way of sharing I/O resources between the ARM and DSP on OMAP-L138 Linux PSP. This is a general question but specific examples are DMA channels and GPIO pins. For example, how does the DSP EDMA3LLD resource manager interact with the Linux environment to ensure that the DSP code doesn't use resources that are used by the ARM. Is there a configuration file on the Linux side that is initially setup to segregate resources between ARM and DSP? Same question for GPIOs and other I/O peripherals.

  • Hi Ruben,

    For EDMA, the kernel driver supports reservation of channels and slots for the DSP. Have a look at the 'rsv_chans' and 'rsv_slots' members of EDMA platform information: http://arago-project.org/git/people/?p=sekhar/linux-omapl1.git;a=blob;f=arch/arm/mach-davinci/devices-da8xx.c;h=0842590e3acbf4109e683d7c24678a1777c22a0f;hb=2acf935c01b9adb50164d421c40cdc5862b9e143#l138

    For GPIO you can reduce the number of banks Linux controls by changing the gpio_num member of SoC info: http://arago-project.org/git/people/?p=sekhar/linux-omapl1.git;a=blob;f=arch/arm/mach-davinci/da850.c;h=cfecd3c3d474bccb87ad866e02379477d2acc22c;hb=2acf935c01b9adb50164d421c40cdc5862b9e143#l1402

    Thanks,

    Sekhar

  • Hi Sekhar,

    Thank you for your information.

    However, in the current configuration, each bank contains multiple pins that are controlled by DSP / ARM. If we don''t want to reorganize pins into separate banks but still want pins to be controlled by DSP/ARM only. Is there a way to do it?

    i.e An interrupt triggered at GPIO 40 will only cause DSP to act upon it. ARM wouldn't get notified at all.

    regards,

    Francis

  • Francis,

    I'll let Sekhar answer on what is possible from a S/W standpoint but this may be difficult to handle.

    From a H/W standpoint, each GPIO pin within a given bank (16 total) shares a single interrupt line. In your example below, do you require that any of the other GPIOs in bank2 (besides GPIO 40) trigger interrupts on the ARM? If so than both the ARM and DSP must be interrupted on any GPIO bank 2 transition and the interrupt handlers must analyze the INTSTATx register to determine if the interrupt is caused by one of its assigned pins. Maybe the question is, does this mechanism exist in the Linux code?

    Francis Wong said:

    i.e An interrupt triggered at GPIO 40 will only cause DSP to act upon it. ARM wouldn't get notified at all.

  • Hi Ruben, Francis,

    Ruben Perez said:
    If so than both the ARM and DSP must be interrupted on any GPIO bank 2 transition and the interrupt handlers must analyze the INTSTATx register to determine if the interrupt is caused by one of its assigned pins. Maybe the question is, does this mechanism exist in the Linux code?

    Linux does not have a mechanism to ack only some pins within a bank. So, if a bank interrupt is received, it will ack all the pins that show-up as set in INTSTATx. In general, it will be difficult for ARM/DSP to share interrupts within the same bank because of the race it might cause in acking the INTSTATx registers.

    Thanks,

    Sekhar

  • Hi Ruben and Sekhar,

        I agree that separate the banks to only ARM/DSP pins only will be the best solution.

        However, due to some design issues, we have to share some GPIOs interrupts in the same bank and come up with a fix.

        Please comment on this approach.

    Target:

    Linux wouldn't clear the INSTATEx interrupt bit that doesn't target for ARM

    Solution:

     modify the gpio_irq_handler(unsigned irq, struct irq_desc *desc)     in gpio.c

     so instead let everything through  =>  mask = 0xffff;  only selected programs that has previously called static void gpio_irq_enable(unsigned irq) first, will have the chance to register for the interrupt call back handle

    Question:

    1) Since Linux will still act upon the bank interrupts, would this cause a lot of extra  MIPs?

    2) Would this approach has potential to impact any other legacy functions?

    3) Any general comments?

     

    thanks

    Francis

     

  • Hi,

       This is a follow up question regarding separate the gpio bank interrupts into per processor base.

       i.e. ARM should only handle the interrupts from bank 0 4 5

       My approach is to target the for loop at  davinci_gpio_irq_setup in gpio.c. for (gpio = 0, irq = gpio_to_irq(0), bank = 0; gpio < ngpio; bank++, bank_irq++)

       Instead of using the for loop to alter the bank and bank_irq variables, it should only handle this combination

    gpio     bank    bank_irq

    0           0            42

    4           4            47

    5           5            48

       Can you comment on this approach? Is there any other functions I have to touch?

    thanks

    Francis

  • Hi Sekhar,

     

    I don't want to change the topic from Francis' question, however I would like to continue the other part of the original question regarding DMA sharing.

    After reviewing the link you posted, I'm still a bit confused on what the reservation of channels and slots means for the ARM.   From the link I see that, for instance,


     138 static const s16 da850_dma0_rsv_chans[][2] = {
     139         /* (offset, number) */
     140         { 8,  6},
     141         {24,  4},
     142         {30,  2},
     143         {-1, -1}
     144 };

     

    8, 24, and 30 seem to correspond to various rx EDMA events as shown in SPRS590A, under the EDMA section.     I don't understand the other numbers 6, 4, and 2.  What is a slot?

    Also, If I have a whole list of Events which I would like to assign to the DSP, are they all in this same file?   How do I know which structure to put a PRU Event or a Timer compare event in?   It seems reasonable that da850_dma0_rsv_chans contains rx oriented serial channels for da850, but what about other event types?

     

    Next part:  Since the DMA is a shared resource, either the ARM or DSP would take ownership of setting global registers for it.   For instance, initially, we would clear all events, disable all interrupts, insure that the event-missed, secondary event-missed, and other registers were initialized to a known state.  Does the Linux BSP do this by default?   It would be bad if both cores thought they had the responsibility for it correct?

    My thinking here is that if the ARM is booting, it should do it.  If the DSP is booting, then it should do it - what are your thoughts?

    Thanks,
    Matt

  • Hi Matt,

    mes said:

    8, 24, and 30 seem to correspond to various rx EDMA events as shown in SPRS590A, under the EDMA section.     I don't understand the other numbers 6, 4, and 2.  What is a slot?

    Tuple {8, 6} indicates reservation of 6 channels starting from channel #8. So 8, 9, 10, 11, 12, 13 will be reserved. slot is short for "parameter ram slot" (PaRAM slot).

    mes said:
    Also, If I have a whole list of Events which I would like to assign to the DSP, are they all in this same file?

    Yes.

    mes said:
    How do I know which structure to put a PRU Event or a Timer compare event in?

    For reserving channel on CC0 you will use the da850_dma0_rsv_chans. For reserving channel on CC1 you will use da850_dma1_rsv_chans.

    mes said:
    It seems reasonable that da850_dma0_rsv_chans contains rx oriented serial channels for da850, but what about other event types?

    All the channels pertaining to the same channel controller can be reserved using the same structure.

    mes said:

    Next part:  Since the DMA is a shared resource, either the ARM or DSP would take ownership of setting global registers for it.   For instance, initially, we would clear all events, disable all interrupts, insure that the event-missed, secondary event-missed, and other registers were initialized to a known state.  Does the Linux BSP do this by default?   It would be bad if both cores thought they had the responsibility for it correct?

    My thinking here is that if the ARM is booting, it should do it.  If the DSP is booting, then it should do it - what are your thoughts?

     Yes, I believe DSP side EDMA library has an option to skip initializing global registers. Linux BSP doesnt have such an option though.

    Thanks,

    Sekhar

  • Hi,

    Thanks for the previous answers regarding the edma - very helpful.   I have a new one though which is in the same vein as the previous ones. 

    Can you comment on some of the non-shadowed registers of the EDMA that may be accessed from both cores?   Two examples that come to mind are the queue assignment registers and the missed event registers, for instance.
     
    On the DSP side, as a part of the configurable initialization, we may erase all queue assignments and clear all missed-event registers.   What is done on the arm side for this?  

    Are there other global registers that are not-shadowed, which can be touched by Linux?

     

    Thanks,
    Matt

     

  • Matt,

    On the DSP side, if you are using framework components, the libraries will touch these global registers only at the bits corresponding to the channels that have explicitly been assigned to the DSP. Assuming the ARM side initializes all the global registers once (before the DSP side comes up), these global registers should not be blindly cleared etc after that.

    If some other DSP side library is being used to program the DMA, that library has to ensure that it doesn't any bits corresponding to channels the DSP side doesn't own.

    Gunjan

  • Hello Gunjan,

     

    Thank you for the response!    Even if the DSP and ARM only touched their own assigned bits in a global register, we could still have a read-modify-write problem if both cores were to try to assign their bits at the same time in the same global register?  The example I am thinking of is either the queue assignment or clearing miss-event conditions etc.

     

    Thanks,
    Matt

  • T he hardware doesn't have any way of preventing simultaneous access of the these global registers by both ARM and DSP. But there are methods that can be followed avoid this:-

    Initialization of registers such as QDMAQNUM/DMAQNUM should happen only once and preferably by only the ARM or the DSP. Do you have a use-case where this mapping needs to be modified multiple times ? Are there good reasons for this  ? (Sekhar ?)

    If ARM does its initialization only once, and before the DSP comes up after that and does its initialization, that will avoid RMW issues.

    - Modifications to the Missed even registers should happen only for the channel owned by the particular CPU. If this operation is done as a single write like 0x1 << Num, where Num  corresponds to the channel you own, since there are no reads required for this operation, this should not cause RMW issues. That sound right ?

  • Gunjan said:

    Initialization of registers such as QDMAQNUM/DMAQNUM should happen only once and preferably by only the ARM or the DSP. Do you have a use-case where this mapping needs to be modified multiple times ? Are there good reasons for this  ? (Sekhar ?)

    On Linux DMAQNUM setting is done when channel is allocated. For most drivers the channel allocation happens during init time. For audio driver the channels are allocated at the time of audio open. So in this case the audio device should be opened at the time of application initialization.

    Thanks,

    Sekhar

  • Is there a TI wiki describing this setup?  I have tried setting up the edma3 DSP libraries to be a slave (isSlave and isMaster parameters), but then my SPI bus stops working; my guess is the DMA is now not set up properly.  The ARM core has the 2.6.33-rc4 PSP kernel running.

  • Seems like I was configuring the ownPaRAMSets and ownDmaChannels incorrectly (trying to match up to what the linux kernel was configured for).  SPI works again for me when linux is up and running.  It looks like miscParam.isSlave should be TRUE, so that the shared registers are not overwritten, but initCfg.isMaster should remain TRUE, because it is the Master of the DSP driver.  Can anyone confirm this change?