Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4/5] ARM: dts: exynos: add support for ISP power domain to exynos4x12 clocks device
From: Ulf Hansson @ 2016-09-15 14:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <6e52af56-8b0e-d8c4-62c2-6efeee0e912d@samsung.com>

[...]

>>> I see some serious design problems with multiple entries in power domains
>>> property. First how to show that some part of the device IS NOT in
>>> any domain?
>>
>> Is that even possible? Every device should be in some power
>> domain, even if it's just an "always on" power domain that we
>> don't really control from software.
>
>
> Right now none dts of which I'm aware of doesn't define the power domain for
> the parts of the SoC, which are always on and doesn't need any additional
> management.

Actually there's is one reason for doing this, as it would allow
devices to be monitored for device PM QoS constraints by the genpd
governor.

Although, I doubt's someone actually does it because of this benefit,
at least yet.

[...]

Kind regards
Uffe

^ permalink raw reply

* [RFC PATCH v2 05/11] ACPI: platform: setup MSI domain for ACPI based platform device
From: Hanjun Guo @ 2016-09-15 14:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <57D97087.5040703@arm.com>

Hi Marc,

Thanks for your review, reply inline.

On 09/14/2016 11:45 PM, Marc Zyngier wrote:
> On 14/09/16 15:21, Hanjun Guo wrote:
>> From: Hanjun Guo <hanjun.guo@linaro.org>
>>
>> With the platform msi domain created, we can set up the msi domain
>> for a platform device when it's probed.
>>
>> This patch introduces acpi_configure_msi_domain(), which retrieves
>> the domain from iort and set it to platform device.
>>
>> As some platform devices such as an irqchip needs the msi irqdomain
>> to be the interrupt parent domain, we need to get irqdomain before
>> platform device is probed.
>>
>> Cc: Marc Zyngier <marc.zyngier@arm.com>
>> Cc: Greg KH <gregkh@linuxfoundation.org>
>> Cc: Thomas Gleixner <tglx@linutronix.de>
>> Cc: Bjorn Helgaas <bhelgaas@google.com>
>> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Tomasz Nowicki <tn@semihalf.com>
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> ---
>>   drivers/acpi/arm64/iort.c   |  5 ++++-
>>   drivers/base/platform-msi.c | 15 ++++++++++++++-
>>   drivers/base/platform.c     |  2 ++
>>   include/linux/msi.h         |  1 +
>>   4 files changed, 21 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
>> index 13a1905..bccd3cc 100644
>> --- a/drivers/acpi/arm64/iort.c
>> +++ b/drivers/acpi/arm64/iort.c
>> @@ -478,6 +478,7 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id)
>>   {
>>   	struct fwnode_handle *handle;
>>   	int its_id;
>> +	enum irq_domain_bus_token bus_token;
>>
>>   	if (iort_dev_find_its_id(dev, req_id, 0, &its_id))
>>   		return NULL;
>> @@ -486,7 +487,9 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id)
>>   	if (!handle)
>>   		return NULL;
>>
>> -	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
>> +	bus_token = dev_is_pci(dev) ?
>> +			DOMAIN_BUS_PCI_MSI : DOMAIN_BUS_PLATFORM_MSI;
>> +	return irq_find_matching_fwnode(handle, bus_token);
>>   }
>>
>>   static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
>> diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
>> index 279e539..f6eae18 100644
>> --- a/drivers/base/platform-msi.c
>> +++ b/drivers/base/platform-msi.c
>> @@ -17,8 +17,8 @@
>>    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>    */
>>
>> +#include <linux/acpi_iort.h>
>>   #include <linux/device.h>
>> -#include <linux/idr.h>
>>   #include <linux/irq.h>
>>   #include <linux/irqdomain.h>
>>   #include <linux/msi.h>
>> @@ -416,3 +416,16 @@ int platform_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
>>
>>   	return err;
>>   }
>> +
>> +int acpi_configure_msi_domain(struct device *dev)
>> +{
>> +	struct irq_domain *d = NULL;
>> +
>> +	d = iort_get_device_domain(dev, 0);
>
> This looks completely wrong. Why RID 0? As far as I can see, 0 is not a
> special value, and could be something else.

You are right. I tried to reuse the API of get irqdomain in IORT for
PCI devices, but for platform device, we don't have req id in named
component, so I just pass 0 here, I think I need to prepare another
API for platform devices.

>
>> +	if (d) {
>> +		dev_set_msi_domain(dev, d);
>> +		return 0;
>> +	}
>> +
>> +	return -EINVAL;
>> +}
>
> I really hate this, as the platform MSI code is intentionally free of
> any firmware reference. This should live in the ACPI code.

Will do, I think locate it in iort.c is better.

