diff mbox series

[RFC,4/7] irqchip/apple-aic: Add support for Apple AIC

Message ID 20210120132717.395873-5-mohamed.mediouni@caramail.com (mailing list archive)
State New, archived
Headers show
Series Linux on Apple Silicon | expand

Commit Message

Mohamed Mediouni Jan. 20, 2021, 1:27 p.m. UTC
From: Stan Skowronek <stan@corellium.com>

Apple SoCs use the Apple AIC interrupt controller.
The Arm architectural timers is wired over FIQ on that hardware.

Signed-off-by: Stan Skowronek <stan@corellium.com>
Signed-off-by: Mohamed Mediouni <mohamed.mediouni@caramail.com>
---
 .../interrupt-controller/apple,aic.yaml       |  49 ++++
 MAINTAINERS                                   |   6 +
 drivers/irqchip/Kconfig                       |   6 +
 drivers/irqchip/Makefile                      |   1 +
 drivers/irqchip/irq-apple-aic.c               | 211 ++++++++++++++++++
 5 files changed, 273 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
 create mode 100644 drivers/irqchip/irq-apple-aic.c

--
2.29.2

Comments

Alexander Graf Jan. 20, 2021, 5:11 p.m. UTC | #1
On 20.01.21 14:27, Mohamed Mediouni wrote:
> From: Stan Skowronek <stan@corellium.com>
> 
> Apple SoCs use the Apple AIC interrupt controller.
> The Arm architectural timers is wired over FIQ on that hardware.
> 
> Signed-off-by: Stan Skowronek <stan@corellium.com>
> Signed-off-by: Mohamed Mediouni <mohamed.mediouni@caramail.com>
> ---
>   .../interrupt-controller/apple,aic.yaml       |  49 ++++
>   MAINTAINERS                                   |   6 +
>   drivers/irqchip/Kconfig                       |   6 +
>   drivers/irqchip/Makefile                      |   1 +
>   drivers/irqchip/irq-apple-aic.c               | 211 ++++++++++++++++++
>   5 files changed, 273 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
>   create mode 100644 drivers/irqchip/irq-apple-aic.c
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
> new file mode 100644
> index 000000000000..e615eaaca869
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
> @@ -0,0 +1,49 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/interrupt-controller/apple,aic.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Apple Advanced Interrupt Controller (AIC)
> +
> +description:
> +  Interrupt controller present on Apple processors. AIC
> +  is used by Apple on their AArch64 SoCs since the Apple A7.
> +
> +maintainers:
> +  - Stan Skowronek <stan@corellium.com>
> +
> +properties:
> +  compatible:
> +    items:
> +      - const: apple,aic
> +
> +  reg:
> +    maxItems: 1
> +
> +  '#interrupt-cells':
> +    const: 3
> +
> +  interrupt-controller: true
> +
> +  fast-ipi:
> +    description:
> +      Fast IPI support.
> +
> +required:
> +  - compatible
> +  - '#interrupt-cells'
> +  - interrupt-controller
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +        aic: interrupt-controller@23b100000 {
> +             compatible = "apple,aic";
> +             #interrupt-cells = <3>;
> +             interrupt-controller;
> +             reg = <0x2 0x3b100000 0x0 0x8000>;
> +             fast-ipi;
> +         };
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 00836f6452f0..e609ede99dd4 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1218,6 +1218,12 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
>   F:	Documentation/admin-guide/LSM/apparmor.rst
>   F:	security/apparmor/
> 
> +APPLE ADVANCED INTERRUPT CONTROLLER DRIVER
> +M:	Stan Skowronek <stan@corellium.com>

Signing someone else up for maintainership is ... unusual :). Do you 
have buy in from Stan that he'll be responsive and handle patch reviews?

> +L:	linux-arm-kernel@lists.infradead.org
> +S:	Maintained
> +F:	drivers/irqchip/irq-apple-aic.c
> +


