5

I read that the Software generated interrupts in ARM are used as Inter-processor interrupts. I can also see that 5 of those interrupts are already in use. I also know that ARM provides 16 Software generated interrupts.

In my application i am running a bare metal application on of the ARM-cortex cores and Linux on the other. I want to communicate some data from the core running bare metal application to the core which is running Linux. I plan to copy the data to the on chip memory ( which is shared) and I will trigger a SGI on the Core ( running linux) to indicate some data is available for it to process. Now I am able to generate the SGI from the core ( running bare-metal application ). But for handling the interrupt in the linux side, I am not sure of the SGI IRQ numbers which are free and I am also not sure whether i can use the IRQ number directly ( in general SGI are from 0-15). Does any one have an idea how to write a handler for SGI in Linux?

Edit: This is a re-wording of the above text, because the question was closed for SSCE reasons. The Cortex-A CPUs are used in multi-CPU systems. An ARM generic interrupt controller (GIC) monitors all global interrupts and dispatches them to a particular CPU. In order for individual CPUs to signal each other, a software generated interrupt (SGI) is sent from one core to the other; this uses peripheral private interrupts (PPI). This question is,

How to implement a Linux kernel driver that can receive an SGI as a PPI?

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Nuetrino
  • 1,099
  • 1
  • 14
  • 32

2 Answers2

7

Does any one have an idea how to write a handler for SGI in Linux?

As you didn't give the Linux version, I will assume you work with the latest (or at least recent). The ARM GIC has device tree bindings. Typically, you need to specify the SGI interrupt number in a device tree node,

 ipc: ipc@address {
        compatible = "company,board-ipc"; /* Your driver */
        reg = <address range>;
        interrupts = <1 SGI 0x02>;  /* SGI is your CPU interrupt. */
        status = "enabled";
 };

The first number in the interrupt stanza denotes a PPI. The SGI will probably be between 0-15 as this is where the SGI interrupts are routed (at least on a Cortex-A5).

Then you can just use the platform_get_irq() in your driver to get the PPI (peripheral private interrupt). I guess that address is the shared memory (physical) where you wish to do the communications; maybe reg is not appropriate, but I think it will work. This area will be remapped by the Linux MMU and you can use it with,

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mem = devm_ioremap_resource(dev, res);

The address in the device tree above is a hex value of the physical address. The platform_get_irq() should return an irq number which you can use with the request_irq() family of functions. Just connect this to your routine.

Edit: Unfortunately, interrupts below 16 are forbidden by the Linux irq-gic.c. For example, gic_handle_irq(), limits handler to interrupts between 16 and 1020. If SMP is enabled, then handle_IPI() is called for the interrupts of interest. gic_raise_softirq() can be used to signal an interrupt. To handle the SGI with the current Linux, smp.c needs additional enum ipi_msg_type values and code to handle these in handle_IPI(). It looks like newer kernels (3.14+ perhaps?) may add a set_ipi_handler() to smp.c to make such a modification unneeded.

artless noise
  • 21,212
  • 6
  • 68
  • 105
  • thank you for your answer. I have couple of questions. how do i populate the structures pdev and dev?. I suppose i cannot fill that using the probe function, since it is no hardware interrupt. And the field in the device tree entry will be the starting address of my shared physical memory(reg) and number of bytes which are to be accessed (range) Am i correct? – Nuetrino Dec 07 '13 at 04:58
  • 1
    Both `pdev` and `dev` are sent to the `probe()` function. `static int probe(struct platform_device *pdev)...`, `static struct platform_driver driver = { .probe = probe };` and `module_platform_driver(driver);` and `dev = &pdev->dev`. – artless noise Dec 09 '13 at 14:49
  • See [ARM Cortex interrupt sources and types](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0407e/CCHDBEBE.html). Section 4.3.15 of the GIC document gives the `ICDSGIR`. The `NSATT` specifies *trustzone* secure or not. You can choose any interrupt not used (0-15). – artless noise Dec 09 '13 at 15:34
  • 1
    @artlessnoise thank you. I solved this problem. I got an error ( EINVaL = -22 invalid arguement) when i tried using the irq number in request_irq function( for all the SgI irq numbers ) so i used another funtion set_ipi_handlers (arch/arm/kernel/smp.c ) to register my irq handler. I suppose request_irq cannot be used in this context. – Nuetrino Dec 10 '13 at 20:01
2

I would like to add that an example of such inter-core communication can be found in TI multicore SoC's (i.e. OMAP3530). Some time ago when I was using such a mechanism, means were provided by TI. Specifically, it was the DSPLink Linux device driver which was providing such a functionality. At that time, unfortunately, it wasn't an open source solution, but maybe there is some technical paper from TI describing how it works ... Just a direction what you could investigate further :)

EDIT: In the meantime, it seems that they've made it open source. So, if that's what you are looking for, you can have a look: DSPLink and SysLink (successor of DSPLink)

Adi
  • 1,296
  • 10
  • 13