>
>> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
>> index 6482d47..ea01a37 100644
>> --- a/drivers/base/platform.c
>> +++ b/drivers/base/platform.c
>> @@ -24,6 +24,7 @@
>>   #include <linux/pm_domain.h>
>>   #include <linux/idr.h>
>>   #include <linux/acpi.h>
>> +#include <linux/msi.h>
>>   #include <linux/clk/clk-conf.h>
>>   #include <linux/limits.h>
>>   #include <linux/property.h>
>> @@ -500,6 +501,7 @@ struct platform_device *platform_device_register_full(
>>   	pdev->dev.parent = pdevinfo->parent;
>>   	pdev->dev.fwnode = pdevinfo->fwnode;
>>
>> +	acpi_configure_msi_domain(&pdev->dev);
>
> It feels odd to put this in the generic code, while you could perfectly
> put the call into acpi_platform.c and keep the firmware stuff away from
> the generic code.

My feeling is the same, I'm still trying to find a new way to do it,
but I can't simply put that in acpi_platform.c, because

acpi_create_platform_device()
    platform_device_register_full()
	platform_device_alloc()  --> dev is alloced
         ...
         dev.fwnode  is set
	(I get the msi domain by the fwnode in acpi_configure_msi_domain)
         ...
         platform_device_add()  --> which the device is probed.

For devices like irqchip which needs the dev->msi_domain to be
set before it's really probed, because it needs the msi domain
to be the parent domain.

If I call the function in acpi_create_platform_device() before
platform_device_register_full(), we just can't set dev's msi
domain, but if call it after platform_device_register_full(),
the irqchip like mbigen will not get its parent domain...

DT is using another API for platform device probe, so has no
problems like I said above, any suggestions to do it right in
ACPI?

Thanks
Hanjun

^ permalink raw reply

* [PATCH 0/8] drm/rockchip: Flip wait clean-up
From: Sean Paul @ 2016-09-15 14:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473857701-9250-1-git-send-email-tfiga@chromium.org>

On Wed, Sep 14, 2016 at 8:54 AM, Tomasz Figa <tfiga@chromium.org> wrote:
> The display controller found on Rockchip SoCs supported by Rockchip DRM
> driver (VOP) is a bit problematic, because it does not provide hardware
> vblank counter. Because vblank interrupt is used to feed the software
> counter, the driver had custom code to wait for flip completion to avoid
> race between atomic flush and vblank interrupt handler.
>
> This, however, brought a different set of issues. In fact, even with the
> custom wait code, there is stil a race between the handler and driver
> state update (of the values used to compare with registers to determine
> if flip has completed). On top of that, legacy cursor updates are not
> implemented properly and have to wait for vblank to complete, which
> is against the API specification.
>
> This series attempts to clean up the driver from this custom waiting code,
> eliminating related races and bringing correct handling of legacy cursor
> plane. It also gives a nice effect of more than 100 lines of code removed.
>
> This is a forward port of patches from 4.4 kernel used by ChromiumOS and
> tested there. Even though the code base has not changed significantly, it
> would be nice if someone with proper testing environment could give them
> a try.
>
> Based on for-next branch of Sean Paul's dogwood tree:
> https://cgit.freedesktop.org/~seanpaul/dogwood/log/?h=for-next
> git://people.freedesktop.org/~seanpaul/dogwood
>

Thanks for the patches, Tomasz.

I'll queue them up in my rockchip for-next branch.

Sean



> Tomasz Figa (8):
>   drm/rockchip: Clear interrupt status bits before enabling
>   drm/rockchip: Get rid of some unnecessary code
>   drm/rockchip: Avoid race with vblank count increment
>   drm/rockchip: Unreference framebuffers from flip work
>   drm/rockchip: Replace custom wait_for_vblanks with helper
>   drm/rockchip: Do not enable vblank without event
>   drm/rockchip: Always signal event in next vblank after cfg_done
>   drm/rockchip: Kill vop_plane_state
>
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 -
>  drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |  64 +------
>  drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 247 +++++++++++-----------------
>  3 files changed, 95 insertions(+), 217 deletions(-)
>
> --
> 2.8.0.rc3.226.g39d4020
>

^ permalink raw reply

* [REGRESSION] BISECTED : ethernet gadget not working anymore on several atmel platforms
From: Alexandre Belloni @ 2016-09-15 13:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACQ1gAhUDq4G5Prjp0Fp2yY7++c3TNHuHZj=_st4JTVCLO1wRA@mail.gmail.com>

Hi,

On 15/09/2016 at 14:29:24 +0200, Richard Genoud wrote :
> Since:
> commit c32b5bcfa3c43a3c9bb59f65b5e76adb7384c4c8
> Author: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> Date:   Tue Jul 12 22:45:59 2016 +0200
> 
>     ARM: dts: at91: Fix USB endpoint nodes
> 
>     Endpoint nodes have a reg property. Add their mandatory unit-address.
> 
> Booting with an USB gadget configured as Ethernet gadget + RNDIS

Good catch, I seem to have forgotten a patch in that series. I4ll send
that shortly.

> Gives a warning:
> 
> On AT91SAM9x5 platform (g35) :
> g_ether gadget: high-speed config #1: CDC Ethernet (ECM)
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 1 at drivers/usb/gadget/udc/core.c:264
> usb_ep_queue+0x4c/0xec
> CPU: 0 PID: 1 Comm: swapper Not tainted 4.8.0-rc6-00071-gcc183ac148d0 #134
> Hardware name: Atmel AT91SAM9
> [<c000f164>] (unwind_backtrace) from [<c000d158>] (show_stack+0x20/0x24)
> [<c000d158>] (show_stack) from [<c01ba940>] (dump_stack+0x20/0x28)
> [<c01ba940>] (dump_stack) from [<c0017f30>] (__warn+0xe0/0x10c)
> [<c0017f30>] (__warn) from [<c001802c>] (warn_slowpath_null+0x30/0x38)
> [<c001802c>] (warn_slowpath_null) from [<c02cd78c>] (usb_ep_queue+0x4c/0xec)
> [<c02cd78c>] (usb_ep_queue) from [<c02d55b8>] (ecm_do_notify+0x134/0x150)
> [<c02d55b8>] (ecm_do_notify) from [<c02d5840>] (ecm_set_alt+0x14c/0x154)
> [<c02d5840>] (ecm_set_alt) from [<c02c9144>] (composite_setup+0xa2c/0x13c0)
> [<c02c9144>] (composite_setup) from [<c02d3a90>] (usba_udc_irq+0x888/0xb4c)
> [<c02d3a90>] (usba_udc_irq) from [<c00458a0>]
> (__handle_irq_event_percpu+0x74/0x1dc)
> [<c00458a0>] (__handle_irq_event_percpu) from [<c0045a34>]
> (handle_irq_event_percpu+0x2c/0x68)
> [<c0045a34>] (handle_irq_event_percpu) from [<c0045aa8>]
> (handle_irq_event+0x38/0x4c)
> [<c0045aa8>] (handle_irq_event) from [<c0048a94>]
> (handle_fasteoi_irq+0xa0/0x114)
> [<c0048a94>] (handle_fasteoi_irq) from [<c004512c>]
> (generic_handle_irq+0x28/0x38)
> [<c004512c>] (generic_handle_irq) from [<c00451cc>]
> (__handle_domain_irq+0x90/0xb8)
> [<c00451cc>] (__handle_domain_irq) from [<c0009450>] (aic_handle+0xb0/0xb8)
> [<c0009450>] (aic_handle) from [<c000dca8>] (__irq_svc+0x68/0x84)
> Exception stack(0xc788dc68 to 0xc788dcb0)
> dc60:                   00000151 000004f6 00000151 c7075b70 c89693b0 c8964000
> dc80: c79c7400 000060e8 c79aa000 c7bd55c0 00000023 c788dd3c c788dd00 c788dcb8
> dca0: c0319cc0 c0319cd4 80000013 ffffffff
> [<c000dca8>] (__irq_svc) from [<c0319cd4>] (ubi_attach_fastmap+0x858/0xcc8)
> [<c0319cd4>] (ubi_attach_fastmap) from [<c0278744>]
> (ubi_scan_fastmap+0x644/0x854)
> [<c0278744>] (ubi_scan_fastmap) from [<c027542c>] (scan_fast+0x10c/0x17c)
> [<c027542c>] (scan_fast) from [<c02757c0>] (ubi_attach+0xb0/0x21c)
> [<c02757c0>] (ubi_attach) from [<c0269520>] (ubi_attach_mtd_dev+0x320/0x820)
> [<c0269520>] (ubi_attach_mtd_dev) from [<c06b42d4>] (ubi_init+0x1a8/0x248)
> [<c06b42d4>] (ubi_init) from [<c0697df0>] (do_one_initcall+0xb4/0x16c)
> [<c0697df0>] (do_one_initcall) from [<c0697fb0>]
> (kernel_init_freeable+0x108/0x1d4)
> [<c0697fb0>] (kernel_init_freeable) from [<c04e3c84>] (kernel_init+0x18/0x100)
> [<c04e3c84>] (kernel_init) from [<c000a470>] (ret_from_fork+0x14/0x24)
> ---[ end trace 8150ab0dc38dec93 ]---
> 
> Same on SAMA5D3:
> g_ether gadget: high-speed config #1: CDC Ethernet (ECM)
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 0 at drivers/usb/gadget/udc/core.c:264
> usb_ep_queue+0x5c/0x64
> Modules linked in:
> CPU: 0 PID: 0 Comm: swapper Not tainted 4.8.0-rc6+ #135
> Hardware name: Atmel SAMA5
> [<c010ce70>] (unwind_backtrace) from [<c010a88c>] (show_stack+0x10/0x14)
> [<c010a88c>] (show_stack) from [<c0115bb0>] (__warn+0xe4/0xfc)
> [<c0115bb0>] (__warn) from [<c0115c78>] (warn_slowpath_null+0x20/0x28)
> [<c0115c78>] (warn_slowpath_null) from [<c03cc608>] (usb_ep_queue+0x5c/0x64)
> [<c03cc608>] (usb_ep_queue) from [<c03d1124>] (ecm_do_notify+0xec/0x14c)
> [<c03d1124>] (ecm_do_notify) from [<c03d130c>] (ecm_set_alt+0x74/0x150)
> [<c03d130c>] (ecm_set_alt) from [<c03c9364>] (composite_setup+0xb84/0x1570)
> [<c03c9364>] (composite_setup) from [<c03cf364>] (usba_udc_irq+0x878/0xd4c)
> [<c03cf364>] (usba_udc_irq) from [<c013f12c>]
> (__handle_irq_event_percpu+0x88/0x124)
> [<c013f12c>] (__handle_irq_event_percpu) from [<c013f1e4>]
> (handle_irq_event_percpu+0x1c/0x58)
> [<c013f1e4>] (handle_irq_event_percpu) from [<c013f248>]
> (handle_irq_event+0x28/0x3c)
> [<c013f248>] (handle_irq_event) from [<c0141c8c>]
> (handle_fasteoi_irq+0xa0/0x168)
> [<c0141c8c>] (handle_fasteoi_irq) from [<c013e87c>]
> (generic_handle_irq+0x24/0x34)
> [<c013e87c>] (generic_handle_irq) from [<c013ead8>]
> (__handle_domain_irq+0x54/0xa8)
> [<c013ead8>] (__handle_domain_irq) from [<c010b34c>] (__irq_svc+0x6c/0x90)
> [<c010b34c>] (__irq_svc) from [<c0130be4>] (finish_task_switch+0x4c/0x144)
> [<c0130be4>] (finish_task_switch) from [<c054b9d0>] (schedule+0x44/0x9c)
> [<c054b9d0>] (schedule) from [<c054bbd4>] (schedule_preempt_disabled+0xc/0x10)
> [<c054bbd4>] (schedule_preempt_disabled) from [<c01374b8>]
> (cpu_startup_entry+0x98/0xf4)
> [<c01374b8>] (cpu_startup_entry) from [<c0800c38>] (start_kernel+0x35c/0x368)
> [<c0800c38>] (start_kernel) from [<20008078>] (0x20008078)
> ---[ end trace 27b3e952067e1be6 ]---
> 
> And I guess it's the same on g45, 9rl, sama5d[2-4].
> 
> Bisect done with a 4.8-rc6 kernel.
> Here's the bisect log:
> git bisect start 'arch/arm/boot/dts/'
> # good: [882bd9fc46321c9d4721b376039a142cbfe8a17a] usb: gadget: udc:
> atmel: Also get regmap for at91sam9x5-pmc
> git bisect good 882bd9fc46321c9d4721b376039a142cbfe8a17a
> # bad: [694d0d0bb2030d2e36df73e2d23d5770511dbc8d] Linux 4.8-rc2
> git bisect bad 694d0d0bb2030d2e36df73e2d23d5770511dbc8d
> # good: [ab4b4340c7d74310a132cb457665bf3d98fdff79] Merge tag
> 'imx-dt-4.8' of
> git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into
> next/dt
> git bisect good ab4b4340c7d74310a132cb457665bf3d98fdff79
> # good: [349f9d5239c3dae3b984679fc9ee00b8deec542b] Merge tag
> 'sunxi-dt-for-4.8' of
> https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into
> next/dt
> git bisect good 349f9d5239c3dae3b984679fc9ee00b8deec542b
> # bad: [262a5d84b2aea8deb67eca813dc3008836330596] Merge tag
> 'sunxi-dt-for-4.8-2-bis' of
> https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into
> next/dt
> git bisect bad 262a5d84b2aea8deb67eca813dc3008836330596
> # good: [cda1c2bdf6df90c12363877fda594a0a1b7ac74a] Merge tag
> 'sti-late-v4.8' of
> git://git.kernel.org/pub/scm/linux/kernel/git/pchotard/sti into
> next/late
> git bisect good cda1c2bdf6df90c12363877fda594a0a1b7ac74a
> # good: [a0e4eb4b81b44663f21b289d8126ca6f6dc8a863] ARM: dts: sun8i:
> Use sun8i-reference-design-tablet for polaroid mid2809pxe04
> git bisect good a0e4eb4b81b44663f21b289d8126ca6f6dc8a863
> # bad: [d3c1c7181f55f3464529decad189f2317a2932da] ARM: dts: at91:
> vinco: fix regulator name
> git bisect bad d3c1c7181f55f3464529decad189f2317a2932da
> # bad: [a63f6a64cc1e78366382657cab70772240b6dcc2] ARM: dts: at91:
> sama5d3_xplained: fix regulator name
> git bisect bad a63f6a64cc1e78366382657cab70772240b6dcc2
> # bad: [c32b5bcfa3c43a3c9bb59f65b5e76adb7384c4c8] ARM: dts: at91: Fix
> USB endpoint nodes
> git bisect bad c32b5bcfa3c43a3c9bb59f65b5e76adb7384c4c8
> # good: [c94afa132b6d7f8e412a12da44da6203d2cd23d4] ARM: dts: at91: Fix
> ADC trigger nodes
> git bisect good c94afa132b6d7f8e412a12da44da6203d2cd23d4
> # first bad commit: [c32b5bcfa3c43a3c9bb59f65b5e76adb7384c4c8] ARM:
> dts: at91: Fix USB endpoint nodes
> 
> on xplained board, I used at91-sama5d3_xplained.dtb and sama5_defconfig plus :
> CONFIG_USB_ETH=y
> CONFIG_USB_ETH_RNDIS=y

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [RFC PATCH 8/8] arm64: split thread_info from task stack
From: Mark Rutland @ 2016-09-15 13:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473947349-14521-1-git-send-email-mark.rutland@arm.com>

This patch moves arm64's struct thread_info from the task stack into
task_struct. This protects thread_info from corruption in the case of
stack overflows, and makes its address harder to determine if stack
addresses are leaked, making a number of attacks more difficult. Precise
detection and handling of overflow is left for subsequent patches.

Largely, this involves changing code to store the task_struct in sp_el0,
and acquire the thread_info from the task struct (which is the opposite
way around to the current code). Both secondary entry and idle are
updated to stash the sp and task pointer separately.

Userspace clobbers sp_el0, and we can no longer restore this from the
stack. Instead, the current task is cached in a per-cpu variable that we
can safely access from early assembly as interrupts are disabled (and we
are thus not preemptible).

There remain opportunities for improvement. Currently we cannot remove
thread_info::cpu and always use task_struct::cpu, as this would result
in a circular include dependency for raw_smp_processor_id():

  <asm/smp.h> -> <linux/sched.h> -> <linux/smp.h> -> <asm/smp.h>

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: AKASHI Takahiro <takahiro.akashi@linaro.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/Kconfig                   |  2 ++
 arch/arm64/include/asm/Kbuild        |  1 -
 arch/arm64/include/asm/current.h     | 22 ++++++++++++++++++++++
 arch/arm64/include/asm/smp.h         |  1 +
 arch/arm64/include/asm/thread_info.h | 19 -------------------
 arch/arm64/kernel/asm-offsets.c      |  1 +
 arch/arm64/kernel/entry.S            |  4 ++--
 arch/arm64/kernel/head.S             | 11 +++++------
 arch/arm64/kernel/process.c          | 31 ++++++++++++++++++++++++++-----
 arch/arm64/kernel/smp.c              |  2 ++
 arch/arm64/kernel/stacktrace.c       |  5 +++++
 11 files changed, 66 insertions(+), 33 deletions(-)
 create mode 100644 arch/arm64/include/asm/current.h

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index bc3f00f..9f57318 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -11,6 +11,7 @@ config ARM64
 	select ARCH_HAS_GCOV_PROFILE_ALL
 	select ARCH_HAS_KCOV
 	select ARCH_HAS_SG_CHAIN
+	select ARCH_HAS_OWN_THREAD_INFO
 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
 	select ARCH_USE_CMPXCHG_LOCKREF
 	select ARCH_SUPPORTS_ATOMIC_RMW
@@ -110,6 +111,7 @@ config ARM64
 	select POWER_SUPPLY
 	select SPARSE_IRQ
 	select SYSCTL_EXCEPTION_TRACE
+	select THREAD_INFO_IN_TASK
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index f43d2c4..a716c6f 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -2,7 +2,6 @@ generic-y += bug.h
 generic-y += bugs.h
 generic-y += clkdev.h
 generic-y += cputime.h
-generic-y += current.h
 generic-y += delay.h
 generic-y += div64.h
 generic-y += dma.h
diff --git a/arch/arm64/include/asm/current.h b/arch/arm64/include/asm/current.h
new file mode 100644
index 0000000..f2bcbe2
--- /dev/null
+++ b/arch/arm64/include/asm/current.h
@@ -0,0 +1,22 @@
+#ifndef __ASM_CURRENT_H
+#define __ASM_CURRENT_H
+
+#include <linux/compiler.h>
+
+#include <asm/sysreg.h>
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+
+static __always_inline struct task_struct *get_current(void)
+{
+	return (struct task_struct *)read_sysreg(sp_el0);
+}
+
+#define current get_current()
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_CURRENT_H */
+
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 0226447..fef90c0 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -73,6 +73,7 @@ asmlinkage void secondary_start_kernel(void);
  */
 struct secondary_data {
 	void *stack;
+	struct task_struct *task;
 	long status;
 };
 
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 796af24..5b16b34 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -46,14 +46,12 @@ typedef unsigned long mm_segment_t;
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	mm_segment_t		addr_limit;	/* address limit */
-	struct task_struct	*task;		/* main task structure */
 	int			preempt_count;	/* 0 => preemptable, <0 => bug */
 	int			cpu;		/* cpu */
 };
 
 #define INIT_THREAD_INFO(tsk)						\
 {									\
-	.task		= &tsk,						\
 	.flags		= 0,						\
 	.preempt_count	= INIT_PREEMPT_COUNT,				\
 	.addr_limit	= KERNEL_DS,					\
@@ -66,23 +64,6 @@ struct thread_info {
  */
 register unsigned long current_stack_pointer asm ("sp");
 
-/*
- * how to get the thread information struct from C
- */
-static inline struct thread_info *current_thread_info(void) __attribute_const__;
-
-/*
- * struct thread_info can be accessed directly via sp_el0.
- */
-static inline struct thread_info *current_thread_info(void)
-{
-	unsigned long sp_el0;
-
-	asm ("mrs %0, sp_el0" : "=r" (sp_el0));
-
-	return (struct thread_info *)sp_el0;
-}
-
 #define thread_saved_pc(tsk)	\
 	((unsigned long)(tsk->thread.cpu_context.pc))
 #define thread_saved_sp(tsk)	\
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index ee764eb..242fe909 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -120,6 +120,7 @@ int main(void)
   DEFINE(TZ_DSTTIME,		offsetof(struct timezone, tz_dsttime));
   BLANK();
   DEFINE(CPU_BOOT_STACK,	offsetof(struct secondary_data, stack));
+  DEFINE(CPU_BOOT_TASK,		offsetof(struct secondary_data, task));
   BLANK();
 #ifdef CONFIG_KVM_ARM_HOST
   DEFINE(VCPU_CONTEXT,		offsetof(struct kvm_vcpu, arch.ctxt));
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 52b4241..f844e7f 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -123,6 +123,7 @@
 	 * Set sp_el0 to current thread_info.
 	 */
 	.if	\el == 0
+	ldr_this_cpu	tsk, __entry_task, x21
 	msr	sp_el0, tsk
 	.endif
 
@@ -680,8 +681,7 @@ ENTRY(cpu_switch_to)
 	ldp	x29, x9, [x8], #16
 	ldr	lr, [x8]
 	mov	sp, x9
-	and	x9, x9, #~(THREAD_SIZE - 1)
-	msr	sp_el0, x9
+	msr	sp_el0, x1
 	ret
 ENDPROC(cpu_switch_to)
 
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index b77f583..abc7330 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -433,8 +433,7 @@ __primary_switched:
 	dsb	ishst				// Make zero page visible to PTW
 
 	adr_l	sp, initial_sp, x4
-	mov	x4, sp
-	and	x4, x4, #~(THREAD_SIZE - 1)
+	adr_l	x4, init_task
 	msr	sp_el0, x4			// Save thread_info
 	str_l	x21, __fdt_pointer, x5		// Save FDT pointer
 
@@ -680,10 +679,10 @@ __secondary_switched:
 	isb
 
 	adr_l	x0, secondary_data
-	ldr	x0, [x0, #CPU_BOOT_STACK]	// get secondary_data.stack
-	mov	sp, x0
-	and	x0, x0, #~(THREAD_SIZE - 1)
-	msr	sp_el0, x0			// save thread_info
+	ldr	x1, [x0, #CPU_BOOT_STACK]	// get secondary_data.stack
+	mov	sp, x1
+	ldr	x2, [x0, #CPU_BOOT_TASK]
+	msr	sp_el0, x2
 	mov	x29, #0
 	b	secondary_start_kernel
 ENDPROC(__secondary_switched)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 6cd2612..e35043d 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -45,6 +45,7 @@
 #include <linux/personality.h>
 #include <linux/notifier.h>
 #include <trace/events/power.h>
+#include <linux/percpu.h>
 
 #include <asm/alternative.h>
 #include <asm/compat.h>
@@ -314,6 +315,17 @@ static void uao_thread_switch(struct task_struct *next)
 }
 
 /*
+ * We store our current task in sp_el0, which is clobbered by userspace. Keep a
+ * shadow copy so that we can restore this upon entry from userspace.
+ */
+DEFINE_PER_CPU(struct task_struct *, __entry_task) = &init_task;
+
+static void entry_task_switch(struct task_struct *next)
+{
+	__this_cpu_write(__entry_task, next);
+}
+
+/*
  * Thread switching.
  */
 struct task_struct *__switch_to(struct task_struct *prev,
@@ -325,6 +337,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
 	tls_thread_switch(next);
 	hw_breakpoint_thread_switch(next);
 	contextidr_thread_switch(next);
+	entry_task_switch(next);
 	uao_thread_switch(next);
 
 	/*
@@ -342,11 +355,14 @@ struct task_struct *__switch_to(struct task_struct *prev,
 unsigned long get_wchan(struct task_struct *p)
 {
 	struct stackframe frame;
-	unsigned long stack_page;
+	unsigned long stack_page, ret = 0;
 	int count = 0;
 	if (!p || p == current || p->state == TASK_RUNNING)
 		return 0;
 
+	if (!try_get_task_stack(p))
+		return 0;
+
 	frame.fp = thread_saved_fp(p);
 	frame.sp = thread_saved_sp(p);
 	frame.pc = thread_saved_pc(p);
@@ -358,11 +374,16 @@ unsigned long get_wchan(struct task_struct *p)
 		if (frame.sp < stack_page ||
 		    frame.sp >= stack_page + THREAD_SIZE ||
 		    unwind_frame(p, &frame))
-			return 0;
-		if (!in_sched_functions(frame.pc))
-			return frame.pc;
+			goto out;
+		if (!in_sched_functions(frame.pc)) {
+			ret = frame.pc;
+			goto out;
+		}
 	} while (count ++ < 16);
-	return 0;
+
+out:
+	put_task_stack(p);
+	return ret;
 }
 
 unsigned long arch_align_stack(unsigned long sp)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index d93d433..d84be9db 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -146,6 +146,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
 	 * We need to tell the secondary core where to find its stack and the
 	 * page tables.
 	 */
+	secondary_data.task = idle;
 	secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
 	update_cpu_boot_status(CPU_MMU_OFF);
 	__flush_dcache_area(&secondary_data, sizeof(secondary_data));
@@ -170,6 +171,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
 		pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
 	}
 
+	secondary_data.task = NULL;
 	secondary_data.stack = NULL;
 	status = READ_ONCE(secondary_data.status);
 	if (ret && status) {
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index d9751a4..4e0efe8 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -157,6 +157,9 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 	struct stack_trace_data data;
 	struct stackframe frame;
 
+	if (!try_get_task_stack(tsk))
+		return;
+
 	data.trace = trace;
 	data.skip = trace->skip;
 
@@ -178,6 +181,8 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 	walk_stackframe(tsk, &frame, save_trace, &data);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
+
+	put_task_stack(tsk);
 }
 
 void save_stack_trace(struct stack_trace *trace)
-- 
1.9.1

^ permalink raw reply related

* [RFC PATCH 7/8] arm64: move sp_el0 and tpidr_el1 into cpu_suspend_ctx
From: Mark Rutland @ 2016-09-15 13:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473947349-14521-1-git-send-email-mark.rutland@arm.com>

When returning from idle, we rely on the fact that thread_info lives at
the end of the kernel stack, and restore this by masking the saved stack
pointer. Subsequent patches will sever the relationship between the
stack and thread_info, and to cater for this we must save/restore sp_el0
explicitly, storing it in cpu_suspend_ctx.

As cpu_suspend_ctx must be doubleword aligned, this leaves us with an
extra slot in cpu_suspend_ctx. We can use this to save/restore tpidr_el1
in the same way, which simplifies the code, avoiding pointer chasing on
the restore path (as we no longer need to load thread_info::cpu followed
by the relevant slot in __per_cpu_offset based on this).

This patch stashes both registers in cpu_suspend_ctx.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/include/asm/suspend.h | 2 +-
 arch/arm64/kernel/sleep.S        | 3 ---
 arch/arm64/kernel/suspend.c      | 6 ------
 arch/arm64/mm/proc.S             | 6 ++++++
 4 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/suspend.h b/arch/arm64/include/asm/suspend.h
index 024d623..92d6a62 100644
--- a/arch/arm64/include/asm/suspend.h
+++ b/arch/arm64/include/asm/suspend.h
@@ -1,7 +1,7 @@
 #ifndef __ASM_SUSPEND_H
 #define __ASM_SUSPEND_H
 
-#define NR_CTX_REGS 10
+#define NR_CTX_REGS 12
 #define NR_CALLEE_SAVED_REGS 12
 
 /*
diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index ccf79d8..74e6e19 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -132,9 +132,6 @@ ENTRY(_cpu_resume)
 	/* load sp from context */
 	ldr	x2, [x0, #CPU_CTX_SP]
 	mov	sp, x2
-	/* save thread_info */
-	and	x2, x2, #~(THREAD_SIZE - 1)
-	msr	sp_el0, x2
 	/*
 	 * cpu_do_resume expects x0 to contain context address pointer
 	 */
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index b616e365..9c33a49 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -42,12 +42,6 @@ void notrace __cpu_suspend_exit(void)
 	cpu_uninstall_idmap();
 
 	/*
-	 * Restore per-cpu offset before any kernel
-	 * subsystem relying on it has a chance to run.
-	 */
-	set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
-
-	/*
 	 * Restore HW breakpoint registers to sane values
 	 * before debug exceptions are possibly reenabled
 	 * through local_dbg_restore.
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 5bb61de..0293db1 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -70,11 +70,14 @@ ENTRY(cpu_do_suspend)
 	mrs	x8, mdscr_el1
 	mrs	x9, oslsr_el1
 	mrs	x10, sctlr_el1
+	mrs	x11, tpidr_el1
+	mrs	x12, sp_el0
 	stp	x2, x3, [x0]
 	stp	x4, xzr, [x0, #16]
 	stp	x5, x6, [x0, #32]
 	stp	x7, x8, [x0, #48]
 	stp	x9, x10, [x0, #64]
+	stp	x11, x12, [x0, #80]
 	ret
 ENDPROC(cpu_do_suspend)
 
@@ -89,6 +92,7 @@ ENTRY(cpu_do_resume)
 	ldp	x6, x8, [x0, #32]
 	ldp	x9, x10, [x0, #48]
 	ldp	x11, x12, [x0, #64]
+	ldp	x13, x14, [x0, #80]
 	msr	tpidr_el0, x2
 	msr	tpidrro_el0, x3
 	msr	contextidr_el1, x4
@@ -102,6 +106,8 @@ ENTRY(cpu_do_resume)
 	msr	vbar_el1, x9
 	msr	mdscr_el1, x10
 	msr	sctlr_el1, x12
+	msr	tpidr_el1, x13
+	msr	sp_el0, x14
 	/*
 	 * Restore oslsr_el1 by writing oslar_el1
 	 */
-- 
1.9.1

^ permalink raw reply related

* [RFC PATCH 6/8] arm64: traps: use task_struct instead of thread_info
From: Mark Rutland @ 2016-09-15 13:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473947349-14521-1-git-send-email-mark.rutland@arm.com>

In arm64's die and __die routines we pass around a thread_info, and
subsequently use this to determine either the relevant task_struct, or
the end of the thread's stack. This will shortly become problematic when
we move the thread_info out of the thread's stack.

Instead, pass around the task_struct, and use the new end_of_stack
helper, which will work regardless of where thread_info is located.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/kernel/traps.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index e04f838..e9409a9 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -227,10 +227,9 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
 #endif
 #define S_SMP " SMP"
 
-static int __die(const char *str, int err, struct thread_info *thread,
+static int __die(const char *str, int err, struct task_struct *tsk,
 		 struct pt_regs *regs)
 {
-	struct task_struct *tsk = thread->task;
 	static int die_counter;
 	int ret;
 
@@ -245,7 +244,8 @@ static int __die(const char *str, int err, struct thread_info *thread,
 	print_modules();
 	__show_regs(regs);
 	pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n",
-		 TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
+		 TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk),
+		 end_of_stack(tsk));
 
 	if (!user_mode(regs)) {
 		dump_mem(KERN_EMERG, "Stack: ", regs->sp,
@@ -264,7 +264,7 @@ static DEFINE_RAW_SPINLOCK(die_lock);
  */
 void die(const char *str, struct pt_regs *regs, int err)
 {
-	struct thread_info *thread = current_thread_info();
+	struct task_struct *tsk = current;
 	int ret;
 
 	oops_enter();
@@ -272,9 +272,9 @@ void die(const char *str, struct pt_regs *regs, int err)
 	raw_spin_lock_irq(&die_lock);
 	console_verbose();
 	bust_spinlocks(1);
-	ret = __die(str, err, thread, regs);
+	ret = __die(str, err, tsk, regs);
 
-	if (regs && kexec_should_crash(thread->task))
+	if (regs && kexec_should_crash(tsk))
 		crash_kexec(regs);
 
 	bust_spinlocks(0);
-- 
1.9.1

^ permalink raw reply related

* [RFC PATCH 5/8] arm64: assembler: introduce ldr_this_cpu
From: Mark Rutland @ 2016-09-15 13:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473947349-14521-1-git-send-email-mark.rutland@arm.com>

Shortly we will want to load a percpu variable in the return from
userspace path. We can save an instruction by folding the addition of
the percpu offset into the load instruction, and this patch adds a new
helper to do so.

At the same time, we clean up this_cpu_ptr for consistency. As with
{adr,ldr,str}_l, we change the template to take the destination register
first, and name this dst. Secondly, we rename the macro to adr_this_cpu,
following the scheme of adr_l, and matching the newly added
ldr_this_cpu.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/include/asm/assembler.h | 19 +++++++++++++++----
 arch/arm64/kernel/entry.S          |  2 +-
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index d5025c6..265fd81 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -193,14 +193,25 @@ lr	.req	x30		// link register
 	.endm
 
 	/*
+	 * @dst: Result of per_cpu(sym, smp_processor_id())
 	 * @sym: The name of the per-cpu variable
-	 * @reg: Result of per_cpu(sym, smp_processor_id())
 	 * @tmp: scratch register
 	 */
-	.macro this_cpu_ptr, sym, reg, tmp
-	adr_l	\reg, \sym
+	.macro adr_this_cpu, dst, sym, tmp
+	adr_l	\dst, \sym
 	mrs	\tmp, tpidr_el1
-	add	\reg, \reg, \tmp
+	add	\dst, \dst, \tmp
+	.endm
+
+	/*
+	 * @dst: Result of READ_ONCE(per_cpu(sym, smp_processor_id()))
+	 * @sym: The name of the per-cpu variable
+	 * @tmp: scratch register
+	 */
+	.macro ldr_this_cpu dst, sym, tmp
+	adr_l	\dst, \sym
+	mrs	\tmp, tpidr_el1
+	ldr	\dst, [\dst, \tmp]
 	.endm
 
 /*
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 441420c..52b4241 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -206,7 +206,7 @@ alternative_endif
 	cmp	x25, tsk
 	b.ne	9998f
 
-	this_cpu_ptr irq_stack, x25, x26
+	adr_this_cpu x25, irq_stack, x26
 	mov	x26, #IRQ_STACK_START_SP
 	add	x26, x25, x26
 
-- 
1.9.1

^ permalink raw reply related

* [RFC PATCH 4/8] arm64: asm-offsets: remove unused definitions
From: Mark Rutland @ 2016-09-15 13:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473947349-14521-1-git-send-email-mark.rutland@arm.com>

Subsequent patches will move the thread_info::{task,cpu} fields, and the
current TI_{TASK,CPU} offset definitions are not used anywhere.

This patch removes the redundant definitions.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/kernel/asm-offsets.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 05070b7..ee764eb 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -38,8 +38,6 @@ int main(void)
   DEFINE(TI_FLAGS,		offsetof(struct thread_info, flags));
   DEFINE(TI_PREEMPT,		offsetof(struct thread_info, preempt_count));
   DEFINE(TI_ADDR_LIMIT,		offsetof(struct thread_info, addr_limit));
-  DEFINE(TI_TASK,		offsetof(struct thread_info, task));
-  DEFINE(TI_CPU,		offsetof(struct thread_info, cpu));
   BLANK();
   DEFINE(THREAD_CPU_CONTEXT,	offsetof(struct task_struct, thread.cpu_context));
   BLANK();
-- 
1.9.1

^ permalink raw reply related

* [RFC PATCH 3/8] arm64: thread_info remove stale items
From: Mark Rutland @ 2016-09-15 13:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473947349-14521-1-git-send-email-mark.rutland@arm.com>

We have a comment claiming __switch_to() cares about where cpu_context
is located relative to cpu_domain in thread_info. However arm64 has
never had a thread_info::cpu_domain field, and neither __switch_to nor
cpu_switch_to care where the cpu_context field is relative to others.

Additionally, the init_thread_info alias is never used anywhere in the
kernel, and will shortly become problematic when thread_info is moved
into task_struct.

This patch removes both.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/include/asm/thread_info.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index abd64bd..796af24 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -42,7 +42,6 @@ typedef unsigned long mm_segment_t;
 
 /*
  * low level task data that entry.S needs immediate access to.
- * __switch_to() assumes cpu_context follows immediately after cpu_domain.
  */
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
@@ -60,7 +59,6 @@ struct thread_info {
 	.addr_limit	= KERNEL_DS,					\
 }
 
-#define init_thread_info	(init_thread_union.thread_info)
 #define init_stack		(init_thread_union.stack)
 
 /*
-- 
1.9.1

^ permalink raw reply related

* [RFC PATCH 2/8] thread_info: allow custom in-task thread_info
From: Mark Rutland @ 2016-09-15 13:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473947349-14521-1-git-send-email-mark.rutland@arm.com>

Currently, task_struct is defined in <linux/sched.h>, which (indirectly)
pulls in a number of low-level arch headers such as <asm/preempt.h>
through a number of other headers. Thus, code and structures in these
headers can't rely on the definition of task_struct. Some of these
headers are necessary for the definition of task_struct, so moving
task_struct into its own header is insufficient tio avoid circular
includes.

With CONFIG_THREAD_INFO_IN_TASK, arch code needs to implement its own
get_current() for the generic get_thread_info(). To avoid header
dependency issues, this relies on thread_info being the first member of
task_struct. This can be used by low-level arch code, as it doesn't
depend on the definition of task_struct.

For architectures without preempt-safe this_cpu ops, some data required
by low-level arch code (e.g. preempt_count) has to be stored per-thread,
and for the reasons above, we cannot place this in task_struct (or
thread_struct, since we cannot know its offset from within task_struct).
The only practical location for these is thread_info.

This patch allows architectures with CONFIG_ARCH_HAS_OWN_THREAD_INFO to
define their own thread_info, avoiding the problems described above.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: linux-kernel at vger.kernel.org
---
 include/linux/thread_info.h | 3 ++-
 init/Kconfig                | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index d9622f7..7984f87 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -13,7 +13,8 @@
 struct timespec;
 struct compat_timespec;
 
-#ifdef CONFIG_THREAD_INFO_IN_TASK
+#if defined(CONFIG_THREAD_INFO_IN_TASK) && \
+    !defined(CONFIG_ARCH_HAS_OWN_THREAD_INFO)
 struct thread_info {
 	u32			flags;		/* low level flags */
 };
diff --git a/init/Kconfig b/init/Kconfig
index 3b9a47f..f812098 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -26,6 +26,9 @@ config IRQ_WORK
 config BUILDTIME_EXTABLE_SORT
 	bool
 
+config ARCH_HAS_OWN_THREAD_INFO
+	bool
+
 config THREAD_INFO_IN_TASK
 	bool
 	help
-- 
1.9.1

^ permalink raw reply related

* [RFC PATCH 1/8] thread_info: include <current.h> for THREAD_INFO_IN_TASK
From: Mark Rutland @ 2016-09-15 13:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473947349-14521-1-git-send-email-mark.rutland@arm.com>

When CONFIG_THREAD_INFO_IN_TASK is selected, the current_thread_info()
macro relies on current having been defined prior to its use. However,
not all users of current_thread_info() include <asm/current.h>, and thus
current is not guaranteed to be defined.

When CONFIG_THREAD_INFO_IN_TASK is not selected, it's possible that
get_current() / current are based upon current_thread_info(), and
<asm/current.h> includes <asm/thread_info.h>. Thus always including
<asm/current.h> would result in circular dependences on some platforms.

To ensure both cases work, this patch includes <asm/current.h>, but only
when CONFIG_THREAD_INFO_IN_TASK is selected.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: linux-kernel at vger.kernel.org
---
 include/linux/thread_info.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index cb0ed34..d9622f7 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -25,6 +25,7 @@ struct thread_info {
 #endif
 
 #ifdef CONFIG_THREAD_INFO_IN_TASK
+#include <asm/current.h>
 #define current_thread_info() ((struct thread_info *)current)
 #endif
 
-- 
1.9.1

^ permalink raw reply related

* [RFC PATCH 0/8] arm64: move thread_info off of the task stack
From: Mark Rutland @ 2016-09-15 13:49 UTC (permalink / raw)
  To: linux-arm-kernel

Building atop of Andy's work on x86 and generic code, these patches move
arm64's thread_info off of the stack and into task_struct. This protects
thread_info from corruption in the face of stack overflow, and serves as
a step towards fully robust stack overflow handling will be addressed by
subsequent patches.

In contrast to x86, we can't place some critical data such as
preempt_count in percpu variables, and we must store these in some
per-task location. This, compounded with the way headers are organised
conspires to require us to still define our own thread_info. I
understand that the longer term plan is to kill off thread_info
entirely, hence I'm sending this as an RFC so we can figure out if/how
we can achieve that.

These patches are based on Andy's x86/vmap_stack branch [1,2], and I've
pushed a copy to me arm64/ti-stack-split branch [3,4]. The result of
these patches boots happily on platforms within reach of my desk, but
has not seen much stressing so far.

Thanks,
Mark.

[1] git://git.kernel.org/pub/scm/linux/kernel/git/luto/linux.git x86/vmap_stack
[2] https://git.kernel.org/cgit/linux/kernel/git/luto/linux.git/log/?h=x86/vmap_stack
[3] git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git arm64/ti-stack-split
[4] https://git.kernel.org/cgit/linux/kernel/git/mark/linux.git/log/?h=arm64/ti-stack-split

Mark Rutland (8):
  thread_info: include <current.h> for THREAD_INFO_IN_TASK
  thread_info: allow custom in-task thread_info
  arm64: thread_info remove stale items
  arm64: asm-offsets: remove unused definitions
  arm64: assembler: introduce ldr_this_cpu
  arm64: traps: use task_struct instead of thread_info
  arm64: move sp_el0 and tpidr_el1 into cpu_suspend_ctx
  arm64: split thread_info from task stack

 arch/arm64/Kconfig                   |  2 ++
 arch/arm64/include/asm/Kbuild        |  1 -
 arch/arm64/include/asm/assembler.h   | 19 +++++++++++++++----
 arch/arm64/include/asm/current.h     | 22 ++++++++++++++++++++++
 arch/arm64/include/asm/smp.h         |  1 +
 arch/arm64/include/asm/suspend.h     |  2 +-
 arch/arm64/include/asm/thread_info.h | 21 ---------------------
 arch/arm64/kernel/asm-offsets.c      |  3 +--
 arch/arm64/kernel/entry.S            |  6 +++---
 arch/arm64/kernel/head.S             | 11 +++++------
 arch/arm64/kernel/process.c          | 31 ++++++++++++++++++++++++++-----
 arch/arm64/kernel/sleep.S            |  3 ---
 arch/arm64/kernel/smp.c              |  2 ++
 arch/arm64/kernel/stacktrace.c       |  5 +++++
 arch/arm64/kernel/suspend.c          |  6 ------
 arch/arm64/kernel/traps.c            | 12 ++++++------
 arch/arm64/mm/proc.S                 |  6 ++++++
 include/linux/thread_info.h          |  4 +++-
 init/Kconfig                         |  3 +++
 19 files changed, 101 insertions(+), 59 deletions(-)
 create mode 100644 arch/arm64/include/asm/current.h

-- 
1.9.1

^ permalink raw reply

* [PATCH] of/platform: Initialise dev->fwnode appropriately
From: Rob Herring @ 2016-09-15 13:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <38259ab3716da072fab37f06d034329244491c13.1473865096.git.robin.murphy@arm.com>

On Wed, Sep 14, 2016 at 04:01:24PM +0100, Robin Murphy wrote:
> Whilst we're some of the way towards a universal firmware property
> interface, drivers which deal with both OF and ACPI probing end up
> having to do things like this:
> 
>     dev->of_node ? &dev->of_node->fwnode : dev->fwnode
> 
> This seems unnecessary, when the OF code could instead simply fill in
> the device's fwnode when binding the of_node, and let the drivers use
> dev->fwnode either way. Let's give it a go and see what falls out.
> 
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
>  drivers/of/platform.c | 2 ++
>  1 file changed, 2 insertions(+)

I've applied this, but what about non-platform devices such as i2c?

Rob

^ permalink raw reply

* [PATCH v5 0/3] Add ZTE ZX296718 support
From: Arnd Bergmann @ 2016-09-15 13:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160913072146.GA7398@tiger>

On Tuesday, September 13, 2016 3:21:46 PM CEST Shawn Guo wrote:
> 
> Reviewed-by: Shawn Guo <shawnguo@kernel.org>
> 
> Arnd, Olof,
> 
> If you like, I can help collect ZTE DTS patches to reduce your
> maintenance burden, considering we have an established pull-request
> work flow and I get ZTE platform on hands to test patches.

Thanks, I think that would be a good idea. I was going to apply
the patches manually, but I'll just wait for you to forward
them to me.

Also thanks for your thorough reviews of the patch series!

	Arnd

^ permalink raw reply

* [RESEND PATCH] arm64: kgdb: fix single stepping
From: Jason Wessel @ 2016-09-15 13:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1429578793-3971-1-git-send-email-takahiro.akashi@linaro.org>

On 04/20/2015 08:13 PM, AKASHI Takahiro wrote:
> Jason,
>
> Could you please review my patch below?
> See also arm64 maintainer's comment:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/313712.html
>
> Thanks,
> -Takahiro AKASHI
>
> I tried to verify kgdb in vanilla kernel on fast model, but it seems that
> the single stepping with kgdb doesn't work correctly since its first
> appearance at v3.15.
>
> On v3.15, 'stepi' command after breaking the kernel at some breakpoint
> steps forward to the next instruction, but the succeeding 'stepi' never
> goes beyond that.
> On v3.16, 'stepi' moves forward and stops at the next instruction just
> after enable_dbg in el1_dbg, and never goes beyond that. This variance of
> behavior seems to come in with the following patch in v3.16:
>
>     commit 2a2830703a23 ("arm64: debug: avoid accessing mdscr_el1 on fault
>     paths where possible")
>
> This patch
> (1) moves kgdb_disable_single_step() from 'c' command handling to single
>     step handler.
>     This makes sure that single stepping gets effective at every 's' command.
>     Please note that, under the current implementation, single step bit in
>     spsr, which is cleared by the first single stepping, will not be set
>     again for the consecutive 's' commands because single step bit in mdscr
>     is still kept on (that is, kernel_active_single_step() in
>     kgdb_arch_handle_exception() is true).
> (2) re-implements kgdb_roundup_cpus() because the current implementation
>     enabled interrupts naively. See below.
> (3) removes 'enable_dbg' in el1_dbg.
>     Single step bit in mdscr is turned on in do_handle_exception()->
>     kgdb_handle_expection() before returning to debugged context, and if
>     debug exception is enabled in el1_dbg, we will see unexpected single-
>     stepping in el1_dbg.
>     Since v3.18, the following patch does the same:
>       commit 1059c6bf8534 ("arm64: debug: don't re-enable debug exceptions
>       on return from el1_dbg)
> (4) masks interrupts while single-stepping one instruction.
>     If an interrupt is caught during processing a single-stepping, debug
>     exception is unintentionally enabled by el1_irq's 'enable_dbg' before
>     returning to debugged context.
>     Thus, like in (2), we will see unexpected single-stepping in el1_irq.
>
> Basically (1) and (2) are for v3.15, (3) and (4) for v3.1[67].
>
> @@ -176,18 +183,14 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
>  		 * over and over again.
>  		 */
>  		kgdb_arch_update_addr(linux_regs, remcom_in_buffer);
> -		atomic_set(&kgdb_cpu_doing_single_step, -1);
> -		kgdb_single_step =  0;


This is a subtle change, but I assume it is what you intended?  All the CPUs will get released into the run state when exiting the kgdb exception handler.


> -
> -		/*
> -		 * Received continue command, disable single step
> -		 */
> -		if (kernel_active_single_step())
> -			kernel_disable_single_step();
>


I see why this is not needed above any more given that you have a function that cleans up the state on entry to the kgdb exception handler.

The rest of the patch is fine.

I added the patch to kgdb-next after fixing up the context since it no longer applied to the mainline ( https://git.kernel.org/cgit/linux/kernel/git/jwessel/kgdb.git/log/?h=kgdb-next).  If there is further discussion on the point above, another patch can be added, but it I am assuming this is the way you desire it to work as there are some other architectures that use the same behaviour.  I do not presently have any ARM64 hardware to validate this particular change.

I also added to the patch a "Cc: linux-stable <stable@vger.kernel.org>" so we can have this appear on some of the older kernels.


Thanks,
Jason.

^ permalink raw reply

* [GIT PULL] STi DT update for v4.9
From: Patrice Chotard @ 2016-09-15 13:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <ede2d2b6-7e0c-f31e-72bd-06aae5838327@st.com>


On 09/14/2016 03:15 PM, Patrice Chotard wrote:
> Hi Arnd, Kevin, Olof
> 
> PLease consider this next batch for v4.9
> 
> The following changes since commit ba5ba11906d5462993f5fd4e3da4d234505427a0:
> 
>   ARM: dts: STiH41x-b2020: Update gpio specifier (2016-09-02 15:15:14 +0200)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/pchotard/sti.git tags/sti-dt-for-v4.9-2
> 
> for you to fetch changes up to 443fd7c92f5a000796b02683157d17b2575450e1:
> 
>   ARM: DT: STi: stihxxx-b2120: Add DT nodes for STi audio card (2016-09-14 13:37:29 +0200)
> 
> ----------------------------------------------------------------
> STi dts update:
> 
> Update gpio-cells and gpio specifier for STiH415/416
> Add PWM capture support for STiH416 and STiH407 family
> Add USB3 support for B2260
> Add HVA support for STiH410
> Add clk_ignore_unused in bootargs of B2260
> Add Flexible Direct Memory Access (FDMA) support for STiH407 family
> Add internal audio codec IP spport for STiH407 family
> Add uniperif player/reader IP blocks for STiH407 family
> 
> ----------------------------------------------------------------
> Jean-Christophe Trotin (1):
>       ARM: dts: STiH410: Add hva dt nodes
> 
> Lee Jones (6):
>       ARM: dts: STiH407: Supply PWM Capture IRQ
>       ARM: dts: STiH407: Declare PWM Capture data lines via Pinctrl
>       ARM: dts: STiH416: Supply PWM Capture IRQs
>       ARM: dts: STiH416: Declare PWM Capture data lines via Pinctrl
>       ARM: dts: STiH416: Define PWM Capture clock
>       ARM: dts: STiH416: Define the number of PWM Capture channels
> 
> Patrice Chotard (7):
>       ARM: dts: STiH415-pinctrl: update gpio-cells to 2
>       ARM: dts: STiH416-pinctrl: update gpio-cells to 2
>       ARM: dts: STiHxxx-b2120: update gpio specifier
>       ARM: dts: STiH41x-b2000: update gpio specifier
>       ARM: dts: STiH416-b2020e: update gpio specifier
>       ARM: dts: STiH410-b2260: add USB3 node
>       ARM: dts: STiH410-b2260: add clk_ignore_unused in bootargs
> 
> Peter Griffin (8):
>       ARM: STi: DT: STiH407: Add FDMA driver dt nodes.
>       ARM: DT: STiH407: Add i2s_out pinctrl configuration
>       ARM: DT: STiH407: Add i2s_in pinctrl configuration
>       ARM: DT: STiH407: Add spdif_out pinctrl config
>       ARM: STi: DT: STiH407: Add sti-sasg-codec dt node
>       ARM: STi: DT: STiH407: Add uniperif player dt nodes
>       ARM: STi: DT: STiH407: Add uniperif reader dt nodes
>       ARM: DT: STi: stihxxx-b2120: Add DT nodes for STi audio card
> 
>  arch/arm/boot/dts/stih407-family.dtsi  | 168 +++++++++++++++++++++++++++++++++
>  arch/arm/boot/dts/stih407-pinctrl.dtsi |  58 ++++++++++++
>  arch/arm/boot/dts/stih410-b2260.dts    |   6 +-
>  arch/arm/boot/dts/stih410.dtsi         |  10 ++
>  arch/arm/boot/dts/stih415-pinctrl.dtsi |  54 +++++------
>  arch/arm/boot/dts/stih416-b2020e.dts   |   6 +-
>  arch/arm/boot/dts/stih416-pinctrl.dtsi |  65 +++++++------
>  arch/arm/boot/dts/stih416.dtsi         |   8 +-
>  arch/arm/boot/dts/stih41x-b2000.dtsi   |   5 +-
>  arch/arm/boot/dts/stihxxx-b2120.dtsi   |  51 +++++++++-
>  10 files changed, 362 insertions(+), 69 deletions(-)
> 

Hi Arnd

1) As you indicated on IRC, this pull request has been send after the 
11th September, it must be applied as well on arm-soc/for-next.

2) This morning we just had confirmation from Stephen Boyd that a 
STi clocks series will be applied as well. This series was submitted 
since a while for v4.8 but unfortunately, clock maintainers forgot to 
merge it and we missed v4.8 merge window.

It's important for us to get it in v4.9 which will support the 
new ST's 96Board. 
Will you accept the STi DT counterpart of this clocks series ? 
If yes, i have a STi clocks DT pull request to send (already ready, 
just to push the button ;-) )

Thanks

Patrice

^ permalink raw reply

* [PATCH 5/9] mtd: nand: Expose data interface for ONFI mode 0
From: Boris Brezillon @ 2016-09-15 12:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473928373-8680-6-git-send-email-s.hauer@pengutronix.de>

On Thu, 15 Sep 2016 10:32:49 +0200
Sascha Hauer <s.hauer@pengutronix.de> wrote:

> The nand layer will need ONFI mode 0 to use it as timing mode
> before and right after reset.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  drivers/mtd/nand/nand_timings.c | 11 +++++++++++
>  include/linux/mtd/nand.h        |  2 ++
>  2 files changed, 13 insertions(+)
> 
> diff --git a/drivers/mtd/nand/nand_timings.c b/drivers/mtd/nand/nand_timings.c
> index 608d098..9cdbc16 100644
> --- a/drivers/mtd/nand/nand_timings.c
> +++ b/drivers/mtd/nand/nand_timings.c
> @@ -297,3 +297,14 @@ int onfi_init_data_interface(struct nand_chip *chip,
>  
>  	return 0;
>  }
> +
> +/**
> + * nand_get_default_data_interface - [NAND Interface] Retrieve NAND
> + * data interface for mode 0. This is used as default timing after
> + * reset.
> + */
> +const struct nand_data_interface *nand_get_default_data_interface(void)
> +{
> +	return &onfi_sdr_timings[0];
> +}
> +EXPORT_SYMBOL(nand_get_default_data_interface);

You export nand_get_default_data_interface() here, but you don't export
onfi_init_data_interface().
None of these functions should be called from NAND controller drivers,
so they don't need to be exported. ITOH, the prototypes are public
(defined in nand.h), so nothing prevents a driver from calling these
functions.

I don't know what's the best solution here:
1/ Export both nand_get_default_data_interface() and
   onfi_init_data_interface()
2/ Do not export them, but keep their prototypes in nand.h with a
   comment saying that they should not be directly called by NAND
   controller drivers
3/ Removing the prototypes from nand.h and defining them in nand_base.c
   (or in a private header).

Brian, Richard, Sascha, any comments?

> diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
> index 7216f54..29ae324 100644
> --- a/include/linux/mtd/nand.h
> +++ b/include/linux/mtd/nand.h
> @@ -1146,6 +1146,8 @@ static inline int jedec_feature(struct nand_chip *chip)
>  
>  /* get timing characteristics from ONFI timing mode. */
>  const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode);
> +/* get data interface from ONFI timing mode 0, used after reset. */
> +const struct nand_data_interface *nand_get_default_data_interface(void);
>  
>  int nand_check_erased_ecc_chunk(void *data, int datalen,
>  				void *ecc, int ecclen,

^ permalink raw reply

* [GIT PULL] Greybus driver subsystem for 4.9-rc1
From: Mark Rutland @ 2016-09-15 12:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473940088.10230.65.camel@nexus-software.ie>

On Thu, Sep 15, 2016 at 12:48:08PM +0100, Bryan O'Donoghue wrote:
> On Thu, 2016-09-15 at 12:20 +0100, Mark Rutland wrote:
> > For example, you have absolutely no guarantee as to what backs
> > get_cycles(). Despite this, the code assumes that get_cycles() is
> > backed by something running at the frequency described in a
> > "google,greybus-frame-time-counter" node.
> > 
> > Even if this *happens* to match what some piece of arch code provides
> > today on some platform, it is in no way *guaranteed*.
> 
> That's the point though, if you declare "google,greybus-frame-time-
> counter" in your platform code - then you can use 'get_cycles()' in
> this manner

To be clear, *some* properties (and perhaps additional nodes) may need
to be in the DT, in order to capture the hardware property or
relationship that you are reliant upon.

However, the DT cannot possibly know anything about get_cycles(), as
get_cycles() is a kernel implementation details that's subject to
arbitrary change at any point in time, independent of the DT.

The "google,greybus-frame-time-counter" node, as it stands, does not
capture any relevant hardware detail, and does not belong in the DT.

> > Without a higher-level view of what you're trying to achieve, it's
> > not clear to me whether get_cycles() is the right interface.
> 
> I appreciate that.

Until that's clarified, we won't make any progress here.

Thanks,
Mark.

^ permalink raw reply

* [PATCH 0/7] mfd: Fix all W=1 warnings
From: Linus Walleij @ 2016-09-15 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160915104521.14286-1-lee.jones@linaro.org>

On Thu, Sep 15, 2016 at 12:45 PM, Lee Jones <lee.jones@linaro.org> wrote:

> It really is as simple as it sounds!
>
> Lee Jones (7):
>   mfd: max8997-irq: 'inline' should be at the beginning of the
>     declaration
>   mfd: ab8500-debugfs: Prevent initialised field from being over-written
>   mfd: db8500-prcmu: Remove unused *prcmu_set_ddr_opp() calls
>   mfd: ab8500-debugfs: Remove ab8500_dump_all_banks_to_mem()
>   mfd: ab8500-debugfs: Remove 'weak' function
>     suspend_test_wake_cause_interrupt_is_mine()
>   mfd: omap-usb-host: Return value is not 'const int'
>   mfd: cros_ec_spi: Remove unused variable 'request'

Acked-by: Linus Walleij <linus.walleij@linaro.org>

For all the ab8500 and db8500 stuff.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH v6 2/2] iio: adc: add support for Allwinner SoCs ADC
From: Quentin Schulz @ 2016-09-15 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473943444-23979-1-git-send-email-quentin.schulz@free-electrons.com>

The Allwinner SoCs all have an ADC that can also act as a touchscreen
controller and a thermal sensor. This patch adds the ADC driver which is
based on the MFD for the same SoCs ADC.

This also registers the thermal adc channel in the iio map array so
iio_hwmon could use it without modifying the Device Tree. This registers
the driver in the thermal framework.

This driver probes on three different platform_device_id to take into
account slight differences (registers bit and temperature computation)
between Allwinner SoCs ADCs.

Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Jonathan Cameron <jic23@kernel.org>
---

v6:
 - remove useless member (regs) from sun4i_gpadc_dev structure,
 - rename sun4i_gpadc_dev structure to sun4i_gpadc_iio,
 - remove regmap_update_bits used to disable hardware interrupts, it is already
 handled by devm functions,

v5:
 - correct mail address,
 - correct several typos,
 - move from const to static for sunxi_gpadc_chan_select functions,
 - rename soc_specific struct to gpadc_data,
 - rename soc_specific field to data in sun4i_gpadc_dev,
 - return error code from regmap_write in case of failure in read_raws,
 - share if condition in IIO_CHAN_INFO_RAW case,
 - add comment on why we use parent device for registering in thermal,
 - reordering remove function,

v4:
 - rename files and variables from sunxi* to sun4i*,
 - shorten sunxi_gpadc_soc_specific structure to soc_specific,
 - factorize sysfs ADC and temp read_raws,
 - use cached values when read_raw times out (except before a first value
   is gotten),
 - remove mutex locks and unlocks from runtime_pm functions,
 - factorize irq initializations,
 - initialize temp_data and fifo_data values to -1 (error value),
 - "impersonate" MFD to register in thermal framework,
 - deactivate hardware interrupts one by one when probe fails or when
   removing driver instead of blindly deactivating all hardware interrupts,
 - selects THERMAL_OF in Kconfig,

v3:
 - correct wrapping,
 - add comment about thermal sensor inner working,
 - move defines in mfd header,
 - use structure to define SoC specific registers or behaviour,
 - attach this structure to the device according to of_device_id of the
   platform device,
 - use new mutex instead of iio_dev mutex,
 - use atomic flags to avoid race between request_irq and disable_irq in
   probe,
 - switch from processed value to raw, offset and scale values for
   temperature ADC channel,
 - remove faulty sentinel in iio_chan_spec array,
 - add pm_runtime support,
 - register thermal sensor in thermal framework (forgotten since the
   beginning whereas it is present in current sun4i-ts driver),
 - remove useless ret variables to store return value of regmap_reads,
 - move comments on thermal sensor acquisition period in code instead of
   header,
 - adding goto label to unregister iio_map_array when failing to register
   iio_dev,

v2:
 - add SUNXI_GPADC_ prefixes for defines,
 - correct typo in Kconfig,
 - reorder alphabetically includes, makefile,
 - add license header,
 - fix architecture variations not being handled in interrupt handlers or
   read raw functions,
 - fix unability to return negative values from thermal sensor,
 - add gotos to reduce code repetition,
 - fix irq variable being unsigned int instead of int,
 - remove useless dev_err and dev_info,
 - deactivate all interrupts if probe fails,
 - fix iio_device_register on NULL variable,
 - deactivate ADC in the IP when probe fails or when removing driver,

 drivers/iio/adc/Kconfig           |  13 +
 drivers/iio/adc/Makefile          |   1 +
 drivers/iio/adc/sun4i-gpadc-iio.c | 522 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 536 insertions(+)
 create mode 100644 drivers/iio/adc/sun4i-gpadc-iio.c

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 25378c5..ea36a4f 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -384,6 +384,19 @@ config ROCKCHIP_SARADC
 	  To compile this driver as a module, choose M here: the
 	  module will be called rockchip_saradc.
 
+config SUN4I_GPADC
+	tristate "Support for the Allwinner SoCs GPADC"
+	depends on IIO
+	depends on MFD_SUN4I_GPADC
+	select THERMAL_OF
+	help
+	  Say yes here to build support for Allwinner (A10, A13 and A31) SoCs
+	  GPADC. This ADC provides 4 channels which can be used as an ADC or as
+	  a touchscreen input and one channel for thermal sensor.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called sun4i-gpadc-iio.
+
 config TI_ADC081C
 	tristate "Texas Instruments ADC081C/ADC101C/ADC121C family"
 	depends on I2C
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 38638d4..204372d 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
 obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
 obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
 obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
+obj-$(CONFIG_SUN4I_GPADC) += sun4i-gpadc-iio.o
 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
 obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
 obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
new file mode 100644
index 0000000..e2c5ba8
--- /dev/null
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -0,0 +1,522 @@
+/* ADC driver for sunxi platforms' (A10, A13 and A31) GPADC
+ *
+ * Copyright (c) 2016 Quentin Schulz <quentin.schulz@free-electrons.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.
+ *
+ * The Allwinner SoCs all have an ADC that can also act as a touchscreen
+ * controller and a thermal sensor.
+ * The thermal sensor works only when the ADC acts as a touchscreen controller
+ * and is configured to throw an interrupt every fixed periods of time (let say
+ * every X seconds).
+ * One would be tempted to disable the IP on the hardware side rather than
+ * disabling interrupts to save some power but that resets the internal clock of
+ * the IP, resulting in having to wait X seconds every time we want to read the
+ * value of the thermal sensor.
+ * This is also the reason of using autosuspend in pm_runtime. If there was no
+ * autosuspend, the thermal sensor would need X seconds after every
+ * pm_runtime_get_sync to get a value from the ADC. The autosuspend allows the
+ * thermal sensor to be requested again in a certain time span before it gets
+ * shutdown for not being used.
+ */
+
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/thermal.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/driver.h>
+#include <linux/iio/machine.h>
+#include <linux/mfd/sun4i-gpadc.h>
+
+static unsigned int sun4i_gpadc_chan_select(unsigned int chan)
+{
+	return SUN4I_GPADC_CTRL1_ADC_CHAN_SELECT(chan);
+}
+
+static unsigned int sun6i_gpadc_chan_select(unsigned int chan)
+{
+	return SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(chan);
+}
+
+struct gpadc_data {
+	int		temp_offset;
+	int		temp_scale;
+	unsigned int	tp_mode_en;
+	unsigned int	tp_adc_select;
+	unsigned int	(*adc_chan_select)(unsigned int chan);
+};
+
+static const struct gpadc_data sun4i_gpadc_data = {
+	.temp_offset = -1932,
+	.temp_scale = 133,
+	.tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN,
+	.tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,
+	.adc_chan_select = &sun4i_gpadc_chan_select,
+};
+
+static const struct gpadc_data sun5i_gpadc_data = {
+	.temp_offset = -1447,
+	.temp_scale = 100,
+	.tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN,
+	.tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,
+	.adc_chan_select = &sun4i_gpadc_chan_select,
+};
+
+static const struct gpadc_data sun6i_gpadc_data = {
+	.temp_offset = -1623,
+	.temp_scale = 167,
+	.tp_mode_en = SUN6I_GPADC_CTRL1_TP_MODE_EN,
+	.tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT,
+	.adc_chan_select = &sun6i_gpadc_chan_select,
+};
+
+struct sun4i_gpadc_iio {
+	struct iio_dev			*indio_dev;
+	struct completion		completion;
+	int				temp_data;
+	u32				adc_data;
+	struct regmap			*regmap;
+	unsigned int			fifo_data_irq;
+	atomic_t			ignore_fifo_data_irq;
+	unsigned int			temp_data_irq;
+	atomic_t			ignore_temp_data_irq;
+	const struct gpadc_data		*data;
+	/* prevents concurrent reads of temperature and ADC */
+	struct mutex			mutex;
+};
+
+#define SUN4I_GPADC_ADC_CHANNEL(_channel, _name) {		\
+	.type = IIO_VOLTAGE,					\
+	.indexed = 1,						\
+	.channel = _channel,					\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+	.datasheet_name = _name,				\
+}
+
+static struct iio_map sun4i_gpadc_hwmon_maps[] = {
+	{
+		.adc_channel_label = "temp_adc",
+		.consumer_dev_name = "iio_hwmon.0",
+	},
+	{ /* sentinel */ },
+};
+
+static const struct iio_chan_spec sun4i_gpadc_channels[] = {
+	SUN4I_GPADC_ADC_CHANNEL(0, "adc_chan0"),
+	SUN4I_GPADC_ADC_CHANNEL(1, "adc_chan1"),
+	SUN4I_GPADC_ADC_CHANNEL(2, "adc_chan2"),
+	SUN4I_GPADC_ADC_CHANNEL(3, "adc_chan3"),
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE) |
+				      BIT(IIO_CHAN_INFO_OFFSET),
+		.datasheet_name = "temp_adc",
+	},
+};
+
+static int sun4i_gpadc_read(struct iio_dev *indio_dev, int channel, int *val,
+			    unsigned int irq)
+{
+	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
+	int ret = 0;
+
+	pm_runtime_get_sync(indio_dev->dev.parent);
+	mutex_lock(&info->mutex);
+
+	reinit_completion(&info->completion);
+
+	ret = regmap_write(info->regmap, SUN4I_GPADC_INT_FIFOC,
+			   SUN4I_GPADC_INT_FIFOC_TP_FIFO_TRIG_LEVEL(1) |
+			   SUN4I_GPADC_INT_FIFOC_TP_FIFO_FLUSH);
+	if (ret)
+		return ret;
+
+	if (irq == info->fifo_data_irq) {
+		ret = regmap_write(info->regmap, SUN4I_GPADC_CTRL1,
+				   info->data->tp_mode_en |
+				   info->data->tp_adc_select |
+				   info->data->adc_chan_select(channel));
+	} else {
+		/*
+		 * The temperature sensor returns valid data only when the ADC
+		 * operates in touchscreen mode.
+		 */
+		ret = regmap_write(info->regmap, SUN4I_GPADC_CTRL1,
+				   info->data->tp_mode_en);
+	}
+
+	if (ret)
+		return ret;
+
+	enable_irq(irq);
+
+	if (!wait_for_completion_timeout(&info->completion,
+					 msecs_to_jiffies(100))) {
+		if ((irq == info->fifo_data_irq && info->adc_data == -1) ||
+		    (irq == info->temp_data_irq && info->temp_data == -1)) {
+			ret = -ETIMEDOUT;
+			goto out;
+		}
+	}
+
+	if (irq == info->fifo_data_irq)
+		*val = info->adc_data;
+	else
+		*val = info->temp_data;
+
+	ret = 0;
+
+out:
+	disable_irq(irq);
+	mutex_unlock(&info->mutex);
+	pm_runtime_mark_last_busy(indio_dev->dev.parent);
+	pm_runtime_put_autosuspend(indio_dev->dev.parent);
+
+	return ret;
+}
+
+static int sun4i_gpadc_adc_read(struct iio_dev *indio_dev, int channel,
+				int *val)
+{
+	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
+
+	return sun4i_gpadc_read(indio_dev, channel, val, info->fifo_data_irq);
+}
+
+static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val)
+{
+	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
+
+	return sun4i_gpadc_read(indio_dev, 0, val, info->temp_data_irq);
+}
+
+static int sun4i_gpadc_temp_offset(struct iio_dev *indio_dev, int *val)
+{
+	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
+
+	*val = info->data->temp_offset;
+
+	return 0;
+}
+
+static int sun4i_gpadc_temp_scale(struct iio_dev *indio_dev, int *val)
+{
+	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
+
+	*val = info->data->temp_scale;
+
+	return 0;
+}
+
+static int sun4i_gpadc_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan, int *val,
+				int *val2, long mask)
+{
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_OFFSET:
+		ret = sun4i_gpadc_temp_offset(indio_dev, val);
+		if (ret)
+			return ret;
+
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_RAW:
+		if (chan->type == IIO_VOLTAGE)
+			ret = sun4i_gpadc_adc_read(indio_dev, chan->channel,
+						   val);
+		else
+			ret = sun4i_gpadc_temp_read(indio_dev, val);
+
+		if (ret)
+			return ret;
+
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		ret = sun4i_gpadc_temp_scale(indio_dev, val);
+		if (ret)
+			return ret;
+
+		return IIO_VAL_INT;
+	default:
+		return -EINVAL;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info sun4i_gpadc_iio_info = {
+	.read_raw = sun4i_gpadc_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static irqreturn_t sun4i_gpadc_temp_data_irq_handler(int irq, void *dev_id)
+{
+	struct sun4i_gpadc_iio *info = dev_id;
+
+	if (atomic_read(&info->ignore_temp_data_irq))
+		return IRQ_HANDLED;
+
+	if (!regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, &info->temp_data))
+		complete(&info->completion);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t sun4i_gpadc_fifo_data_irq_handler(int irq, void *dev_id)
+{
+	struct sun4i_gpadc_iio *info = dev_id;
+
+	if (atomic_read(&info->ignore_fifo_data_irq))
+		return IRQ_HANDLED;
+
+	if (!regmap_read(info->regmap, SUN4I_GPADC_DATA, &info->adc_data))
+		complete(&info->completion);
+
+	return IRQ_HANDLED;
+}
+
+static int sun4i_gpadc_runtime_suspend(struct device *dev)
+{
+	struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));
+
+	/* Disable the ADC on IP */
+	regmap_write(info->regmap, SUN4I_GPADC_CTRL1, 0);
+	/* Disable temperature sensor on IP */
+	regmap_write(info->regmap, SUN4I_GPADC_TPR, 0);
+
+	return 0;
+}
+
+static int sun4i_gpadc_runtime_resume(struct device *dev)
+{
+	struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));
+
+	/* clkin = 6MHz */
+	regmap_write(info->regmap, SUN4I_GPADC_CTRL0,
+		     SUN4I_GPADC_CTRL0_ADC_CLK_DIVIDER(2) |
+		     SUN4I_GPADC_CTRL0_FS_DIV(7) |
+		     SUN4I_GPADC_CTRL0_T_ACQ(63));
+	regmap_write(info->regmap, SUN4I_GPADC_CTRL1, info->data->tp_mode_en);
+	regmap_write(info->regmap, SUN4I_GPADC_CTRL3,
+		     SUN4I_GPADC_CTRL3_FILTER_EN |
+		     SUN4I_GPADC_CTRL3_FILTER_TYPE(1));
+	/* period = SUN4I_GPADC_TPR_TEMP_PERIOD * 256 * 16 / clkin; ~1.3s */
+	regmap_write(info->regmap, SUN4I_GPADC_TPR,
+		     SUN4I_GPADC_TPR_TEMP_ENABLE |
+		     SUN4I_GPADC_TPR_TEMP_PERIOD(1953));
+
+	return 0;
+}
+
+static int sun4i_gpadc_get_temp(void *data, int *temp)
+{
+	struct sun4i_gpadc_iio *info = (struct sun4i_gpadc_iio *)data;
+	int val, scale, offset;
+
+	/* If reading temperature times out, take stored previous value. */
+	if (sun4i_gpadc_temp_read(info->indio_dev, &val))
+		val = info->temp_data;
+	sun4i_gpadc_temp_scale(info->indio_dev, &scale);
+	sun4i_gpadc_temp_offset(info->indio_dev, &offset);
+
+	*temp = (val + offset) * scale;
+
+	return 0;
+}
+
+static const struct thermal_zone_of_device_ops sun4i_ts_tz_ops = {
+	.get_temp = &sun4i_gpadc_get_temp,
+};
+
+static const struct dev_pm_ops sun4i_gpadc_pm_ops = {
+	.runtime_suspend = &sun4i_gpadc_runtime_suspend,
+	.runtime_resume = &sun4i_gpadc_runtime_resume,
+};
+
+static int sun4i_irq_init(struct platform_device *pdev, const char *name,
+			  irq_handler_t handler, const char *devname,
+			  unsigned int *irq, atomic_t *atomic)
+{
+	int ret;
+	struct sun4i_gpadc_dev *mfd_dev = dev_get_drvdata(pdev->dev.parent);
+	struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(&pdev->dev));
+
+	/*
+	 * Once the interrupt is activated, the IP continuously performs
+	 * conversions thus throws interrupts. The interrupt is activated right
+	 * after being requested but we want to control when these interrupts
+	 * occur thus we disable it right after being requested. However, an
+	 * interrupt might occur between these two instructions and we have to
+	 * make sure that does not happen, by using atomic flags. We set the
+	 * flag before requesting the interrupt and unset it right after
+	 * disabling the interrupt. When an interrupt occurs between these two
+	 * instructions, reading the atomic flag will tell us to ignore the
+	 * interrupt.
+	 */
+	atomic_set(atomic, 1);
+
+	*irq = platform_get_irq_byname(pdev, name);
+	if (*irq < 0) {
+		dev_err(&pdev->dev, "no %s interrupt registered\n", name);
+		return *irq;
+	}
+
+	*irq = regmap_irq_get_virq(mfd_dev->regmap_irqc, *irq);
+	ret = devm_request_any_context_irq(&pdev->dev, *irq, handler, 0,
+					   devname, info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "could not request %s interrupt: %d\n",
+			name, ret);
+		return ret;
+	}
+
+	disable_irq(*irq);
+	atomic_set(atomic, 0);
+
+	return 0;
+}
+
+static int sun4i_gpadc_probe(struct platform_device *pdev)
+{
+	struct sun4i_gpadc_iio *info;
+	struct iio_dev *indio_dev;
+	int ret;
+	struct sun4i_gpadc_dev *sun4i_gpadc_dev;
+	struct thermal_zone_device *tzd;
+
+	sun4i_gpadc_dev = dev_get_drvdata(pdev->dev.parent);
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	info = iio_priv(indio_dev);
+	platform_set_drvdata(pdev, indio_dev);
+
+	mutex_init(&info->mutex);
+	info->regmap = sun4i_gpadc_dev->regmap;
+	info->indio_dev = indio_dev;
+	info->temp_data = -1;
+	info->adc_data = -1;
+	init_completion(&info->completion);
+	indio_dev->name = dev_name(&pdev->dev);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->dev.of_node = pdev->dev.of_node;
+	indio_dev->info = &sun4i_gpadc_iio_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->num_channels = ARRAY_SIZE(sun4i_gpadc_channels);
+	indio_dev->channels = sun4i_gpadc_channels;
+
+	info->data = (struct gpadc_data *)platform_get_device_id(pdev)->driver_data;
+
+	/*
+	 * This driver is a child of an MFD which has a node in the DT but not
+	 * its children. Therefore, the resulting devices of this driver do not
+	 * have an of_node variable.
+	 * However, its parent (the MFD driver) has an of_node variable and
+	 * since devm_thermal_zone_of_sensor_register uses its first argument to
+	 * match the phandle defined in the node of the thermal driver with the
+	 * of_node of the device passed as first argument and the third argument
+	 * to call ops from thermal_zone_of_device_ops, the solution is to use
+	 * the parent device as first argument to match the phandle with its
+	 * of_node, and the device from this driver as third argument to return
+	 * the temperature.
+	 */
+	tzd = devm_thermal_zone_of_sensor_register(pdev->dev.parent, 0, info,
+						   &sun4i_ts_tz_ops);
+	if (IS_ERR(tzd)) {
+		dev_err(&pdev->dev, "could not register thermal sensor: %ld\n",
+			PTR_ERR(tzd));
+		return PTR_ERR(tzd);
+	}
+
+	pm_runtime_set_autosuspend_delay(&pdev->dev,
+					 SUN4I_GPADC_AUTOSUSPEND_DELAY);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	ret = sun4i_irq_init(pdev, "TEMP_DATA_PENDING",
+			     sun4i_gpadc_temp_data_irq_handler, "temp_data",
+			     &info->temp_data_irq, &info->ignore_temp_data_irq);
+	if (ret < 0)
+		goto err;
+
+	ret = sun4i_irq_init(pdev, "FIFO_DATA_PENDING",
+			     sun4i_gpadc_fifo_data_irq_handler, "fifo_data",
+			     &info->fifo_data_irq, &info->ignore_fifo_data_irq);
+	if (ret < 0)
+		goto err;
+
+	ret = iio_map_array_register(indio_dev, sun4i_gpadc_hwmon_maps);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register iio map array\n");
+		goto err;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "could not register the device\n");
+		goto err_map;
+	}
+
+	return 0;
+
+err_map:
+	iio_map_array_unregister(indio_dev);
+
+err:
+	pm_runtime_put(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	return ret;
+}
+
+static int sun4i_gpadc_remove(struct platform_device *pdev)
+{
+	struct sun4i_gpadc_iio *info;
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+	pm_runtime_put(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	info = iio_priv(indio_dev);
+	iio_map_array_unregister(indio_dev);
+	iio_device_unregister(indio_dev);
+
+	return 0;
+}
+
+static const struct platform_device_id sun4i_gpadc_id[] = {
+	{ "sun4i-a10-gpadc-iio", (kernel_ulong_t)&sun4i_gpadc_data },
+	{ "sun5i-a13-gpadc-iio", (kernel_ulong_t)&sun5i_gpadc_data },
+	{ "sun6i-a31-gpadc-iio", (kernel_ulong_t)&sun6i_gpadc_data },
+	{ /* sentinel */ },
+};
+
+static struct platform_driver sun4i_gpadc_driver = {
+	.driver = {
+		.name = "sun4i-gpadc-iio",
+		.pm = &sun4i_gpadc_pm_ops,
+	},
+	.id_table = sun4i_gpadc_id,
+	.probe = sun4i_gpadc_probe,
+	.remove = sun4i_gpadc_remove,
+};
+
+module_platform_driver(sun4i_gpadc_driver);
+
+MODULE_DESCRIPTION("ADC driver for sunxi platforms");
+MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
+MODULE_LICENSE("GPL v2");
-- 
2.5.0

^ permalink raw reply related

* [PATCH v6 1/2] mfd: add support for Allwinner SoCs ADC
From: Quentin Schulz @ 2016-09-15 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473943444-23979-1-git-send-email-quentin.schulz@free-electrons.com>

The Allwinner SoCs all have an ADC that can also act as a touchscreen
controller and a thermal sensor. For now, only the ADC and the thermal
sensor drivers are probed by the MFD, the touchscreen controller support
will be added later.

Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Jonathan Cameron <jic23@kernel.org>
---

v6:
 - remove "-mfd" from filenames and variables inside MFD driver,
 - use DEFINE_RES_IRQ_NAMED instead of setting resources manually,
 - cosmetic changes,
 - use IDs and switch over ID to get cells specific to an architecture, instead
 of using cells direclty, in of_device_id.data,
 - compute size of mfd_cells array instead of hardcoded one,

v5:
 - correct mail address,

v4:
 - rename files and variables from sunxi* to sun4i*,
 - rename defines from SUNXI_* to SUN4I_* or SUN6I_*,
 - remove TP in defines name,
 - rename SUNXI_IRQ_* to SUN4I_GPADC_IRQ_* for consistency,
 - use devm functions for regmap_add_irq_chip and mfd_add_devices,
 - remove remove functions (now empty thanks to devm functions),

v3:
 - use defines in regmap_irq instead of hard coded BITs,
 - use of_device_id data field to chose which MFD cells to add considering
   the compatible responsible of the MFD probe,
 - remove useless initializations,
 - disable all interrupts before adding them to regmap_irqchip,
 - add goto error label in probe,
 - correct wrapping in header license,
 - move defines from IIO driver to header,
 - use GENMASK to limit the size of the variable passed to a macro,
 - prefix register BIT defines with the name of the register,
 - reorder defines,

v2:
 - add license headers,
 - reorder alphabetically includes,
 - add SUNXI_GPADC_ prefixes for defines,

 drivers/mfd/Kconfig             |  15 ++++
 drivers/mfd/Makefile            |   2 +
 drivers/mfd/sun4i-gpadc.c       | 181 ++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/sun4i-gpadc.h |  94 +++++++++++++++++++++
 4 files changed, 292 insertions(+)
 create mode 100644 drivers/mfd/sun4i-gpadc.c
 create mode 100644 include/linux/mfd/sun4i-gpadc.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 1bcf601..45db3f4 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -29,6 +29,21 @@ config MFD_ACT8945A
 	  linear regulators, along with a complete ActivePath battery
 	  charger.
 
+config MFD_SUN4I_GPADC
+	tristate "Allwinner sunxi platforms' GPADC MFD driver"
+	select MFD_CORE
+	select REGMAP_MMIO
+	depends on ARCH_SUNXI || COMPILE_TEST
+	help
+	  Select this to get support for Allwinner SoCs (A10, A13 and A31) ADC.
+	  This driver will only map the hardware interrupt and registers, you
+	  have to select individual drivers based on this MFD to be able to use
+	  the ADC or the thermal sensor. This will try to probe the ADC driver
+	  sun4i-gpadc-iio and the hwmon driver iio_hwmon.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called sun4i-gpadc.
+
 config MFD_AS3711
 	bool "AMS AS3711"
 	select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 42a66e1..12c49af 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -205,3 +205,5 @@ intel-soc-pmic-objs		:= intel_soc_pmic_core.o intel_soc_pmic_crc.o
 intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC)	+= intel_soc_pmic_bxtwc.o
 obj-$(CONFIG_INTEL_SOC_PMIC)	+= intel-soc-pmic.o
 obj-$(CONFIG_MFD_MT6397)	+= mt6397-core.o