Alex



Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879
Mohamed Mediouni Jan. 20, 2021, 6:04 p.m. UTC | #2
> On 20 Jan 2021, at 18:11, Alexander Graf <graf@amazon.com> wrote:
> 
> On 20.01.21 14:27, Mohamed Mediouni wrote:
>> From: Stan Skowronek <stan@corellium.com>
>> Apple SoCs use the Apple AIC interrupt controller.
>> The Arm architectural timers is wired over FIQ on that hardware.
>> Signed-off-by: Stan Skowronek <stan@corellium.com>
>> Signed-off-by: Mohamed Mediouni <mohamed.mediouni@caramail.com>
>> ---
>>  .../interrupt-controller/apple,aic.yaml       |  49 ++++
>>  MAINTAINERS                                   |   6 +
>>  drivers/irqchip/Kconfig                       |   6 +
>>  drivers/irqchip/Makefile                      |   1 +
>>  drivers/irqchip/irq-apple-aic.c               | 211 ++++++++++++++++++
>>  5 files changed, 273 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
>>  create mode 100644 drivers/irqchip/irq-apple-aic.c
>> diff --git a/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
>> new file mode 100644
>> index 000000000000..e615eaaca869
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
>> @@ -0,0 +1,49 @@
>> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/interrupt-controller/apple,aic.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Apple Advanced Interrupt Controller (AIC)
>> +
>> +description:
>> +  Interrupt controller present on Apple processors. AIC
>> +  is used by Apple on their AArch64 SoCs since the Apple A7.
>> +
>> +maintainers:
>> +  - Stan Skowronek <stan@corellium.com>
>> +
>> +properties:
>> +  compatible:
>> +    items:
>> +      - const: apple,aic
>> +
>> +  reg:
>> +    maxItems: 1
>> +
>> +  '#interrupt-cells':
>> +    const: 3
>> +
>> +  interrupt-controller: true
>> +
>> +  fast-ipi:
>> +    description:
>> +      Fast IPI support.
>> +
>> +required:
>> +  - compatible
>> +  - '#interrupt-cells'
>> +  - interrupt-controller
>> +  - reg
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> +  - |
>> +        aic: interrupt-controller@23b100000 {
>> +             compatible = "apple,aic";
>> +             #interrupt-cells = <3>;
>> +             interrupt-controller;
>> +             reg = <0x2 0x3b100000 0x0 0x8000>;
>> +             fast-ipi;
>> +         };
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 00836f6452f0..e609ede99dd4 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -1218,6 +1218,12 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
>>  F:	Documentation/admin-guide/LSM/apparmor.rst
>>  F:	security/apparmor/
>> +APPLE ADVANCED INTERRUPT CONTROLLER DRIVER
>> +M:	Stan Skowronek <stan@corellium.com>
> 
> Signing someone else up for maintainership is ... unusual :). Do you have buy in from Stan that he'll be responsive and handle patch reviews?

Yeah, I asked Corellium about it explicitly. :)

>> +L:	linux-arm-kernel@lists.infradead.org
>> +S:	Maintained
>> +F:	drivers/irqchip/irq-apple-aic.c
>> +
> 
> 
> Alex
> 
> 
> 
> Amazon Development Center Germany GmbH
> Krausenstr. 38
> 10117 Berlin
> Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
> Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
> Sitz: Berlin
> Ust-ID: DE 289 237 879
Andrew Lunn Jan. 20, 2021, 8:16 p.m. UTC | #3
> >> @@ -1218,6 +1218,12 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
> >>  F:	Documentation/admin-guide/LSM/apparmor.rst
> >>  F:	security/apparmor/
> >> +APPLE ADVANCED INTERRUPT CONTROLLER DRIVER
> >> +M:	Stan Skowronek <stan@corellium.com>
> > 
> > Signing someone else up for maintainership is ... unusual :). Do you have buy in from Stan that he'll be responsive and handle patch reviews?
> 
> Yeah, I asked Corellium about it explicitly. :)

Having an Ack-by: from Stan Skowronek would remove all doubt.

       Andrew
Stan Skowronek Jan. 20, 2021, 9:18 p.m. UTC | #4
Acked-by: Stan Skowronek <stan@corellium.com>

On 1/20/21 8:27 AM, Mohamed Mediouni wrote:
> From: Stan Skowronek <stan@corellium.com>
>
> Apple SoCs use the Apple AIC interrupt controller.
> The Arm architectural timers is wired over FIQ on that hardware.
>
> Signed-off-by: Stan Skowronek <stan@corellium.com>
> Signed-off-by: Mohamed Mediouni <mohamed.mediouni@caramail.com>
> ---
>   .../interrupt-controller/apple,aic.yaml       |  49 ++++
>   MAINTAINERS                                   |   6 +
>   drivers/irqchip/Kconfig                       |   6 +
>   drivers/irqchip/Makefile                      |   1 +
>   drivers/irqchip/irq-apple-aic.c               | 211 ++++++++++++++++++
>   5 files changed, 273 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
>   create mode 100644 drivers/irqchip/irq-apple-aic.c
Linus Walleij Jan. 21, 2021, 9:48 a.m. UTC | #5
Hi Mohamed,

