Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/3] clk: imx6: Fix procedure to switch the parent of LDB_DI_CLK
From: Fabio Estevam @ 2016-10-19 23:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161019000526.GR8871@codeaurora.org>

Hi Stephen,

On Tue, Oct 18, 2016 at 10:05 PM, Stephen Boyd <sboyd@codeaurora.org> wrote:

> Ok that makes it easy. Thanks.

I resent the series yesterday.

https://patchwork.kernel.org/patch/9380917/
https://patchwork.kernel.org/patch/9380919/
https://patchwork.kernel.org/patch/9380921/

Please consider applying them.

Thanks

^ permalink raw reply

* [PATCH V3 1/3] ACPI, PCI IRQ: add PCI_USING penalty for ISA interrupts
From: Rafael J. Wysocki @ 2016-10-19 23:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161019224405.GA14915@localhost>

On Thu, Oct 20, 2016 at 12:44 AM, Bjorn Helgaas <helgaas@kernel.org> wrote:
> On Tue, Oct 18, 2016 at 08:32:44AM -0700, Sinan Kaya wrote:
>> Sorry, I think I didn't have enough morning coffee.
>>
>> Looking at these again and trying to be specific.
>>
>> On 10/18/2016 8:20 AM, Sinan Kaya wrote:
>> > It seems wrong to me that we call acpi_irq_get_penalty() from
>> >> acpi_irq_penalty_update() and acpi_penalize_isa_irq().  It seems like they
>> >> should just manipulate acpi_isa_irq_penalty[irq] directly.
>> >>
>> >> acpi_irq_penalty_update() is for command-line parameters, so it certainly
>> >> doesn't need the acpi_irq_pci_sharing_penalty() information (the
>> >> acpi_link_list should be empty at the time we process the command-line
>> >> parameters).
>>
>> Calling acpi_irq_get_penalty for ISA IRQ is OK as long as it doesn't have
>> any dynamic IRQ calculation such that acpi_isa_irq_penalty[irq] = acpi_irq_get_penalty.
>>
>> If this is broken, then we need special care so that we don't assign
>> dynamically calcualted sci_penalty back to acpi_isa_irq_penalty[irq]. This
>> results in returning incorrect penalty as
>>
>> acpi_irq_get_penalty = acpi_isa_irq_original_penalty[irq] + 2 * sci_penalty.
>>
>> Now that we added sci_penalty into the acpi_irq_get_penalty function,
>> calling acpi_irq_get_penalty is not correct anymore. This line here needs to
>> be replaced with acpi_isa_irq_penalty[irq] as you suggested.
>>
>>                 if (used)
>>                         new_penalty = acpi_irq_get_penalty(irq) +
>>                                         PIRQ_PENALTY_ISA_USED;
>>                 else
>>                         new_penalty = 0;
>>
>>                 acpi_isa_irq_penalty[irq] = new_penalty;
>>
>>
>> >>
>> >> acpi_penalize_isa_irq() is telling us that a PNP or ACPI device is using
>> >> the IRQ -- this should modify the IRQ's penalty, but it shouldn't depend on
>> >> the acpi_irq_pci_sharing_penalty() value at all.
>> >>
>>
>> Same problem here. This line will be broken after the sci_penalty change.
>>
>>                 acpi_isa_irq_penalty[irq] = acpi_irq_get_penalty(irq) +
>>                   (active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING);
>
> I think the fragility of this code is an indication that we have a
> design problem, so I want to step back from the nitty gritty details
> for a bit and look at the overall design.
>
> Let me restate the overall problem: We have a PCI device connected to
> an interrupt link.  The interrupt link can be connected to one of
> several IRQs, and we want to choose one of those IRQs to minimize IRQ
> sharing.
>
> That means we need information about which IRQs are used.
> Historically we've started with a compiled-in table of common ISA IRQ
> usage, and we also collect information about which IRQs are used and
> which *might* be used.  So we have the following inputs:
>
>   - Compiled-in ISA IRQ usage: the static acpi_isa_irq_penalty[]
>     values.  ACPI is *supposed* to tell us about all these usages, so
>     I don't know why we have the table.  But it's been there as long
>     as I can remember.  The table is probably x86-specific, but we
>     keep it in the supposedly generic pci_link.c.
>
>   - The "acpi_irq_isa=" and "acpi_irq_pci=" command-line overrides via
>     acpi_irq_pci().  I suppose these are for cases where we can't
>     figure things out automatically.  I would resist adding parameters
>     like this today (I would treat the need for them as a bug and look
>     for a fix or a quirk), but we might be stuck with these.
>
>   - SCI information from the ACPI FADT (acpi_penalize_sci_irq()).
>
>   - PNPBIOS and PNPACPI device IRQ usage from _CRS and _PRS via
>     acpi_penalize_isa_irq().  This is only for IRQs 0-15, and it does
>     NOT include interrupt link (PNP0C0F) devices because we don't
>     handle them as PNPACPI devices.  I think this is related to the
>     fact that PNP0C0F doesn't appear in acpi_pnp_device_ids[].
>
>   - For non-PNP0C0F, non-PNPACPI devices, we completely ignore IRQ
>     information from _CRS and _PRS.  This seems sub-optimal and
>     possibly buggy.
>
>   - Interrupt link (PNP0C0F) IRQ usage from _CRS and _PRS via
>     acpi_irq_penalty_init().  This is only for IRQs 0-15, and we only
>     call this on x86.  If _PRS exists, we penalize each possible IRQ.
>     If there's no _PRS but _CRS contains an active IRQ, we penalize
>     it.
>
>   - Interrupt link (PNP0C0F) IRQ usage from _CRS and _PRS when
>     enabling a new link.  In acpi_irq_pci_sharing_penalty(), we
>     penalize an IRQ if it appears in _CRS or _PRS of any link device
>     in the system.
>
>     For IRQs 0-15, this overlaps with the penalization done at
>     boot-time by acpi_irq_penalty_init(): if a device has _PRS, we'll
>     add the "possible" penalty twice (once in acpi_irq_penalty_init()
>     and again in acpi_irq_pci_sharing_penalty()), and the "using"
>     penalty once (in acpi_irq_pci_sharing_penalty()).
>
>     If a device has no _PRS but has _CRS, the "using" penalty is
>     applied twice (once in once in acpi_irq_penalty_init() and again
>     in acpi_irq_pci_sharing_penalty())
>
> I think this whole thing is baroque and grotesque.

While I agree, I also would like the regression introduced here to be
fixed ASAP.

So do you want me to revert all of the changes made here so far and start over?

Thanks,
Rafael

^ permalink raw reply

* exynos-drm: display manager fails to start without IOMMU problem
From: Shuah Khan @ 2016-10-19 22:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <58079E16.50302@math.uni-bielefeld.de>

On 10/19/2016 10:23 AM, Tobias Jakobi wrote:
> Hello Shuah,
> 
> just a short note that more misleading comments about default allocation
> flags can be found in libdrm.
> 
> https://cgit.freedesktop.org/mesa/drm/tree/exynos/exynos_drm.c
> 
> See e.g. the comment for exynos_bo_create().
> 
> In my opinion, the whole approach to _set_ a bit to get non-contigious
> memory is messed up. It would make more sense to me to set a bit to
> request an additional property (here "being contiguous") of the memory.
> 
> Anyway, clearing up this situation is highly appreciated!
> 
> More comments below.
> 
> With best wishes,
> Tobias
> 

Hi Tobias,

Thanks for the note. Yes the comments are confusing. It seems like
some old assumptions are persisting. I will fix these as well.

-- Shuah

^ permalink raw reply

* [PATCH] arm64: Add support for additional relocations in the kexec purgatory code
From: Geoff Levand @ 2016-10-19 22:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476892714-27304-1-git-send-email-catalin.marinas@arm.com>

Hi Catalin,

On 10/19/2016 08:58 AM, Catalin Marinas wrote:
> diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
> index 2e8839a..e067a23 100644
> --- a/kexec/arch/arm64/kexec-arm64.c
> +++ b/kexec/arch/arm64/kexec-arm64.c
> @@ -585,6 +598,19 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
>  		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
>  			+ (((value - address) << 3) & 0xffffe0));
>  		break;
> +	case R_AARCH64_ADR_PREL_PG_HI21:
> +		type = "ADR_PREL_PG_HI21";
> +		imm = ((value & ~0xfff) - (address & ~0xfff)) >> 12;
> +		loc32 = ptr;
> +		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
> +			+ ((imm & 3) << 29) + ((imm & 0x1ffffc) << (5 - 2)));
> +		break;
> +	case R_AARCH64_ADD_ABS_LO12_NC:
> +		type = "R_AARCH64_ADD_ABS_LO12_NC";

Following with the others, this should be 'type = "ADD_ABS_LO12_NC"'.

> +		loc32 = ptr;
> +		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
> +			+ ((value & 0xfff) << 10));
> +		break;
>  	case R_AARCH64_JUMP26:
>  		type = "JUMP26";
>  		loc32 = ptr;
> @@ -597,6 +623,15 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
>  		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
>  			+ (((value - address) >> 2) & 0x3ffffff));
>  		break;
> +	case R_AARCH64_LDST64_ABS_LO12_NC:
> +		if (value & 7)
> +			die("%s: ERROR Unaligned value: %lx\n", __func__,
> +				value);
> +		type = "R_AARCH64_LDST64_ABS_LO12_NC";

And type = "LDST64_ABS_LO12_NC" here.

> +		loc32 = ptr;
> +		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
> +			+ ((value & 0xff8) << (10 - 3)));
> +		break;
>  	default:
>  		die("%s: ERROR Unknown type: %lu\n", __func__, r_type);
>  		break;

Otherwise, looks good.  Thanks for taking time to make the fix.

-Geoff 

^ permalink raw reply

* [PATCH V3 1/3] ACPI, PCI IRQ: add PCI_USING penalty for ISA interrupts
From: Bjorn Helgaas @ 2016-10-19 22:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <0a82f2ef-b072-d847-104a-320cf804ebd5@codeaurora.org>