+
+obj-$(CONFIG_MFD_SUN4I_GPADC)	+= sun4i-gpadc.o
diff --git a/drivers/mfd/sun4i-gpadc.c b/drivers/mfd/sun4i-gpadc.c
new file mode 100644
index 0000000..276a1f4
--- /dev/null
+++ b/drivers/mfd/sun4i-gpadc.c
@@ -0,0 +1,181 @@
+/* ADC MFD core driver for sunxi platforms
+ *
+ * Copyright (c) 2016 Quentin Schulz <quentin.schulz@free-electrons.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.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/sun4i-gpadc.h>
+
+#define ARCH_SUN4I_A10 0
+#define ARCH_SUN5I_A13 1
+#define ARCH_SUN6I_A31 2
+
+static struct resource adc_resources[] = {
+	DEFINE_RES_IRQ_NAMED(SUN4I_GPADC_IRQ_FIFO_DATA, "FIFO_DATA_PENDING"),
+	DEFINE_RES_IRQ_NAMED(SUN4I_GPADC_IRQ_TEMP_DATA, "TEMP_DATA_PENDING"),
+};
+
+static const struct regmap_irq sun4i_gpadc_regmap_irq[] = {
+	REGMAP_IRQ_REG(SUN4I_GPADC_IRQ_FIFO_DATA, 0,
+		       SUN4I_GPADC_INT_FIFOC_TP_DATA_IRQ_EN),
+	REGMAP_IRQ_REG(SUN4I_GPADC_IRQ_TEMP_DATA, 0,
+		       SUN4I_GPADC_INT_FIFOC_TEMP_IRQ_EN),
+};
+
+static const struct regmap_irq_chip sun4i_gpadc_regmap_irq_chip = {
+	.name = "sun4i_gpadc_irq_chip",
+	.status_base = SUN4I_GPADC_INT_FIFOS,
+	.ack_base = SUN4I_GPADC_INT_FIFOS,
+	.mask_base = SUN4I_GPADC_INT_FIFOC,
+	.init_ack_masked = true,
+	.mask_invert = true,
+	.irqs = sun4i_gpadc_regmap_irq,
+	.num_irqs = ARRAY_SIZE(sun4i_gpadc_regmap_irq),
+	.num_regs = 1,
+};
+
+static struct mfd_cell sun4i_gpadc_cells[] = {
+	{
+		.name	= "sun4i-a10-gpadc-iio",
+		.resources = adc_resources,
+		.num_resources = ARRAY_SIZE(adc_resources),
+	},
+	{ .name = "iio_hwmon" }
+};
+
+static struct mfd_cell sun5i_gpadc_cells[] = {
+	{
+		.name	= "sun5i-a13-gpadc-iio",
+		.resources = adc_resources,
+		.num_resources = ARRAY_SIZE(adc_resources),
+	},
+	{ .name = "iio_hwmon" },
+};
+
+static struct mfd_cell sun6i_gpadc_cells[] = {
+	{
+		.name	= "sun6i-a31-gpadc-iio",
+		.resources = adc_resources,
+		.num_resources = ARRAY_SIZE(adc_resources),
+	},
+	{ .name = "iio_hwmon" },
+};
+
+static const struct regmap_config sun4i_gpadc_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.fast_io = true,
+};
+
+static const struct of_device_id sun4i_gpadc_of_match[] = {
+	{
+		.compatible = "allwinner,sun4i-a10-ts",
+		.data = (void *)ARCH_SUN4I_A10,
+	}, {
+		.compatible = "allwinner,sun5i-a13-ts",
+		.data = (void *)ARCH_SUN5I_A13,
+	}, {
+		.compatible = "allwinner,sun6i-a31-ts",
+		.data = (void *)ARCH_SUN6I_A31,
+	}, { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_match);
+
+static int sun4i_gpadc_probe(struct platform_device *pdev)
+{
+	struct sun4i_gpadc_dev *dev;
+	struct resource *mem;
+	const struct of_device_id *of_id;
+	const struct mfd_cell *cells;
+	unsigned int irq, size;
+	int ret;
+
+	of_id = of_match_node(sun4i_gpadc_of_match, pdev->dev.of_node);
+	if (!of_id)
+		return -EINVAL;
+
+	switch ((int)of_id->data) {
+	case ARCH_SUN4I_A10:
+		cells = sun4i_gpadc_cells;
+		size = ARRAY_SIZE(sun4i_gpadc_cells);
+		break;
+	case ARCH_SUN5I_A13:
+		cells = sun5i_gpadc_cells;
+		size = ARRAY_SIZE(sun5i_gpadc_cells);
+		break;
+	case ARCH_SUN6I_A31:
+		cells = sun6i_gpadc_cells;
+		size = ARRAY_SIZE(sun6i_gpadc_cells);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dev->base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(dev->base))
+		return PTR_ERR(dev->base);
+
+	dev->dev = &pdev->dev;
+	dev_set_drvdata(dev->dev, dev);
+
+	dev->regmap = devm_regmap_init_mmio(dev->dev, dev->base,
+					    &sun4i_gpadc_regmap_config);
+	if (IS_ERR(dev->regmap)) {
+		ret = PTR_ERR(dev->regmap);
+		dev_err(&pdev->dev, "failed to init regmap: %d\n", ret);
+		return ret;
+	}
+
+	/* Disable all interrupts */
+	regmap_write(dev->regmap, SUN4I_GPADC_INT_FIFOC, 0);
+
+	irq = platform_get_irq(pdev, 0);
+	ret = devm_regmap_add_irq_chip(&pdev->dev, dev->regmap, irq,
+				       IRQF_ONESHOT, 0,
+				       &sun4i_gpadc_regmap_irq_chip,
+				       &dev->regmap_irqc);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add irq chip: %d\n", ret);
+		return ret;
+	}
+
+	ret = devm_mfd_add_devices(dev->dev, 0, cells, size, NULL, 0, NULL);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add MFD devices: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct platform_driver sun4i_gpadc_driver = {
+	.driver = {
+		.name = "sun4i-gpadc",
+		.of_match_table = of_match_ptr(sun4i_gpadc_of_match),
+	},
+	.probe = sun4i_gpadc_probe,
+};
+
+module_platform_driver(sun4i_gpadc_driver);
+
+MODULE_DESCRIPTION("Allwinner sunxi platforms' GPADC MFD core driver");
+MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h
new file mode 100644
index 0000000..d7a29f2
--- /dev/null
+++ b/include/linux/mfd/sun4i-gpadc.h
@@ -0,0 +1,94 @@
+/* Header of ADC MFD core driver for sunxi platforms
+ *
+ * Copyright (c) 2016 Quentin Schulz <quentin.schulz@free-electrons.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.
+ */
+
+#ifndef __SUN4I_GPADC__H__
+#define __SUN4I_GPADC__H__
+
+#define SUN4I_GPADC_CTRL0				0x00
+
+#define SUN4I_GPADC_CTRL0_ADC_FIRST_DLY(x)		((GENMASK(7, 0) & (x)) << 24)
+#define SUN4I_GPADC_CTRL0_ADC_FIRST_DLY_MODE		BIT(23)
+#define SUN4I_GPADC_CTRL0_ADC_CLK_SELECT		BIT(22)
+#define SUN4I_GPADC_CTRL0_ADC_CLK_DIVIDER(x)		((GENMASK(1, 0) & (x)) << 20)
+#define SUN4I_GPADC_CTRL0_FS_DIV(x)			((GENMASK(3, 0) & (x)) << 16)
+#define SUN4I_GPADC_CTRL0_T_ACQ(x)			(GENMASK(15, 0) & (x))
+
+#define SUN4I_GPADC_CTRL1				0x04
+
+#define SUN4I_GPADC_CTRL1_STYLUS_UP_DEBOUNCE(x)		((GENMASK(7, 0) & (x)) << 12)
+#define SUN4I_GPADC_CTRL1_STYLUS_UP_DEBOUNCE_EN		BIT(9)
+#define SUN4I_GPADC_CTRL1_TOUCH_PAN_CALI_EN		BIT(6)
+#define SUN4I_GPADC_CTRL1_TP_DUAL_EN			BIT(5)
+#define SUN4I_GPADC_CTRL1_TP_MODE_EN			BIT(4)
+#define SUN4I_GPADC_CTRL1_TP_ADC_SELECT			BIT(3)
+#define SUN4I_GPADC_CTRL1_ADC_CHAN_SELECT(x)		(GENMASK(2, 0) & (x))
+
+/* TP_CTRL1 bits for sun6i SOCs */
+#define SUN6I_GPADC_CTRL1_TOUCH_PAN_CALI_EN		BIT(7)
+#define SUN6I_GPADC_CTRL1_TP_DUAL_EN			BIT(6)
+#define SUN6I_GPADC_CTRL1_TP_MODE_EN			BIT(5)
+#define SUN6I_GPADC_CTRL1_TP_ADC_SELECT			BIT(4)
+#define SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(x)		(GENMASK(3, 0) & BIT(x))
+
+#define SUN4I_GPADC_CTRL2				0x08
+
+#define SUN4I_GPADC_CTRL2_TP_SENSITIVE_ADJUST(x)	((GENMASK(3, 0) & (x)) << 28)
+#define SUN4I_GPADC_CTRL2_TP_MODE_SELECT(x)		((GENMASK(1, 0) & (x)) << 26)
+#define SUN4I_GPADC_CTRL2_PRE_MEA_EN			BIT(24)
+#define SUN4I_GPADC_CTRL2_PRE_MEA_THRE_CNT(x)		(GENMASK(23, 0) & (x))
+
+#define SUN4I_GPADC_CTRL3				0x0c
+
+#define SUN4I_GPADC_CTRL3_FILTER_EN			BIT(2)
+#define SUN4I_GPADC_CTRL3_FILTER_TYPE(x)		(GENMASK(1, 0) & (x))
+
+#define SUN4I_GPADC_TPR					0x18
+
+#define SUN4I_GPADC_TPR_TEMP_ENABLE			BIT(16)
+#define SUN4I_GPADC_TPR_TEMP_PERIOD(x)			(GENMASK(15, 0) & (x))
+
+#define SUN4I_GPADC_INT_FIFOC				0x10
+
+#define SUN4I_GPADC_INT_FIFOC_TEMP_IRQ_EN		BIT(18)
+#define SUN4I_GPADC_INT_FIFOC_TP_OVERRUN_IRQ_EN		BIT(17)
+#define SUN4I_GPADC_INT_FIFOC_TP_DATA_IRQ_EN		BIT(16)
+#define SUN4I_GPADC_INT_FIFOC_TP_DATA_XY_CHANGE		BIT(13)
+#define SUN4I_GPADC_INT_FIFOC_TP_FIFO_TRIG_LEVEL(x)	((GENMASK(4, 0) & (x)) << 8)
+#define SUN4I_GPADC_INT_FIFOC_TP_DATA_DRQ_EN		BIT(7)
+#define SUN4I_GPADC_INT_FIFOC_TP_FIFO_FLUSH		BIT(4)
+#define SUN4I_GPADC_INT_FIFOC_TP_UP_IRQ_EN		BIT(1)
+#define SUN4I_GPADC_INT_FIFOC_TP_DOWN_IRQ_EN		BIT(0)
+
+#define SUN4I_GPADC_INT_FIFOS				0x14
+
+#define SUN4I_GPADC_INT_FIFOS_TEMP_DATA_PENDING		BIT(18)
+#define SUN4I_GPADC_INT_FIFOS_FIFO_OVERRUN_PENDING	BIT(17)
+#define SUN4I_GPADC_INT_FIFOS_FIFO_DATA_PENDING		BIT(16)
+#define SUN4I_GPADC_INT_FIFOS_TP_IDLE_FLG		BIT(2)
+#define SUN4I_GPADC_INT_FIFOS_TP_UP_PENDING		BIT(1)
+#define SUN4I_GPADC_INT_FIFOS_TP_DOWN_PENDING		BIT(0)
+
+#define SUN4I_GPADC_CDAT				0x1c
+#define SUN4I_GPADC_TEMP_DATA				0x20
+#define SUN4I_GPADC_DATA				0x24
+
+#define SUN4I_GPADC_IRQ_FIFO_DATA			0
+#define SUN4I_GPADC_IRQ_TEMP_DATA			1
+
+/* 10s delay before suspending the IP */
+#define SUN4I_GPADC_AUTOSUSPEND_DELAY			10000
+
+struct sun4i_gpadc_dev {
+	struct device			*dev;
+	struct regmap			*regmap;
+	struct regmap_irq_chip_data	*regmap_irqc;
+	void __iomem			*base;
+};
+
+#endif
-- 
2.5.0

