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