thanks for your patch!

On Wed, Jan 20, 2021 at 2:31 PM Mohamed Mediouni
<mohamed.mediouni@caramail.com> wrote:

> +properties:
> +  compatible:
> +    items:
> +      - const: apple,aic

However weird it may seem, Apple is not in the file
Documentation/devicetree/bindings/vendor-prefixes.yaml

(I think it's weird because I remember clearly that they have been
using device tree for PPC since ages.)

Could you add this 2-liner to that file and send it directly to
DT binding maintainers as a single patch as a preparation?

Yours,
Linus Walleij
Arnd Bergmann Jan. 21, 2021, 10:37 a.m. UTC | #6
On Thu, Jan 21, 2021 at 10:48 AM Linus Walleij <linus.walleij@linaro.org> wrote:
>
> Hi Mohamed,
>
> thanks for your patch!
>
> On Wed, Jan 20, 2021 at 2:31 PM Mohamed Mediouni
> <mohamed.mediouni@caramail.com> wrote:
>
> > +properties:
> > +  compatible:
> > +    items:
> > +      - const: apple,aic
>
> However weird it may seem, Apple is not in the file
> Documentation/devicetree/bindings/vendor-prefixes.yaml
>
> (I think it's weird because I remember clearly that they have been
> using device tree for PPC since ages.)
>
> Could you add this 2-liner to that file and send it directly to
> DT binding maintainers as a single patch as a preparation?

Choosing the vendor prefix here is going to be a little tricky
and non-obvious.

Background:

Traditionally, it should have been the stock ticker symbol of the
company (clearly only publicly traded companies would be able
to produce a Unix capable computer, right?), but there were
already inconsistent: IBM used "ibm" (in small letters), Sun
used "SUNW" (in capitals) but in 2007 changed the stock ticker
symbol to "JAVA", obviously without changing the firmware bindings.

Apple traditionally used "AAPL" (also in caps) in the device tree,
and there is one remnant of that in the M1 device tree, in the form
of the "AAPL,phandle" property in each node, which corresponds
to our "linux,phandle". (phandles were introduced as properties in
both of the flattened DT formats, .dtb and apple's own format).
There are also "AAPL,unit-string properties and some device_type
strings (AAPL,display-crossbar, AAPL,atc-dpxbar, ...) in the M1 DT,
and the CPU nodes (and only those) use "apple" in small letters
as in "apple,icestorm","ARM,v8". The other nodes tend to not have
a vendor prefix, but a lot use a subsystem name as the prefix, such
as compatible="gpio,t8101" or compatible="tempsensor,t8020".

Since Apple are already using both the "AAPL" and the "apple"
prefix themselves, I have a bad feeling about reusing either of
them for defining the devicetree.org bindings that we add to
linux/Documentation/devicetree/bindings. The question is: if
not "apple", what else should we use here?

      Arnd
Hector Martin Jan. 21, 2021, 3:29 p.m. UTC | #7
On 21/01/2021 19.37, Arnd Bergmann wrote:
> On Thu, Jan 21, 2021 at 10:48 AM Linus Walleij <linus.walleij@linaro.org> wrote:
>>
>> However weird it may seem, Apple is not in the file
>> Documentation/devicetree/bindings/vendor-prefixes.yaml
> 
> Since Apple are already using both the "AAPL" and the "apple"
> prefix themselves, I have a bad feeling about reusing either of
> them for defining the devicetree.org bindings that we add to
> linux/Documentation/devicetree/bindings. The question is: if
> not "apple", what else should we use here?

This ties into the larger question of how we should handle devicetrees 
in general on these platforms.

The two extremes are:

1) Have the bootloader outright convert ADT to FDT and make Linux 
support the entirety of Apple's devicetree structure, or

2) Maintain our own devicetrees and ignore Apple's entirely

My feeling is that 1) is a non-starter, because Linux ARM device trees 
and Apple ARM device trees have seen independent evolution from the 
PowerPC era, and many details are completely different. Plus conversion 
is non-trivial, because the endianness is different and the format is 
too ambiguous to do programmatically without complex logic.

