* [PATCH 3/3] usb: ohci-da8xx: rename driver to ohci-da8xx
From: Sekhar Nori @ 2016-11-03 11:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161102124435.31777-4-ahaslam@baylibre.com>
On Wednesday 02 November 2016 06:14 PM, Axel Haslam wrote:
> To be consistent on the usb driver for the davinci
> platform follow the example of musb, and add the
> "-da8xx" postfix to the driver name.
>
> Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
> ---
> drivers/usb/host/ohci-da8xx.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
> index bd6cf3c..b3de8bc 100644
> --- a/drivers/usb/host/ohci-da8xx.c
> +++ b/drivers/usb/host/ohci-da8xx.c
> @@ -27,7 +27,7 @@
> #include "ohci.h"
>
> #define DRIVER_DESC "DA8XX"
> -#define DRV_NAME "ohci"
> +#define DRV_NAME "ohci-da8xx"
To which baseline does this patch apply? I don't see this code in
linux-next.
Thanks,
Sekhar
^ permalink raw reply
* [GIT PULL] DaVinci fix for v4.9-rc
From: Sekhar Nori @ 2016-11-03 11:18 UTC (permalink / raw)
To: linux-arm-kernel
The following changes since commit a909d3e636995ba7c349e2ca5dbb528154d4ac30:
Linux 4.9-rc3 (2016-10-29 13:52:02 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git tags/davinci-fixes-for-v4.9
for you to fetch changes up to 36173c2d023bad4dbad6ed0e6e886fde10ec8f2f:
ARM: davinci: da850: Fix pwm name matching (2016-11-01 15:30:03 +0530)
----------------------------------------------------------------
This patch enables usage of multiple eCAP and eHRPWM devices
using PWM sysfs entries.
Without this patch, creation of multiple entries fails due
to name clash.
This is not a v4.9 regression but it will be nice to fix it
soon.
----------------------------------------------------------------
David Lechner (1):
ARM: davinci: da850: Fix pwm name matching
arch/arm/mach-davinci/da850.c | 48 +++++++++++++++++++++++++++++++++++++---
arch/arm/mach-davinci/da8xx-dt.c | 10 ++++-----
2 files changed, 50 insertions(+), 8 deletions(-)
^ permalink raw reply
* arm64 build failure with CONFIG_ARM64_LSE_ATOMICS=y
From: Artem Savkov @ 2016-11-03 11:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1efb101a-a8ab-5ad9-f2bd-e7d485c71904@arm.com>
On Thu, Nov 03, 2016 at 10:39:43AM +0000, Suzuki K Poulose wrote:
> On 02/11/16 23:28, Will Deacon wrote:
> > Hi Artem,
> >
> > On Wed, Nov 02, 2016 at 05:44:27PM +0100, Artem Savkov wrote:
> > > Hello Catalin,
> > >
> > > Looks like your patch "efd9e03 arm64: Use static keys for CPU features"
> > > breaks arm64 build with "CONFIG_ARM64_LSE_ATOMICS=y" because it creates a
> > > circular dependency for asm/lse.h through jump_label.h:
> > >
> > > CC arch/arm64/kernel/asm-offsets.s
> > > In file included from ./arch/arm64/include/asm/atomic.h:34:0,
> > > from ./include/linux/atomic.h:4,
> > > from ./include/linux/jump_label.h:169,
> > > from ./arch/arm64/include/asm/cpufeature.h:12,
> > > from ./arch/arm64/include/asm/alternative.h:4,
> > > from ./arch/arm64/include/asm/lse.h:7,
> > > from ./arch/arm64/include/asm/spinlock.h:19,
> > > from ./include/linux/spinlock.h:87,
> > > from ./include/linux/seqlock.h:35,
> > > from ./include/linux/time.h:5,
> > > from ./include/uapi/linux/timex.h:56,
> > > from ./include/linux/timex.h:56,
> > > from ./include/linux/sched.h:19,
> > > from arch/arm64/kernel/asm-offsets.c:21:
> > > ./arch/arm64/include/asm/atomic_lse.h: In function ?atomic_andnot?:
> > > ./arch/arm64/include/asm/atomic_lse.h:35:15: error: expected string literal before ? ?
> > > asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC(op), \
> > >
> > > ...
> > >
> > > ./arch/arm64/include/asm/cmpxchg.h: In function ?__xchg_case_1?:
> > > ./arch/arm64/include/asm/cmpxchg.h:38:15: error: expected string literal before ?ARM64_LSE_ATOMIC_INSN?
> > > asm volatile(ARM64_LSE_ATOMIC_INSN( \
> >
> > I'm unable to reproduce this. I've tried enabling LSE with defconfig and
> > mainline, using compilers that both do and don't support the instructions.
>
> I am not able to reproduce it either. One minor problem I see with the commit could
> be fixed with the following change : Does it help ?
Apparently it fails with an older gcc (4.8.5), but doesn't with 6.2.0.
The different bit is that with 4.8.5 I don't have CC_HAVE_ASM_GOTO set.
It is reproducible with 6.2.0 if you manually remove CC_HAVE_ASM_GOTO.
> ----8>-----
>
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 758d74f..62db988 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -9,7 +9,6 @@
> #ifndef __ASM_CPUFEATURE_H
> #define __ASM_CPUFEATURE_H
> -#include <linux/jump_label.h>
> #include <asm/hwcap.h>
> #include <asm/sysreg.h>
> @@ -45,6 +44,7 @@
> #ifndef __ASSEMBLY__
> +#include <linux/jump_label.h>
> #include <linux/kernel.h>
> /* CPU feature register tracking */
No, this doesn't help.
--
Regards,
Artem
^ permalink raw reply
* [PATCH 01/10] Documentation: dt-bindings: Document STM32 ADC DT bindings
From: Fabrice Gasnier @ 2016-11-03 11:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161031030222.vjxcxklpaua3o77d@rob-hp-laptop>
On 10/31/2016 04:02 AM, Rob Herring wrote:
> On Tue, Oct 25, 2016 at 06:25:13PM +0200, Fabrice Gasnier wrote:
>> This patch adds documentation of device tree bindings for the STM32 ADC.
>>
>> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
>> ---
>> .../devicetree/bindings/iio/adc/st,stm32-adc.txt | 78 ++++++++++++++++++++++
>> 1 file changed, 78 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
>>
>> diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
>> new file mode 100644
>> index 0000000..a9a8b3c
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
>> @@ -0,0 +1,78 @@
>> +STMicroelectronics STM32 ADC device driver
>> +
>> +STM32 ADC is a successive approximation analog-to-digital converter.
>> +It has several multiplexed input channels. Conversions can be performed
>> +in single, continuous, scan or discontinuous mode. Result of the ADC is
>> +stored in a left-aligned or right-aligned 32-bit data register.
>> +Conversions can be launched in software or using hardware triggers.
>> +
>> +The analog watchdog feature allows the application to detect if the input
>> +voltage goes beyond the user-defined, higher or lower thresholds.
>> +
>> +Each STM32 ADC block can have up to 3 ADC instances.
>> +
>> +Each instance supports two contexts to manage conversions, each one has its
>> +own configurable sequence and trigger:
>> +- regular conversion can be done in sequence, running in background
>> +- injected conversions have higher priority, and so have the ability to
>> + interrupt regular conversion sequence (either triggered in SW or HW).
>> + Regular sequence is resumed, in case it has been interrupted.
>> +
>> +Required properties:
>> +- compatible: Should be "st,stm32f4-adc".
>> +- reg: Offset and length of the ADC block register set.
>> +- interrupts: Must contain the interrupt for ADC.
>> +- clocks: Clock for the analog circuitry (common to all ADCs).
>> +- clock-names: Must be "adc".
>> +- vref-supply: Phandle to the vref input analog reference voltage.
>> +- #address-cells = <1>;
>> +- #size-cells = <0>;
>> +
>> +Optional properties:
>> +- A pinctrl state named "default" for each ADC channel may be defined to set
>> + inX ADC pins in mode of operation for analog input on external pin.
>> +- gpios: Array of gpios that may be configured as EXTi trigger sources.
>> +
>> +Example:
> This should be last.
Hi Rob,
I'll fix this.
>
>> + adc: adc at 40012000 {
>> + compatible = "st,stm32f4-adc";
>> + reg = <0x40012000 0x400>;
>> + interrupts = <18>;
>> + clocks = <&rcc 0 168>;
>> + clock-names = "adc";
>> + vref-supply = <®_vref>;
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&adc3_in8_pin>;
>> + gpios = <&gpioa 11 0>,
>> + <&gpioa 15 0>;
>> +
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> +
>> + adc1: adc1-master at 0 {
> adc at 0 sufficient?
Yes, if you agree, I'd go for adc1 at 0, adc2 at 100, adc3 at 200, to reflect reg
property for child node.
Is it ok from your point of view ?
>
>> + #io-channel-cells = <1>;
>> + reg = <0x0>;
>> + clocks = <&rcc 0 168>;
>> + st,adc-channels = <8>;
>> + };
>> + ...
>> + other adc child nodes follow...
>> + };
>> +
>> +Contents of a stm32 adc child node:
>> +-----------------------------------
>> +An ADC block node should contain at least one subnode, representing an
>> +ADC instance available on the machine.
>> +
>> +Required properties:
>> +- reg: Offset of ADC instance in ADC block (e.g. may be 0x0, 0x100, 0x200).
>> +- st,adc-channels: List of single-ended channels muxed for this ADC.
> How many? What are valid values?
stm32f4 can have up to 19 channels, numbered from 0 to 18 to match with
reference manual.
I'll add this.
>
>> +- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
>> + Documentation/devicetree/bindings/iio/iio-bindings.txt
>> +
>> +Optional properties:
>> +- clocks: Input clock private to this ADC instance.
>> +- st,injected: Use injected conversion sequence on an ADC, rather than regular.
> Not sure about this one. Seems like this would either be a user choice
> or depend on what's connected to the ADC.
It's related to ADC sequencer, and the way it's being configured/used
(see above paragraph on regular/injected).
This is not related to what's connected to adc inputs.
As suggested by Jonathan, I think I'll drop injected support for now, to
simplify the driver and review.
Thanks,
Best Regards,
Fabrice
>
>> +- dmas: Phandle to dma channel for this ADC instance, only for regular
>> + conversions. See ../../dma/dma.txt for details.
>> +- dma-names: Must be "rx" when dmas property is being used.
>> --
>> 1.9.1
>>
^ permalink raw reply
* [PATCH] iommu: arm-smmu: Set SMTNMB_TLBEN in ACR to enable caching of bypass entries
From: Robin Murphy @ 2016-11-03 11:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <DB6PR0402MB26942C3D65D70A1C1C84F746E6A00@DB6PR0402MB2694.eurprd04.prod.outlook.com>
On 02/11/16 19:26, Nipun Gupta wrote:
>
> Hi Robin,
>
>> -----Original Message-----
>> From: Robin Murphy [mailto:robin.murphy at arm.com]
>> Sent: Wednesday, November 02, 2016 16:51
>> To: Nipun Gupta <nipun.gupta@nxp.com>; will.deacon at arm.com; linux-arm-
>> kernel at lists.infradead.org; iommu at lists.linux-foundation.org
>> Cc: Stuart Yoder <stuart.yoder@nxp.com>
>> Subject: Re: [PATCH] iommu: arm-smmu: Set SMTNMB_TLBEN in ACR to enable
>> caching of bypass entries
>>
>> Hi Nipun,
>>
>> On 02/11/16 13:35, Nipun Gupta wrote:
>>> The SMTNMB_TLBEN in the Auxiliary Configuration Register (ACR)
>>> provides an option to enable the updation of TLB in case of bypass
>>> transactions due to no stream match in the stream match table. This
>>> reduces the latencies of the subsequent transactions with the same stream-id
>> which bypasses the SMMU.
>>> This provides a significant performance benefit for certain networking
>>> workloads.
>>
>> ...at the cost of increased TLB contention against other workloads.
>> However, in the general case we'd expect the system to be fully described, so if
>> there aren't any unmatched Stream IDs there hopefully shouldn't be an impact
>> to leaving this switched on. I'd be interested to see some actual performance
>> numbers, though - you already know my opinion about unsubstantiated quotes
>> from the MMU-500 TRM.
>
> With this change we have seen substantial performance improvement of ~9-10%
> with DPDK l3fwd application (http://dpdk.org/doc/guides/sample_app_ug/l3_forward.html)
> on NXP's LS2088a platform (single core as well as multi-core). Also, with ODP reflector application
> (loopback mode - NXP in-house) we have seen 5% improvement in performance on
> LS1088 platform.
>
> W.r.t. the read latencies, they are reduced to avg. ~50 platform cycles from avg. ~140
> platform cycles per memory read transactions which follow this bypass path (on LS2088
> with DPDK l3fwd application).
>
> (Apologies, I cannot share the DPDK/ODP exact performance numbers on the mailing list).
That's understandable, and I'm not sure I'd know how to interpret them
anyway ;) I reckon the percentages make a sufficiently compelling
qualification of the improvement, so it would be good to have that
summarised in the commit log.
>>
>>> Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com>
>>> ---
>>> drivers/iommu/arm-smmu.c | 21 +++++++++++++++------
>>> 1 file changed, 15 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index
>>> ce2a9d4..7010a5c 100644
>>> --- a/drivers/iommu/arm-smmu.c
>>> +++ b/drivers/iommu/arm-smmu.c
>>> @@ -246,6 +246,7 @@ enum arm_smmu_s2cr_privcfg {
>>>
>>> #define ARM_MMU500_ACTLR_CPRE (1 << 1)
>>>
>>> +#define ACR_SMTNMB_TLBEN (1 << 8)
>>
>> ACR is entirely implementation-defined, so there are no generic field names.
>> Please follow the naming convention handily demonstrated in the subsequent
>> context line.
>>
>>> #define ARM_MMU500_ACR_CACHE_LOCK (1 << 26)
>>
>> Actually, can we also please keep these in descending order of bit position like
>> everything else?
>>
>>> #define CB_PAR_F (1 << 0)
>>> @@ -1569,18 +1570,26 @@ static void arm_smmu_device_reset(struct
>> arm_smmu_device *smmu)
>>> for (i = 0; i < smmu->num_mapping_groups; ++i)
>>> arm_smmu_write_sme(smmu, i);
>>>
>>> + /* Get the major rev required for configuring ACR */
>>
>> That comment is nonsense.
>>
>>> + reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID7);
>>> + major = (reg >> ID7_MAJOR_SHIFT) & ID7_MAJOR_MASK;
>>> +
>>> /*
>>> * Before clearing ARM_MMU500_ACTLR_CPRE, need to
>>> * clear CACHE_LOCK bit of ACR first. And, CACHE_LOCK
>>> * bit is only present in MMU-500r2 onwards.
>>> */
>>> - reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID7);
>>> - major = (reg >> ID7_MAJOR_SHIFT) & ID7_MAJOR_MASK;
>>> - if ((smmu->model == ARM_MMU500) && (major >= 2)) {
>>> - reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sACR);
>>> + reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sACR);
>>> + if ((smmu->model == ARM_MMU500) && (major >= 2))
>>> reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
>>> - writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sACR);
>>> - }
>>> +
>>> + /*
>>> + * Set the SMTNMB_TLBEN in ACR so that the transactions which
>>> + * bypass with SMMU due to no stream match found in the SMR table
>>> + * are updated in the TLB's.
>>
>> Or simply, e.g. "Allow unmatched Stream IDs to allocate bypass TLB entries for
>> reduced latency". It's already clear from the code what bit's being set where, we
>> only need to remember *why*.
>>
>>> + */
>>> + reg |= ACR_SMTNMB_TLBEN;
>>> + writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sACR);
>>
>> Are you sure it's perfectly fine to set that implementation-defined bit on any
>> SMMU implementation other than the two-and-a-half ARM Ltd. ones which
>> happen to share the same meaning? I'm certainly not.
>>
>> The correct flow would be something like this:
>>
>> if (smmu->model == ARM_MMU500) {
>> reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID7);
>> major = (reg >> ID7_MAJOR_SHIFT) & ID7_MAJOR_MASK;
>> reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sACR);
>> if (major >= 2)
>> reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
>> reg |= ACR_SMTNMB_TLBEN;
>> writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sACR);
>> }
>>
>> The shape of the current code avoids an extra level of indentation, but once you
>> have to have the nested conditional anyway, it might as well all be predicated
>> appropriately.
>>
>
> Thank you for providing the useful comments. I would incorporate them all in next version :).
Cool. Just for clarity (I realise I was thinking it, but never said it
outright), whilst MMU-40x do share the same feature with the same ACR
bit definition as MMU-500, I'd be inclined not to bother with them.
Since the monolithic microarchitecture means there's normally a separate
MMU-40x per device, if you don't want translation for that device you
can simply not probe the thing to turn it on in the first place.
Robin.
>
> Regards,
> Nipun
>
>> Robin.
>>
>>> /* Make sure all context banks are disabled and clear CB_FSR */
>>> for (i = 0; i < smmu->num_context_banks; ++i) {
>>>
>
^ permalink raw reply
* [PATCH 1/2] arm64: defconfig: enable I2C and DW MMC controller on rockchip platform
From: Andy Yan @ 2016-11-03 11:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473248790-27101-1-git-send-email-andy.yan@rock-chips.com>
Ping
On 2016?09?07? 19:46, Andy Yan wrote:
> I2C and MMC are very basic modules for a board to bootup, as I2C always
> used to configure PMIC and MMC devices often used to store filesytem.
> So enable them here to let the rockchip based arm64 boards can bootup.
>
> Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
> ---
>
> arch/arm64/configs/defconfig | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index eadf485..427b6dc 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -222,6 +222,7 @@ CONFIG_I2C_QUP=y
> CONFIG_I2C_TEGRA=y
> CONFIG_I2C_UNIPHIER_F=y
> CONFIG_I2C_RCAR=y
> +CONFIG_I2C_RK3X=y
> CONFIG_I2C_CROS_EC_TUNNEL=y
> CONFIG_SPI=y
> CONFIG_SPI_ORION=y
> @@ -323,6 +324,7 @@ CONFIG_MMC_SPI=y
> CONFIG_MMC_DW=y
> CONFIG_MMC_DW_EXYNOS=y
> CONFIG_MMC_DW_K3=y
> +CONFIG_MMC_DW_ROCKCHIP=y
> CONFIG_MMC_SUNXI=y
> CONFIG_NEW_LEDS=y
> CONFIG_LEDS_CLASS=y
^ permalink raw reply
* [PATCH V3 6/6] bus: Add support for Tegra Generic Memory Interface
From: Jon Hunter @ 2016-11-03 10:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477576872-2665-7-git-send-email-mirza.krak@gmail.com>
On 27/10/16 15:01, Mirza Krak wrote:
> From: Mirza Krak <mirza.krak@gmail.com>
>
> The Generic Memory Interface bus can be used to connect high-speed
> devices such as NOR flash, FPGAs, DSPs...
>
> Signed-off-by: Mirza Krak <mirza.krak@gmail.com>
> Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
> Tested-on: Colibri T20/T30 on EvalBoard V3.x and GMI-Memory Board
> ---
>
> Changes in v2:
> - Fixed some checkpatch errors
> - Re-ordered probe to get rid of local variables
> - Moved of_platform_default_populate call to the end of probe
> - Use the timing and configuration properties from the child device
> - Added warning if more then 1 child device exist
>
> Changes in v3:
> - added helper function to disable the controller which is used in remove and
> on error.
> - Added logic to parse CS# from "ranges" property with fallback to "reg"
> property
>
> drivers/bus/Kconfig | 8 ++
> drivers/bus/Makefile | 1 +
> drivers/bus/tegra-gmi.c | 267 ++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 276 insertions(+)
> create mode 100644 drivers/bus/tegra-gmi.c
>
> diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
> index 4ed7d26..2e75a7f 100644
> --- a/drivers/bus/Kconfig
> +++ b/drivers/bus/Kconfig
> @@ -141,6 +141,14 @@ config TEGRA_ACONNECT
> Driver for the Tegra ACONNECT bus which is used to interface with
> the devices inside the Audio Processing Engine (APE) for Tegra210.
>
> +config TEGRA_GMI
> + tristate "Tegra Generic Memory Interface bus driver"
> + depends on ARCH_TEGRA
> + help
> + Driver for the Tegra Generic Memory Interface bus which can be used
> + to attach devices such as NOR, UART, FPGA and more.
> +
> +
Nit-pick ... only one additional line above is needed to be consistent
with the rest of the file.
> config UNIPHIER_SYSTEM_BUS
> tristate "UniPhier System Bus driver"
> depends on ARCH_UNIPHIER && OF
> diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
> index ac84cc4..34e2bab 100644
> --- a/drivers/bus/Makefile
> +++ b/drivers/bus/Makefile
> @@ -18,5 +18,6 @@ obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
> obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
> obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
> obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
> +obj-$(CONFIG_TEGRA_GMI) += tegra-gmi.o
> obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o
> obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
> diff --git a/drivers/bus/tegra-gmi.c b/drivers/bus/tegra-gmi.c
> new file mode 100644
> index 0000000..dd9623e
> --- /dev/null
> +++ b/drivers/bus/tegra-gmi.c
> @@ -0,0 +1,267 @@
> +/*
> + * Driver for NVIDIA Generic Memory Interface
> + *
> + * Copyright (C) 2016 Host Mobility AB. All rights reserved.
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/reset.h>
> +
> +#define TEGRA_GMI_CONFIG 0x00
> +#define TEGRA_GMI_CONFIG_GO BIT(31)
> +#define TEGRA_GMI_BUS_WIDTH_32BIT BIT(30)
> +#define TEGRA_GMI_MUX_MODE BIT(28)
> +#define TEGRA_GMI_RDY_BEFORE_DATA BIT(24)
> +#define TEGRA_GMI_RDY_ACTIVE_HIGH BIT(23)
> +#define TEGRA_GMI_ADV_ACTIVE_HIGH BIT(22)
> +#define TEGRA_GMI_OE_ACTIVE_HIGH BIT(21)
> +#define TEGRA_GMI_CS_ACTIVE_HIGH BIT(20)
> +#define TEGRA_GMI_CS_SELECT(x) ((x & 0x7) << 4)
> +
> +#define TEGRA_GMI_TIMING0 0x10
> +#define TEGRA_GMI_MUXED_WIDTH(x) ((x & 0xf) << 12)
> +#define TEGRA_GMI_HOLD_WIDTH(x) ((x & 0xf) << 8)
> +#define TEGRA_GMI_ADV_WIDTH(x) ((x & 0xf) << 4)
> +#define TEGRA_GMI_CE_WIDTH(x) (x & 0xf)
> +
> +#define TEGRA_GMI_TIMING1 0x14
> +#define TEGRA_GMI_WE_WIDTH(x) ((x & 0xff) << 16)
> +#define TEGRA_GMI_OE_WIDTH(x) ((x & 0xff) << 8)
> +#define TEGRA_GMI_WAIT_WIDTH(x) (x & 0xff)
> +
> +struct tegra_gmi_priv {
> + void __iomem *base;
> + struct reset_control *rst;
> + struct clk *clk;
> +
> + u32 snor_config;
> + u32 snor_timing0;
> + u32 snor_timing1;
> +};
> +
> +static void tegra_gmi_disable(struct tegra_gmi_priv *priv)
> +{
> + u32 config;
> +
> + /* stop GMI operation */
> + config = readl(priv->base + TEGRA_GMI_CONFIG);
> + config &= ~TEGRA_GMI_CONFIG_GO;
> + writel(config, priv->base + TEGRA_GMI_CONFIG);
> +
> + reset_control_assert(priv->rst);
> + clk_disable_unprepare(priv->clk);
> +}
> +
> +static void tegra_gmi_init(struct device *dev, struct tegra_gmi_priv *priv)
> +{
> + writel(priv->snor_timing0, priv->base + TEGRA_GMI_TIMING0);
> + writel(priv->snor_timing1, priv->base + TEGRA_GMI_TIMING1);
> +
> + priv->snor_config |= TEGRA_GMI_CONFIG_GO;
> + writel(priv->snor_config, priv->base + TEGRA_GMI_CONFIG);
> +}
> +
> +static int tegra_gmi_parse_dt(struct device *dev, struct tegra_gmi_priv *priv)
> +{
> + struct device_node *child = of_get_next_available_child(dev->of_node,
> + NULL);
> + u32 property, ranges[4];
> + int ret;
> +
> + if (!child) {
> + dev_warn(dev, "no child nodes found\n");
> + return 0;
Don't we want to return an error here? Otherwise, we will call
tegra_gmi_init() with an invalid configuration.
> + }
> +
> + /*
> + * We currently only support one child device due to lack of
> + * chip-select address decoding. Which means that we only have one
> + * chip-select line from the GMI controller.
> + */
> + if (of_get_child_count(dev->of_node) > 1)
> + dev_warn(dev, "only one child device is supported.");
> +
> + if (of_property_read_bool(child, "nvidia,snor-data-width-32bit"))
> + priv->snor_config |= TEGRA_GMI_BUS_WIDTH_32BIT;
> +
> + if (of_property_read_bool(child, "nvidia,snor-mux-mode"))
> + priv->snor_config |= TEGRA_GMI_MUX_MODE;
> +
> + if (of_property_read_bool(child, "nvidia,snor-rdy-active-before-data"))
> + priv->snor_config |= TEGRA_GMI_RDY_BEFORE_DATA;
> +
> + if (of_property_read_bool(child, "nvidia,snor-rdy-inv"))
> + priv->snor_config |= TEGRA_GMI_RDY_ACTIVE_HIGH;
> +
> + if (of_property_read_bool(child, "nvidia,snor-adv-inv"))
> + priv->snor_config |= TEGRA_GMI_ADV_ACTIVE_HIGH;
> +
> + if (of_property_read_bool(child, "nvidia,snor-oe-inv"))
> + priv->snor_config |= TEGRA_GMI_OE_ACTIVE_HIGH;
> +
> + if (of_property_read_bool(child, "nvidia,snor-cs-inv"))
> + priv->snor_config |= TEGRA_GMI_CS_ACTIVE_HIGH;
> +
> + /* Decode the CS# */
> + ret = of_property_read_u32_array(child, "ranges", ranges, 4);
> + if (ret < 0) {
> + /* Invalid binding */
> + if (ret == -EOVERFLOW) {
> + dev_err(dev, "invalid ranges length\n");
> + goto error_cs_decode;
> + }
> +
> + /*
> + * If we reach here it means that the child node has an empty
> + * ranges or it does not exist at all. Attempt to decode the
> + * CS# from the reg property instead.
> + */
> + ret = of_property_read_u32(child, "reg", &property);
> + if (ret < 0) {
> + dev_err(dev, "no reg property found\n");
> + goto error_cs_decode;
> + }
> + } else {
> + property = ranges[1];
> + }
> +
> + priv->snor_config |= TEGRA_GMI_CS_SELECT(property);
Should we make sure the CS is a valid value before setting?
> +
> + /* The default values that are provided below are reset values */
> + if (!of_property_read_u32(child, "nvidia,snor-muxed-width", &property))
> + priv->snor_timing0 |= TEGRA_GMI_MUXED_WIDTH(property);
> + else
> + priv->snor_timing0 |= TEGRA_GMI_MUXED_WIDTH(1);
> +
> + if (!of_property_read_u32(child, "nvidia,snor-hold-width", &property))
> + priv->snor_timing0 |= TEGRA_GMI_HOLD_WIDTH(property);
> + else
> + priv->snor_timing0 |= TEGRA_GMI_HOLD_WIDTH(1);
> +
> + if (!of_property_read_u32(child, "nvidia,snor-adv-width", &property))
> + priv->snor_timing0 |= TEGRA_GMI_ADV_WIDTH(property);
> + else
> + priv->snor_timing0 |= TEGRA_GMI_ADV_WIDTH(1);
> +
> + if (!of_property_read_u32(child, "nvidia,snor-ce-width", &property))
> + priv->snor_timing0 |= TEGRA_GMI_CE_WIDTH(property);
> + else
> + priv->snor_timing0 |= TEGRA_GMI_CE_WIDTH(4);
> +
> + if (!of_property_read_u32(child, "nvidia,snor-we-width", &property))
> + priv->snor_timing1 |= TEGRA_GMI_WE_WIDTH(property);
> + else
> + priv->snor_timing1 |= TEGRA_GMI_WE_WIDTH(1);
> +
> + if (!of_property_read_u32(child, "nvidia,snor-oe-width", &property))
> + priv->snor_timing1 |= TEGRA_GMI_OE_WIDTH(property);
> + else
> + priv->snor_timing1 |= TEGRA_GMI_OE_WIDTH(1);
> +
> + if (!of_property_read_u32(child, "nvidia,snor-wait-width", &property))
> + priv->snor_timing1 |= TEGRA_GMI_WAIT_WIDTH(property);
> + else
> + priv->snor_timing1 |= TEGRA_GMI_WAIT_WIDTH(3);
> +
> +error_cs_decode:
> + if (ret < 0)
> + dev_err(dev, "failed to decode chip-select number\n");
Nit do we need another error message here? Can we add the "failed to
decode CS" part the earlier message?
> +
> + of_node_put(child);
> + return ret;
> +}
> +
> +static int tegra_gmi_probe(struct platform_device *pdev)
> +{
> + struct resource *res;
> + struct device *dev = &pdev->dev;
> + struct tegra_gmi_priv *priv;
> + int ret;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + priv->base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(priv->base))
> + return PTR_ERR(priv->base);
> +
> + priv->clk = devm_clk_get(dev, "gmi");
> + if (IS_ERR(priv->clk)) {
> + dev_err(dev, "can not get clock\n");
> + return PTR_ERR(priv->clk);
> + }
> +
> + priv->rst = devm_reset_control_get(dev, "gmi");
> + if (IS_ERR(priv->rst)) {
> + dev_err(dev, "can not get reset\n");
> + return PTR_ERR(priv->rst);
> + }
> +
> + ret = tegra_gmi_parse_dt(dev, priv);
> + if (ret)
> + return ret;
> +
> + ret = clk_prepare_enable(priv->clk);
> + if (ret) {
> + dev_err(dev, "fail to enable clock.\n");
> + return ret;
> + }
> +
> + reset_control_assert(priv->rst);
> + udelay(2);
> + reset_control_deassert(priv->rst);
> +
> + tegra_gmi_init(dev, priv);
> +
> + ret = of_platform_default_populate(dev->of_node, NULL, dev);
> + if (ret < 0) {
> + dev_err(dev, "fail to create devices.\n");
> + tegra_gmi_disable(priv);
> + return ret;
> + }
> +
> + dev_set_drvdata(dev, priv);
> +
> + return 0;
> +}
> +
> +static int tegra_gmi_remove(struct platform_device *pdev)
> +{
> + struct tegra_gmi_priv *priv = dev_get_drvdata(&pdev->dev);
> +
> + of_platform_depopulate(&pdev->dev);
> +
> + tegra_gmi_disable(priv);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id tegra_gmi_id_table[] = {
> + { .compatible = "nvidia,tegra20-gmi", },
> + { .compatible = "nvidia,tegra30-gmi", },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, tegra_gmi_id_table);
> +
> +static struct platform_driver tegra_gmi_driver = {
> + .probe = tegra_gmi_probe,
> + .remove = tegra_gmi_remove,
> + .driver = {
> + .name = "tegra-gmi",
> + .of_match_table = tegra_gmi_id_table,
> + },
> +};
> +module_platform_driver(tegra_gmi_driver);
> +
> +MODULE_AUTHOR("Mirza Krak <mirza.krak@gmail.com");
> +MODULE_DESCRIPTION("NVIDIA Tegra GMI Bus Driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.1.4
>
Cheers
Jon
--
nvpublic
^ permalink raw reply
* arm64 build failure with CONFIG_ARM64_LSE_ATOMICS=y
From: Suzuki K Poulose @ 2016-11-03 10:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161102232854.GO22791@arm.com>
On 02/11/16 23:28, Will Deacon wrote:
> Hi Artem,
>
> On Wed, Nov 02, 2016 at 05:44:27PM +0100, Artem Savkov wrote:
>> Hello Catalin,
>>
>> Looks like your patch "efd9e03 arm64: Use static keys for CPU features"
>> breaks arm64 build with "CONFIG_ARM64_LSE_ATOMICS=y" because it creates a
>> circular dependency for asm/lse.h through jump_label.h:
>>
>> CC arch/arm64/kernel/asm-offsets.s
>> In file included from ./arch/arm64/include/asm/atomic.h:34:0,
>> from ./include/linux/atomic.h:4,
>> from ./include/linux/jump_label.h:169,
>> from ./arch/arm64/include/asm/cpufeature.h:12,
>> from ./arch/arm64/include/asm/alternative.h:4,
>> from ./arch/arm64/include/asm/lse.h:7,
>> from ./arch/arm64/include/asm/spinlock.h:19,
>> from ./include/linux/spinlock.h:87,
>> from ./include/linux/seqlock.h:35,
>> from ./include/linux/time.h:5,
>> from ./include/uapi/linux/timex.h:56,
>> from ./include/linux/timex.h:56,
>> from ./include/linux/sched.h:19,
>> from arch/arm64/kernel/asm-offsets.c:21:
>> ./arch/arm64/include/asm/atomic_lse.h: In function ?atomic_andnot?:
>> ./arch/arm64/include/asm/atomic_lse.h:35:15: error: expected string literal before ? ?
>> asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC(op), \
>>
>> ...
>>
>> ./arch/arm64/include/asm/cmpxchg.h: In function ?__xchg_case_1?:
>> ./arch/arm64/include/asm/cmpxchg.h:38:15: error: expected string literal before ?ARM64_LSE_ATOMIC_INSN?
>> asm volatile(ARM64_LSE_ATOMIC_INSN( \
>
> I'm unable to reproduce this. I've tried enabling LSE with defconfig and
> mainline, using compilers that both do and don't support the instructions.
I am not able to reproduce it either. One minor problem I see with the commit could
be fixed with the following change : Does it help ?
----8>-----
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 758d74f..62db988 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -9,7 +9,6 @@
#ifndef __ASM_CPUFEATURE_H
#define __ASM_CPUFEATURE_H
-#include <linux/jump_label.h>
#include <asm/hwcap.h>
#include <asm/sysreg.h>
@@ -45,6 +44,7 @@
#ifndef __ASSEMBLY__
+#include <linux/jump_label.h>
#include <linux/kernel.h>
/* CPU feature register tracking */
Suzuki
^ permalink raw reply related
* [PATCH V3 5/6] ARM: tegra: Add Tegra20 GMI support
From: Jon Hunter @ 2016-11-03 10:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477576872-2665-6-git-send-email-mirza.krak@gmail.com>
On 27/10/16 15:01, Mirza Krak wrote:
> From: Mirza Krak <mirza.krak@gmail.com>
>
> Add a device node for the GMI controller found on Tegra20.
>
> Signed-off-by: Mirza Krak <mirza.krak@gmail.com>
> Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
> Tested-on: Colibri T20/T30 on EvalBoard V3.x and GMI-Memory Board
> ---
>
> Changes in v2:
> - added address-cells, size-cells and ranges properties
>
> Changes in v3:
> - fixed range address which is not the same as Tegra30.
>
> arch/arm/boot/dts/tegra20.dtsi | 16 +++++++++++++++-
> 1 file changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
> index 2207c08..b22cddb 100644
> --- a/arch/arm/boot/dts/tegra20.dtsi
> +++ b/arch/arm/boot/dts/tegra20.dtsi
> @@ -1,4 +1,4 @@
> -#include <dt-bindings/clock/tegra20-car.h>
> +include <dt-bindings/clock/tegra20-car.h>
After fixing up this, can you also ...
> #include <dt-bindings/gpio/tegra-gpio.h>
> #include <dt-bindings/pinctrl/pinctrl-tegra.h>
> #include <dt-bindings/interrupt-controller/arm-gic.h>
> @@ -376,6 +376,20 @@
> status = "disabled";
> };
>
> +
Drop this additional line?
> + gmi at 70009000 {
> + compatible = "nvidia,tegra20-gmi";
> + reg = <0x70009000 0x1000>;
> + #address-cells = <2>;
> + #size-cells = <1>;
> + ranges = <0 0 0xd0000000 0xfffffff>;
> + clocks = <&tegra_car TEGRA20_CLK_NOR>;
> + clock-names = "gmi";
> + resets = < &tegra_car 42>;
Get rid of this additional space?
> + reset-names = "gmi";
> + status = "disabled";
> + };
> +
Otherwise ...
Acked-by: Jon Hunter <jonathanh@nvidia.com>
Cheers
Jon
--
nvpublic
^ permalink raw reply
* [PATCHv6] support for AD5820 camera auto-focus coil
From: Pavel Machek @ 2016-11-03 10:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160818202559.GF3182@valkosipuli.retiisi.org.uk>
Hi!
> > > > > Yeah. I just compiled it but haven't tested it. I presume it'll work. :-)
> > > >
> > > > I'm testing it on n900. I guess simpler hardware with ad5820 would be better for the
> > > > test...
> > > >
> > > > What hardware do you have?
> > >
> > > N900. What else could it be? :-) :-)
> >
> > Heh. Basically anything is easier to develop for than n900 :-(.
>
> Is it?
>
> I actually find the old Nokia devices very practical. It's easy to boot your
> own kernel and things just work... until musb broke a bit recently. It
> requires reconnecting the usb cable again to function.
>
> I have to admit I mostly use an N9.
Well, if you compare that to development on PC, I prefer PC.
Even arm development boards are usually easier, as they don't need too
complex userspace, and do have working serial ports.
But I do have a serial adapter for N900 now (thanks, sre), so my main
problem now is that N900 takes a lot of time to boot into usable
state.
Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161103/fd30267c/attachment.sig>
^ permalink raw reply
* [PATCH] ASoC: sun4i-i2s: Implement capture support
From: Maxime Ripard @ 2016-11-03 10:20 UTC (permalink / raw)
To: linux-arm-kernel
The i2s driver was only implementing playback for now. Implement capture to
make sure that's not a limitation anymore.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
sound/soc/sunxi/sun4i-i2s.c | 52 ++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 49 insertions(+), 3 deletions(-)
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 08f143af7235..f24d19526603 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -95,6 +95,7 @@ struct sun4i_i2s {
unsigned int mclk_freq;
+ struct snd_dmaengine_dai_dma_data capture_dma_data;
struct snd_dmaengine_dai_dma_data playback_dma_data;
};
@@ -350,6 +351,27 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return 0;
}
+static void sun4i_i2s_start_capture(struct sun4i_i2s *i2s)
+{
+ /* Flush RX FIFO */
+ regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG,
+ SUN4I_I2S_FIFO_CTRL_FLUSH_RX,
+ SUN4I_I2S_FIFO_CTRL_FLUSH_RX);
+
+ /* Clear RX counter */
+ regmap_write(i2s->regmap, SUN4I_I2S_RX_CNT_REG, 0);
+
+ /* Enable RX Block */
+ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
+ SUN4I_I2S_CTRL_RX_EN,
+ SUN4I_I2S_CTRL_RX_EN);
+
+ /* Enable RX DRQ */
+ regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG,
+ SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN,
+ SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN);
+}
+
static void sun4i_i2s_start_playback(struct sun4i_i2s *i2s)
{
/* Flush TX FIFO */
@@ -371,6 +393,18 @@ static void sun4i_i2s_start_playback(struct sun4i_i2s *i2s)
SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN);
}
+static void sun4i_i2s_stop_capture(struct sun4i_i2s *i2s)
+{
+ /* Disable RX Block */
+ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
+ SUN4I_I2S_CTRL_RX_EN,
+ 0);
+
+ /* Disable RX DRQ */
+ regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG,
+ SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN,
+ 0);
+}
static void sun4i_i2s_stop_playback(struct sun4i_i2s *i2s)
{
@@ -397,7 +431,7 @@ static int sun4i_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
sun4i_i2s_start_playback(i2s);
else
- return -EINVAL;
+ sun4i_i2s_start_capture(i2s);
break;
case SNDRV_PCM_TRIGGER_STOP:
@@ -406,7 +440,7 @@ static int sun4i_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
sun4i_i2s_stop_playback(i2s);
else
- return -EINVAL;
+ sun4i_i2s_stop_capture(i2s);
break;
default:
@@ -482,7 +516,9 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai)
{
struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
- snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, NULL);
+ snd_soc_dai_init_dma_data(dai,
+ &i2s->playback_dma_data,
+ &i2s->capture_dma_data);
snd_soc_dai_set_drvdata(dai, i2s);
@@ -491,6 +527,13 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai)
static struct snd_soc_dai_driver sun4i_i2s_dai = {
.probe = sun4i_i2s_dai_probe,
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -653,6 +696,9 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
i2s->playback_dma_data.addr = res->start + SUN4I_I2S_FIFO_TX_REG;
i2s->playback_dma_data.maxburst = 4;
+ i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG;
+ i2s->capture_dma_data.maxburst = 4;
+
pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) {
ret = sun4i_i2s_runtime_resume(&pdev->dev);
--
2.10.1
^ permalink raw reply related
* [PATCH v7 3/3] iio: adc: add support for Allwinner SoCs ADC
From: Quentin Schulz @ 2016-11-03 10:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161103101601.24529-1-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.
The thermal sensor requires the IP to be in touchscreen mode to return correct
values. Therefore, if the user is continuously reading the ADC channel(s), the
thermal framework in which the thermal sensor is registered will switch the IP
in touchscreen mode to get a temperature value and requires a delay of 100ms
(because of the mode switching), then the ADC will switch back to ADC mode and
requires also a delay of 100ms. If the ADC readings are critical to user and the
SoC temperature is not, this driver is capable of not registering the thermal
sensor in the thermal framework and thus, "quicken" the ADC readings.
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>
---
v7:
- add Kconfig depends on !TOUCHSCREEN_SUN4I,
- remove Kconfig selects THERMAL_OF,
- do not register thermal sensor if CONFIG_THERMAL_OF is disabled,
- disable irq in irq_handler rather than in read_raw,
- add delay when switching the IP's mode or channel (delay empirically found),
- quicken thermal sensor interrupt period,
- add masks for channel bits,
- fix deadlock in sun4i_gpadc_read if regmap_read/write fails,
- move some logic from sun4i_gpadc_read to sun4i_prepare_for_irq,
- mark last busy for runtime_pm only on success in sun4i_gpadc_read,
- remove cached values,
- increase wait_for_completion_timeout timeout to 1s to be sure to not miss the
thermal interrupt,
- add voltage scale,
- use devm_iio_device_register,
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/iio/adc/Kconfig | 17 ++
drivers/iio/adc/Makefile | 1 +
drivers/iio/adc/sun4i-gpadc-iio.c | 605 ++++++++++++++++++++++++++++++++++++++
include/linux/mfd/sun4i-gpadc.h | 2 +
4 files changed, 625 insertions(+)
create mode 100644 drivers/iio/adc/sun4i-gpadc-iio.c
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 7edcf32..9aa3c945 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -434,6 +434,23 @@ config STX104
The base port addresses for the devices may be configured via the base
array module parameter.
+config SUN4I_GPADC
+ tristate "Support for the Allwinner SoCs GPADC"
+ depends on IIO
+ depends on MFD_SUN4I_GPADC
+ depends on !TOUCHSCREEN_SUN4I
+ 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.
+
+ The thermal sensor is activated by default but slows down ADC
+ readings. You can disable CONFIG_THERMAL_OF to disable the CPU thermal
+ sensor if you want faster ADC readings.
+
+ 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 7a40c04..18ce8d6 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -41,6 +41,7 @@ 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_STX104) += stx104.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_ADC12138) += ti-adc12138.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..f275ccb
--- /dev/null
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -0,0 +1,605 @@
+/* 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/delay.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);
+ unsigned int adc_chan_mask;
+};
+
+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,
+ .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,
+};
+
+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,
+ .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,
+};
+
+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,
+ .adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK,
+};
+
+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), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .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 const struct iio_chan_spec sun4i_gpadc_channels_no_temp[] = {
+ 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"),
+};
+
+static int sun4i_prepare_for_irq(struct iio_dev *indio_dev, int channel,
+ unsigned int irq)
+{
+ struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
+ int ret;
+ u32 reg;
+
+ pm_runtime_get_sync(indio_dev->dev.parent);
+
+ 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;
+
+ ret = regmap_read(info->regmap, SUN4I_GPADC_CTRL1, ®);
+ 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));
+ /*
+ * When the IP changes channel, it needs a bit of time to get
+ * correct values.
+ */
+ if ((reg & info->data->adc_chan_mask) !=
+ info->data->adc_chan_select(channel))
+ mdelay(10);
+
+ } 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;
+
+ /*
+ * When the IP changes mode between ADC or touchscreen, it
+ * needs a bit of time to get correct values.
+ */
+ if ((reg & info->data->tp_adc_select) != info->data->tp_adc_select)
+ mdelay(100);
+
+ return 0;
+}
+
+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;
+
+ mutex_lock(&info->mutex);
+
+ ret = sun4i_prepare_for_irq(indio_dev, channel, irq);
+ if (ret)
+ goto err;
+
+ enable_irq(irq);
+
+ /*
+ * The temperature sensor throws an interruption periodically (currently
+ * set at periods of ~0.6s in sun4i_gpadc_runtime_resume). A 1s delay
+ * makes sure an interruption occurs in normal conditions. If it doesn't
+ * occur, then there is a timeout.
+ */
+ if (!wait_for_completion_timeout(&info->completion,
+ msecs_to_jiffies(1000))) {
+ ret = -ETIMEDOUT;
+ goto err;
+ }
+
+ if (irq == info->fifo_data_irq)
+ *val = info->adc_data;
+ else
+ *val = info->temp_data;
+
+ ret = 0;
+ pm_runtime_mark_last_busy(indio_dev->dev.parent);
+
+err:
+ pm_runtime_put_autosuspend(indio_dev->dev.parent);
+ mutex_unlock(&info->mutex);
+
+ 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:
+ if (chan->type == IIO_VOLTAGE) {
+ /* 3000mV / 4096 * raw */
+ *val = 0;
+ *val2 = 732421875;
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+
+ 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))
+ goto out;
+
+ if (!regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, &info->temp_data))
+ complete(&info->completion);
+
+out:
+ disable_irq_nosync(info->temp_data_irq);
+ 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))
+ goto out;
+
+ if (!regmap_read(info->regmap, SUN4I_GPADC_DATA, &info->adc_data))
+ complete(&info->completion);
+
+out:
+ disable_irq_nosync(info->fifo_data_irq);
+ 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; ~0.6s */
+ regmap_write(info->regmap, SUN4I_GPADC_TPR,
+ SUN4I_GPADC_TPR_TEMP_ENABLE |
+ SUN4I_GPADC_TPR_TEMP_PERIOD(800));
+
+ 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 (sun4i_gpadc_temp_read(info->indio_dev, &val))
+ return -ETIMEDOUT;
+
+ 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;
+ 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;
+
+ /*
+ * Since the thermal sensor needs the IP to be in touchscreen mode and
+ * there is no register to know if the IP has finished its transition
+ * between the two modes, a delay is required when switching modes. This
+ * slows down ADC readings while the latter are critical data to the
+ * user. Disabling CONFIG_THERMAL_OF in kernel configuration allows the
+ * user to avoid registering the thermal sensor (thus unavailable) and
+ * does not switch between modes thus "quicken" the ADC readings.
+ * The thermal sensor should be enabled by default since the SoC
+ * temperature is usually more critical than ADC readings.
+ */
+
+ if (IS_ENABLED(CONFIG_THERMAL_OF)) {
+ /*
+ * 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));
+ goto err;
+ }
+ } else {
+ indio_dev->num_channels =
+ ARRAY_SIZE(sun4i_gpadc_channels_no_temp);
+ indio_dev->channels = sun4i_gpadc_channels_no_temp;
+ }
+
+ 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);
+
+ if (IS_ENABLED(CONFIG_THERMAL_OF)) {
+ 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;
+
+ if (IS_ENABLED(CONFIG_THERMAL_OF)) {
+ 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 = devm_iio_device_register(&pdev->dev, indio_dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "could not register the device\n");
+ goto err_map;
+ }
+
+ return 0;
+
+err_map:
+ if (IS_ENABLED(CONFIG_THERMAL_OF))
+ 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 iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ if (IS_ENABLED(CONFIG_THERMAL_OF))
+ iio_map_array_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");
diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h
index d7a29f2..509e736 100644
--- a/include/linux/mfd/sun4i-gpadc.h
+++ b/include/linux/mfd/sun4i-gpadc.h
@@ -28,6 +28,7 @@
#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))
+#define SUN4I_GPADC_CTRL1_ADC_CHAN_MASK GENMASK(2, 0)
/* TP_CTRL1 bits for sun6i SOCs */
#define SUN6I_GPADC_CTRL1_TOUCH_PAN_CALI_EN BIT(7)
@@ -35,6 +36,7 @@
#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 SUN6I_GPADC_CTRL1_ADC_CHAN_MASK GENMASK(3, 0)
#define SUN4I_GPADC_CTRL2 0x08
--
2.9.3
^ permalink raw reply related
* [PATCH v7 2/3] ARM: sunxi_defconfig: Add CONFIG_THERMAL_OF
From: Quentin Schulz @ 2016-11-03 10:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161103101601.24529-1-quentin.schulz@free-electrons.com>
This enables CONFIG_THERMAL_OF by default for sunxi_defconfig.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
added in v7
arch/arm/configs/sunxi_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index 714da33..8aaeae3 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -83,6 +83,7 @@ CONFIG_GPIO_SYSFS=y
CONFIG_POWER_SUPPLY=y
CONFIG_AXP20X_POWER=y
CONFIG_THERMAL=y
+CONFIG_THERMAL_OF=y
CONFIG_CPU_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_SUNXI_WATCHDOG=y
--
2.9.3
^ permalink raw reply related
* [PATCH v7 1/3] input: touchscreen: TOUCHSCREEN_SUN4I depends on !SUN4I_GPADC
From: Quentin Schulz @ 2016-11-03 10:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161103101601.24529-1-quentin.schulz@free-electrons.com>
SUN4I_GPADC and TOUCHSCREEN_SUN4I are incompatible (both are drivers
for Allwinner SoCs' ADC). This makes sure TOUCHSCREEN_SUN4I isn't
enabled while SUN4I_GPADC is enabled.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
added in v7
drivers/input/touchscreen/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index efca013..c618cb9 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1120,6 +1120,7 @@ config TOUCHSCREEN_SUN4I
depends on ARCH_SUNXI || COMPILE_TEST
depends on HWMON
depends on THERMAL || !THERMAL_OF
+ depends on !SUN4I_GPADC
help
This selects support for the resistive touchscreen controller
found on Allwinner sunxi SoCs.
--
2.9.3
^ permalink raw reply related
* [PATCH v7 0/3] add support for Allwinner SoCs ADC
From: Quentin Schulz @ 2016-11-03 10:15 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).
When changing modes or channels, the IP is in inconsistent mode and has no
register or interrupt to notify the kernel when it's stable and ready to return
correct values. Therefore, we add a delay of 100ms when changing modes and 10ms
when changing channels. These values have been found empirically.
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.
The thermal sensor requires the IP to be in touchscreen mode to return correct
values. Therefore, if the user is continuously reading the ADC channel(s), the
thermal framework in which the thermal sensor is registered will switch the IP
in touchscreen mode to get a temperature value and requires a delay of 100ms
(because of the mode switching), then the ADC will switch back to ADC mode and
requires also a delay of 100ms. If the ADC readings are critical to user and the
SoC temperature is not, this driver is capable of not registering the thermal
sensor in the thermal framework and thus, "quicken" the ADC readings. In most
use cases, the SoC temperature is more critical (for cpu throttling for example
or activating cooling devices) than ADC readings, thus it is enabled by default
in multi_v7_defconfig and in sunxi_defconfig (default being added in this patch
series).
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.
This patch series requires this[1] patch which has already been merged by Lee
Jones.
[1] https://patchwork.kernel.org/patch/9333547/
Quentin Schulz (3):
input: touchscreen: TOUCHSCREEN_SUN4I depends on !SUN4I_GPADC
ARM: sunxi_defconfig: Add CONFIG_THERMAL_OF
iio: adc: add support for Allwinner SoCs ADC
arch/arm/configs/sunxi_defconfig | 1 +
drivers/iio/adc/Kconfig | 17 ++
drivers/iio/adc/Makefile | 1 +
drivers/iio/adc/sun4i-gpadc-iio.c | 605 ++++++++++++++++++++++++++++++++++++++
drivers/input/touchscreen/Kconfig | 1 +
include/linux/mfd/sun4i-gpadc.h | 2 +
6 files changed, 627 insertions(+)
create mode 100644 drivers/iio/adc/sun4i-gpadc-iio.c
--
2.9.3
^ permalink raw reply
* [PATCH V3 4/6] ARM: tegra: Add Tegra30 GMI support
From: Jon Hunter @ 2016-11-03 10:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477576872-2665-5-git-send-email-mirza.krak@gmail.com>
On 27/10/16 15:01, Mirza Krak wrote:
> From: Mirza Krak <mirza.krak@gmail.com>
>
> Add a device node for the GMI controller found on Tegra30.
>
> Signed-off-by: Mirza Krak <mirza.krak@gmail.com>
> Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
> Tested-on: Colibri T20/T30 on EvalBoard V3.x and GMI-Memory Board
> ---
>
> Changes in v2:
> - added address-cells, size-cells and ranges properties
>
> Changes in v3:
> - no changes
>
> arch/arm/boot/dts/tegra30.dtsi | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
> index 5030065..bbb1c00 100644
> --- a/arch/arm/boot/dts/tegra30.dtsi
> +++ b/arch/arm/boot/dts/tegra30.dtsi
> @@ -439,6 +439,19 @@
> status = "disabled";
> };
>
> + gmi at 70009000 {
> + compatible = "nvidia,tegra30-gmi";
> + reg = <0x70009000 0x1000>;
> + #address-cells = <2>;
> + #size-cells = <1>;
> + ranges = <0 0 0x48000000 0x7ffffff>;
> + clocks = <&tegra_car TEGRA30_CLK_NOR>;
> + clock-names = "gmi";
> + resets = <&tegra_car 42>;
> + reset-names = "gmi";
> + status = "disabled";
> + };
> +
Acked-by: Jon Hunter <jonathanh@nvidia.com>
Cheers
Jon
--
nvpublic
^ permalink raw reply
* [PATCH V3 1/6] clk: tegra: add TEGRA20_CLK_NOR to init table
From: Jon Hunter @ 2016-11-03 10:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477576872-2665-2-git-send-email-mirza.krak@gmail.com>
Hi Mirza,
On 27/10/16 15:01, Mirza Krak wrote:
> From: Mirza Krak <mirza.krak@gmail.com>
>
> Add TEGRA20_CLK_NOR to init table and set default rate to 92 MHz which
> is max rate.
>
> The maximum rate value of 92 MHz is pulled from the downstream L4T
> kernel.
Thanks for adding this. I assume that this is from an L4T r16 release
with a v3.1 kernel. I had a quick poke through the kernel sources for
v3.1 but was unable to see where this is set. Obviously v3.1 did not
have CCF and so everything seems to be in the arch/arm/mach-tegra
directory for setting up clocks. Can you point me to the appropriate
sources so I can ACK this?
Cheers
Jon
--
nvpublic
^ permalink raw reply
* how to enable suspend to ram for arm-64 bits
From: Pavel Machek @ 2016-11-03 9:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161019131145.GA11036@leverpostej>
On Wed 2016-10-19 14:11:45, Mark Rutland wrote:
> On Wed, Oct 19, 2016 at 11:42:27AM +0200, Pavel Machek wrote:
> > On Tue 2016-10-18 11:45:39, Mark Rutland wrote:
>
> > Either the lowlevel suspend code is stable and bug free, and then
> > having that code is not a problem.
>
> This ignores the cost of maintaining that code. Kernel APIs change over
> time, and no code is ever completely stable, even if at one point in
> time it happens to be bug-free.
Well, kernel interfaces only change when there's good reason for a
change, and if you force stable binary interface to external
component, and there _is_ need for a change, we are all screwed.
> > BSD is better than closed source, but it also means that you will not
> > get the sources from your hw vendor.
>
> That depends on your hardware vendor, as always. There are a number of
> platform ports in the upstream ATF repo.
>
> It's also worth considering that a number of 32-bit arm parts require
> closed firmware (as far as I can tell, including the N900).
Yeah, but we are trying to remove closed firmware. Don't make people
add more of it...
> > Being separate module means it will be hard to debug, in area where
> > debugging is already pretty hard.
>
> It can be harder, yes. There are also benefits, given the same code can
> be tested on a variety of platforms.
What benefits? You are able to share code between platforms in kernel,
too.
> > Can it do advanced stuff like deep powersaving on N900 idle?
>
> Sorry, I don't know precisely what you're referring to.
>
> It can do things like shutting down entire CPU clusters (and IIRC
> associated interconnect) when all relevant CPUs are idle, if that's what
> you mean.
I mean equivalent power savings between idle system and system in
s2ram.
Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161103/b3b419d1/attachment.sig>
^ permalink raw reply
* [PATCH 0/5] drm/sun4i: Handle TV overscan
From: Russell King - ARM Linux @ 2016-11-03 9:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161103090106.dq2bn4z7m2hzhi53@lukather>
On Thu, Nov 03, 2016 at 10:01:06AM +0100, Maxime Ripard wrote:
> Hi Russell,
>
> On Mon, Oct 31, 2016 at 08:42:34AM +0000, Russell King - ARM Linux wrote:
> > On Tue, Oct 18, 2016 at 12:03:49PM +0200, Maxime Ripard wrote:
> > > The first one is that this overscanning should be reported by the
> > > connector I guess? but this is really TV specific, so we need one way
> > > to let the user tell how the image is displayed on its side, and we
> > > cannot really autodetect it, and this needs to be done at runtime so
> > > that we can present some shiny interface to let it select which
> > > overscan ratio works for him/her.
> >
> > See xbmc... they go through a nice shiny setup which includes adjusting
> > the visible area. From what I remember, it has pointers on each corner
> > which you can adjust to be just visible on the screen, so xbmc knows
> > how much overscan there is, and xbmc itself reduces down to the user
> > set size.
I was replying to your comment "so we need one way to let the user tell
how the image is displayed".
> Yes. And that is an XBMC only solution, that doesn't work with the
> fbdev emulation and is probably doing an additional composition to
> scale down and center their frames through OpenGL.
Well, it will have to be doing a scaling step anyway. If the video
frame is a different size to the active area, scaling is required
no matter what. A 576p SD image needs to be scaled up, and a 1080p
image would need to be scaled down for a 1080p overscanned display
with a reduced active area to counter the overscanning - no matter
how you do it.
For graphics, userspace could add mode(s) with increased porches and
reduced active area itself to achieve an underscanned display on a
timing which the display device always overscans - there's no need to
do that in the kernel, all the APIs are there to be able to do it
already.
That means your framebuffer will be smaller, but that's the case
anyway.
> > > The second one is that we still need to expose the reduced modes to
> > > userspace, and not only the displayed size, so that the applications
> > > know what they must draw on. But I guess this could be adjusted by the
> > > core too.
> > >
> > > In order to work consistently, I think all planes should be adjusted
> > > that way, so that relative coordinates are from the primary plane
> > > origin, and not the display origin. But that could be adjusted too by
> > > the core I guess.
> >
> > I'm not sure about that - we want the graphics to be visible, but that
> > may not be appropriate for an video overlay frame. It's quite common
> > for (eg) broadcast video to contain dead pixels or other artifacts on
> > the right hand side, and the broadcast video expects overscan to be
> > present.
> >
> > I know this because I have run my TV with overscan disabled, even for
> > broadcast TV.
>
> I know, but on this particular hardware, composite really is just
> another video output. There's not even a TV receiver in it, so I don't
> think we have to worry about it.
Whether or not there's a TV receiver is irrelevant - if you can decode
broadcast video, then you run into the problem. For example, if you
plug in a USB DVB stick, stream it across the network, etc.
Remember, you're proposing a generic solution, so making arguments
about things that are not possible with your specific hardware isn't
really that relevant to a generic solution.
So, I may want my graphics to appear on an overscanned display such
that I can see the borders, but I may want the overlaid video to use
the full active area (including overscan) to hide some of the broadcast
mess at the edges of the screen.
> > Yea, that's quite sad, "analog" has become a dirty word, but really
> > this has nothing to do with "analog" at all - there are LCD TVs (and
> > some monitors) out there which take HDMI signals but refuse to
> > disable overscan no matter what you do to them if you provide them
> > with a "broadcast" mode - so the analog excuse is very poor.
>
> I'd agree with you, but I was also told to not turn that into a
> generic code and deal with that in my driver.
I guess whoever told you that was wrong. I used to have a cheap TV
here which took HDMI, and always overscans broadcast modes, and
underscans PC modes. No amount of fiddling with various settings
(either in the TV or AVI frames) changes that.
I've run into that with a _monitor_ that Andrew Hutton has, which has
a HDMI input - exactly the same thing - 1080p, 720p etc are all
unconditionally overscanned, 1024x768 etc are all unconditionally
underscanned and there's nothing that can be done to change it.
The problem is that TVs are at liberty to have this behaviour, so
the overscaned problem is always going to be there, and each driver
should not be dealing with it in their own specific ways.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* [PATCH] video: ARM CLCD: fix Vexpress regression
From: Linus Walleij @ 2016-11-03 9:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <f95e05ef-e8e0-c5f4-9635-ae392c1812a3@ti.com>
On Wed, Nov 2, 2016 at 9:34 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> On 20/10/16 09:46, Linus Walleij wrote:
>> The CLCD does not come up on Versatile Express as it does not
>> (currently) have a syscon node for controlling the block apart
>> from the CLCD itself. Make sure the .init() function can bail
>> out without an error making it probe again.
>>
>> Reported-by: Amit Pundir <amit.pundir@linaro.org>
>> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
>> ---
>> drivers/video/fbdev/amba-clcd-versatile.c | 3 ++-
>> 1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/video/fbdev/amba-clcd-versatile.c b/drivers/video/fbdev/amba-clcd-versatile.c
>> index 19ad8645d93c..d909b7dda14d 100644
>> --- a/drivers/video/fbdev/amba-clcd-versatile.c
>> +++ b/drivers/video/fbdev/amba-clcd-versatile.c
>> @@ -527,7 +527,8 @@ int versatile_clcd_init_panel(struct clcd_fb *fb,
>> &clcd_id);
>> if (!np) {
>> dev_err(dev, "no Versatile syscon node\n");
>> - return -ENODEV;
>> + /* Vexpress does not have this */
>> + return 0;
>> }
>> versatile_clcd_type = (enum versatile_clcd)clcd_id->data;
>
> Actually, the above doesn't look correct. If this is not an error, then
> the driver shouldn't print an error.
>
> Shall I just remove the print?
You're right, sorry for not thinking deeper :(
Just cut the print.
Thanks!
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 3/3] ARM: dts: Add gyro and accel to APQ8060 Dragonboard
From: Linus Walleij @ 2016-11-03 9:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478164390-21613-1-git-send-email-linus.walleij@linaro.org>
This adds the MPU-3050 gyroscope and the KXSD9 accelerometer to
the Qualcomm APQ8060 Dragonboard. The KXSD9 is mounted beyond the
MPU-3050 and appear as a subdevice beyond it. We set up the
required GPIO and interrupt lines to make the devices work.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v3:
- Move the interrupt to the pm8058 alias to reflect the two patches
properly specifying the PMIC as interrupt parent.
ChangeLog v1->v2:
- Use the new I2C mux gate bindings from Peter Rosin (merged to
the I2C subsystem)
---
arch/arm/boot/dts/qcom-apq8060-dragonboard.dts | 53 ++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts b/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
index ea660ffa03ea..c1b99c9cb318 100644
--- a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
+++ b/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
@@ -220,6 +220,14 @@
function = "ebi2";
};
};
+
+ /* Interrupt line for the KXSD9 accelerometer */
+ dragon_kxsd9_gpios: kxsd9 {
+ irq {
+ pins = "gpio57"; /* IRQ line */
+ bias-pull-up;
+ };
+ };
};
qcom,ssbi at 500000 {
@@ -272,6 +280,15 @@
power-source = <PM8058_GPIO_S3>;
};
};
+ dragon_mpu3050_gpios: mpu3050-gpios {
+ pinconf {
+ pins = "gpio17";
+ function = "normal";
+ input-enable;
+ bias-disable;
+ power-source = <PM8058_GPIO_S3>;
+ };
+ };
dragon_sdcc3_gpios: sdcc3-gpios {
pinconf {
pins = "gpio22";
@@ -389,6 +406,42 @@
vddd-supply = <&pm8058_lvs0>; // 1.8V
vdda-supply = <&pm8058_l14>; // 2.85V
};
+ mpu3050 at 68 {
+ compatible = "invensense,mpu3050";
+ reg = <0x68>;
+ /*
+ * GPIO17 has interrupt 208 on the
+ * PM8058, it is pulled high by a 10k
+ * resistor to VLOGIC so needs to be
+ * active low/falling edge.
+ */
+ interrupt-parent = <&pm8058>;
+ interrupts = <208 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_mpu3050_gpios>;
+ vlogic-supply = <&pm8058_lvs0>; // 1.8V
+ vdd-supply = <&pm8058_l14>; // 2.85V
+
+ /*
+ * The MPU-3050 acts as a hub for the
+ * accelerometer.
+ */
+ i2c-gate {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ kxsd9 at 18 {
+ compatible = "kionix,kxsd9";
+ reg = <0x18>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <57 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_kxsd9_gpios>;
+ iovdd-supply = <&pm8058_lvs0>; // 1.8V
+ vdd-supply = <&pm8058_l14>; // 2.85V
+ };
+ };
+ };
};
};
--
2.7.4
^ permalink raw reply related
* [PATCH 2/3] ARM: dts: reference PM8058 as IRQ parent
From: Linus Walleij @ 2016-11-03 9:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478164390-21613-1-git-send-email-linus.walleij@linaro.org>
Some nodes are referencing the pm8058_gpio as IRQ parent, but
the HW IRQ offset they are supplying is actually that for the
parent to that controller: the PM8058 itself. Since that is the
proper parent, reference it directly.
We can switch this to the pm8058_gpio and the proper offset
once we have fixed the SSBI GPIO driver to properly deal with
the hierarchical IRQ domain and get proper local offset
translation.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
arch/arm/boot/dts/qcom-apq8060-dragonboard.dts | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts b/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
index 4a532ddab53a..ea660ffa03ea 100644
--- a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
+++ b/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
@@ -369,8 +369,8 @@
ak8975 at 0c {
compatible = "asahi-kasei,ak8975";
reg = <0x0c>;
- /* GPIO33 has interrupt 224 on the PM8058 */
- interrupt-parent = <&pm8058_gpio>;
+ /* FIXME: GPIO33 has interrupt 224 on the PM8058 */
+ interrupt-parent = <&pm8058>;
interrupts = <224 IRQ_TYPE_EDGE_RISING>;
pinctrl-names = "default";
pinctrl-0 = <&dragon_ak8975_gpios>;
@@ -380,8 +380,8 @@
bmp085 at 77 {
compatible = "bosch,bmp085";
reg = <0x77>;
- /* GPIO16 has interrupt 207 on the PM8058 */
- interrupt-parent = <&pm8058_gpio>;
+ /* FIXME: GPIO16 has interrupt 207 on the PM8058 */
+ interrupt-parent = <&pm8058>;
interrupts = <207 IRQ_TYPE_EDGE_RISING>;
reset-gpios = <&tlmm 86 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
--
2.7.4
^ permalink raw reply related
* [PATCH 1/3] ARM: dts: rename MSM8660/APQ8060 pmicintc to pm8058
From: Linus Walleij @ 2016-11-03 9:13 UTC (permalink / raw)
To: linux-arm-kernel
The name "pmicintc" is ambiguous: there is a second power
management IC named PM8901 on these systems, and it is also
an interrupt controller. To make things clear, just name the
node alias "pm8058", this in unambigous and has all information
we need.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
arch/arm/boot/dts/qcom-apq8060-dragonboard.dts | 2 +-
arch/arm/boot/dts/qcom-msm8660-surf.dts | 2 +-
arch/arm/boot/dts/qcom-msm8660.dtsi | 12 ++++++------
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts b/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
index 4b8872cc8bf9..4a532ddab53a 100644
--- a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
+++ b/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
@@ -412,7 +412,7 @@
* The second interrupt is the PME interrupt
* for network wakeup, connected to the TLMM.
*/
- interrupts-extended = <&pmicintc 198 IRQ_TYPE_EDGE_FALLING>,
+ interrupts-extended = <&pm8058 198 IRQ_TYPE_EDGE_FALLING>,
<&tlmm 29 IRQ_TYPE_EDGE_RISING>;
reset-gpios = <&tlmm 30 GPIO_ACTIVE_LOW>;
vdd33a-supply = <&dragon_veth>;
diff --git a/arch/arm/boot/dts/qcom-msm8660-surf.dts b/arch/arm/boot/dts/qcom-msm8660-surf.dts
index 23de764558ab..1adc04978a47 100644
--- a/arch/arm/boot/dts/qcom-msm8660-surf.dts
+++ b/arch/arm/boot/dts/qcom-msm8660-surf.dts
@@ -48,7 +48,7 @@
};
};
-&pmicintc {
+&pm8058 {
keypad at 148 {
linux,keymap = <
MATRIX_KEY(0, 0, KEY_FN_F1)
diff --git a/arch/arm/boot/dts/qcom-msm8660.dtsi b/arch/arm/boot/dts/qcom-msm8660.dtsi
index 4d828f810746..91c9a62ae725 100644
--- a/arch/arm/boot/dts/qcom-msm8660.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8660.dtsi
@@ -163,7 +163,7 @@
reg = <0x500000 0x1000>;
qcom,controller-type = "pmic-arbiter";
- pmicintc: pmic at 0 {
+ pm8058: pmic at 0 {
compatible = "qcom,pm8058";
interrupt-parent = <&tlmm>;
interrupts = <88 8>;
@@ -176,7 +176,7 @@
compatible = "qcom,pm8058-gpio",
"qcom,ssbi-gpio";
reg = <0x150>;
- interrupt-parent = <&pmicintc>;
+ interrupt-parent = <&pm8058>;
interrupts = <192 IRQ_TYPE_NONE>,
<193 IRQ_TYPE_NONE>,
<194 IRQ_TYPE_NONE>,
@@ -232,7 +232,7 @@
reg = <0x50>;
gpio-controller;
#gpio-cells = <2>;
- interrupt-parent = <&pmicintc>;
+ interrupt-parent = <&pm8058>;
interrupts =
<128 IRQ_TYPE_NONE>,
<129 IRQ_TYPE_NONE>,
@@ -251,7 +251,7 @@
pwrkey at 1c {
compatible = "qcom,pm8058-pwrkey";
reg = <0x1c>;
- interrupt-parent = <&pmicintc>;
+ interrupt-parent = <&pm8058>;
interrupts = <50 1>, <51 1>;
debounce = <15625>;
pull-up;
@@ -260,7 +260,7 @@
keypad at 148 {
compatible = "qcom,pm8058-keypad";
reg = <0x148>;
- interrupt-parent = <&pmicintc>;
+ interrupt-parent = <&pm8058>;
interrupts = <74 1>, <75 1>;
debounce = <15>;
scan-delay = <32>;
@@ -270,7 +270,7 @@
rtc at 1e8 {
compatible = "qcom,pm8058-rtc";
reg = <0x1e8>;
- interrupt-parent = <&pmicintc>;
+ interrupt-parent = <&pm8058>;
interrupts = <39 1>;
allow-set-time;
};
--
2.7.4
^ permalink raw reply related
* [PATCH 0/8] firmware: arm_scpi: add support for legacy SCPI protocol
From: Neil Armstrong @ 2016-11-03 9:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478148731-11712-1-git-send-email-sudeep.holla@arm.com>
On 11/03/2016 05:52 AM, Sudeep Holla wrote:
> Hi,
>
> This is minor rework of the series[1] from Neil Armstrong's to support
> legacy SCPI protocol to make DT bindings more generic and move out all
> the platform specific bindings out of the generic binding document.
>
> --
> Regards,
> Sudeep
>
> [1] http://www.spinics.net/lists/arm-kernel/msg534999.html
>
> Neil Armstrong (4):
> firmware: arm_scpi: increase MAX_DVFS_OPPS to 16 entries
> firmware: arm_scpi: add alternative legacy structures, functions and
> macros
> firmware: arm_scpi: allow firmware with get_capabilities not
> implemented
> Documentation: bindings: Add support for Amlogic GXBB SCPI protocol
>
> Sudeep Holla (4):
> firmware: arm_scpi: add command indirection to support legacy commands
> Documentation: bindings: decouple juno specific details from generic
> binding
> Documentation: bindings: add compatible specific to legacy SCPI
> protocol
> firmware: arm_scpi: add support for legacy SCPI compatible
>
> .../devicetree/bindings/arm/amlogic,scpi.txt | 20 ++
> Documentation/devicetree/bindings/arm/arm,scpi.txt | 24 +-
> .../devicetree/bindings/arm/juno,scpi.txt | 26 ++
> drivers/firmware/arm_scpi.c | 276 ++++++++++++++++++---
> 4 files changed, 300 insertions(+), 46 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/arm/amlogic,scpi.txt
> create mode 100644 Documentation/devicetree/bindings/arm/juno,scpi.txt
>
Hi Sudeep,
Ok for me, I submitted the fix for the GXBB dtsi.
Neil
^ permalink raw reply
* [PATCH 2/2] ARM64: configs: Add Platform MHU in defconfig
From: Neil Armstrong @ 2016-11-03 9:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478164284-24958-1-git-send-email-narmstrong@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index dab2cb0..6631bda 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -394,6 +394,7 @@ CONFIG_MSM_MMCC_8996=y
CONFIG_HWSPINLOCK_QCOM=y
CONFIG_MAILBOX=y
CONFIG_ARM_MHU=y
+CONFIG_PLATFORM_MHU=y
CONFIG_HI6220_MBOX=y
CONFIG_ARM_SMMU=y
CONFIG_QCOM_SMEM=y
--
1.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox