GIC - interrupts interpretation in DTS/FDT

Julien Grall julien.grall at citrix.com
Fri Aug 28 13:07:36 UTC 2015


Hi,

On 28/08/15 09:40, Mihai Carabas wrote:
> On Fri, Aug 28, 2015 at 11:35 AM, Zbigniew Bodek <zbodek at gmail.com> wrote:
> 
>> Hello Mihai,
>>
>> This documents may be helpful:
>>
>> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/arm/gic.txt
>>
>> The meaning of each interrupt cell (for ARM GIC) is described there.
>>
>> Thank you for pointing me out that document.
> 
> The problem I was asking was specific to the FreeBSD gic code:
> """
> 165 >------->------- * The hardware only supports active-high-level or
> rising-edge.
> 166 >------->------- */
> 167 >------->-------if (fdt32_to_cpu(intr[2]) & 0x0a) {
> 168 >------->------->-------printf("unsupported trigger/polarity
> configuration "
> 169 >------->------->-------    "0x%2x\n", fdt32_to_cpu(intr[2]) & 0x0f);
> 170 >------->------->-------return (ENOTSUP);
> 171 >------->-------}
>  """
> 
> It is verified the not supported bits in both cases (PPIs and SPIs) and I
> didn't understand why. Probably a bug.

It's a bug, based on the documentation pointed by Zbigniew this check should
only be done for SPIs.

I hit this problem when porting FreeBSD as Xen ARM guest because our Xen
interrupt is a PPI active-low level-sentive. I got a patch which I carry in
my branch but never took the time to upstream it:

--- a/sys/arm/arm/gic.c
+++ b/sys/arm/arm/gic.c
@@ -221,15 +221,16 @@ gic_decode_fdt(uint32_t iparent, uint32_t *intr, int *interrupt,
                 *   2 = high-to-low edge triggered
                 *   4 = active high level-sensitive
                 *   8 = active low level-sensitive
-                * The hardware only supports active-high-level or rising-edge.
+                * The hardware only supports active-high-level or rising-edge
+                * for SPIs
                 */
-               if (fdt32_to_cpu(intr[2]) & 0x0a) {
+               if (*interrupt >= 32 && fdt32_to_cpu(intr[2]) & 0x0a) {
                        printf("unsupported trigger/polarity configuration "
                            "0x%2x\n", fdt32_to_cpu(intr[2]) & 0x0f);
                        return (ENOTSUP);
                }
                *pol  = INTR_POLARITY_CONFORM;
-               if (fdt32_to_cpu(intr[2]) & 0x01)
+               if (fdt32_to_cpu(intr[2]) & 0x03)
                        *trig = INTR_TRIGGER_EDGE;
                else
                        *trig = INTR_TRIGGER_LEVEL;

Regards,

-- 
Julien Grall


More information about the freebsd-arm mailing list