On the other hand, cranking out devicetrees by hand for every device 
variant that Apple puts out is a waste of time.

Obviously at the bare minimum the bootloader will need to move some 
dynamic information from the ADT to the FDT, but that can be a very 
specific set of properties (memory layout, MAC addresses, etc).

My current thinking is that we should write offline, automated tooling 
to parse, diff, and automatically convert portions of Apple devicetrees 
into Linux ones. Then we can more easily maintain our own, but still 
ultimately have humans decide what goes into the Linux device trees.

It's worth noting that AIUI Apple does not consider their devicetree 
layout to be stable, and it may change any time. On M1 devices, the 
devicetree is provided as part of the iBoot2 firmware bundle, which 
means it changes from one macOS version to the next (this is paired with 
the Darwin kernel itself, and they are upgraded as a unit). It includes 
placeholder values that iBoot2 then replaces with data from NOR before 
handing control over to the kernel. My goal for our long-term project 
[1] is to keep up with iBoot2 updates so that we do not have to instruct 
users to dig up old macOS versions.

Quick TL;DR on how these things boot:
- Boot ROM boots
- iBoot1 (system firmware) in NOR flash which looks for a bootable OS in 
internal storage (only!) in the form of an APFS container+volume and 
then boots
- iBoot2 (OS loader) which loads a bunch of firmware blobs and the 
devicetree off of storage, customizes it with system data from NOR, and 
then loads a wrapped mach-o file containing
- A Darwin kernel, or in our case a Linux bootloader which then boots
- A standard arm64 Linux blob

The boot ROM is ROM. iBoot1 only ever rolls forward (downgrades 
impossible). iBoot2 downgrades are possible but Apple already proved 
they can break this willingly or not, at least in betas (macOS 11.2 
Beta2 iBoot1 cannot boot Beta1 iBoot2). The secureboot chain goes all 
the way up to the mach-o kernel load, that is the first point where we 
can change boot policy to load anything we want (with user consent).

[1] https://asahilinux.org/
Rob Herring Jan. 21, 2021, 4:44 p.m. UTC | #8
On Thu, Jan 21, 2021 at 3:49 AM Linus Walleij <linus.walleij@linaro.org> wrote:
>
> Hi Mohamed,
>
> thanks for your patch!
>
> On Wed, Jan 20, 2021 at 2:31 PM Mohamed Mediouni
> <mohamed.mediouni@caramail.com> wrote:
>
> > +properties:
> > +  compatible:
> > +    items:
> > +      - const: apple,aic

As mentioned in patch 7, this needs to be SoC specific.

Also, bindings should be separate patch. checkpatch.pl will tell you this.

> However weird it may seem, Apple is not in the file
> Documentation/devicetree/bindings/vendor-prefixes.yaml
>
> (I think it's weird because I remember clearly that they have been
> using device tree for PPC since ages.)

That's because the vendor prefix is 'AAPL' which is the stock ticker
and it predates documenting anything.

> Could you add this 2-liner to that file and send it directly to
> DT binding maintainers as a single patch as a preparation?

So this is still needed. Happy to take that given already in use.

Rob
Hector Martin Jan. 21, 2021, 4:53 p.m. UTC | #9
On 20/01/2021 22.27, Mohamed Mediouni wrote:
> +		irq_domain_set_info(d, virq, hw, &apple_aic_irq_chip,
> +				    d->host_data, handle_level_irq, NULL, NULL);

The AIC automatically masks IRQs on reason fetch, which means the 
handle_level_irq flow is redundant. Using the fasteoi flow, as in [1], 
should be more efficient.

[1] https://github.com/AsahiLinux/linux/commit/d4cb18c93
Rob Herring Jan. 21, 2021, 5:09 p.m. UTC | #10
On Thu, Jan 21, 2021 at 9:31 AM Hector Martin 'marcan' <marcan@marcan.st> wrote:
>
> On 21/01/2021 19.37, Arnd Bergmann wrote:
> > On Thu, Jan 21, 2021 at 10:48 AM Linus Walleij <linus.walleij@linaro.org> wrote:
> >>
> >> However weird it may seem, Apple is not in the file
> >> Documentation/devicetree/bindings/vendor-prefixes.yaml
> >
> > Since Apple are already using both the "AAPL" and the "apple"
> > prefix themselves, I have a bad feeling about reusing either of
> > them for defining the devicetree.org bindings that we add to
> > linux/Documentation/devicetree/bindings. The question is: if
> > not "apple", what else should we use here?
>
> This ties into the larger question of how we should handle devicetrees
> in general on these platforms.
>
> The two extremes are:
>
> 1) Have the bootloader outright convert ADT to FDT and make Linux
> support the entirety of Apple's devicetree structure, or
>
> 2) Maintain our own devicetrees and ignore Apple's entirely
>
> My feeling is that 1) is a non-starter, because Linux ARM device trees
> and Apple ARM device trees have seen independent evolution from the
> PowerPC era, and many details are completely different. Plus conversion
> is non-trivial, because the endianness is different and the format is
> too ambiguous to do programmatically without complex logic.