^ permalink raw reply related

* [PATCH v6 0/2] add support for Allwinner SoCs ADC
From: Quentin Schulz @ 2016-09-15 12:44 UTC (permalink / raw)
  To: linux-arm-kernel

The Allwinner SoCs all have an ADC that can also act as a touchscreen
controller and a thermal sensor. The first four channels can be used either
for the ADC or the touchscreen and the fifth channel is used for the
thermal sensor. We currently have a driver for the two latter functions in
drivers/input/touchscreen/sun4i-ts.c but we don't have access to the ADC
feature at all. It is meant to replace the current driver by using MFD and
subdrivers.

This adds initial support for Allwinner SoCs ADC with all features. Yet,
the touchscreen is not implemented but will be added later. To switch
between touchscreen and ADC modes, you need to poke a few bits in registers
and (de)activate an interrupt (pen-up).
An MFD is provided to let the input driver activate the pen-up interrupt
through a virtual interrupt, poke a few bits via regmap and read data from
the ADC driver while both (and iio_hwmon) are probed by the MFD.

There are slight variations between the different SoCs ADC like the address
of some registers and the scale and offset to apply to raw thermal sensor
values. These variations are handled by using different platform_device_id,
passed to the sub-drivers when they are probed by the MFD.

Removal of proposed patch for iio_hwmon's iio channel's label in v3. The
patch induces irreversible ABI changes and will be handled as a separate
patch since I think it is not absolutely necessary to have labels yet in
iio_hwmon.