On Tue, Oct 18, 2016 at 08:32:44AM -0700, Sinan Kaya wrote:
> Sorry, I think I didn't have enough morning coffee.
> 
> Looking at these again and trying to be specific.
> 
> On 10/18/2016 8:20 AM, Sinan Kaya wrote:
> > It seems wrong to me that we call acpi_irq_get_penalty() from
> >> acpi_irq_penalty_update() and acpi_penalize_isa_irq().  It seems like they
> >> should just manipulate acpi_isa_irq_penalty[irq] directly.
> >> 
> >> acpi_irq_penalty_update() is for command-line parameters, so it certainly
> >> doesn't need the acpi_irq_pci_sharing_penalty() information (the
> >> acpi_link_list should be empty at the time we process the command-line
> >> parameters).
> 
> Calling acpi_irq_get_penalty for ISA IRQ is OK as long as it doesn't have
> any dynamic IRQ calculation such that acpi_isa_irq_penalty[irq] = acpi_irq_get_penalty.
> 
> If this is broken, then we need special care so that we don't assign
> dynamically calcualted sci_penalty back to acpi_isa_irq_penalty[irq]. This
> results in returning incorrect penalty as
> 
> acpi_irq_get_penalty = acpi_isa_irq_original_penalty[irq] + 2 * sci_penalty.
> 
> Now that we added sci_penalty into the acpi_irq_get_penalty function,
> calling acpi_irq_get_penalty is not correct anymore. This line here needs to
> be replaced with acpi_isa_irq_penalty[irq] as you suggested.
> 
>                 if (used)
>                         new_penalty = acpi_irq_get_penalty(irq) +
>                                         PIRQ_PENALTY_ISA_USED;
>                 else
>                         new_penalty = 0;
> 
>                 acpi_isa_irq_penalty[irq] = new_penalty;
> 
> 
> >> 
> >> acpi_penalize_isa_irq() is telling us that a PNP or ACPI device is using
> >> the IRQ -- this should modify the IRQ's penalty, but it shouldn't depend on
> >> the acpi_irq_pci_sharing_penalty() value at all.
> >> 
> 
> Same problem here. This line will be broken after the sci_penalty change.
> 
>                 acpi_isa_irq_penalty[irq] = acpi_irq_get_penalty(irq) +
>                   (active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING);

I think the fragility of this code is an indication that we have a
design problem, so I want to step back from the nitty gritty details
for a bit and look at the overall design.

Let me restate the overall problem: We have a PCI device connected to
an interrupt link.  The interrupt link can be connected to one of
several IRQs, and we want to choose one of those IRQs to minimize IRQ
sharing.

That means we need information about which IRQs are used.
Historically we've started with a compiled-in table of common ISA IRQ
usage, and we also collect information about which IRQs are used and
which *might* be used.  So we have the following inputs:

  - Compiled-in ISA IRQ usage: the static acpi_isa_irq_penalty[]
    values.  ACPI is *supposed* to tell us about all these usages, so
    I don't know why we have the table.  But it's been there as long
    as I can remember.  The table is probably x86-specific, but we
    keep it in the supposedly generic pci_link.c.

  - The "acpi_irq_isa=" and "acpi_irq_pci=" command-line overrides via
    acpi_irq_pci().  I suppose these are for cases where we can't
    figure things out automatically.  I would resist adding parameters
    like this today (I would treat the need for them as a bug and look
    for a fix or a quirk), but we might be stuck with these.

  - SCI information from the ACPI FADT (acpi_penalize_sci_irq()).

  - PNPBIOS and PNPACPI device IRQ usage from _CRS and _PRS via
    acpi_penalize_isa_irq().  This is only for IRQs 0-15, and it does
    NOT include interrupt link (PNP0C0F) devices because we don't
    handle them as PNPACPI devices.  I think this is related to the
    fact that PNP0C0F doesn't appear in acpi_pnp_device_ids[].

  - For non-PNP0C0F, non-PNPACPI devices, we completely ignore IRQ
    information from _CRS and _PRS.  This seems sub-optimal and
    possibly buggy.

  - Interrupt link (PNP0C0F) IRQ usage from _CRS and _PRS via
    acpi_irq_penalty_init().  This is only for IRQs 0-15, and we only
    call this on x86.  If _PRS exists, we penalize each possible IRQ.
    If there's no _PRS but _CRS contains an active IRQ, we penalize
    it.

  - Interrupt link (PNP0C0F) IRQ usage from _CRS and _PRS when
    enabling a new link.  In acpi_irq_pci_sharing_penalty(), we
    penalize an IRQ if it appears in _CRS or _PRS of any link device
    in the system.
    
    For IRQs 0-15, this overlaps with the penalization done at
    boot-time by acpi_irq_penalty_init(): if a device has _PRS, we'll
    add the "possible" penalty twice (once in acpi_irq_penalty_init()
    and again in acpi_irq_pci_sharing_penalty()), and the "using"
    penalty once (in acpi_irq_pci_sharing_penalty()).

    If a device has no _PRS but has _CRS, the "using" penalty is
    applied twice (once in once in acpi_irq_penalty_init() and again
    in acpi_irq_pci_sharing_penalty())

I think this whole thing is baroque and grotesque.

Here's a strawman idea:

  - Maintain a mapping of (IRQ, penalty).  Initially all penalties are
    zero.  This is for *all* IRQs, not just ISA ones.  This could be a
    linked list, but the structure is not important as long as we can
    add things dynamically.

  - Add a "acpi_penalize_irq()" function similar to
    acpi_penalize_isa_irq(), but not restricted to ISA, so we can
    increase the penalty for any IRQ, and maybe we can specify how
    much penalty to add.

  - Make acpi_irq_get_penalty() a simple lookup in the mapping.  No
    iterating through all link devices.

  - If we think the compiled-in penalties are really necessary, move
    the table to x86 code and add a boot-time loop to use
    acpi_penalize_irq() to penalize these IRQs.  Same for the
    command-line options.

  - Change acpi_penalize_sci_irq() to use acpi_penalize_irq().
    Probably the mapping needs to pay attention to trigger/polarity
    somehow, too.

  - Figure out how to make the ACPI core use acpi_penalize_irq() to
    based on the _CRS and _PRS of every ACPI device, including
    PNPACPI, PNP0C0F, etc.  Then we can remove acpi_irq_penalty_init().

  - Change acpi_pci_link_set() to use acpi_penalize_irq() for the IRQ
    it is enabling.  Conceptually maybe this should be done in the
    acpi_set_current_resources() path so it happens whenever we use
    _CRS to enable an IRQ on *any* ACPI device.

I think the biggest issue is figuring out how to get the ACPI core to
look at the _CRS for *all* devices.  If we could do that, I think it
could substantially simplify this code.

Bjorn

^ permalink raw reply

* [PATCH] exynos-drm: Fix display manager failing to start without IOMMU problem
From: Shuah Khan @ 2016-10-19 22:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAAQKjZMFOe7Aa5Hq5gbMj7=h2VfgXq5jgqbB1wqcZcYZ0ZKZxA@mail.gmail.com>

On 10/19/2016 08:16 AM, Inki Dae wrote:
> Hi Shuah,
> 
> 2016-10-13 8:11 GMT+09:00 Shuah Khan <shuahkh@osg.samsung.com>:
>> Hi Inki,
>>
>> On 08/15/2016 10:40 PM, Inki Dae wrote:
>>
>>>>
>>>> okay the very first commit that added IOMMU support
>>>> introduced the code that rejects non-contig gem memory
>>>> type without IOMMU.
>>>>
>>>> commit 0519f9a12d0113caab78980c48a7902d2bd40c2c
>>>> Author: Inki Dae <inki.dae@samsung.com>
>>>> Date:   Sat Oct 20 07:53:42 2012 -0700
>>>>
>>>>     drm/exynos: add iommu support for exynos drm framework
>>>>
>>
>> I haven't given up on this yet. I am still seeing the following failure:
>>
>> Additional debug messages I added:
>> [   15.287403] exynos_drm_gem_create_ioctl() 1
>> [   15.287419] exynos_drm_gem_create() flags 1
>>
>> [   15.311511] [drm:exynos_drm_framebuffer_init] *ERROR* Non-contiguous GEM memory is not supported.
>>
>> Additional debug message I added:
>> [   15.318981] [drm:exynos_user_fb_create] *ERROR* failed to initialize framebuffer
>>
>> This is what happens:
>>
>> 1. exynos_drm_gem_create_ioctl() gets called with EXYNOS_BO_NONCONTIG request
>> 2. exynos_drm_gem_create(0 goes ahead and creates the GEM buffers
>> 3. exynos_user_fb_create() tries to associate GEM to fb and fails during
>>    check_fb_gem_memory_type()
>>
>> At this point, there is no recovery and lightdm fails
>>
>> xf86-video-armsoc/src/drmmode_exynos/drmmode_exynos.c assumes contiguous
>> allocations are not supported in some exynos drm versions: The following
>> commit introduced this change:
>>
>> https://git.linaro.org/arm/xorg/driver/xf86-video-armsoc.git/commitdiff/3be1f6273441fe95dd442f44064387322e16b7e9
>>
>> excerpts from the diff:-       if (create_gem->buf_type == ARMSOC_BO_SCANOUT)
>> -               create_exynos.flags = EXYNOS_BO_CONTIG;
>> -       else
>> -               create_exynos.flags = EXYNOS_BO_NONCONTIG;
>> +
>> +       /* Contiguous allocations are not supported in some exynos drm versions.
>> +        * When they are supported all allocations are effectively contiguous
>> +        * anyway, so for simplicity we always request non contiguous buffers.
>> +        */
>> +       create_exynos.flags = EXYNOS_BO_NONCONTIG;
>>
> 
> Above comment, "Contiguous allocations are not supported in some
> exynos drm versions.", seems wrong assumption.
> The root cause, contiguous allocation is not supported, would be that
> they used Linux kernel which didn't have CMA region enough - as
> default 16MB, or didn't declare CMA region enough for the DMA device.
> So I think they should not force to flag EXYNOS_BO_NONCONTIG and they
> should manage the error case if the allocation failed.

This assumption doesn't sound correct and forcing NONCONTIG isn't right
either. 

> 
>> There might have been logic on exynos_drm that forced Contig when it coudn't
>> support NONCONTIG. At least, that is what this comment suggests. This assumption
>> doesn't appear to be a good one and not sure if this change was made to fix a bug.
>>
>> After the IOMMU support, this assumption is no longer true. Hence, with IOMMU
>> support, latest kernels have a mismatch with the installed xf86-video-armsoc
>>
>> This is what I am running into. This leads to the following question:
>>
>> 1. How do we ensure exynos_drm kernel changes don't break user-space
>>    specifically xf86-video-armsoc
>> 2. This seems to have gone undetected for a while. I see a change in
>>    exynos_drm_gem_dumb_create() that is probably addressing this type
>>    of breakage. Commit 122beea84bb90236b1ae545f08267af58591c21b adds
>>    handling for IOMMU NONCONTIG case.
> 
> Seems this patch has a problem. This patch forces to flag NONCONTIG if
> iommu is enabled. The flag should be depend on the argument from
> user-space.
> I.e., if user-space requested a gem allocation with CONTIG flag, then
> Exynos drm driver should allocate contiguous memory even though iommu
> is enabled.
> 
>>
>> Anyway, I am interested in getting the exynos_drm kernel side code
>> and xf86-video-armsoc in sync to resolve the issue.
>>
>> Could you recommend a going forward plan?
> 
> My opinion are,
> 
> 1. Do not force to flag EXYNOS_BO_NONCONTIG at xf86-video-armsoc
> 2. Do not force to flag NONCONTIG at Exynos drm driver even though
> iommu is enabled and flag allocation type with the argument from
> user-space.
> 
> I think you could try to post above patches.
> 

Sounds good. I will work on the above two patches.

thanks,
-- Shuah

^ permalink raw reply

* [PATCH V3 1/3] ACPI, PCI IRQ: add PCI_USING penalty for ISA interrupts
From: Sinan Kaya @ 2016-10-19 22:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161018135912.GD18903@localhost>

Bjorn,

On 10/18/2016 6:59 AM, Bjorn Helgaas wrote:
> It seems wrong to me that we call acpi_irq_get_penalty() from
> acpi_irq_penalty_update() and acpi_penalize_isa_irq().  It seems like they
> should just manipulate acpi_isa_irq_penalty[irq] directly.
> 
> acpi_irq_penalty_update() is for command-line parameters, so it certainly
> doesn't need the acpi_irq_pci_sharing_penalty() information (the
> acpi_link_list should be empty at the time we process the command-line
> parameters).
> 
> acpi_penalize_isa_irq() is telling us that a PNP or ACPI device is using
> the IRQ -- this should modify the IRQ's penalty, but it shouldn't depend on
> the acpi_irq_pci_sharing_penalty() value at all.