You are right it's a non-starter. Apple's DT even from PowerPC days
were weird and the hardware was much simpler then. Given we're still
maintaining that code I don't care to add what they've evolved on
their own over the last 15 years and support it for the next 20+ years
(given folks notice when we break 1998 era Macs).

> On the other hand, cranking out devicetrees by hand for every device
> variant that Apple puts out is a waste of time.
>
> Obviously at the bare minimum the bootloader will need to move some
> dynamic information from the ADT to the FDT, but that can be a very
> specific set of properties (memory layout, MAC addresses, etc).
>
> My current thinking is that we should write offline, automated tooling
> to parse, diff, and automatically convert portions of Apple devicetrees
> into Linux ones. Then we can more easily maintain our own, but still
> ultimately have humans decide what goes into the Linux device trees.

Seems reasonable.

> It's worth noting that AIUI Apple does not consider their devicetree
> layout to be stable, and it may change any time.

Yeah, also not something we want to support.

> On M1 devices, the
> devicetree is provided as part of the iBoot2 firmware bundle, which
> means it changes from one macOS version to the next (this is paired with
> the Darwin kernel itself, and they are upgraded as a unit). It includes
> placeholder values that iBoot2 then replaces with data from NOR before
> handing control over to the kernel. My goal for our long-term project
> [1] is to keep up with iBoot2 updates so that we do not have to instruct
> users to dig up old macOS versions.
>
> Quick TL;DR on how these things boot:
> - Boot ROM boots
> - iBoot1 (system firmware) in NOR flash which looks for a bootable OS in
> internal storage (only!) in the form of an APFS container+volume and
> then boots
> - iBoot2 (OS loader) which loads a bunch of firmware blobs and the
> devicetree off of storage, customizes it with system data from NOR, and
> then loads a wrapped mach-o file containing
> - A Darwin kernel, or in our case a Linux bootloader which then boots
> - A standard arm64 Linux blob
>
> The boot ROM is ROM. iBoot1 only ever rolls forward (downgrades
> impossible). iBoot2 downgrades are possible but Apple already proved
> they can break this willingly or not, at least in betas (macOS 11.2
> Beta2 iBoot1 cannot boot Beta1 iBoot2). The secureboot chain goes all
> the way up to the mach-o kernel load, that is the first point where we
> can change boot policy to load anything we want (with user consent).
>
> [1] https://asahilinux.org/
>
> --
> Hector Martin "marcan" (marcan@marcan.st)
> Public Key: https://mrcn.st/pub
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Rob Herring Jan. 21, 2021, 5:45 p.m. UTC | #11
On Thu, Jan 21, 2021 at 4:38 AM Arnd Bergmann <arnd@kernel.org> wrote:
>
> On Thu, Jan 21, 2021 at 10:48 AM Linus Walleij <linus.walleij@linaro.org> wrote:
> >
> > Hi Mohamed,
> >
> > thanks for your patch!
> >
> > On Wed, Jan 20, 2021 at 2:31 PM Mohamed Mediouni
> > <mohamed.mediouni@caramail.com> wrote:
> >
> > > +properties:
> > > +  compatible:
> > > +    items:
> > > +      - const: apple,aic
> >
> > However weird it may seem, Apple is not in the file
> > Documentation/devicetree/bindings/vendor-prefixes.yaml
> >
> > (I think it's weird because I remember clearly that they have been
> > using device tree for PPC since ages.)
> >
> > Could you add this 2-liner to that file and send it directly to
> > DT binding maintainers as a single patch as a preparation?
>
> Choosing the vendor prefix here is going to be a little tricky
> and non-obvious.
>
> Background:
>
> Traditionally, it should have been the stock ticker symbol of the
> company (clearly only publicly traded companies would be able
> to produce a Unix capable computer, right?), but there were
> already inconsistent: IBM used "ibm" (in small letters), Sun
> used "SUNW" (in capitals) but in 2007 changed the stock ticker
> symbol to "JAVA", obviously without changing the firmware bindings.
>
> Apple traditionally used "AAPL" (also in caps) in the device tree,
> and there is one remnant of that in the M1 device tree, in the form
> of the "AAPL,phandle" property in each node, which corresponds
> to our "linux,phandle". (phandles were introduced as properties in
> both of the flattened DT formats, .dtb and apple's own format).
> There are also "AAPL,unit-string properties and some device_type
> strings (AAPL,display-crossbar, AAPL,atc-dpxbar, ...) in the M1 DT,
> and the CPU nodes (and only those) use "apple" in small letters
> as in "apple,icestorm","ARM,v8". The other nodes tend to not have
> a vendor prefix, but a lot use a subsystem name as the prefix, such
> as compatible="gpio,t8101" or compatible="tempsensor,t8020".
>
> Since Apple are already using both the "AAPL" and the "apple"
> prefix themselves, I have a bad feeling about reusing either of
> them for defining the devicetree.org bindings that we add to
> linux/Documentation/devicetree/bindings. The question is: if
> not "apple", what else should we use here?

IMO, 'AAPL' as that is what is already in use in the kernel. I don't
see why it matters at all what Apple is using. It might if we used any
of the ADT as-is, but I don't see that happening from what I've seen.

Rob
diff mbox series

Patch

diff --git a/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
new file mode 100644
index 000000000000..e615eaaca869
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
@@ -0,0 +1,49 @@ 
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/apple,aic.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Apple Advanced Interrupt Controller (AIC)
+
+description:
+  Interrupt controller present on Apple processors. AIC
+  is used by Apple on their AArch64 SoCs since the Apple A7.
+
+maintainers:
+  - Stan Skowronek <stan@corellium.com>
+
+properties:
+  compatible:
+    items:
+      - const: apple,aic
+
+  reg:
+    maxItems: 1
+
+  '#interrupt-cells':
+    const: 3
+
+  interrupt-controller: true
+
+  fast-ipi:
+    description:
+      Fast IPI support.
+
+required:
+  - compatible
+  - '#interrupt-cells'
+  - interrupt-controller
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+        aic: interrupt-controller@23b100000 {
+             compatible = "apple,aic";
+             #interrupt-cells = <3>;
+             interrupt-controller;
+             reg = <0x2 0x3b100000 0x0 0x8000>;
+             fast-ipi;
+         };
diff --git a/MAINTAINERS b/MAINTAINERS
index 00836f6452f0..e609ede99dd4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1218,6 +1218,12 @@  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
 F:	Documentation/admin-guide/LSM/apparmor.rst
 F:	security/apparmor/

+APPLE ADVANCED INTERRUPT CONTROLLER DRIVER
+M:	Stan Skowronek <stan@corellium.com>
+L:	linux-arm-kernel@lists.infradead.org
+S:	Maintained
+F:	drivers/irqchip/irq-apple-aic.c
+
 APPLE BCM5974 MULTITOUCH DRIVER
 M:	Henrik Rydberg <rydberg@bitmath.org>
 L:	linux-input@vger.kernel.org
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 94920a51c628..3aa9e711324b 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -56,6 +56,12 @@  config ARM_GIC_V3_ITS_FSL_MC
 	depends on FSL_MC_BUS
 	default ARM_GIC_V3_ITS

+config APPLE_AIC
+	bool
+	select IRQ_DOMAIN_HIERARCHY
+	select GENERIC_IRQ_MULTI_HANDLER
+	select GENERIC_IRQ_EFFECTIVE_AFF_MASK
+
 config ARM_NVIC
 	bool
 	select IRQ_DOMAIN_HIERARCHY
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 0ac93bfaec61..2f5a9a0cf40f 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -34,6 +34,7 @@  obj-$(CONFIG_ARM_GIC_V3)		+= irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o
 obj-$(CONFIG_ARM_GIC_V3_ITS)		+= irq-gic-v3-its.o irq-gic-v3-its-platform-msi.o irq-gic-v4.o
 obj-$(CONFIG_ARM_GIC_V3_ITS_PCI)	+= irq-gic-v3-its-pci-msi.o
 obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC)	+= irq-gic-v3-its-fsl-mc-msi.o