Removal of proposed patch for reattaching of_node of the MFD to the MFD
cell device structure in v3. As Lee Jones said, this patch might cause
"unintended side-effects for existing drivers.". Moreover, this patch
introduced a bug of multiple probe of this MFD driver I haven't identified
yet. This patch aimed at allowing the ADC driver (which is a child of the
MFD and not present in the DT) to register in the thermal framework. The
thermal driver has a phandle to the MFD node which is used to match against
the MFD of_node but since the ADC driver has no node in the DT, could not
register in the thermal framework. The other solution is to "impersonate"
the MFD when registering in the thermal framework since the device is only
used to match the phandle and the of_node, an other structure passed by
parameter being used to compute temperatures.

(in the ADC driver, probed by the MFD driver) instead of:
tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, info,
					   &sun4i_ts_tz_ops);
we now have:
tzd = devm_thermal_zone_of_sensor_register(pdev->dev.parent, 0, info,
					   &sun4i_ts_tz_ops);

Removal of proposed patch to use late_initcall for iio_hwmon probe deferring.

Removal of patch for iio_hwmon probe deferring due to being applied to -next by
Guenter Roeck.

Quentin Schulz (2):
  mfd: add support for Allwinner SoCs ADC
  iio: adc: add support for Allwinner SoCs ADC

 drivers/iio/adc/Kconfig           |  13 +
 drivers/iio/adc/Makefile          |   1 +
 drivers/iio/adc/sun4i-gpadc-iio.c | 522 ++++++++++++++++++++++++++++++++++++++
 drivers/mfd/Kconfig               |  15 ++
 drivers/mfd/Makefile              |   2 +
 drivers/mfd/sun4i-gpadc.c         | 181 +++++++++++++
 include/linux/mfd/sun4i-gpadc.h   |  94 +++++++
 7 files changed, 828 insertions(+)
 create mode 100644 drivers/iio/adc/sun4i-gpadc-iio.c
 create mode 100644 drivers/mfd/sun4i-gpadc.c
 create mode 100644 include/linux/mfd/sun4i-gpadc.h