I posted v4 with this change and also went back to the original implementation
for sharing penalty calculation whether the IRQ is ISA or PCI.

Let us know what you think. 

I also realized that calculating sharing penalty while the link object is not 
initialized is not right.

Sinan

-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH V4 3/3] Revert "ACPI, PCI, IRQ: separate ISA penalty calculation"
From: Sinan Kaya @ 2016-10-19 22:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476915664-27231-1-git-send-email-okaya@codeaurora.org>

This reverts commit f7eca374f000 ("ACPI,PCI,IRQ: separate ISA penalty
calculation") and commit 487cf917ed0d ("revert "ACPI, PCI, IRQ: remove
redundant code in acpi_irq_penalty_init()"").

Now that we understand the real issue (SCI and ISA penalty getting
calculated before ACPI start), there is no need for special handling
for ISA interrupts.

Let's try to simplify the code one more time to share code.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
 arch/x86/pci/acpi.c         |  1 -
 drivers/acpi/pci_link.c     | 44 +++++---------------------------------------
 include/acpi/acpi_drivers.h |  1 -
 3 files changed, 5 insertions(+), 41 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 3cd6983..b2a4e2a 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -396,7 +396,6 @@ int __init pci_acpi_init(void)
 		return -ENODEV;
 
 	printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
-	acpi_irq_penalty_init();
 	pcibios_enable_irq = acpi_pci_irq_enable;
 	pcibios_disable_irq = acpi_pci_irq_disable;
 	x86_init.pci.init_irq = x86_init_noop;
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 294b190..dd14d78 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -478,7 +478,8 @@ static int acpi_irq_pci_sharing_penalty(int irq)
 		 * If a link is active, penalize its IRQ heavily
 		 * so we try to choose a different IRQ.
 		 */
-		if (link->irq.active && link->irq.active == irq)
+		if ((link->irq.active && link->irq.active == irq) &&
+				(link->irq.initialized == 1))
 			penalty += PIRQ_PENALTY_PCI_USING;
 
 		/*
@@ -501,45 +502,10 @@ static int acpi_irq_get_penalty(int irq)
 		penalty += sci_penalty;
 
 	if (irq < ACPI_MAX_ISA_IRQS)
-		return penalty + acpi_isa_irq_penalty[irq];
+		penalty += acpi_isa_irq_penalty[irq];
 
-	return penalty + acpi_irq_pci_sharing_penalty(irq);
-}
-
-int __init acpi_irq_penalty_init(void)
-{
-	struct acpi_pci_link *link;
-	int i;
-
-	/*
-	 * Update penalties to facilitate IRQ balancing.
-	 */
-	list_for_each_entry(link, &acpi_link_list, list) {
-
-		/*
-		 * reflect the possible and active irqs in the penalty table --
-		 * useful for breaking ties.
-		 */
-		if (link->irq.possible_count) {
-			int penalty =
-			    PIRQ_PENALTY_PCI_POSSIBLE /
-			    link->irq.possible_count;
-
-			for (i = 0; i < link->irq.possible_count; i++) {
-				if (link->irq.possible[i] < ACPI_MAX_ISA_IRQS)
-					acpi_isa_irq_penalty[link->irq.
-							 possible[i]] +=
-					    penalty;
-			}
-
-		} else if (link->irq.active &&
-				(link->irq.active < ACPI_MAX_ISA_IRQS)) {
-			acpi_isa_irq_penalty[link->irq.active] +=
-			    PIRQ_PENALTY_PCI_POSSIBLE;
-		}
-	}
-
-	return 0;
+	penalty += acpi_irq_pci_sharing_penalty(irq);
+	return penalty;
 }
 
 static int acpi_irq_balance = -1;	/* 0: static, 1: balance */
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index 29c6912..797ae2e 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -78,7 +78,6 @@
 
 /* ACPI PCI Interrupt Link (pci_link.c) */
 
-int acpi_irq_penalty_init(void);
 int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
 			       int *polarity, char **name);
 int acpi_pci_link_free_irq(acpi_handle handle);
-- 
1.9.1

^ permalink raw reply related

* [PATCH V4 2/3] Revert "ACPI,PCI,IRQ: remove SCI penalize function"
From: Sinan Kaya @ 2016-10-19 22:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476915664-27231-1-git-send-email-okaya@codeaurora.org>

The SCI penalize function was removed in two steps (first refactor
and then remove) and these changes are reverted here in one go.

The commit 103544d86976 ("ACPI,PCI,IRQ: reduce resource requirements")
refactored the original code so that SCI penalty is calculated dynamically
by the time get_penalty function is called. That change is partially
reverted here, specifically for the SCI IRQ alone.

The SCI penalize function was finally dropped by commit 9e5ed6d1fb87
("ACPI,PCI,IRQ: remove SCI penalize function") that replaced the old SCI
penalty API with penalty calculation carried out dynamically and based
on the acpi_gbl_FADT.sci_interrupt value.

However, that new algorithm relies on the accurate setting of IRQ
types and that doesn't happen early enough on some platforms which
leads to incorrect penalty assignments for PCI IRQs.  In those cases,
irq_get_trigger_type() returns incorrect values for the IRQs in
question, because they have not been registered yet by the time the
penalties are calculated.

To fix this problem, we only need to fix the penalty for the SCI interrupt.
It seems better to add a single "sci_penalty" variable, set it to
PIRQ_PENALTY_PCI_USING if it's level/low or PIRQ_PENALTY_ISA_ALWAYS
otherwise, and add "sci_penalty" in when appropriate.  That should fix it
for *any* SCI IRQ, not just those less than 256, and we don't have to add
these extra penalty table entries that are all unused (except possibly for
one entry if we have an SCI in the 16-255 range).

For this reason, revert commit 9e5ed6d1fb87 ("ACPI,PCI,IRQ: remove SCI
penalize function") completely to restore the correct behavior.

Link: https://lkml.org/lkml/2016/10/4/283
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Fixes: commit 103544d86976 ("ACPI,PCI,IRQ: reduce resource requirements")
Fixes: commit 9e5ed6d1fb87 ("ACPI,PCI,IRQ: remove SCI penalize function")
---
 arch/x86/kernel/acpi/boot.c |  1 +
 drivers/acpi/pci_link.c     | 30 +++++++++++++++---------------
 include/linux/acpi.h        |  1 +
 3 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 90d84c3..0ffd26e 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -453,6 +453,7 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
 		polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
 
 	mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
+	acpi_penalize_sci_irq(bus_irq, trigger, polarity);
 
 	/*
 	 * stash over-ride to indicate we've been here
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 4f37938..294b190 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -87,6 +87,7 @@ struct acpi_pci_link {
 
 static LIST_HEAD(acpi_link_list);
 static DEFINE_MUTEX(acpi_link_lock);
+static int sci_irq = -1, sci_penalty;
 
 /* --------------------------------------------------------------------------
                             PCI Link Device Management
@@ -496,25 +497,13 @@ static int acpi_irq_get_penalty(int irq)
 {
 	int penalty = 0;
 
-	/*
-	* Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict
-	* with PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be
-	* use for PCI IRQs.
-	*/
-	if (irq == acpi_gbl_FADT.sci_interrupt) {
-		u32 type = irq_get_trigger_type(irq) & IRQ_TYPE_SENSE_MASK;
-
-		if (type != IRQ_TYPE_LEVEL_LOW)
-			penalty += PIRQ_PENALTY_ISA_ALWAYS;
-		else
-			penalty += PIRQ_PENALTY_PCI_USING;
-	}
+	if (irq == sci_irq)
+		penalty += sci_penalty;
 
 	if (irq < ACPI_MAX_ISA_IRQS)
 		return penalty + acpi_isa_irq_penalty[irq];
 
-	penalty += acpi_irq_pci_sharing_penalty(irq);
-	return penalty;
+	return penalty + acpi_irq_pci_sharing_penalty(irq);
 }
 
 int __init acpi_irq_penalty_init(void)
