Hi everyone, I've been trying to implement a feature on recent Tegra chips that's called "wake events". These wake events are implemented as part of the power management controller (PMC) and they control which events can be used to wake the system from suspend. Events include things like an alarm interrupt from an RTC, or the GPIO interrupt hooked up to a power button for example. We already have a driver for a couple of other things that the PMC does, so I thought it'd be natural to implement this functionality as an IRQ chip in the PMC driver. The way that this would work is that for all the devices that are wakeup sources, we'd end up specifying the PMC as the interrupt parent and the PMC would then itself have the main GIC as its parent. That way, the hierarchical IRQ domain infrastructure would take care of pretty much everything. Unfortunately I've run into some issues here. One problem that I'm facing is that PMC could have more than one parent. For example, the RTC alarm interrupt goes straight to the GIC, but the power button GPIO goes through the GPIO controller first and then to the GIC. This doesn't seem to be something that's currently possible. The way I imagine this to work from a DT perspective is as follows: rtc: rtc@c2a0000 { compatible = "nvidia,tegra194-rtc", "nvidia,tegra20-rtc"; reg = <0x0c2a0000 0x10000>; interrupt-parent = <&pmc>; interrupts = <73 &gic GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; pmc: pmc@c360000 { compatible = "nvidia,tegra194-pmc"; reg = <0x0c360000 0x10000>, <0x0c370000 0x10000>, <0x0c380000 0x10000>, <0x0c390000 0x10000>, <0x0c3a0000 0x10000>; reg-names = "pmc", "wake", "aotag", "scratch", "misc"; #interrupt-cells = <5>; interrupt-controller; }; gpio-keys { compatible = "gpio-keys"; power { label = "Power"; gpios = <&gpio_aon TEGRA194_AON_GPIO(EE, 4) GPIO_ACTIVE_LOW>; linux,input-type = <EV_KEY>; linux,code = <KEY_POWER>; debounce-interval = <10>; interrupt-parent = <&pmc>; interrupts = <29 &gpio_aon TEGRA194_AON_GPIO(EE, 4) IRQ_TYPE_LEVEL_LOW 0>; wakeup-source; }; }; The above is somewhat brittle because the PMC needs to be able to cover both GIC and GPIO interrupt specifiers, so it gets 5 interrupt cells (one for the wake event ID, one for a phandle to the parent controller and two or three for the parent specifier). It'd be nicer if we could actually have specifiers that exactly match the bindings for the respective parent controllers (so that the GPIO specifier didn't have to contain the dummy 0 at the end), but I don't see a way how that can be achieved, given how we have to "embed" the specifier in another. We could probably make it work in code, but DTC would still flag these as errors. One thing I briefly looked into was using interrupt-map to implement this, which would give us a nice way of mapping arbitrary parent interrupts to wake events. However, since we need to program some of the PMC registers at ->irq_set_wake() time, using simply an interrupt-map wouldn't do the trick, since we wouldn't be implementing an IRQ chip and hence wouldn't be able to install any callbacks. Perhaps a simple way to implement this would be to just blindly enable all wake events, but that's not really what we want. We really only want to enable them for devices that can be wakeup sources. Otherwise we may get wakeups for completely unrelated GPIO activity. I tried implementing support for multiple parents within the PMC driver by looking up the parent domain based on the phandle from the specifier at IRQ domain ->alloc() and ->translate() time, but I run into deadlock when I do that, so before I go and open up a can of worms I wanted to get your input on what the best way forward would be. Does anyone have any ideas on how to solve this? Perhaps there's a better solution to this that doesn't involve IRQ infrastructure that I'm not aware of? Thanks, Thierry
Attachment:
signature.asc
Description: PGP signature