-- 
2.5.0

^ permalink raw reply

* [PATCH 14/19] pinctrl: st: Remove obsolete platforms from pinctrl-st dt doc
From: Linus Walleij @ 2016-09-15 12:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473859677-9231-15-git-send-email-peter.griffin@linaro.org>

On Wed, Sep 14, 2016 at 3:27 PM, Peter Griffin <peter.griffin@linaro.org> wrote:

> STiH415/6 SoC support is being removed from the kernel.
> This patch updates the ST pinctrl dt doc and removes
> references to these obsolete platforms. It also updates
> the dt example to the currently supported STiH407
> platform.
>
> Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> Cc: <linus.walleij@linaro.org>
> Cc: <robh+dt@kernel.org>
> Cc: <linux-gpio@vger.kernel.org>

Patch applied, had to do some rebasing so check the
result.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH 13/19] pinctrl: st: Remove STiH415/6 SoC pinctrl driver support.
From: Linus Walleij @ 2016-09-15 12:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473859677-9231-14-git-send-email-peter.griffin@linaro.org>

On Wed, Sep 14, 2016 at 3:27 PM, Peter Griffin <peter.griffin@linaro.org> wrote:

> STiH415/6 SoC support is being removed from the kernel.
> This patch updates the ST pinctrl driver and removes
> references to these obsolete platforms. As some structures
> referenced by STiH407 based configuration were shared with
> STiH416 we update these names to match the remaining
> supported platform.
>
> Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> Cc: <linus.walleij@linaro.org>
> Cc: <linux-gpio@vger.kernel.org>

Patch applied.

Yours,
Linus Walleij

^ permalink raw reply


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