@@ -881,6 +870,17 @@ bool acpi_isa_irq_available(int irq)
 		    acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
 }
 
+void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
+{
+	sci_irq = irq;
+
+	if (trigger == ACPI_MADT_TRIGGER_LEVEL &&
+	    polarity == ACPI_MADT_POLARITY_ACTIVE_LOW)
+		sci_penalty = PIRQ_PENALTY_PCI_USING;
+	else
+		sci_penalty = PIRQ_PENALTY_ISA_ALWAYS;
+}
+
 /*
  * Over-ride default table to reserve additional IRQs for use by ISA
  * e.g. acpi_irq_isa=5
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index c5eaf2f..67d1d3e 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -318,6 +318,7 @@ struct pci_dev;
 int acpi_pci_irq_enable (struct pci_dev *dev);
 void acpi_penalize_isa_irq(int irq, int active);
 bool acpi_isa_irq_available(int irq);
+void acpi_penalize_sci_irq(int irq, int trigger, int polarity);
 void acpi_pci_irq_disable (struct pci_dev *dev);
 
 extern int ec_read(u8 addr, u8 *val);
-- 
1.9.1

^ permalink raw reply related

* [PATCH V4 1/3] ACPI, PCI, IRQ: assign ISA IRQ directly during early boot stages
From: Sinan Kaya @ 2016-10-19 22:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476915664-27231-1-git-send-email-okaya@codeaurora.org>

The penalty determination of ISA IRQ goes through 4 paths.
1. assign PCI_USING during power up via acpi_irq_penalty_init.
2. update the penalty with acpi_penalize_isa_irq function based on the
active parameter.
3. kernel command line penalty update via acpi_irq_penalty_update function.
4. increment the penalty as USING right after the IRQ is assign to PCI.

acpi_penalize_isa_irq and acpi_irq_penalty_update functions get called
before the ACPI subsystem is started.

These API need to bypass the acpi_irq_get_penalty function.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
 drivers/acpi/pci_link.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index c983bf7..4f37938 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -849,7 +849,7 @@ static int __init acpi_irq_penalty_update(char *str, int used)
 			continue;
 
 		if (used)
-			new_penalty = acpi_irq_get_penalty(irq) +
+			new_penalty = acpi_isa_irq_penalty[irq] +
 					PIRQ_PENALTY_ISA_USED;
 		else
 			new_penalty = 0;
@@ -871,7 +871,7 @@ static int __init acpi_irq_penalty_update(char *str, int used)
 void acpi_penalize_isa_irq(int irq, int active)
 {
 	if ((irq >= 0) && (irq < ARRAY_SIZE(acpi_isa_irq_penalty)))
-		acpi_isa_irq_penalty[irq] = acpi_irq_get_penalty(irq) +
+		acpi_isa_irq_penalty[irq] = acpi_isa_irq_penalty[irq] +
 		  (active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING);
 }
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH V4 0/3] ACPI, PCI, IRQ: revert penalty calculation for ISA and SCI interrupts
From: Sinan Kaya @ 2016-10-19 22:21 UTC (permalink / raw)
  To: linux-arm-kernel

By the time ACPI gets initialized, this code tries to determine an
IRQ number based on penalty values in this array. It will try to locate
the IRQ with the least penalty assignment so that interrupt sharing is
avoided if possible.

A couple of notes about the external APIs:
1. These API can be called before the ACPI is started. Therefore, one
cannot assume that the PCI link objects are initialized for calculating
penalties.
2. The polarity and trigger information passed via the
acpi_penalize_sci_irq from the BIOS may not match what the IRQ subsystem
is reporting as the call might have been placed before the IRQ is
registered by the interrupt subsystem.

The reverted changes were in the direction to remove these external API and
try to calculate the penalties at runtime for the ISA, SCI as well as PCI
IRQS.
This didn't work out well with the existing platforms.

V4:
* Drop ACPI, PCI IRQ: add PCI_USING penalty for ISA interrupts
* A new patch to isolate early boot ISA penalty calculations from dynamic
penalty calculation by directly modifying the array members in
("ACPI, PCI, IRQ: assign ISA IRQ directly during early boot stages")
* Now that we isolated both SCI and ISA interrupts, revert commit ("Revert
"ACPI,PCI,IRQ: separate ISA penalty calculation"") and commit
("487cf917ed0d
(Revert "ACPI, PCI, IRQ: remove redundant code in acpi_irq_penalty_init()")
to share code between ISA and PCI penalties as originally intended.

V3:
http://www.spinics.net/lists/arm-kernel/msg536208.html
* drop patch #1 as discussed with Bjorn
* add patch #3 to track SCI irq and penalty separately

V2: https://lkml.org/lkml/2016/10/1/106
* Commit message updates

V1:
http://lists-archives.com/linux-kernel/28673954-revert-acpi-pci-irq-reduce-static-irq-array-size-to-16.html
* initial implementation

Sinan Kaya (3):
  ACPI, PCI, IRQ: assign ISA IRQ directly during early boot stages
  Revert "ACPI,PCI,IRQ: remove SCI penalize function"
  Revert "ACPI,PCI,IRQ: separate ISA penalty calculation"

 arch/x86/kernel/acpi/boot.c |  1 +
 arch/x86/pci/acpi.c         |  1 -
 drivers/acpi/pci_link.c     | 72 ++++++++++++---------------------------------
 include/acpi/acpi_drivers.h |  1 -
 include/linux/acpi.h        |  1 +
 5 files changed, 21 insertions(+), 55 deletions(-)

-- 
1.9.1

^ permalink raw reply

* [PATCH] perf tools: Removing miscellaneous debug output
From: Mathieu Poirier @ 2016-10-19 21:42 UTC (permalink / raw)
  To: linux-arm-kernel

Printing the full path of the selected link is obviously not needed,
hence removing.

Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
 tools/perf/arch/arm/util/cs-etm.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
index 47d584da5819..dfea6b635525 100644
--- a/tools/perf/arch/arm/util/cs-etm.c
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -575,8 +575,6 @@ static FILE *cs_device__open_file(const char *name)
 	snprintf(path, PATH_MAX,
 		 "%s" CS_BUS_DEVICE_PATH "%s", sysfs, name);
 
-	printf("path: %s\n", path);
-
 	if (stat(path, &st) < 0)
 		return NULL;
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH 0/5] Switch to the DT cpufreq policy on the Integrator
From: Rafael J. Wysocki @ 2016-10-19 21:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476871154-32243-1-git-send-email-linus.walleij@linaro.org>

On Wednesday, October 19, 2016 11:59:09 AM Linus Walleij wrote:
> This switches the ARM Integrator/AP and Integrator/CP to use the
> Device Tree cpufreq policy with its definition of operating points
> using the generic OPP library.
> 
> The Integrators does not need to control a regulator to switch
> frequency, only a clock. This clock and its device tree bindings
> have been defined in the device tree and merged upstream for v4.9.
> 
> This approach provides a little better granularity on the
> Integrator/AP where I defined a few operating points: before
> this change the Integrator would just switch between min speed
> (12 MHz) and max speed (71 MHz). Now it can switch between a
> few arbitrarily chosen OPPs as in the examples below:
> 
> The following tests were made on the Integrator/AP:
> 
> /sys/devices/system/cpu/cpufreq/policy0 echo ondemand > scaling_governor
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 71000000 Hz --> 24000000 Hz
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 24000000 Hz --> 12000000 Hz
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 12000000 Hz --> 24000000 Hz
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 24000000 Hz --> 12000000 Hz
> 
> The switch from 12 to 24 MHz is triggered by as little as using the
> command line with the ondemand governor. If we do this:
> 
> yes > /dev/null &
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 12000000 Hz --> 36000000 Hz
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 36000000 Hz --> 71000000 Hz
> pkill yes
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 71000000 Hz --> 12000000 Hz
> 
> So the algorithm is indeed using all the OPPs.
> 
> Also as a confirmation test to make sure performance is affected by the
> speed changes, we set the performance governor and:
> 
> echo 12000 > scaling_max_freq
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 71000000 Hz --> 12000000 Hz
> time find /sys|sort|uniq > /dev/null
> real    0m 45.51s
> user    0m 11.15s
> sys     0m 26.74s
> 
> echo 71000 > scaling_max_freq
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 12000000 Hz --> 71000000 Hz
> time find /sys|sort|uniq
>  > /dev/null
> real    0m 9.13s
> user    0m 2.35s
> sys     0m 5.50s
> 
> So it is working.
> 
> If people are happy with this approach and approve of the patches
> I'd like an ACK from the cpufreq people and then merge the whole set
> through ARM SoC.
> 
> Linus Walleij (5):
>   cpufreq: enable the DT cpufreq driver on the Integrators
>   ARM: dts: Add Integrator/AP cpus node and operating points
>   ARM: dts: Add Integrator/CP cpus node and operating points
>   ARM: defconfig: turn on the DT cpufreq for Integrator
>   cpufreq: retire the Integrator cpufreq driver

The cpufreq changes look good to me, but Viresh is the expert for the DT stuff.

Thanks,
Rafael

^ permalink raw reply

* [PATCH 4/4] PM / devfreq: exynos-ppmu: Fix module autoload
From: Javier Martinez Canillas @ 2016-10-19 21:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476911187-11040-1-git-send-email-javier@osg.samsung.com>

If the driver is built as a module, autoload won't work because the module
alias information is not filled. So user-space can't match the registered
device with the corresponding module.

Export the module alias information using the MODULE_DEVICE_TABLE() macro.

Before this patch:

$ modinfo drivers/devfreq/event/exynos-ppmu.ko | grep alias
$

After this patch:

$ modinfo drivers/devfreq/event/exynos-ppmu.ko | grep alias
alias:          of:N*T*Csamsung,exynos-ppmu-v2C*
alias:          of:N*T*Csamsung,exynos-ppmu-v2
alias:          of:N*T*Csamsung,exynos-ppmuC*
alias:          of:N*T*Csamsung,exynos-ppmu

Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>

---

 drivers/devfreq/event/exynos-ppmu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c
index f55cf0eb2a66..a112034997eb 100644
--- a/drivers/devfreq/event/exynos-ppmu.c
+++ b/drivers/devfreq/event/exynos-ppmu.c
@@ -351,6 +351,7 @@ static const struct of_device_id exynos_ppmu_id_match[] = {
 	},
 	{ /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, exynos_ppmu_id_match);
 
 static struct devfreq_event_ops *exynos_bus_get_ops(struct device_node *np)
 {
-- 
2.7.4

^ permalink raw reply related

* [PATCH 3/4] PM / devfreq: rockchip-dfi: Fix module autoload
From: Javier Martinez Canillas @ 2016-10-19 21:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476911187-11040-1-git-send-email-javier@osg.samsung.com>

If the driver is built as a module, autoload won't work because the module
alias information is not filled. So user-space can't match the registered
device with the corresponding module.

Export the module alias information using the MODULE_DEVICE_TABLE() macro.

Before this patch:

$ modinfo drivers/devfreq/event/rockchip-dfi.ko | grep alias
$

After this patch:

$ modinfo drivers/devfreq/event/rockchip-dfi.ko | grep alias
alias:          of:N*T*Crockchip,rk3399-dfiC*
alias:          of:N*T*Crockchip,rk3399-dfi

Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
---

 drivers/devfreq/event/rockchip-dfi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c
index 43fcc5a7f515..22b113363ffc 100644
--- a/drivers/devfreq/event/rockchip-dfi.c
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -188,6 +188,7 @@ static const struct of_device_id rockchip_dfi_id_match[] = {
 	{ .compatible = "rockchip,rk3399-dfi" },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match);
 
 static int rockchip_dfi_probe(struct platform_device *pdev)
 {
-- 
2.7.4

^ permalink raw reply related

* [PATCH 2/4] PM / devfreq: exynos-nocp: Fix module autoload
From: Javier Martinez Canillas @ 2016-10-19 21:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476911187-11040-1-git-send-email-javier@osg.samsung.com>

If the driver is built as a module, autoload won't work because the module
alias information is not filled. So user-space can't match the registered
device with the corresponding module.

Export the module alias information using the MODULE_DEVICE_TABLE() macro.

Before this patch:

$ modinfo drivers/devfreq/event/exynos-nocp.ko | grep alias
$

After this patch:

$ modinfo drivers/devfreq/event/exynos-nocp.ko | grep alias
alias:          of:N*T*Csamsung,exynos5420-nocpC*
alias:          of:N*T*Csamsung,exynos5420-nocp

Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
---

 drivers/devfreq/event/exynos-nocp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/devfreq/event/exynos-nocp.c b/drivers/devfreq/event/exynos-nocp.c
index 49e712aca0c1..5c3e7b11e8a6 100644
--- a/drivers/devfreq/event/exynos-nocp.c
+++ b/drivers/devfreq/event/exynos-nocp.c
@@ -190,6 +190,7 @@ static const struct of_device_id exynos_nocp_id_match[] = {
 	{ .compatible = "samsung,exynos5420-nocp", },
 	{ /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, exynos_nocp_id_match);
 
 static struct regmap_config exynos_nocp_regmap_config = {
 	.reg_bits = 32,
-- 
2.7.4

^ permalink raw reply related

* [PATCH 0/4] PM / devfreq: Fix module autoload for platform drivers
From: Javier Martinez Canillas @ 2016-10-19 21:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

I noticed that module autoload won't be working in some of the defreq
platform drivers. This patch series contains the fixes for these.

Best regards,
Javier


Javier Martinez Canillas (4):
  PM / devfreq: rk3399_dmc: Fix module autoload
  PM / devfreq: exynos-nocp: Fix module autoload
  PM / devfreq: rockchip-dfi: Fix module autoload
  PM / devfreq: exynos-ppmu: Fix module autoload

 drivers/devfreq/event/exynos-nocp.c  | 1 +
 drivers/devfreq/event/exynos-ppmu.c  | 1 +
 drivers/devfreq/event/rockchip-dfi.c | 1 +
 drivers/devfreq/rk3399_dmc.c         | 1 +
 4 files changed, 4 insertions(+)

-- 
2.7.4

^ permalink raw reply

* [PATCH] Revert "gpio/mvebu: convert to use irq_domain_add_simple()"
From: Jason Gunthorpe @ 2016-10-19 21:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <871szcerxl.fsf@free-electrons.com>

On Wed, Oct 19, 2016 at 09:09:10AM +0200, Gregory CLEMENT wrote:
>  On mer., oct. 19 2016, Jason Gunthorpe <jgunthorpe@obsidianresearch.com> wrote:
> 
> > This reverts commit ce931f571b6dcf8534e8740e8cd16565cf362536.
> >
> > The only difference betwen _simple and _legacy is that _simple
> > calls irq_alloc_descs, however mvebu_gpio_probe already called
> > irq_alloc_descs a few lines above.
> 
> And what about removing the irq_alloc_descs ?

I didn't think I had a test system for that complex work, but it turns
out I do..

> Going back to use the _legacy version seems wrong for me.

Both _legacy and _simple are described as deprecated, and using
_simple is clearly the wrong choice for this driver, so I can't see
how it is 'wrong' to go back.

But it is legit to ask if the driver can be converted to use the
modern style for setting up irq domains, so here is a patch that does
that instead.

I was only able to test LEVEL interrupts, but I think both kinds
should be OK.

>From 7566f05ac445b652ba7607cc1899fed10fea1c76 Mon Sep 17 00:00:00 2001
From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Date: Wed, 19 Oct 2016 14:57:45 -0600
Subject: [PATCH] gpio/mvebu: Use irq_domain_add_linear

This fixes the irq allocation in this driver to not print:
 irq: Cannot allocate irq_descs @ IRQ34, assuming pre-allocated
 irq: Cannot allocate irq_descs @ IRQ66, assuming pre-allocated

Which happens because the driver already called irq_alloc_descs()
and so the change to use irq_domain_add_simple resulted in calling
irq_alloc_descs() twice.

Modernize the irq allocation in this driver to use the
irq_domain_add_linear flow directly and eliminate the use of
irq_domain_add_simple/legacy

Fixes: ce931f571b6d ("gpio/mvebu: convert to use irq_domain_add_simple()")
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
 drivers/gpio/gpio-mvebu.c | 92 ++++++++++++++++++++++-------------------------
 1 file changed, 43 insertions(+), 49 deletions(-)

diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index cd5dc27320a2..1ed6132b993c 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -293,10 +293,10 @@ static void mvebu_gpio_irq_ack(struct irq_data *d)
 {
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
 	struct mvebu_gpio_chip *mvchip = gc->private;
-	u32 mask = ~(1 << (d->irq - gc->irq_base));
+	u32 mask = d->mask;
 
 	irq_gc_lock(gc);
-	writel_relaxed(mask, mvebu_gpioreg_edge_cause(mvchip));
+	writel_relaxed(~mask, mvebu_gpioreg_edge_cause(mvchip));
 	irq_gc_unlock(gc);
 }
 
@@ -305,7 +305,7 @@ static void mvebu_gpio_edge_irq_mask(struct irq_data *d)
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
 	struct mvebu_gpio_chip *mvchip = gc->private;
 	struct irq_chip_type *ct = irq_data_get_chip_type(d);
-	u32 mask = 1 << (d->irq - gc->irq_base);
+	u32 mask = d->mask;
 
 	irq_gc_lock(gc);
 	ct->mask_cache_priv &= ~mask;
@@ -319,8 +319,7 @@ static void mvebu_gpio_edge_irq_unmask(struct irq_data *d)
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
 	struct mvebu_gpio_chip *mvchip = gc->private;
 	struct irq_chip_type *ct = irq_data_get_chip_type(d);
-
-	u32 mask = 1 << (d->irq - gc->irq_base);
+	u32 mask = d->mask;
 
 	irq_gc_lock(gc);
 	ct->mask_cache_priv |= mask;
@@ -333,8 +332,7 @@ static void mvebu_gpio_level_irq_mask(struct irq_data *d)
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
 	struct mvebu_gpio_chip *mvchip = gc->private;
 	struct irq_chip_type *ct = irq_data_get_chip_type(d);
-
-	u32 mask = 1 << (d->irq - gc->irq_base);
+	u32 mask = d->mask;
 
 	irq_gc_lock(gc);
 	ct->mask_cache_priv &= ~mask;
@@ -347,8 +345,7 @@ static void mvebu_gpio_level_irq_unmask(struct irq_data *d)
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
 	struct mvebu_gpio_chip *mvchip = gc->private;
 	struct irq_chip_type *ct = irq_data_get_chip_type(d);
-
-	u32 mask = 1 << (d->irq - gc->irq_base);
+	u32 mask = d->mask;
 
 	irq_gc_lock(gc);
 	ct->mask_cache_priv |= mask;
@@ -462,7 +459,7 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
 	for (i = 0; i < mvchip->chip.ngpio; i++) {
 		int irq;
 
-		irq = mvchip->irqbase + i;
+		irq = irq_find_mapping(mvchip->domain, i);
 
 		if (!(cause & (1 << i)))
 			continue;
@@ -655,6 +652,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 	struct irq_chip_type *ct;
 	struct clk *clk;
 	unsigned int ngpios;
+	bool have_irqs;
 	int soc_variant;
 	int i, cpu, id;
 	int err;
@@ -665,6 +663,9 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 	else
 		soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
 
+	/* Some gpio controllers do not provide irq support */
+	have_irqs = of_irq_count(np) != 0;
+
 	mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip),
 			      GFP_KERNEL);
 	if (!mvchip)