+obj-$(CONFIG_APPLE_AIC)			+= irq-apple-aic.o
 obj-$(CONFIG_PARTITION_PERCPU)		+= irq-partition-percpu.o
 obj-$(CONFIG_HISILICON_IRQ_MBIGEN)	+= irq-mbigen.o
 obj-$(CONFIG_ARM_NVIC)			+= irq-nvic.o
diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c
new file mode 100644
index 000000000000..c601bc4b501a
--- /dev/null
+++ b/drivers/irqchip/irq-apple-aic.c
@@ -0,0 +1,211 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Apple chip interrupt controller
+ *
+ * Copyright (C) 2020 Corellium LLC
+ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/exception.h>
+#include <asm/irq.h>
+
+#define REG_ID_REVISION 0x0000
+#define REG_ID_CONFIG 0x0004
+#define REG_GLOBAL_CFG 0x0010
+#define REG_TIME_LO 0x0020
+#define REG_TIME_HI 0x0028
+#define REG_ID_CPUID 0x2000
+#define REG_IRQ_ACK 0x2004
+#define REG_IRQ_ACK_TYPE_MASK (15 << 16)
+#define REG_IRQ_ACK_TYPE_NONE (0 << 16)
+#define REG_IRQ_ACK_TYPE_IRQ (1 << 16)
+#define REG_IRQ_ACK_TYPE_IPI (4 << 16)
+#define REG_IRQ_ACK_IPI_OTHER 0x40001
+#define REG_IRQ_ACK_IPI_SELF 0x40002
+#define REG_IRQ_ACK_NUM_MASK (4095)
+#define REG_IPI_SET 0x2008
+#define REG_IPI_FLAG_SELF (1 << 31)
+#define REG_IPI_FLAG_OTHER (1 << 0)
+#define REG_IPI_CLEAR 0x200C
+#define REG_IPI_DISABLE 0x2024
+#define REG_IPI_ENABLE 0x2028
+#define REG_IPI_DEFER_SET 0x202C
+#define REG_IPI_DEFER_CLEAR 0x2030
+#define REG_TSTAMP_CTRL 0x2040
+#define REG_TSTAMP_LO 0x2048
+#define REG_TSTAMP_HI 0x204C
+#define REG_IRQ_AFFINITY(i) (0x3000 + ((i) << 2))
+#define REG_IRQ_DISABLE(i) (0x4100 + (((i) >> 5) << 2))
+#define REG_IRQ_xABLE_MASK(i) (1 << ((i)&31))
+#define REG_IRQ_ENABLE(i) (0x4180 + (((i) >> 5) << 2))
+#define REG_CPU_REGION 0x5000
+#define REG_CPU_LOCAL 0x2000
+#define REG_CPU_SHIFT 7
+#define REG_PERCPU(r, c)                                                       \
+	((r) + REG_CPU_REGION - REG_CPU_LOCAL + ((c) << REG_CPU_SHIFT))
+
+static struct aic_chip_data {
+	void __iomem *base;
+	struct irq_domain *domain;
+	unsigned int num_irqs;
+} aic;
+
+static void apple_aic_irq_mask(struct irq_data *d)
+{
+	writel(REG_IRQ_xABLE_MASK(d->hwirq),
+	       aic.base + REG_IRQ_DISABLE(d->hwirq));
+}
+
+static void apple_aic_irq_unmask(struct irq_data *d)
+{
+	writel(REG_IRQ_xABLE_MASK(d->hwirq),
+	       aic.base + REG_IRQ_ENABLE(d->hwirq));
+}
+
+static struct irq_chip apple_aic_irq_chip = {
+	.name = "apple_aic",
+	.irq_mask = apple_aic_irq_mask,
+	.irq_mask_ack = apple_aic_irq_mask,
+	.irq_unmask = apple_aic_irq_unmask,
+};
+
+static void apple_aic_fiq_mask(struct irq_data *d)
+{
+}
+
+static void apple_aic_fiq_unmask(struct irq_data *d)
+{
+}
+
+static struct irq_chip apple_aic_irq_chip_fiq = {
+	.name = "apple_aic_fiq",
+	.irq_mask = apple_aic_fiq_mask,
+	.irq_unmask = apple_aic_fiq_unmask,
+};
+
+static int apple_aic_irq_domain_xlate(struct irq_domain *d,
+				      struct device_node *ctrlr,
+				      const u32 *intspec, unsigned int intsize,
+				      unsigned long *out_hwirq,
+				      unsigned int *out_type)
+{
+	if (intspec[0]) { /* FIQ */
+		if (intspec[1] >= 2)
+			return -EINVAL;
+		if (out_hwirq)
+			*out_hwirq = aic.num_irqs + intspec[1];
+	} else {
+		if (intspec[1] >= aic.num_irqs)
+			return -EINVAL;
+		if (out_hwirq)
+			*out_hwirq = intspec[1];
+	}
+
+	if (out_type)
+		*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+
+static int apple_aic_irq_domain_map(struct irq_domain *d, unsigned int virq,
+				    irq_hw_number_t hw)
+{
+	if (hw >= aic.num_irqs) {
+		irq_set_percpu_devid(virq);
+		irq_domain_set_info(d, virq, hw, &apple_aic_irq_chip_fiq,
+				    d->host_data, handle_percpu_devid_irq, NULL,
+				    NULL);
+		irq_set_status_flags(virq, IRQ_NOAUTOEN);
+	} else {
+		irq_domain_set_info(d, virq, hw, &apple_aic_irq_chip,
+				    d->host_data, handle_level_irq, NULL, NULL);
+		irq_set_probe(virq);
+		irqd_set_single_target(
+			irq_desc_get_irq_data(irq_to_desc(virq)));
+	}
+	return 0;
+}
+
+static const struct irq_domain_ops apple_aic_irq_domain_ops = {
+	.xlate = apple_aic_irq_domain_xlate,
+	.map = apple_aic_irq_domain_map,
+};
+
+static void __exception_irq_entry apple_aic_handle_irq(struct pt_regs *regs)
+{
+	uint32_t ack;
+	unsigned done = 0;
+
+	while (1) {
+		ack = readl(aic.base + REG_IRQ_ACK);
+		switch (ack & REG_IRQ_ACK_TYPE_MASK) {
+		case REG_IRQ_ACK_TYPE_NONE:
+			done = 1;
+			break;
+		case REG_IRQ_ACK_TYPE_IRQ:
+			handle_domain_irq(aic.domain,
+					  ack & REG_IRQ_ACK_NUM_MASK, regs);
+			break;
+		}
+		if (done)
+			break;
+	}
+}
+
+static void __exception_irq_entry apple_aic_handle_fiq(struct pt_regs *regs)
+{
+	handle_domain_irq(aic.domain, aic.num_irqs, regs);
+}
+
+void apple_aic_cpu_prepare(unsigned int cpu)
+{
+	unsigned i;
+
+	for (i = 0; i < aic.num_irqs; i++)
+		writel(readl(aic.base + REG_IRQ_AFFINITY(i)) | (1u << cpu),
+		       aic.base + REG_IRQ_AFFINITY(i));
+}
+
+static int __init apple_aic_init(struct device_node *node,
+				 struct device_node *interrupt_parent)
+{
+	unsigned i;
+
+	if (!node)
+		return -ENODEV;
+
+	aic.base = of_iomap(node, 0);
+	if (WARN(!aic.base, "unable to map aic registers\n"))
+		return -EINVAL;
+
+	aic.num_irqs = readl(aic.base + REG_ID_CONFIG) & 0xFFFF;
+	pr_info("Apple AIC: %d IRQs + 1 FIQ + 1 dummy\n", aic.num_irqs);
+
+	for (i = 0; i < aic.num_irqs; i++)
+		writel(1, aic.base + REG_IRQ_AFFINITY(i));
+	for (i = 0; i < aic.num_irqs; i += 32)
+		writel(-1u, aic.base + REG_IRQ_DISABLE(i));
+	writel((readl(aic.base + REG_GLOBAL_CFG) & ~0xF00000) | 0x700000,
+	       aic.base + REG_GLOBAL_CFG);
+
+	set_handle_irq(apple_aic_handle_irq);
+	set_handle_fiq(apple_aic_handle_fiq);
+
+	apple_aic_cpu_prepare(0);
+
+	aic.domain = irq_domain_add_linear(node, aic.num_irqs + 2,
+					   &apple_aic_irq_domain_ops,
+					   &apple_aic_irq_chip);
+	irq_set_default_host(aic.domain);
+	return 0;
+}
+
+IRQCHIP_DECLARE(apple_aic_irq_chip, "apple,aic", apple_aic_init);