@@ -697,7 +698,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 	mvchip->chip.get = mvebu_gpio_get;
 	mvchip->chip.direction_output = mvebu_gpio_direction_output;
 	mvchip->chip.set = mvebu_gpio_set;
-	mvchip->chip.to_irq = mvebu_gpio_to_irq;
+	if (have_irqs)
+		mvchip->chip.to_irq = mvebu_gpio_to_irq;
 	mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK;
 	mvchip->chip.ngpio = ngpios;
 	mvchip->chip.can_sleep = false;
@@ -758,34 +760,30 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 	devm_gpiochip_add_data(&pdev->dev, &mvchip->chip, mvchip);
 
 	/* Some gpio controllers do not provide irq support */
-	if (!of_irq_count(np))
+	if (!have_irqs)
 		return 0;
 
-	/* Setup the interrupt handlers. Each chip can have up to 4
-	 * interrupt handlers, with each handler dealing with 8 GPIO
-	 * pins. */
-	for (i = 0; i < 4; i++) {
-		int irq = platform_get_irq(pdev, i);
-
-		if (irq < 0)
-			continue;
-		irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler,
-						 mvchip);
-	}
-
-	mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);
-	if (mvchip->irqbase < 0) {
-		dev_err(&pdev->dev, "no irqs\n");
-		return mvchip->irqbase;
+	mvchip->domain =
+	    irq_domain_add_linear(np, ngpios, &irq_generic_chip_ops, NULL);
+	if (!mvchip->domain) {
+		dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
+			mvchip->chip.label);
+		return -ENODEV;
 	}
 
-	gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase,
-				    mvchip->membase, handle_level_irq);
-	if (!gc) {
-		dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n");
-		return -ENOMEM;
+	err = irq_alloc_domain_generic_chips(
+	    mvchip->domain, ngpios, 2, np->name, handle_level_irq,
+	    IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0);
+	if (err) {
+		dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n",
+			mvchip->chip.label);
+		goto err_domain;
 	}
 
+	/* NOTE: The common accessors cannot be used because of the percpu
+	 * access to the mask registers
+	 */
+	gc = irq_get_domain_generic_chip(mvchip->domain, 0);
 	gc->private = mvchip;
 	ct = &gc->chip_types[0];
 	ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
@@ -803,27 +801,23 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 	ct->handler = handle_edge_irq;
 	ct->chip.name = mvchip->chip.label;
 
-	irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,
-			       IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
+	/* Setup the interrupt handlers. Each chip can have up to 4
+	 * interrupt handlers, with each handler dealing with 8 GPIO
+	 * pins.
+	 */
+	for (i = 0; i < 4; i++) {
+		int irq = platform_get_irq(pdev, i);
 
-	/* Setup irq domain on top of the generic chip. */
-	mvchip->domain = irq_domain_add_simple(np, mvchip->chip.ngpio,
-					       mvchip->irqbase,
-					       &irq_domain_simple_ops,
-					       mvchip);
-	if (!mvchip->domain) {
-		dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
-			mvchip->chip.label);
-		err = -ENODEV;
-		goto err_generic_chip;
+		if (irq < 0)
+			continue;
+		irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler,
+						 mvchip);
 	}
 
 	return 0;
 
-err_generic_chip:
-	irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST,
-				IRQ_LEVEL | IRQ_NOPROBE);
-	kfree(gc);
+err_domain:
+	irq_domain_remove(mvchip->domain);
 
 	return err;
 }
-- 
2.1.4

^ permalink raw reply related

* [PATCH] ARM: dts: socfpga: Enable QSPI on the Arria5 devkit
From: dinguyen at opensource.altera.com @ 2016-10-19 20:52 UTC (permalink / raw)
  To: linux-arm-kernel

From: Dinh Nguyen <dinguyen@opensource.altera.com>

Enable the QSPI node and add the flash chip.

Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
---
 arch/arm/boot/dts/socfpga_arria5_socdk.dts |   33 ++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/arch/arm/boot/dts/socfpga_arria5_socdk.dts b/arch/arm/boot/dts/socfpga_arria5_socdk.dts
index 3c88678..f739ead 100644
--- a/arch/arm/boot/dts/socfpga_arria5_socdk.dts
+++ b/arch/arm/boot/dts/socfpga_arria5_socdk.dts
@@ -82,6 +82,39 @@
 	status = "okay";
 };
 
+&qspi {
+	status = "okay";
+
+	flash: flash at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "n25q256a";
+		reg = <0>;
+		spi-max-frequency = <100000000>;
+
+		m25p,fast-read;
+		cdns,page-size = <256>;
+		cdns,block-size = <16>;
+		cdns,read-delay = <4>;
+		cdns,tshsl-ns = <50>;
+		cdns,tsd2d-ns = <50>;
+		cdns,tchsh-ns = <4>;
+		cdns,tslch-ns = <4>;
+
+		partition at qspi-boot {
+			/* 8MB for raw data. */
+			label = "Flash 0 Raw Data";
+			reg = <0x0 0x800000>;
+		};
+
+		partition at qspi-rootfs {
+			/* 120MB for jffs2 data. */
+			label = "Flash 0 jffs2 Filesystem";
+			reg = <0x800000 0x7800000>;
+		};
+	};
+};
+
 &usb1 {
 	status = "okay";
 };
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 4/6] clk: stm32f4: Add RTC clock
From: Stephen Boyd @ 2016-10-19 20:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476436699-21879-5-git-send-email-gabriel.fernandez@st.com>

On 10/14, gabriel.fernandez at st.com wrote:
> @@ -310,6 +310,15 @@ static inline void enable_power_domain_write_protection(void)
>  	regmap_update_bits(pdrm, 0x00, (1 << 8), (0 << 8));
>  }
>  
> +static inline void sofware_reset_backup_domain(void)
> +{
> +	unsigned long val;
> +
> +	val = readl(base + STM32F4_RCC_BDCR);
> +	writel(val |= (1 << 16), base + STM32F4_RCC_BDCR);

Interesting C style here! Why set the bit in val that will then
be cleared in the next function call? Please just don't do it. It
would be better to do writel(val | BIT(16), ...)

> +	writel(val & ~(1 << 16), base + STM32F4_RCC_BDCR);
> +}
> +
>  struct stm32_rgate {
>  	struct	clk_hw hw;
>  	struct	clk_gate gate;
> @@ -396,6 +405,113 @@ static struct clk_hw *clk_register_rgate(struct device *dev, const char *name,
>  	return hw;
>  }
>  
> +static int cclk_gate_enable(struct clk_hw *hw)
> +{
> +	int ret;
> +
> +	disable_power_domain_write_protection();
> +
> +	ret = clk_gate_ops.enable(hw);
> +
> +	enable_power_domain_write_protection();
> +
> +	return ret;
> +}
> +
> +static void cclk_gate_disable(struct clk_hw *hw)
> +{
> +	disable_power_domain_write_protection();
> +
> +	clk_gate_ops.disable(hw);
> +
> +	enable_power_domain_write_protection();
> +}
> +
> +static int cclk_gate_is_enabled(struct clk_hw *hw)
> +{
> +	return clk_gate_ops.is_enabled(hw);
> +}
> +
> +static const struct clk_ops cclk_gate_ops = {
> +	.enable		= cclk_gate_enable,
> +	.disable	= cclk_gate_disable,
> +	.is_enabled	= cclk_gate_is_enabled,
> +};
> +
> +static u8 cclk_mux_get_parent(struct clk_hw *hw)
> +{
> +	return clk_mux_ops.get_parent(hw);
> +}
> +
> +

Weird double newline here. Please remove one.

> +static int cclk_mux_set_parent(struct clk_hw *hw, u8 index)
> +{
> +	int ret;
> +
> +	disable_power_domain_write_protection();
> +
> +	sofware_reset_backup_domain();
> +
> +	ret = clk_mux_ops.set_parent(hw, index);
> +
> +	enable_power_domain_write_protection();
> +
> +	return ret;
> +}
> +
> +

Same.

> +static const struct clk_ops cclk_mux_ops = {
> +	.get_parent = cclk_mux_get_parent,
> +	.set_parent = cclk_mux_set_parent,
> +};
> +
> +static struct clk_hw *stm32_register_cclk(struct device *dev, const char *name,
> +		const char * const *parent_names, int num_parents,
> +		void __iomem *reg, u8 bit_idx, u8 shift, unsigned long flags,
> +		spinlock_t *lock)
> +{
> +	struct clk_hw *hw;
> +	struct clk_gate *gate;
> +	struct clk_mux *mux;
> +
> +	gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);

sizeof(*gate) please.

> +	if (!gate) {
> +		hw = ERR_PTR(-EINVAL);
> +		goto fail;
> +	}
> +
> +	mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);

sizeof(*mux) please.

> +	if (!mux) {
> +		kfree(gate);
> +		hw = ERR_PTR(-EINVAL);
> +		goto fail;
> +	}
> +

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH RESEND] ARM: AM43XX: Select OMAP_INTERCONNECT in Kconfig
From: Dave Gerlach @ 2016-10-19 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

AM437x makes use of the omap_l3_noc driver so explicitly select
OMAP_INTERCONNECT in the Kconfig for SOC_AM43XX to ensure it gets enabled
for AM43XX only builds.

Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
This was supposed to be picked up for v4.7 [1] but doesn't seem to have
ever been merged, maybe it was missed? Here it is again, rebased
on v4.9-rc1.

[1] http://www.spinics.net/lists/linux-omap/msg129708.html

 arch/arm/mach-omap2/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index a9afeebd59f2..0465338183c7 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -71,6 +71,7 @@ config SOC_AM43XX
 	select HAVE_ARM_TWD
 	select ARM_ERRATA_754322
 	select ARM_ERRATA_775420
+	select OMAP_INTERCONNECT
 
 config SOC_DRA7XX
 	bool "TI DRA7XX"
-- 
2.9.3

^ permalink raw reply related

* [PATCH 1/2] efi: add support for seeding the RNG from a UEFI config table
From: Ard Biesheuvel @ 2016-10-19 20:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAGXu5jKx5cvZsBwC1AJZ3Q4CCn-nxD3Jejs5irQLRan+j305Cw@mail.gmail.com>


> On 19 Oct 2016, at 21:20, Kees Cook <keescook@chromium.org> wrote:
> 
> On Wed, Oct 19, 2016 at 1:18 PM, Ard Biesheuvel
> <ard.biesheuvel@linaro.org> wrote:
>> On 19 October 2016 at 21:14, Kees Cook <keescook@chromium.org> wrote:
>>>> On Wed, Oct 19, 2016 at 4:22 AM, Matt Fleming <matt@codeblueprint.co.uk> wrote:
>>>>> On Wed, 19 Oct, at 12:13:55PM, Ard Biesheuvel wrote:
>>>>>> On 19 October 2016 at 12:09, Mark Rutland <mark.rutland@arm.com> wrote:
>>>>>> 
>>>>>> I think to some extent this mush be treated as an ABI, given cases like
>>>>>> kexec.
>>>>>> 
>>>>> 
>>>>> Perhaps, yes. That would also allow GRUB or other EFI aware
>>>>> bootloaders to generate the seed.
>>>> 
>>>> If we're going to go down this route, we should try and get the GUID
>>>> into the UEFI spec.
>>> 
>>> It seems like maybe under UEFI, both this table (which sounds like
>>> it'll not be rotated regularly)
>> 
>> What do you mean 'rotated'? It is generated at boot. My 2/2 patch
>> generates it from the stub using the EFI_RNG_PROTOCOL on ARM/arm64
> 
> Oh! I entirely misunderstood. I thought doing regular writes to EFI
> variables was discouraged (since they may be stored in NVRAM that
> would "wear out")

Uefi config tables only live in memory. They are used to provide the os with data that the firmware generates at boot, e.g., smbios and acpi tables etc

>>> could be mixed with calls to
>>> EFI_PROTOCOL_RNG by the kernel? (Similar to how kaslr is seeded?)
>>> 
>> 
>> That is kind of the point. KASLR is different because we need the
>> entropy before even jumping to C code, but for all other uses of early
>> entropy, this seemed like a useful approach
> 
> Yup, cool. If the table changes per boot, yeah, my suggestion is pointless. :)
> 

Yes, but as Mark pointed out, we need to decide how to handle kexec, which does not go through the stub

^ permalink raw reply

* [PATCH v2 4/4] ARM: keystone: Drop PM domain support for k2g
From: Dave Gerlach @ 2016-10-19 20:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161019203347.17893-1-d-gerlach@ti.com>

K2G will use a different power domain driver than the rest of the
keystone family in order to make use of the TI SCI protocol so prevent
the standard keystone pm_domain code from registering itself in
preparation for a new driver.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 arch/arm/mach-keystone/pm_domain.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-keystone/pm_domain.c b/arch/arm/mach-keystone/pm_domain.c
index 8cbb35765a19..fe57e2692629 100644
--- a/arch/arm/mach-keystone/pm_domain.c
+++ b/arch/arm/mach-keystone/pm_domain.c
@@ -32,7 +32,9 @@ static struct pm_clk_notifier_block platform_domain_notifier = {
 };
 
 static const struct of_device_id of_keystone_table[] = {
-	{.compatible = "ti,keystone"},
+	{.compatible = "ti,k2hk"},
+	{.compatible = "ti,k2e"},
+	{.compatible = "ti,k2l"},
 	{ /* end of list */ },
 };
 
-- 
2.9.3

^ permalink raw reply related

* [PATCH v2 3/4] soc: ti: Add ti_sci_pm_domains driver
From: Dave Gerlach @ 2016-10-19 20:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161019203347.17893-1-d-gerlach@ti.com>

Introduce a ti_sci_pm_domains driver to act as a generic pm domain provider
to allow each device to attach and associate it's ti-sci-id so that it can
be controlled through the TI SCI protocol.

This driver implements a simple genpd where each device node has
a phandle to the power domain node and also must provide an index which
represents the ID to be passed with TI SCI representing the device using a
ti,sci-id property. Through this interface the genpd dev_ops start and
stop hooks will use TI SCI to turn on and off each device as determined
by pm_runtime usage.

Signed-off-by: Keerthy <j-keerthy@ti.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 MAINTAINERS                        |   1 +
 arch/arm/mach-keystone/Kconfig     |   1 +
 drivers/soc/ti/Kconfig             |  12 +++
 drivers/soc/ti/Makefile            |   1 +
 drivers/soc/ti/ti_sci_pm_domains.c | 198 +++++++++++++++++++++++++++++++++++++
 5 files changed, 213 insertions(+)
 create mode 100644 drivers/soc/ti/ti_sci_pm_domains.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d894873c2bff..3eaac5ede847 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11894,6 +11894,7 @@ F:	drivers/firmware/ti_sci*
 F:	include/linux/soc/ti/ti_sci_protocol.h
 F:	Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
 F:	include/dt-bindings/genpd/k2g.h
+F:	drivers/soc/ti/ti_sci_pm_domains.c
 
 THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER
 M:	Hans Verkuil <hverkuil@xs4all.nl>
diff --git a/arch/arm/mach-keystone/Kconfig b/arch/arm/mach-keystone/Kconfig
index 24bd64dabdfc..18d49465cafb 100644
--- a/arch/arm/mach-keystone/Kconfig
+++ b/arch/arm/mach-keystone/Kconfig
@@ -9,6 +9,7 @@ config ARCH_KEYSTONE
 	select ARCH_SUPPORTS_BIG_ENDIAN
 	select ZONE_DMA if ARM_LPAE
 	select PINCTRL
+	select PM_GENERIC_DOMAINS if PM
 	help
 	  Support for boards based on the Texas Instruments Keystone family of
 	  SoCs.
diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig
index 3557c5e32a93..39e152abe6b9 100644
--- a/drivers/soc/ti/Kconfig
+++ b/drivers/soc/ti/Kconfig
@@ -38,4 +38,16 @@ config WKUP_M3_IPC
 	  to communicate and use the Wakeup M3 for PM features like suspend
 	  resume and boots it using wkup_m3_rproc driver.
 
+config TI_SCI_PM_DOMAINS
+	tristate "TI SCI PM Domains Driver"
+	depends on TI_SCI_PROTOCOL
+	depends on PM_GENERIC_DOMAINS
+	help
+	  Generic power domain implementation for TI device implementing
+	  the TI SCI protocol.
+
+	  To compile this as a module, choose M here. The module will be
+	  called ti_sci_pm_domains. Note this is needed early in boot before
+	  rootfs may be available.
+
 endif # SOC_TI
diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile
index 48ff3a79634f..7d572736c86e 100644
--- a/drivers/soc/ti/Makefile
+++ b/drivers/soc/ti/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS)	+= knav_qmss.o
 knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o
 obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA)	+= knav_dma.o
 obj-$(CONFIG_WKUP_M3_IPC)		+= wkup_m3_ipc.o
+obj-$(CONFIG_TI_SCI_PM_DOMAINS)		+= ti_sci_pm_domains.o
diff --git a/drivers/soc/ti/ti_sci_pm_domains.c b/drivers/soc/ti/ti_sci_pm_domains.c
new file mode 100644
index 000000000000..ec76215d64c7
--- /dev/null
+++ b/drivers/soc/ti/ti_sci_pm_domains.c
@@ -0,0 +1,198 @@
+/*
+ * TI SCI Generic Power Domain Driver
+ *
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *	J Keerthy <j-keerthy@ti.com>
+ *	Dave Gerlach <d-gerlach@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+
+/**
+ * struct ti_sci_genpd_dev_data: holds data needed for every device attached
+ *				 to this genpd
+ * @idx: index of the device that identifies it with the system
+ *	 control processor.
+ */
+struct ti_sci_genpd_dev_data {
+	int idx;
+};
+
+/**
+ * struct ti_sci_pm_domain: TI specific data needed for power domain
+ * @ti_sci: handle to TI SCI protocol driver that provides ops to
+ *	    communicate with system control processor.
+ * @dev: pointer to dev for the driver for devm allocs
+ * @pd: generic_pm_domain for use with the genpd framework
+ */
+struct ti_sci_pm_domain {
+	const struct ti_sci_handle *ti_sci;
+	struct device *dev;
+	struct generic_pm_domain pd;
+};
+
+#define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd)
+
+/**
+ * ti_sci_dev_id(): get prepopulated ti_sci id from struct dev
+ * @dev: pointer to device associated with this genpd
+ *
+ * Returns device_id stored from ti,sci_id property
+ */
+static int ti_sci_dev_id(struct device *dev)
+{
+	struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
+	struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
+
+	return sci_dev_data->idx;
+}
+
+/**
+ * ti_sci_dev_to_sci_handle(): get pointer to ti_sci_handle
+ * @dev: pointer to device associated with this genpd
+ *
+ * Returns ti_sci_handle to be used to communicate with system
+ *	   control processor.
+ */
+static const struct ti_sci_handle *ti_sci_dev_to_sci_handle(struct device *dev)
+{
+	struct generic_pm_domain *pd = pd_to_genpd(dev->pm_domain);
+	struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(pd);
+
+	return ti_sci_genpd->ti_sci;
+}
+
+/**
+ * ti_sci_dev_start(): genpd device start hook called to turn device on
+ * @dev: pointer to device associated with this genpd to be powered on
+ */
+static int ti_sci_dev_start(struct device *dev)
+{
+	const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev);
+	int idx = ti_sci_dev_id(dev);
+
+	return ti_sci->ops.dev_ops.get_device(ti_sci, idx);
+}
+
+/**
+ * ti_sci_dev_stop(): genpd device stop hook called to turn device off
+ * @dev: pointer to device associated with this genpd to be powered off
+ */
+static int ti_sci_dev_stop(struct device *dev)
+{
+	const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev);
+	int idx = ti_sci_dev_id(dev);
+
+	return ti_sci->ops.dev_ops.put_device(ti_sci, idx);
+}
+
+static int ti_sci_pd_attach_dev(struct generic_pm_domain *domain,
+				struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(domain);
+	const struct ti_sci_handle *ti_sci = ti_sci_genpd->ti_sci;
+	struct ti_sci_genpd_dev_data *sci_dev_data;
+	struct generic_pm_domain_data *genpd_data;
+	int idx, ret = 0;
+
+	ret = of_property_read_u32(np, "ti,sci-id", &idx);
+	if (ret) {
+		dev_err(ti_sci_genpd->dev, "Cannot find ti,sci-id for %s\n",
+			dev_name(dev));
+		return -ENODEV;
+	}
+
+	/*
+	 * Check the validity of the requested idx, if the index is not valid
+	 * the PMMC will return a NAK here and we will not allocate it.
+	 */
+	ret = ti_sci->ops.dev_ops.is_valid(ti_sci, idx);
+	if (ret)
+		return -EINVAL;
+
+	sci_dev_data = kzalloc(sizeof(*sci_dev_data), GFP_KERNEL);
+	if (!sci_dev_data)
+		return -ENOMEM;
+
+	sci_dev_data->idx = idx;
+
+	genpd_data = dev_gpd_data(dev);
+	genpd_data->data = sci_dev_data;
+
+	return 0;
+}
+
+static void ti_sci_pd_detach_dev(struct generic_pm_domain *domain,
+				 struct device *dev)
+{
+	struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
+	struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
+
+	kfree(sci_dev_data);
+	genpd_data->data = NULL;
+}
+
+static const struct of_device_id ti_sci_pm_domain_matches[] = {
+	{ .compatible = "ti,sci-pm-domain", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ti_sci_pm_domain_matches);
+
+static int ti_sci_pm_domain_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct ti_sci_pm_domain *ti_sci_pd;
+	int ret;
+
+	ti_sci_pd = devm_kzalloc(dev, sizeof(*ti_sci_pd), GFP_KERNEL);
+	if (!ti_sci_pd)
+		return -ENOMEM;
+
+	ti_sci_pd->ti_sci = devm_ti_sci_get_handle(dev);
+	if (IS_ERR(ti_sci_pd->ti_sci))
+		return PTR_ERR(ti_sci_pd->ti_sci);
+
+	ti_sci_pd->dev = dev;
+
+	ti_sci_pd->pd.attach_dev = ti_sci_pd_attach_dev;
+	ti_sci_pd->pd.detach_dev = ti_sci_pd_detach_dev;
+
+	ti_sci_pd->pd.dev_ops.start = ti_sci_dev_start;
+	ti_sci_pd->pd.dev_ops.stop = ti_sci_dev_stop;
+
+	pm_genpd_init(&ti_sci_pd->pd, NULL, true);
+
+	ret = of_genpd_add_provider_simple(np, &ti_sci_pd->pd);
+
+	return ret;
+}
+
+static struct platform_driver ti_sci_pm_domains_driver = {
+	.probe = ti_sci_pm_domain_probe,
+	.driver = {
+		.name = "ti_sci_pm_domains",
+		.of_match_table = ti_sci_pm_domain_matches,
+	},
+};
+module_platform_driver(ti_sci_pm_domains_driver);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TI System Control Interface (SCI) Power Domain driver");
+MODULE_AUTHOR("Dave Gerlach");
-- 
2.9.3

^ permalink raw reply related

* [PATCH v2 2/4] dt-bindings: Add TI SCI PM Domains
From: Dave Gerlach @ 2016-10-19 20:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161019203347.17893-1-d-gerlach@ti.com>

Add a generic power domain implementation, TI SCI PM Domains, that
will hook into the genpd framework and allow the TI SCI protocol to
control device power states.

Also, provide macros representing each device index as understood
by TI SCI to be used in the device node power-domain references.
These are identifiers for the K2G devices managed by the PMMC.

Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 .../devicetree/bindings/soc/ti/sci-pm-domain.txt   | 54 +++++++++++++
 MAINTAINERS                                        |  2 +
 include/dt-bindings/genpd/k2g.h                    | 90 ++++++++++++++++++++++
 3 files changed, 146 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
 create mode 100644 include/dt-bindings/genpd/k2g.h

diff --git a/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
new file mode 100644
index 000000000000..32f38a349656
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
@@ -0,0 +1,54 @@
+Texas Instruments TI-SCI Generic Power Domain
+---------------------------------------------
+
+Some TI SoCs contain a system controller (like the PMMC, etc...) that is
+responsible for controlling the state of the IPs that are present.
+Communication between the host processor running an OS and the system
+controller happens through a protocol known as TI-SCI [1]. This pm domain
+implementation plugs into the generic pm domain framework and makes use of
+the TI SCI protocol power on and off each device when needed.
+
+[1] Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
+
+PM Domain Node
+==============
+The PM domain node represents the global PM domain managed by the PMMC,
+which in this case is the single implementation as documented by the generic
+PM domain bindings in Documentation/devicetree/bindings/power/power_domain.txt.
+
+Required Properties:
+--------------------
+- compatible: should be "ti,sci-pm-domain"
+- #power-domain-cells: Must be 0.
+- ti,sci: Phandle to the TI SCI device to use for managing the devices.
+
+Example:
+--------------------
+k2g_pds: k2g_pds {
+        compatible = "ti,sci-pm-domain";
+        #power-domain-cells = <0>;
+        ti,sci = <&pmmc>;
+};
+
+PM Domain Consumers
+===================
+Hardware blocks that require SCI control over their state must provide
+a reference to the sci-pm-domain they are part of and a unique device
+specific ID that identifies the device.
+
+Required Properties:
+--------------------
+- power-domains: phandle pointing to the corresponding PM domain node.
+- ti,sci-id: index representing the device id to be passed oevr SCI to
+	     be used for device control.
+
+See dt-bindings/genpd/k2g.h for the list of valid identifiers for k2g.
+
+Example:
+--------------------
+uart0: serial at 02530c00 {
+	compatible = "ns16550a";
+	...
+	power-domains = <&k2g_pds>;
+	ti,sci-id = <K2G_DEV_UART0>;
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 467b29fafaca..d894873c2bff 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11892,6 +11892,8 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
 F:	drivers/firmware/ti_sci*
 F:	include/linux/soc/ti/ti_sci_protocol.h
+F:	Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
+F:	include/dt-bindings/genpd/k2g.h
 
 THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER
 M:	Hans Verkuil <hverkuil@xs4all.nl>
diff --git a/include/dt-bindings/genpd/k2g.h b/include/dt-bindings/genpd/k2g.h
new file mode 100644
index 000000000000..91ad827e0ca1
--- /dev/null
+++ b/include/dt-bindings/genpd/k2g.h
@@ -0,0 +1,90 @@
+/*
+ * TI K2G SoC Device definitions
+ *
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_GENPD_K2G_H
+#define _DT_BINDINGS_GENPD_K2G_H
+
+/* Documented in http://processors.wiki.ti.com/index.php/TISCI */
+
+#define K2G_DEV_PMMC0			0x0000
+#define K2G_DEV_MLB0			0x0001
+#define K2G_DEV_DSS0			0x0002
+#define K2G_DEV_MCBSP0			0x0003
+#define K2G_DEV_MCASP0			0x0004
+#define K2G_DEV_MCASP1			0x0005
+#define K2G_DEV_MCASP2			0x0006
+#define K2G_DEV_DCAN0			0x0008
+#define K2G_DEV_DCAN1			0x0009
+#define K2G_DEV_EMIF0			0x000a
+#define K2G_DEV_MMCHS0			0x000b
+#define K2G_DEV_MMCHS1			0x000c
+#define K2G_DEV_GPMC0			0x000d
+#define K2G_DEV_ELM0			0x000e
+#define K2G_DEV_SPI0			0x0010
+#define K2G_DEV_SPI1			0x0011
+#define K2G_DEV_SPI2			0x0012
+#define K2G_DEV_SPI3			0x0013
+#define K2G_DEV_ICSS0			0x0014
+#define K2G_DEV_ICSS1			0x0015
+#define K2G_DEV_USB0			0x0016
+#define K2G_DEV_USB1			0x0017
+#define K2G_DEV_NSS0			0x0018
+#define K2G_DEV_PCIE0			0x0019
+#define K2G_DEV_GPIO0			0x001b
+#define K2G_DEV_GPIO1			0x001c
+#define K2G_DEV_TIMER64_0		0x001d
+#define K2G_DEV_TIMER64_1		0x001e
+#define K2G_DEV_TIMER64_2		0x001f
+#define K2G_DEV_TIMER64_3		0x0020
+#define K2G_DEV_TIMER64_4		0x0021
+#define K2G_DEV_TIMER64_5		0x0022
+#define K2G_DEV_TIMER64_6		0x0023
+#define K2G_DEV_MSGMGR0			0x0025
+#define K2G_DEV_BOOTCFG0		0x0026
+#define K2G_DEV_ARM_BOOTROM0		0x0027
+#define K2G_DEV_DSP_BOOTROM0		0x0029
+#define K2G_DEV_DEBUGSS0		0x002b
+#define K2G_DEV_UART0			0x002c
+#define K2G_DEV_UART1			0x002d
+#define K2G_DEV_UART2			0x002e
+#define K2G_DEV_EHRPWM0			0x002f
+#define K2G_DEV_EHRPWM1			0x0030
+#define K2G_DEV_EHRPWM2			0x0031
+#define K2G_DEV_EHRPWM3			0x0032
+#define K2G_DEV_EHRPWM4			0x0033
+#define K2G_DEV_EHRPWM5			0x0034
+#define K2G_DEV_EQEP0			0x0035
+#define K2G_DEV_EQEP1			0x0036
+#define K2G_DEV_EQEP2			0x0037
+#define K2G_DEV_ECAP0			0x0038
+#define K2G_DEV_ECAP1			0x0039
+#define K2G_DEV_I2C0			0x003a
+#define K2G_DEV_I2C1			0x003b
+#define K2G_DEV_I2C2			0x003c
+#define K2G_DEV_EDMA0			0x003f
+#define K2G_DEV_SEMAPHORE0		0x0040
+#define K2G_DEV_INTC0			0x0041
+#define K2G_DEV_GIC0			0x0042
+#define K2G_DEV_QSPI0			0x0043
+#define K2G_DEV_ARM_64B_COUNTER0	0x0044
+#define K2G_DEV_TETRIS0			0x0045
+#define K2G_DEV_CGEM0			0x0046
+#define K2G_DEV_MSMC0			0x0047
+#define K2G_DEV_CBASS0			0x0049
+#define K2G_DEV_BOARD0			0x004c
+#define K2G_DEV_EDMA1			0x004f
+
+#endif
-- 
2.9.3

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox