Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] arm/arm64: KVM: Perform local TLB invalidation when multiplexing vcpus on a single CPU
From: Christoffer Dall @ 2016-11-01 18:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <86ins7kvcu.fsf@arm.com>

On Tue, Nov 01, 2016 at 04:39:29PM +0000, Marc Zyngier wrote:
> [messed up my initial reply, resending]
> 
> On Tue, Nov 01 2016 at 09:04:08 AM, Christoffer Dall
> <christoffer.dall@linaro.org> wrote:
> > On Fri, Oct 28, 2016 at 11:27:50AM +0100, Marc Zyngier wrote:
> >> Architecturally, TLBs are private to the (physical) CPU they're
> >> associated with. But when multiple vcpus from the same VM are
> >> being multiplexed on the same CPU, the TLBs are not private
> >> to the vcpus (and are actually shared across the VMID).
> >> 
> >> Let's consider the following scenario:
> >> 
> >> - vcpu-0 maps PA to VA
> >> - vcpu-1 maps PA' to VA
> >> 
> >> If run on the same physical CPU, vcpu-1 can hit TLB entries generated
> >> by vcpu-0 accesses, and access the wrong physical page.
> >> 
> >> The solution to this is to keep a per-VM map of which vcpu ran last
> >> on each given physical CPU, and invalidate local TLBs when switching
> >> to a different vcpu from the same VM.
> >> 
> >> Reviewed-by: Mark Rutland <mark.rutland@arm.com>
> >> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >> ---
> >> Fixed comments, added Mark's RB.
> >> 
> >>  arch/arm/include/asm/kvm_host.h   | 11 ++++++++++-
> >>  arch/arm/include/asm/kvm_hyp.h    |  1 +
> >>  arch/arm/kvm/arm.c                | 35 ++++++++++++++++++++++++++++++++++-
> >>  arch/arm/kvm/hyp/switch.c         |  9 +++++++++
> >>  arch/arm64/include/asm/kvm_host.h | 11 ++++++++++-
> >>  arch/arm64/kvm/hyp/switch.c       |  8 ++++++++
> >>  6 files changed, 72 insertions(+), 3 deletions(-)
> >> 
> 
> [...]
> 
> >> @@ -310,6 +322,27 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
> >>  	return 0;
> >>  }
> >>  
> >> +void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu)
> >> +{
> >
> > why is calling this from here sufficient?
> >
> > You only get a notification from preempt notifiers if you were preempted
> > while running (or rather while the vcpu was loaded).  I think this
> > needs
> 
> Arghh. I completely miss-read the code when writing that patch.
> 
> > to go in kvm_arch_vcpu_load, but be aware that the vcpu_load gets called
> > for other vcpu ioctls and doesn't necessarily imply that the vcpu will
> > actually run, which is also the case for the sched_in notification, btw.
> > The worst that will happen in that case is a bit of extra TLB
> > invalidation, so sticking with kvm_arch_vcpu_load is probably fine.
> 
> Indeed. I don't mind the extra invalidation, as long as it is rare
> enough. Another possibility would be to do this test on the entry path,
> once preemption is disabled.
> 
> >
> >> +	int *last_ran;
> >> +
> >> +	last_ran = per_cpu_ptr(vcpu->kvm->arch.last_vcpu_ran, cpu);
> >> +
> >> +	/*
> >> +	 * We might get preempted before the vCPU actually runs, but
> >> +	 * this is fine. Our TLBI stays pending until we actually make
> >> +	 * it to __activate_vm, so we won't miss a TLBI. If another
> >> +	 * vCPU gets scheduled, it will see our vcpu_id in last_ran,
> >> +	 * and pend a TLBI for itself.
> >> +	 */
> >> +	if (*last_ran != vcpu->vcpu_id) {
> >> +		if (*last_ran != -1)
> >> +			vcpu->arch.tlb_vmid_stale = true;
> >> +
> >> +		*last_ran = vcpu->vcpu_id;
> >> +	}
> >> +}
> >> +
> >>  void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
> >>  {
> >>  	vcpu->cpu = cpu;
> >> diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c
> >> index 92678b7..a411762 100644
> >> --- a/arch/arm/kvm/hyp/switch.c
> >> +++ b/arch/arm/kvm/hyp/switch.c
> >> @@ -75,6 +75,15 @@ static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)
> >>  {
> >>  	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
> >>  	write_sysreg(kvm->arch.vttbr, VTTBR);
> >> +	if (vcpu->arch.tlb_vmid_stale) {
> >> +		/* Force vttbr to be written */
> >> +		isb();
> >> +		/* Local invalidate only for this VMID */
> >> +		write_sysreg(0, TLBIALL);
> >> +		dsb(nsh);
> >> +		vcpu->arch.tlb_vmid_stale = false;
> >> +	}
> >> +
> >
> > why not call this directly when you notice it via kvm_call_hyp as
> > opposed to adding another conditional in the critical path?
> 
> Because the cost of a hypercall is very likely to be a lot higher than
> that of testing a variable. Not to mention that at this point we're
> absolutely sure that we're going to run the guest, while the hook in
> vcpu_load is only probabilistic.
> 
Hmmm, I think for for performance workloads you care about, you will pin
VCPUs, so you'd rather take this hit in the case where your're bouncing
VCPUs all over the place, as opposed to the situation where you care
about being able to quickly exit, for example to take an interrupt for a
passthrough device.

As a comparison, the many-many debug flag checks and function calls we
currently take costs us over 150 cycles for each save/restore on both
Seattle and Mustang, so I don't think the conditionals are free.

I think doing this in the non-preemptible load_vcpu part is just fine,
and it's in line with the other tlbi stuff we do.

-Christoffer

^ permalink raw reply

* Use of GICv3/ITS with PCIe host-generic driver - resizing ITS MAPD?
From: Marc Zyngier @ 2016-11-01 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CY1PR07MB2506C5C771B446139A743B99D8A10@CY1PR07MB2506.namprd07.prod.outlook.com>

Hi Alan,

On Tue, Nov 01 2016 at 11:47:46 AM, Alan Douglas <adouglas@cadence.com> wrote:
> I am using a Cadence PCIe Root Port in an ECAM setup with A53 and
> GICv3 with ITS, and have configured the host-generic driver to use
> MSI, using Device Tree.  Setup works well and the bus is correctly
> enumerated.  However, to get MSI/MSI-X working correctly I needed to
> make a change in drivers/irqchip/irq-gic-v3-its.c
>
> The PCI setup I am currently testing is:
> # lspci -t
> -[0000:00]---00.0-[01-04]----00.0-[02-04]--+-03.0-[03]----00.0
>                                            \-07.0-[04]----00.0
>
> Device 00:00.0 is a pci-bridge, and claims 1 MSI interrupt.
>        01:00.0 is a pci-bridge, 1 MSI interrupt
>        02:03.0 is a pci-bridge, 1 MSI interrupt
>        02:03.0 is a pci-bridge, 1 MSI interrupt
>        03:00.0 is a USB controller with 2 MSI-X interrupts
>        04:00.0 is a SATA controller with 1 MSI interrupt
>
> When setting up bus 0, the ITS device is created, and
> its_build_map_cmd() sets the size of the ITS MAPD based on the number
> of interrupts claimed by bus 0.  When subsequent buses are enumerated,
> the ITS device will be reused, however we do not increase the number
> of supported interrupts to allow for the additional interrupts claimed
> by the additional devices being enumerated.  (This can be seen in
> its_msi_prepare(), which is called for each device which has MSI/MSI-X
> enabled, and will reuse an existing ITS. )

Am I right in understanding that all the PCIe devices in your system
end-up aliasing to the same RequesterID? If so, that's a major
issue. The ITS is designed so that each device exposes its *own* RID,
and have its own Interrupt Translation Table (ITT).

In your case, you seem to first discover the root port, which is not
upstream of anything, so it doesn't alias with anything at that
point. We allocate the corresponding ITT, and it's all fine. Until we
start probing the rest, and ugly things happen.

> The solution I have implemented is in its_alloc_device_irq(), if the
> offset into the LPI table for the allocated interrupt is greater than
> the ITS MAPD, I reallocate the itt area, and resize the ITS MAPD.  I'm
> looking for comments as to whether this is a suitable solution and I
> should submit as a patch, is there some other recommendation or am I
> missing something regarding reuse of the ITS?

Not seeing the patch doesn't help, but in general reallocating an ITT
implies unmapping everything at the ITS level (LPIs, devices),
recreating the ITT, remapping everything, and then replaying fake
interrupts to cater for anything that you;ve missed in between. Not
exactly fun.

So before we have to introduce all of this, it would be good to find out
*why* are all the devices aliased together. Because this completely
screws all the ITS isolation, and makes device assignment to guest VM
completely insecure.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply

* [PATCH v6 2/2] iio: adc: add support for Allwinner SoCs ADC
From: Jonathan Cameron @ 2016-11-01 18:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <957e3e8f-1d4b-8b44-b3c8-df26f8574bcc@free-electrons.com>

On 31/10/16 09:34, Quentin Schulz wrote:
> Hi Jonathan and Lee,
> 
> On 30/10/2016 17:59, Jonathan Cameron wrote:
>> On 15/09/16 13:44, Quentin Schulz wrote:
>>> 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>
>> Hi Lee,
>>
>> As you applied the MFD part of this series, could you pick this up as well?
>>
> 
> Someone reported some bugs on the CHIP (sun5i-r8). I'm investigating that.
> 
> Also, it misses a scale for voltage (not that critical but still).
> 
> And also, Thomas Petazzoni just found a deadlock in sun4i_gpadc_read. If
> a regmap_write fails after getting the mutex, it is never released.
> 
> Is there some sort of deadline you want for a v7 since the mfd patch has
> been merged?
> 
No rush at all.  Doesn't matter as long as we know it's on it's way
sooner or later.  If it falls into the next cycle, that's fine -
I'll just pick it up directly as dependencies will in place by then.

Jonathan
> Thanks,
> Quentin
> 
>> Thanks,
>>
>> Jonathan
>>> ---
>>>
>>> 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");
>>>
>>
> 

^ permalink raw reply

* [PATCH v3 0/6] add NS2 support to bgmac
From: Scott Branden @ 2016-11-01 18:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478022694-25308-1-git-send-email-jon.mason@broadcom.com>

Hi Jon,

On 16-11-01 10:51 AM, Jon Mason wrote:
> Changes in v3:
> * Clean-up the bgmac DT binding doc (per Rob Herring)
> * Document the lane swap binding and make it generic (Per Andrew Lunn)
Where is the documentation of the lane swap binding?

>
>
> Changes in v2:
> * Remove the PHY power-on (per Andrew Lunn)
> * Misc PHY clean-ups regarding comments and #defines (per Andrew Lunn)
>   This results on none of the original PHY code from Vikas being
>   present.  So, I'm removing him as an author and giving him
>   "Inspired-by" credit.
> * Move PHY lane swapping to PHY driver (per Andrew Lunn and Florian
>   Fainelli)
> * Remove bgmac sleep (per Florian Fainelli)
> * Re-add bgmac chip reset (per Florian Fainelli and Ray Jui)
> * Rebased on latest net-next
> * Added patch for bcm54xx_auxctl_read, which is used in the BCM54810
>
>
> Add support for the amac found in the Broadcom Northstar2 SoC to the
> bgmac driver.  This necessitates adding support to connect to an
> externally defined phy (as described in the device tree) in the driver.
> These phy changes are in addition to the changes necessary to get NS2
> working.
>
>
> Jon Mason (6):
>   net: phy: broadcom: add bcm54xx_auxctl_read
>   net: phy: broadcom: Add BCM54810 PHY entry
>   Documentation: devicetree: net: add NS2 bindings to amac
>   net: ethernet: bgmac: device tree phy enablement
>   net: ethernet: bgmac: add NS2 support
>   arm64: dts: NS2: add AMAC ethernet support
>
>  .../devicetree/bindings/net/brcm,amac.txt          |  16 ++--
>  arch/arm64/boot/dts/broadcom/ns2-svk.dts           |   5 ++
>  arch/arm64/boot/dts/broadcom/ns2.dtsi              |  12 +++
>  drivers/net/ethernet/broadcom/bgmac-bcma.c         |  48 ++++++++++
>  drivers/net/ethernet/broadcom/bgmac-platform.c     | 100 ++++++++++++++++++++-
>  drivers/net/ethernet/broadcom/bgmac.c              |  55 ++----------
>  drivers/net/ethernet/broadcom/bgmac.h              |   8 ++
>  drivers/net/phy/Kconfig                            |   2 +-
>  drivers/net/phy/broadcom.c                         |  68 +++++++++++++-
>  include/linux/brcmphy.h                            |  11 +++
>  10 files changed, 268 insertions(+), 57 deletions(-)
>

^ permalink raw reply

* [PATCH v3] KVM: arm/arm64: vgic: Prevent access to invalid SPIs
From: Andre Przywara @ 2016-11-01 18:00 UTC (permalink / raw)
  To: linux-arm-kernel

In our VGIC implementation we limit the number of SPIs to a number
that the userland application told us. Accordingly we limit the
allocation of memory for virtual IRQs to that number.
However in our MMIO dispatcher we didn't check if we ever access an
IRQ beyond that limit, leading to out-of-bound accesses.
Add a test against the number of allocated SPIs in check_region().
Adjust the VGIC_ADDR_TO_INT macro to avoid an actual division, which
is not implemented on ARM(32).

[maz: cleaned-up original patch]

Cc: stable at vger.kernel.org
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
Hi,

I checked that the old and new VGIC_ADDR_TO_INTID() algorithm give
identical results by moving it into a small userland unit-test, using
all <bits> values we use in the VGIC and calling it with quite some test
addresses. No differences were found.

Cheers,
Andre.

Changelog v2 .. v3:
- further simplify VGIC_ADDR_TO_INTID
- adjust VGIC_ADDR_TO_INTID comment

Changelog v1 .. v2:
- fix compilation for 32-bit ARM

 virt/kvm/arm/vgic/vgic-mmio.c | 41 +++++++++++++++++++++++++++--------------
 virt/kvm/arm/vgic/vgic-mmio.h | 14 +++++++-------
 2 files changed, 34 insertions(+), 21 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index e18b30d..ebe1b9f 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -453,17 +453,33 @@ struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
 	return container_of(dev, struct vgic_io_device, dev);
 }
 
-static bool check_region(const struct vgic_register_region *region,
+static bool check_region(const struct kvm *kvm,
+			 const struct vgic_register_region *region,
 			 gpa_t addr, int len)
 {
-	if ((region->access_flags & VGIC_ACCESS_8bit) && len == 1)
-		return true;
-	if ((region->access_flags & VGIC_ACCESS_32bit) &&
-	    len == sizeof(u32) && !(addr & 3))
-		return true;
-	if ((region->access_flags & VGIC_ACCESS_64bit) &&
-	    len == sizeof(u64) && !(addr & 7))
-		return true;
+	int flags, nr_irqs = kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+
+	switch (len) {
+	case sizeof(u8):
+		flags = VGIC_ACCESS_8bit;
+		break;
+	case sizeof(u32):
+		flags = VGIC_ACCESS_32bit;
+		break;
+	case sizeof(u64):
+		flags = VGIC_ACCESS_64bit;
+		break;
+	default:
+		return false;
+	}
+
+	if ((region->access_flags & flags) && IS_ALIGNED(addr, len)) {
+		if (!region->bits_per_irq)
+			return true;
+
+		/* Do we access a non-allocated IRQ? */
+		return VGIC_ADDR_TO_INTID(addr, region->bits_per_irq) < nr_irqs;
+	}
 
 	return false;
 }
@@ -477,7 +493,7 @@ static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
 
 	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
 				       addr - iodev->base_addr);
-	if (!region || !check_region(region, addr, len)) {
+	if (!region || !check_region(vcpu->kvm, region, addr, len)) {
 		memset(val, 0, len);
 		return 0;
 	}
@@ -510,10 +526,7 @@ static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
 
 	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
 				       addr - iodev->base_addr);
-	if (!region)
-		return 0;
-
-	if (!check_region(region, addr, len))
+	if (!region || !check_region(vcpu->kvm, region, addr, len))
 		return 0;
 
 	switch (iodev->iodev_type) {
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 4c34d39..84961b4 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -50,15 +50,15 @@ extern struct kvm_io_device_ops kvm_io_gic_ops;
 #define VGIC_ADDR_IRQ_MASK(bits) (((bits) * 1024 / 8) - 1)
 
 /*
- * (addr & mask) gives us the byte offset for the INT ID, so we want to
- * divide this with 'bytes per irq' to get the INT ID, which is given
- * by '(bits) / 8'.  But we do this with fixed-point-arithmetic and
- * take advantage of the fact that division by a fraction equals
- * multiplication with the inverted fraction, and scale up both the
- * numerator and denominator with 8 to support at most 64 bits per IRQ:
+ * (addr & mask) gives us the _byte_ offset for the INT ID.
+ * We multiply this by 8 the get the _bit_ offset, then divide this by
+ * the number of bits to learn the actual INT ID.
+ * But instead of a division (which requires a "long long div" implementation),
+ * we shift by the binary logarithm of <bits>.
+ * This assumes that <bits> is a power of two.
  */
 #define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
-					64 / (bits) / 8)
+					8 >> ilog2(bits))
 
 /*
  * Some VGIC registers store per-IRQ information, with a different number
-- 
2.9.0

^ permalink raw reply related

* [PATCH v3 6/6] arm64: dts: NS2: add AMAC ethernet support
From: Jon Mason @ 2016-11-01 17:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478022694-25308-1-git-send-email-jon.mason@broadcom.com>

Add support for the AMAC ethernet to the Broadcom Northstar2 SoC device
tree

Signed-off-by: Jon Mason <jon.mason@broadcom.com>
---
 arch/arm64/boot/dts/broadcom/ns2-svk.dts |  5 +++++
 arch/arm64/boot/dts/broadcom/ns2.dtsi    | 12 ++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
index 2d7872a..2e4d90d 100644
--- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts
+++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
@@ -56,6 +56,10 @@
 	};
 };
 
+&enet {
+	status = "ok";
+};
+
 &pci_phy0 {
 	status = "ok";
 };
@@ -172,6 +176,7 @@
 &mdio_mux_iproc {
 	mdio at 10 {
 		gphy0: eth-phy at 10 {
+			enet-phy-lane-swap;
 			reg = <0x10>;
 		};
 	};
diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi
index d95dc40..773ed59 100644
--- a/arch/arm64/boot/dts/broadcom/ns2.dtsi
+++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi
@@ -191,6 +191,18 @@
 
 		#include "ns2-clock.dtsi"
 
+		enet: ethernet at 61000000 {
+			compatible = "brcm,ns2-amac";
+			reg = <0x61000000 0x1000>,
+			      <0x61090000 0x1000>,
+			      <0x61030000 0x100>;
+			reg-names = "amac_base", "idm_base", "nicpm_base";
+			interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
+			phy-handle = <&gphy0>;
+			phy-mode = "rgmii";
+			status = "disabled";
+		};
+
 		dma0: dma at 61360000 {
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x61360000 0x1000>;
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 5/6] net: ethernet: bgmac: add NS2 support
From: Jon Mason @ 2016-11-01 17:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478022694-25308-1-git-send-email-jon.mason@broadcom.com>

Add support for the variant of amac hardware present in the Broadcom
Northstar2 based SoCs.  Northstar2 requires an additional register to be
configured with the port speed/duplexity (NICPM).  This can be added to
the link callback to hide it from the instances that do not use this.
Also, clearing of the pending interrupts on init is required due to
observed issues on some platforms.

Signed-off-by: Jon Mason <jon.mason@broadcom.com>
---
 drivers/net/ethernet/broadcom/bgmac-platform.c | 56 +++++++++++++++++++++++++-
 drivers/net/ethernet/broadcom/bgmac.c          |  3 ++
 drivers/net/ethernet/broadcom/bgmac.h          |  1 +
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bgmac-platform.c b/drivers/net/ethernet/broadcom/bgmac-platform.c
index aed5dc5..f6d48c7 100644
--- a/drivers/net/ethernet/broadcom/bgmac-platform.c
+++ b/drivers/net/ethernet/broadcom/bgmac-platform.c
@@ -14,12 +14,21 @@
 #define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt
 
 #include <linux/bcma/bcma.h>
+#include <linux/brcmphy.h>
 #include <linux/etherdevice.h>
 #include <linux/of_address.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include "bgmac.h"
 
+#define NICPM_IOMUX_CTRL		0x00000008
+
+#define NICPM_IOMUX_CTRL_INIT_VAL	0x3196e000
+#define NICPM_IOMUX_CTRL_SPD_SHIFT	10
+#define NICPM_IOMUX_CTRL_SPD_10M	0
+#define NICPM_IOMUX_CTRL_SPD_100M	1
+#define NICPM_IOMUX_CTRL_SPD_1000M	2
+
 static u32 platform_bgmac_read(struct bgmac *bgmac, u16 offset)
 {
 	return readl(bgmac->plat.base + offset);
@@ -87,12 +96,46 @@ static void platform_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset,
 	WARN_ON(1);
 }
 
+static void bgmac_nicpm_speed_set(struct net_device *net_dev)
+{
+	struct bgmac *bgmac = netdev_priv(net_dev);
+	u32 val;
+
+	if (!bgmac->plat.nicpm_base)
+		return;
+
+	val = NICPM_IOMUX_CTRL_INIT_VAL;
+	switch (bgmac->net_dev->phydev->speed) {
+	default:
+		pr_err("Unsupported speed.  Defaulting to 1000Mb\n");
+	case SPEED_1000:
+		val |= NICPM_IOMUX_CTRL_SPD_1000M << NICPM_IOMUX_CTRL_SPD_SHIFT;
+		break;
+	case SPEED_100:
+		val |= NICPM_IOMUX_CTRL_SPD_100M << NICPM_IOMUX_CTRL_SPD_SHIFT;
+		break;
+	case SPEED_10:
+		val |= NICPM_IOMUX_CTRL_SPD_10M << NICPM_IOMUX_CTRL_SPD_SHIFT;
+		break;
+	}
+
+	writel(val, bgmac->plat.nicpm_base + NICPM_IOMUX_CTRL);
+
+	bgmac_adjust_link(bgmac->net_dev);
+}
+
 static int platform_phy_connect(struct bgmac *bgmac)
 {
 	struct phy_device *phy_dev;
 
-	phy_dev = of_phy_get_and_connect(bgmac->net_dev, bgmac->dev->of_node,
-					 bgmac_adjust_link);
+	if (bgmac->plat.nicpm_base)
+		phy_dev = of_phy_get_and_connect(bgmac->net_dev,
+						 bgmac->dev->of_node,
+						 bgmac_nicpm_speed_set);
+	else
+		phy_dev = of_phy_get_and_connect(bgmac->net_dev,
+						 bgmac->dev->of_node,
+						 bgmac_adjust_link);
 	if (!phy_dev) {
 		dev_err(bgmac->dev, "Phy connect failed\n");
 		return -ENODEV;
@@ -182,6 +225,14 @@ static int bgmac_probe(struct platform_device *pdev)
 	if (IS_ERR(bgmac->plat.idm_base))
 		return PTR_ERR(bgmac->plat.idm_base);
 
+	regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nicpm_base");
+	if (regs) {
+		bgmac->plat.nicpm_base = devm_ioremap_resource(&pdev->dev,
+							       regs);
+		if (IS_ERR(bgmac->plat.nicpm_base))
+			return PTR_ERR(bgmac->plat.nicpm_base);
+	}
+
 	bgmac->read = platform_bgmac_read;
 	bgmac->write = platform_bgmac_write;
 	bgmac->idm_read = platform_bgmac_idm_read;
@@ -213,6 +264,7 @@ static int bgmac_remove(struct platform_device *pdev)
 static const struct of_device_id bgmac_of_enet_match[] = {
 	{.compatible = "brcm,amac",},
 	{.compatible = "brcm,nsp-amac",},
+	{.compatible = "brcm,ns2-amac",},
 	{},
 };
 
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 4584958..a805cc8 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1082,6 +1082,9 @@ static void bgmac_enable(struct bgmac *bgmac)
 /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipinit */
 static void bgmac_chip_init(struct bgmac *bgmac)
 {
+	/* Clear any erroneously pending interrupts */
+	bgmac_write(bgmac, BGMAC_INT_STATUS, ~0);
+
 	/* 1 interrupt per received frame */
 	bgmac_write(bgmac, BGMAC_INT_RECV_LAZY, 1 << BGMAC_IRL_FC_SHIFT);
 
diff --git a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h
index ea52ac3..b1820ea 100644
--- a/drivers/net/ethernet/broadcom/bgmac.h
+++ b/drivers/net/ethernet/broadcom/bgmac.h
@@ -463,6 +463,7 @@ struct bgmac {
 		struct {
 			void *base;
 			void *idm_base;
+			void *nicpm_base;
 		} plat;
 		struct {
 			struct bcma_device *core;
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 4/6] net: ethernet: bgmac: device tree phy enablement
From: Jon Mason @ 2016-11-01 17:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478022694-25308-1-git-send-email-jon.mason@broadcom.com>

Change the bgmac driver to allow for phy's defined by the device tree

Signed-off-by: Jon Mason <jon.mason@broadcom.com>
---
 drivers/net/ethernet/broadcom/bgmac-bcma.c     | 48 ++++++++++++++++++++++++
 drivers/net/ethernet/broadcom/bgmac-platform.c | 48 +++++++++++++++++++++++-
 drivers/net/ethernet/broadcom/bgmac.c          | 52 ++------------------------
 drivers/net/ethernet/broadcom/bgmac.h          |  7 ++++
 4 files changed, 105 insertions(+), 50 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bgmac-bcma.c b/drivers/net/ethernet/broadcom/bgmac-bcma.c
index c16ec3a..3e3efde 100644
--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
@@ -80,6 +80,50 @@ static void bcma_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset, u32 mask,
 	bcma_maskset32(bgmac->bcma.cmn, offset, mask, set);
 }
 
+static int bcma_phy_connect(struct bgmac *bgmac)
+{
+	struct phy_device *phy_dev;
+	char bus_id[MII_BUS_ID_SIZE + 3];
+
+	/* Connect to the PHY */
+	snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id,
+		 bgmac->phyaddr);
+	phy_dev = phy_connect(bgmac->net_dev, bus_id, bgmac_adjust_link,
+			      PHY_INTERFACE_MODE_MII);
+	if (IS_ERR(phy_dev)) {
+		dev_err(bgmac->dev, "PHY connecton failed\n");
+		return PTR_ERR(phy_dev);
+	}
+
+	return 0;
+}
+
+static int bcma_phy_direct_connect(struct bgmac *bgmac)
+{
+	struct fixed_phy_status fphy_status = {
+		.link = 1,
+		.speed = SPEED_1000,
+		.duplex = DUPLEX_FULL,
+	};
+	struct phy_device *phy_dev;
+	int err;
+
+	phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
+	if (!phy_dev || IS_ERR(phy_dev)) {
+		dev_err(bgmac->dev, "Failed to register fixed PHY device\n");
+		return -ENODEV;
+	}
+
+	err = phy_connect_direct(bgmac->net_dev, phy_dev, bgmac_adjust_link,
+				 PHY_INTERFACE_MODE_MII);
+	if (err) {
+		dev_err(bgmac->dev, "Connecting PHY failed\n");
+		return err;
+	}
+
+	return err;
+}
+
 static const struct bcma_device_id bgmac_bcma_tbl[] = {
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT,
 		  BCMA_ANY_REV, BCMA_ANY_CLASS),
@@ -275,6 +319,10 @@ static int bgmac_probe(struct bcma_device *core)
 	bgmac->cco_ctl_maskset = bcma_bgmac_cco_ctl_maskset;
 	bgmac->get_bus_clock = bcma_bgmac_get_bus_clock;
 	bgmac->cmn_maskset32 = bcma_bgmac_cmn_maskset32;
+	if (bgmac->mii_bus)
+		bgmac->phy_connect = bcma_phy_connect;
+	else
+		bgmac->phy_connect = bcma_phy_direct_connect;
 
 	err = bgmac_enet_probe(bgmac);
 	if (err)
diff --git a/drivers/net/ethernet/broadcom/bgmac-platform.c b/drivers/net/ethernet/broadcom/bgmac-platform.c
index be52f27..aed5dc5 100644
--- a/drivers/net/ethernet/broadcom/bgmac-platform.c
+++ b/drivers/net/ethernet/broadcom/bgmac-platform.c
@@ -16,6 +16,7 @@
 #include <linux/bcma/bcma.h>
 #include <linux/etherdevice.h>
 #include <linux/of_address.h>
+#include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include "bgmac.h"
 
@@ -86,6 +87,46 @@ static void platform_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset,
 	WARN_ON(1);
 }
 
+static int platform_phy_connect(struct bgmac *bgmac)
+{
+	struct phy_device *phy_dev;
+
+	phy_dev = of_phy_get_and_connect(bgmac->net_dev, bgmac->dev->of_node,
+					 bgmac_adjust_link);
+	if (!phy_dev) {
+		dev_err(bgmac->dev, "Phy connect failed\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int platform_phy_direct_connect(struct bgmac *bgmac)
+{
+	struct fixed_phy_status fphy_status = {
+		.link = 1,
+		.speed = SPEED_1000,
+		.duplex = DUPLEX_FULL,
+	};
+	struct phy_device *phy_dev;
+	int err;
+
+	phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
+	if (!phy_dev || IS_ERR(phy_dev)) {
+		dev_err(bgmac->dev, "Failed to register fixed PHY device\n");
+		return -ENODEV;
+	}
+
+	err = phy_connect_direct(bgmac->net_dev, phy_dev, bgmac_adjust_link,
+				 PHY_INTERFACE_MODE_MII);
+	if (err) {
+		dev_err(bgmac->dev, "Connecting PHY failed\n");
+		return err;
+	}
+
+	return err;
+}
+
 static int bgmac_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -102,7 +143,6 @@ static int bgmac_probe(struct platform_device *pdev)
 	/* Set the features of the 4707 family */
 	bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 	bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
-	bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
 	bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4;
 	bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP;
 	bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP;
@@ -151,6 +191,12 @@ static int bgmac_probe(struct platform_device *pdev)
 	bgmac->cco_ctl_maskset = platform_bgmac_cco_ctl_maskset;
 	bgmac->get_bus_clock = platform_bgmac_get_bus_clock;
 	bgmac->cmn_maskset32 = platform_bgmac_cmn_maskset32;
+	if (of_parse_phandle(np, "phy-handle", 0)) {
+		bgmac->phy_connect = platform_phy_connect;
+	} else {
+		bgmac->phy_connect = platform_phy_direct_connect;
+		bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
+	}
 
 	return bgmac_enet_probe(bgmac);
 }
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 856379c..4584958 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1388,7 +1388,7 @@ static const struct ethtool_ops bgmac_ethtool_ops = {
  * MII
  **************************************************/
 
-static void bgmac_adjust_link(struct net_device *net_dev)
+void bgmac_adjust_link(struct net_device *net_dev)
 {
 	struct bgmac *bgmac = netdev_priv(net_dev);
 	struct phy_device *phy_dev = net_dev->phydev;
@@ -1411,50 +1411,7 @@ static void bgmac_adjust_link(struct net_device *net_dev)
 		phy_print_status(phy_dev);
 	}
 }
-
-static int bgmac_phy_connect_direct(struct bgmac *bgmac)
-{
-	struct fixed_phy_status fphy_status = {
-		.link = 1,
-		.speed = SPEED_1000,
-		.duplex = DUPLEX_FULL,
-	};
-	struct phy_device *phy_dev;
-	int err;
-
-	phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
-	if (!phy_dev || IS_ERR(phy_dev)) {
-		dev_err(bgmac->dev, "Failed to register fixed PHY device\n");
-		return -ENODEV;
-	}
-
-	err = phy_connect_direct(bgmac->net_dev, phy_dev, bgmac_adjust_link,
-				 PHY_INTERFACE_MODE_MII);
-	if (err) {
-		dev_err(bgmac->dev, "Connecting PHY failed\n");
-		return err;
-	}
-
-	return err;
-}
-
-static int bgmac_phy_connect(struct bgmac *bgmac)
-{
-	struct phy_device *phy_dev;
-	char bus_id[MII_BUS_ID_SIZE + 3];
-
-	/* Connect to the PHY */
-	snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id,
-		 bgmac->phyaddr);
-	phy_dev = phy_connect(bgmac->net_dev, bus_id, &bgmac_adjust_link,
-			      PHY_INTERFACE_MODE_MII);
-	if (IS_ERR(phy_dev)) {
-		dev_err(bgmac->dev, "PHY connecton failed\n");
-		return PTR_ERR(phy_dev);
-	}
-
-	return 0;
-}
+EXPORT_SYMBOL_GPL(bgmac_adjust_link);
 
 int bgmac_enet_probe(struct bgmac *info)
 {
@@ -1507,10 +1464,7 @@ int bgmac_enet_probe(struct bgmac *info)
 
 	netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);
 
-	if (!bgmac->mii_bus)
-		err = bgmac_phy_connect_direct(bgmac);
-	else
-		err = bgmac_phy_connect(bgmac);
+	err = bgmac_phy_connect(bgmac);
 	if (err) {
 		dev_err(bgmac->dev, "Cannot connect to phy\n");
 		goto err_dma_free;
diff --git a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h
index 80836b4..ea52ac3 100644
--- a/drivers/net/ethernet/broadcom/bgmac.h
+++ b/drivers/net/ethernet/broadcom/bgmac.h
@@ -513,10 +513,12 @@ struct bgmac {
 	u32 (*get_bus_clock)(struct bgmac *bgmac);
 	void (*cmn_maskset32)(struct bgmac *bgmac, u16 offset, u32 mask,
 			      u32 set);
+	int (*phy_connect)(struct bgmac *bgmac);
 };
 
 int bgmac_enet_probe(struct bgmac *info);
 void bgmac_enet_remove(struct bgmac *bgmac);
+void bgmac_adjust_link(struct net_device *net_dev);
 
 struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr);
 void bcma_mdio_mii_unregister(struct mii_bus *mii_bus);
@@ -583,4 +585,9 @@ static inline void bgmac_set(struct bgmac *bgmac, u16 offset, u32 set)
 {
 	bgmac_maskset(bgmac, offset, ~0, set);
 }
+
+static inline int bgmac_phy_connect(struct bgmac *bgmac)
+{
+	return bgmac->phy_connect(bgmac);
+}
 #endif /* _BGMAC_H */
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 3/6] Documentation: devicetree: net: add NS2 bindings to amac
From: Jon Mason @ 2016-11-01 17:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478022694-25308-1-git-send-email-jon.mason@broadcom.com>

Clean-up the documentation to the bgmac-amac driver, per suggestion by
Rob Herring, and add details for NS2 support.

Signed-off-by: Jon Mason <jon.mason@broadcom.com>
---
 Documentation/devicetree/bindings/net/brcm,amac.txt | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/brcm,amac.txt b/Documentation/devicetree/bindings/net/brcm,amac.txt
index ba5ecc1..2fefa1a 100644
--- a/Documentation/devicetree/bindings/net/brcm,amac.txt
+++ b/Documentation/devicetree/bindings/net/brcm,amac.txt
@@ -2,11 +2,17 @@ Broadcom AMAC Ethernet Controller Device Tree Bindings
 -------------------------------------------------------------
 
 Required properties:
- - compatible:	"brcm,amac" or "brcm,nsp-amac"
- - reg:		Address and length of the GMAC registers,
-		Address and length of the GMAC IDM registers
- - reg-names:	Names of the registers.  Must have both "amac_base" and
-		"idm_base"
+ - compatible:	"brcm,amac"
+		"brcm,nsp-amac"
+		"brcm,ns2-amac"
+ - reg:		Address and length of the register set for the device. It
+		contains the information of registers in the same order as
+		described by reg-names
+ - reg-names:	Names of the registers.
+		"amac_base":	Address and length of the GMAC registers
+		"idm_base":	Address and length of the GMAC IDM registers
+		"nicpm_base":	Address and length of the NIC Port Manager
+				registers (required for Northstar2)
  - interrupts:	Interrupt number
 
 Optional properties:
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 2/6] net: phy: broadcom: Add BCM54810 PHY entry
From: Jon Mason @ 2016-11-01 17:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478022694-25308-1-git-send-email-jon.mason@broadcom.com>

The BCM54810 PHY requires some semi-unique configuration, which results
in some additional configuration in addition to the standard config.
Also, some users of the BCM54810 require the PHY lanes to be swapped.
Since there is no way to detect this, add a device tree query to see if
it is applicable.

Inspired-by: Vikas Soni <vsoni@broadcom.com>
Signed-off-by: Jon Mason <jon.mason@broadcom.com>
---
 drivers/net/phy/Kconfig    |  2 +-
 drivers/net/phy/broadcom.c | 58 +++++++++++++++++++++++++++++++++++++++++++++-
 include/linux/brcmphy.h    | 10 ++++++++
 3 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 45f68ea..31967ca 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -217,7 +217,7 @@ config BROADCOM_PHY
 	select BCM_NET_PHYLIB
 	---help---
 	  Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
-	  BCM5481 and BCM5482 PHYs.
+	  BCM5481, BCM54810 and BCM5482 PHYs.
 
 config CICADA_PHY
 	tristate "Cicada PHYs"
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 3a64b3d..b1e32e9 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -18,7 +18,7 @@
 #include <linux/module.h>
 #include <linux/phy.h>
 #include <linux/brcmphy.h>
-
+#include <linux/of.h>
 
 #define BRCM_PHY_MODEL(phydev) \
 	((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
@@ -45,6 +45,34 @@ static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
 	return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
 }
 
+static int bcm54810_config(struct phy_device *phydev)
+{
+	int rc, val;
+
+	val = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
+	val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
+	rc = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL,
+			       val);
+	if (rc < 0)
+		return rc;
+
+	val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
+	val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
+	val |= MII_BCM54XX_AUXCTL_MISC_WREN;
+	rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
+				  val);
+	if (rc < 0)
+		return rc;
+
+	val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
+	val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
+	rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
+	if (rc < 0)
+		return rc;
+
+	return 0;
+}
+
 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
 static int bcm50610_a0_workaround(struct phy_device *phydev)
 {
@@ -217,6 +245,12 @@ static int bcm54xx_config_init(struct phy_device *phydev)
 	    (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
 		bcm54xx_adjust_rxrefclk(phydev);
 
+	if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
+		err = bcm54810_config(phydev);
+		if (err)
+			return err;
+	}
+
 	bcm54xx_phydsp_config(phydev);
 
 	return 0;
@@ -314,6 +348,7 @@ static int bcm5482_read_status(struct phy_device *phydev)
 
 static int bcm5481_config_aneg(struct phy_device *phydev)
 {
+	struct device_node *np = phydev->mdio.dev.of_node;
 	int ret;
 
 	/* Aneg firsly. */
@@ -344,6 +379,14 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
 		phy_write(phydev, 0x18, reg);
 	}
 
+	if (of_property_read_bool(np, "enet-phy-lane-swap")) {
+		/* Lane Swap - Undocumented register...magic! */
+		ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9,
+					0x11B);
+		if (ret < 0)
+			return ret;
+	}
+
 	return ret;
 }
 
@@ -578,6 +621,18 @@ static struct phy_driver broadcom_drivers[] = {
 	.ack_interrupt	= bcm_phy_ack_intr,
 	.config_intr	= bcm_phy_config_intr,
 }, {
+	.phy_id         = PHY_ID_BCM54810,
+	.phy_id_mask    = 0xfffffff0,
+	.name           = "Broadcom BCM54810",
+	.features       = PHY_GBIT_FEATURES |
+			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+	.flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+	.config_init    = bcm54xx_config_init,
+	.config_aneg    = bcm5481_config_aneg,
+	.read_status    = genphy_read_status,
+	.ack_interrupt  = bcm_phy_ack_intr,
+	.config_intr    = bcm_phy_config_intr,
+}, {
 	.phy_id		= PHY_ID_BCM5482,
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Broadcom BCM5482",
@@ -661,6 +716,7 @@ static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
 	{ PHY_ID_BCM54616S, 0xfffffff0 },
 	{ PHY_ID_BCM5464, 0xfffffff0 },
 	{ PHY_ID_BCM5481, 0xfffffff0 },
+	{ PHY_ID_BCM54810, 0xfffffff0 },
 	{ PHY_ID_BCM5482, 0xfffffff0 },
 	{ PHY_ID_BCM50610, 0xfffffff0 },
 	{ PHY_ID_BCM50610M, 0xfffffff0 },
diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h
index 0ed6691..69c7a79 100644
--- a/include/linux/brcmphy.h
+++ b/include/linux/brcmphy.h
@@ -13,6 +13,7 @@
 #define PHY_ID_BCM5241			0x0143bc30
 #define PHY_ID_BCMAC131			0x0143bc70
 #define PHY_ID_BCM5481			0x0143bca0
+#define PHY_ID_BCM54810			0x03625d00
 #define PHY_ID_BCM5482			0x0143bcb0
 #define PHY_ID_BCM5411			0x00206070
 #define PHY_ID_BCM5421			0x002060e0
@@ -56,6 +57,8 @@
 #define PHY_BRCM_EXT_IBND_TX_ENABLE	0x00002000
 #define PHY_BRCM_CLEAR_RGMII_MODE	0x00004000
 #define PHY_BRCM_DIS_TXCRXC_NOENRGY	0x00008000
+#define PHY_BRCM_EXP_LANE_SWAP		0x00010000
+
 /* Broadcom BCM7xxx specific workarounds */
 #define PHY_BRCM_7XXX_REV(x)		(((x) >> 8) & 0xff)
 #define PHY_BRCM_7XXX_PATCH(x)		((x) & 0xff)
@@ -111,6 +114,7 @@
 #define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC	0x7000
 #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC	0x0007
 #define MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT	12
+#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN	(1 << 8)
 
 #define MII_BCM54XX_AUXCTL_SHDWSEL_MASK	0x0007
 
@@ -192,6 +196,12 @@
 #define BCM5482_SSD_SGMII_SLAVE_EN	0x0002	/* Slave mode enable */
 #define BCM5482_SSD_SGMII_SLAVE_AD	0x0001	/* Slave auto-detection */
 
+/* BCM54810 Registers */
+#define BCM54810_EXP_BROADREACH_LRE_MISC_CTL	(MII_BCM54XX_EXP_SEL_ER + 0x90)
+#define BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN	(1 << 0)
+#define BCM54810_SHD_CLK_CTL			0x3
+#define BCM54810_SHD_CLK_CTL_GTXCLK_EN		(1 << 9)
+
 
 /*****************************************************************************/
 /* Fast Ethernet Transceiver definitions. */
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 1/6] net: phy: broadcom: add bcm54xx_auxctl_read
From: Jon Mason @ 2016-11-01 17:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478022694-25308-1-git-send-email-jon.mason@broadcom.com>

Add a helper function to read the AUXCTL register for the BCM54xx.  This
mirrors the bcm54xx_auxctl_write function already present in the code.

Signed-off-by: Jon Mason <jon.mason@broadcom.com>
---
 drivers/net/phy/broadcom.c | 10 ++++++++++
 include/linux/brcmphy.h    |  1 +
 2 files changed, 11 insertions(+)

diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 583ef8a..3a64b3d 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -30,6 +30,16 @@ MODULE_DESCRIPTION("Broadcom PHY driver");
 MODULE_AUTHOR("Maciej W. Rozycki");
 MODULE_LICENSE("GPL");
 
+static int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum)
+{
+	/* The register must be written to both the Shadow Register Select and
+	 * the Shadow Read Register Selector
+	 */
+	phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum |
+		  regnum << MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT);
+	return phy_read(phydev, MII_BCM54XX_AUX_CTL);
+}
+
 static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
 {
 	return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h
index 60def78..0ed6691 100644
--- a/include/linux/brcmphy.h
+++ b/include/linux/brcmphy.h
@@ -110,6 +110,7 @@
 #define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX	0x0200
 #define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC	0x7000
 #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC	0x0007
+#define MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT	12
 
 #define MII_BCM54XX_AUXCTL_SHDWSEL_MASK	0x0007
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 0/6] add NS2 support to bgmac
From: Jon Mason @ 2016-11-01 17:51 UTC (permalink / raw)
  To: linux-arm-kernel

Changes in v3:
* Clean-up the bgmac DT binding doc (per Rob Herring)
* Document the lane swap binding and make it generic (Per Andrew Lunn)


Changes in v2:
* Remove the PHY power-on (per Andrew Lunn)
* Misc PHY clean-ups regarding comments and #defines (per Andrew Lunn)
  This results on none of the original PHY code from Vikas being
  present.  So, I'm removing him as an author and giving him
  "Inspired-by" credit.
* Move PHY lane swapping to PHY driver (per Andrew Lunn and Florian
  Fainelli)
* Remove bgmac sleep (per Florian Fainelli)
* Re-add bgmac chip reset (per Florian Fainelli and Ray Jui)
* Rebased on latest net-next
* Added patch for bcm54xx_auxctl_read, which is used in the BCM54810


Add support for the amac found in the Broadcom Northstar2 SoC to the
bgmac driver.  This necessitates adding support to connect to an
externally defined phy (as described in the device tree) in the driver.
These phy changes are in addition to the changes necessary to get NS2
working.


Jon Mason (6):
  net: phy: broadcom: add bcm54xx_auxctl_read
  net: phy: broadcom: Add BCM54810 PHY entry
  Documentation: devicetree: net: add NS2 bindings to amac
  net: ethernet: bgmac: device tree phy enablement
  net: ethernet: bgmac: add NS2 support
  arm64: dts: NS2: add AMAC ethernet support

 .../devicetree/bindings/net/brcm,amac.txt          |  16 ++--
 arch/arm64/boot/dts/broadcom/ns2-svk.dts           |   5 ++
 arch/arm64/boot/dts/broadcom/ns2.dtsi              |  12 +++
 drivers/net/ethernet/broadcom/bgmac-bcma.c         |  48 ++++++++++
 drivers/net/ethernet/broadcom/bgmac-platform.c     | 100 ++++++++++++++++++++-
 drivers/net/ethernet/broadcom/bgmac.c              |  55 ++----------
 drivers/net/ethernet/broadcom/bgmac.h              |   8 ++
 drivers/net/phy/Kconfig                            |   2 +-
 drivers/net/phy/broadcom.c                         |  68 +++++++++++++-
 include/linux/brcmphy.h                            |  11 +++
 10 files changed, 268 insertions(+), 57 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH] fpga zynq: Check the bitstream for validity
From: Michal Simek @ 2016-11-01 17:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161101153326.GA6193@obsidianresearch.com>

On 1.11.2016 16:33, Jason Gunthorpe wrote:
> On Tue, Nov 01, 2016 at 07:39:22AM +0100, Michal Simek wrote:
> 
>> Regarding BIT and BIN format. This support is in vivado for a long time
>> and it is up2you what you want to support. We have removed that BIT
>> support and not doing any swap by saying only BIN format is supported.
> 
> BIN is not supported, it needs a swap as well.
> 
> Moritz has it right, you have to use vivado to create a PROM image to be
> compatible with the driver.

hm than that's bad.

Thanks,
Michal

^ permalink raw reply

* [PATCH] ARM: dts: imx6sx-udoo: Add board specific compatible strings
From: Fabio Estevam @ 2016-11-01 17:38 UTC (permalink / raw)
  To: linux-arm-kernel

Add a compatible entry for the specific board versions.

Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
---
 arch/arm/boot/dts/imx6sx-udoo-neo-basic.dts    | 2 +-
 arch/arm/boot/dts/imx6sx-udoo-neo-extended.dts | 2 +-
 arch/arm/boot/dts/imx6sx-udoo-neo-full.dts     | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/imx6sx-udoo-neo-basic.dts b/arch/arm/boot/dts/imx6sx-udoo-neo-basic.dts
index 0b88878..0c1fc1a 100644
--- a/arch/arm/boot/dts/imx6sx-udoo-neo-basic.dts
+++ b/arch/arm/boot/dts/imx6sx-udoo-neo-basic.dts
@@ -46,7 +46,7 @@
 
 / {
 	model = "UDOO Neo Basic";
-	compatible = "fsl,imx6sx";
+	compatible = "udoo,neobasic", "fsl,imx6sx";
 
 	memory {
 		reg = <0x80000000 0x20000000>;
diff --git a/arch/arm/boot/dts/imx6sx-udoo-neo-extended.dts b/arch/arm/boot/dts/imx6sx-udoo-neo-extended.dts
index d6fdd17..5d6c227 100644
--- a/arch/arm/boot/dts/imx6sx-udoo-neo-extended.dts
+++ b/arch/arm/boot/dts/imx6sx-udoo-neo-extended.dts
@@ -46,7 +46,7 @@
 
 / {
 	model = "UDOO Neo Extended";
-	compatible = "fsl,imx6sx";
+	compatible = "udoo,neoextended", "fsl,imx6sx";
 
 	memory {
 		reg = <0x80000000 0x40000000>;
diff --git a/arch/arm/boot/dts/imx6sx-udoo-neo-full.dts b/arch/arm/boot/dts/imx6sx-udoo-neo-full.dts
index d8c3577..653ceb2 100644
--- a/arch/arm/boot/dts/imx6sx-udoo-neo-full.dts
+++ b/arch/arm/boot/dts/imx6sx-udoo-neo-full.dts
@@ -46,7 +46,7 @@
 
 / {
 	model = "UDOO Neo Full";
-	compatible = "fsl,imx6sx";
+	compatible = "udoo,neofull", "fsl,imx6sx";
 
 	memory {
 		reg = <0x80000000 0x40000000>;
-- 
2.7.4

^ permalink raw reply related

* [GIT PULL] firmware: SCPI updates for v4.10
From: Sudeep Holla @ 2016-11-01 17:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161029183951.GE4195@localhost>

On Sat, Oct 29, 2016 at 11:39:51AM -0700, Olof Johansson wrote:
> Hi Sudeep,
> 
> On Fri, Oct 28, 2016 at 12:29:20PM +0100, Sudeep Holla wrote:
> > Hi ARM-SoC Team,
> > 
> > Please pull !
> > 
> > --
> > Regards,
> > Sudeep
> > 
> > The following changes since commit 1001354ca34179f3db924eb66672442a173147dc:
> > 
> >   Linux 4.9-rc1 (2016-10-15 12:17:50 -0700)
> > 
> > are available in the git repository at:
> > 
> >   git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git tags/scpi-updates-4.10
> > 
> > for you to fetch changes up to a9e0192d8b35c6ab115a154ed1499ff39a0e5b06:
> > 
> >   firmware: arm_scpi: add support for legacy match table on Amlogic GXBB SoC (2016-10-19 15:17:28 +0100)
> > 
> > ----------------------------------------------------------------
> > SCPI updates for v4.10
> > 
> > 1. Adds support for Legacy SCPI(pre- SCPI v1.0) protocol
> > 
> > 2. Adds support for SCPI used on Amlogic GXBB SoC using the legacy
> >    SCPI protocol
> > 
> > ----------------------------------------------------------------
> > Neil Armstrong (5):
> >       dt-bindings: Add support for Amlogic GXBB SCPI Interface
> 
> I had comments on this patch, just emailed as follow-up to it.
>

Thanks for having a look, will address it.

> Also, you didn't sign off on it when applying it, seems like a mistake.
>

Ah, yes that was stupid mistake as I pulled that last minute.

> Please respin, ideally with the other changes also done (i.e. splitting off
> Juno stuff from arm,scpi.txt).
>

OK.

--
Regards,
Sudeep

^ permalink raw reply

* [PATCH] arm/vdso: introduce vdso_mremap hook
From: Dmitry Safonov @ 2016-11-01 17:22 UTC (permalink / raw)
  To: linux-arm-kernel

  Add vdso_mremap hook which will fix context.vdso pointer after mremap()
on vDSO vma. This is needed for correct landing after syscall execution.
Primary goal of this is for CRIU on arm - we need to restore vDSO image
at the exactly same place where the vma was in dumped application. With
the help of this hook we'll move vDSO at the new position.
  The CRIU code handles situations like when vDSO of dumped application
was different from vDSO on restoring system. This usally happens when
some new symbols are being added to vDSO. In these situations CRIU
inserts jump trampolines from old vDSO blob to new vDSO on restore.
By that reason even if on restore vDSO blob lies on the same address as
blob in dumped application - we still need to move it if it differs.

  There was previously attempt to add this functionality for arm64 by
arch_mremap hook [1], while this patch introduces this with minimal
effort - the same way I've added it to x86:
commit b059a453b1cf ("x86/vdso: Add mremap hook to vm_special_mapping")

  At this moment, vdso restoring code is disabled for arm/arm64 arch
in CRIU [2], so C/R is only working for !CONFIG_VDSO kernels. This patch
is aimed to fix that.
  The same hook may be introduced for arm64 kernel, but at this moment
arm64 vdso code is actively reworked by Kevin, so we can do it on top.
  Separately, I've refactored arch_remap hook out from ppc64 [3].

[1]: https://marc.info/?i=1448455781-26660-1-git-send-email-cov at codeaurora.org
[2]: https://github.com/xemul/criu/blob/master/Makefile#L39
[3]: https://marc.info/?i=20161027170948.8279-1-dsafonov at virtuozzo.com

Cc: Kevin Brodsky <kevin.brodsky@arm.com>
Cc: Christopher Covington <cov@codeaurora.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Will Deacon <will.deacon@arm.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-mm at kvack.org
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
---
 arch/arm/kernel/vdso.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c
index 53cf86cf2d1a..d1001f87c2f6 100644
--- a/arch/arm/kernel/vdso.c
+++ b/arch/arm/kernel/vdso.c
@@ -54,8 +54,11 @@ static const struct vm_special_mapping vdso_data_mapping = {
 	.pages = &vdso_data_page,
 };
 
+static int vdso_mremap(const struct vm_special_mapping *sm,
+		struct vm_area_struct *new_vma);
 static struct vm_special_mapping vdso_text_mapping __ro_after_init = {
 	.name = "[vdso]",
+	.mremap = vdso_mremap,
 };
 
 struct elfinfo {
@@ -254,6 +257,24 @@ void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
 		mm->context.vdso = addr;
 }
 
+static int vdso_mremap(const struct vm_special_mapping *sm,
+		struct vm_area_struct *new_vma)
+{
+	unsigned long new_size = new_vma->vm_end - new_vma->vm_start;
+	unsigned long vdso_size = (vdso_total_pages - 1) << PAGE_SHIFT;
+
+	/* Disallow partial vDSO blob remap */
+	if (vdso_size != new_size)
+		return -EINVAL;
+
+	if (WARN_ON_ONCE(current->mm != new_vma->vm_mm))
+		return -EFAULT;
+
+	current->mm->context.vdso = new_vma->vm_start;
+
+	return 0;
+}
+
 static void vdso_write_begin(struct vdso_data *vdata)
 {
 	++vdso_data->seq_count;
-- 
2.10.2

^ permalink raw reply related

* [RFC v2 2/7] arm: Use generic VDSO unmap and remap
From: Russell King - ARM Linux @ 2016-11-01 17:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161101171101.24704-2-cov@codeaurora.org>

You know, on its own, this patch is totally meaningless.  Sorry, there's
nothing more I can say about this.

On Tue, Nov 01, 2016 at 11:10:56AM -0600, Christopher Covington wrote:
> Checkpoint/Restore In Userspace (CRIU) needs to be able to unmap and remap
> the VDSO to successfully checkpoint and restore applications in the face of
> changing VDSO addresses due to Address Space Layout Randomization (ASLR,
> randmaps). Previously, this was implemented in architecture-specific code
> for PowerPC and x86. However, a generic version based on Laurent Dufour's
> PowerPC implementation is now available, so begin using it on ARM.
> 
> Signed-off-by: Christopher Covington <cov@codeaurora.org>
> ---
>  arch/arm/mm/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
> index c1799dd..1d3312b 100644
> --- a/arch/arm/mm/Kconfig
> +++ b/arch/arm/mm/Kconfig
> @@ -845,6 +845,7 @@ config VDSO
>  	depends on AEABI && MMU && CPU_V7
>  	default y if ARM_ARCH_TIMER
>  	select GENERIC_TIME_VSYSCALL
> +	select GENERIC_VDSO
>  	help
>  	  Place in the process address space an ELF shared object
>  	  providing fast implementations of gettimeofday and
> -- 
> Qualcomm Datacenter Technologies as an affiliate of Qualcomm Technologies, Inc.
> Qualcomm Technologies, Inc. is a member of the
> Code Aurora Forum, a Linux Foundation Collaborative Project.
> 

-- 
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

* [RFC v2 4/7] arm64: Use generic VDSO unmap and remap functions
From: Christopher Covington @ 2016-11-01 17:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161101171101.24704-1-cov@codeaurora.org>

Checkpoint/Restore In Userspace (CRIU) must be able to remap and unmap the
Virtual Dynamic Shared Object (VDSO) to be able to handle the changing
addresses that result from address space layout randomization. Now that
generic support is available and arm64 has adopted unsigned long for the
type of mm->context.vdso, opt-in to VDSO unmap and remap support.

Signed-off-by: Christopher Covington <cov@codeaurora.org>
---
 arch/arm64/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 969ef88..534df3f 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -50,6 +50,7 @@ config ARM64
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
 	select GENERIC_TIME_VSYSCALL
+	select GENERIC_VDSO
 	select HANDLE_DOMAIN_IRQ
 	select HARDIRQS_SW_RESEND
 	select HAVE_ALIGNED_STRUCT_PAGE if SLUB
-- 
Qualcomm Datacenter Technologies as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply related

* [RFC v2 3/7] arm64: Use unsigned long for VDSO
From: Christopher Covington @ 2016-11-01 17:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161101171101.24704-1-cov@codeaurora.org>

Use an unsigned long type for the base address of the VDSO in order to be
compatible with the new generic VDSO remap and unmap functions originating
from PowerPC and now also used by 32-bit ARM.

Signed-off-by: Christopher Covington <cov@codeaurora.org>
---
 arch/arm64/include/asm/mmu.h | 2 +-
 arch/arm64/kernel/vdso.c     | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 8d9fce0..5b00198 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -18,7 +18,7 @@
 
 typedef struct {
 	atomic64_t	id;
-	void		*vdso;
+	unsigned long	vdso;
 } mm_context_t;
 
 /*
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index a2c2478..4b10e72 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -97,7 +97,7 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)
 
 	if (down_write_killable(&mm->mmap_sem))
 		return -EINTR;
-	current->mm->context.vdso = (void *)addr;
+	current->mm->context.vdso = addr;
 
 	/* Map vectors page at the high address. */
 	ret = _install_special_mapping(mm, addr, PAGE_SIZE,
@@ -178,7 +178,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 		goto up_fail;
 
 	vdso_base += PAGE_SIZE;
-	mm->context.vdso = (void *)vdso_base;
+	mm->context.vdso = vdso_base;
 	ret = _install_special_mapping(mm, vdso_base, vdso_text_len,
 				       VM_READ|VM_EXEC|
 				       VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
@@ -191,7 +191,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 	return 0;
 
 up_fail:
-	mm->context.vdso = NULL;
+	mm->context.vdso = 0;
 	up_write(&mm->mmap_sem);
 	return PTR_ERR(ret);
 }
-- 
Qualcomm Datacenter Technologies as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply related

* [RFC v2 2/7] arm: Use generic VDSO unmap and remap
From: Christopher Covington @ 2016-11-01 17:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161101171101.24704-1-cov@codeaurora.org>

Checkpoint/Restore In Userspace (CRIU) needs to be able to unmap and remap
the VDSO to successfully checkpoint and restore applications in the face of
changing VDSO addresses due to Address Space Layout Randomization (ASLR,
randmaps). Previously, this was implemented in architecture-specific code
for PowerPC and x86. However, a generic version based on Laurent Dufour's
PowerPC implementation is now available, so begin using it on ARM.

Signed-off-by: Christopher Covington <cov@codeaurora.org>
---
 arch/arm/mm/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index c1799dd..1d3312b 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -845,6 +845,7 @@ config VDSO
 	depends on AEABI && MMU && CPU_V7
 	default y if ARM_ARCH_TIMER
 	select GENERIC_TIME_VSYSCALL
+	select GENERIC_VDSO
 	help
 	  Place in the process address space an ELF shared object
 	  providing fast implementations of gettimeofday and
-- 
Qualcomm Datacenter Technologies as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply related

* [PATCH v2 5/5] ARM: dts: imx6qdl-nitrogen6_max: use hyphens for nodes name
From: Gary Bisson @ 2016-11-01 17:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161101171006.24594-1-gary.bisson@boundarydevices.com>

Therefore aligning the panel nodes name across all platforms.

Signed-off-by: Gary Bisson <gary.bisson@boundarydevices.com>
---
 arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
index b0b3220..34887a1 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
@@ -229,7 +229,7 @@
 		};
 	};
 
-	backlight_lcd: backlight_lcd {
+	backlight_lcd: backlight-lcd {
 		compatible = "pwm-backlight";
 		pwms = <&pwm1 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -238,7 +238,7 @@
 		status = "okay";
 	};
 
-	backlight_lvds0: backlight_lvds0 {
+	backlight_lvds0: backlight-lvds0 {
 		compatible = "pwm-backlight";
 		pwms = <&pwm4 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -247,7 +247,7 @@
 		status = "okay";
 	};
 
-	backlight_lvds1: backlight_lvds1 {
+	backlight_lvds1: backlight-lvds1 {
 		compatible = "pwm-backlight";
 		pwms = <&pwm2 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -282,7 +282,7 @@
 		};
 	};
 
-	panel_lcd {
+	panel-lcd {
 		compatible = "okaya,rs800480t-7x0gp";
 		backlight = <&backlight_lcd>;
 
@@ -293,7 +293,7 @@
 		};
 	};
 
-	panel_lvds0 {
+	panel-lvds0 {
 		compatible = "hannstar,hsd100pxn1";
 		backlight = <&backlight_lvds0>;
 
@@ -304,7 +304,7 @@
 		};
 	};
 
-	panel_lvds1 {
+	panel-lvds1 {
 		compatible = "hannstar,hsd100pxn1";
 		backlight = <&backlight_lvds1>;
 
@@ -447,7 +447,7 @@
 };
 
 &iomuxc {
-	imx6q-nitrogen6_max {
+	imx6q-nitrogen6-max {
 		pinctrl_audmux: audmuxgrp {
 			fsl,pins = <
 				MX6QDL_PAD_CSI0_DAT7__AUD3_RXD		0x130b0
@@ -504,7 +504,7 @@
 			>;
 		};
 
-		pinctrl_gpio_keys: gpio_keysgrp {
+		pinctrl_gpio_keys: gpio-keysgrp {
 			fsl,pins = <
 				/* Power Button */
 				MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1b0b0
@@ -720,7 +720,7 @@
 			>;
 		};
 
-		pinctrl_wlan_vmmc: wlan_vmmcgrp {
+		pinctrl_wlan_vmmc: wlan-vmmcgrp {
 			fsl,pins = <
 				MX6QDL_PAD_NANDF_CS0__GPIO6_IO11	0x100b0
 				MX6QDL_PAD_NANDF_CS2__GPIO6_IO15	0x000b0
-- 
2.9.3

^ permalink raw reply related

* [PATCH v2 4/5] ARM: dts: imx6qdl-nit6xlite: use hyphens for nodes name
From: Gary Bisson @ 2016-11-01 17:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161101171006.24594-1-gary.bisson@boundarydevices.com>

Therefore aligning the panel nodes name across all platforms.

Also removing the bt_rfkill node since the mainline rfkill-gpio driver
doesn't support device trees.

Signed-off-by: Gary Bisson <gary.bisson@boundarydevices.com>
---
 arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi | 32 +++++---------------------------
 1 file changed, 5 insertions(+), 27 deletions(-)

diff --git a/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi b/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
index 880bd78..63acd54 100644
--- a/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
@@ -97,15 +97,6 @@
 		};
 	};
 
-	bt_rfkill {
-		compatible = "rfkill-gpio";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_bt_rfkill>;
-		gpios = <&gpio6 8 GPIO_ACTIVE_HIGH>;
-		name = "bt_rfkill";
-		type = <2>;
-	};
-
 	gpio-keys {
 		compatible = "gpio-keys";
 		pinctrl-names = "default";
@@ -160,7 +151,7 @@
 		};
 	};
 
-	backlight_lcd {
+	backlight-lcd {
 		compatible = "pwm-backlight";
 		pwms = <&pwm1 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -169,7 +160,7 @@
 		status = "okay";
 	};
 
-	backlight_lvds0: backlight_lvds0 {
+	backlight_lvds0: backlight-lvds0 {
 		compatible = "pwm-backlight";
 		pwms = <&pwm4 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -178,7 +169,7 @@
 		status = "okay";
 	};
 
-	panel_lvds0 {
+	panel-lvds0 {
 		compatible = "hannstar,hsd100pxn1";
 		backlight = <&backlight_lvds0>;
 
@@ -328,19 +319,6 @@
 			>;
 		};
 
-		pinctrl_bt_rfkill: bt_rfkillgrp {
-			fsl,pins = <
-				/* BT wake */
-				MX6QDL_PAD_NANDF_D2__GPIO2_IO02		0x1b0b0
-				/* BT reset */
-				MX6QDL_PAD_NANDF_ALE__GPIO6_IO08	0x0b0b0
-				/* BT reg en */
-				MX6QDL_PAD_NANDF_CS2__GPIO6_IO15	0x1b0b0
-				/* BT host wake irq */
-				MX6QDL_PAD_NANDF_CS3__GPIO6_IO16	0x100b0
-			>;
-		};
-
 		pinctrl_ecspi1: ecspi1grp {
 			fsl,pins = <
 				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
@@ -374,7 +352,7 @@
 			>;
 		};
 
-		pinctrl_gpio_keys: gpio_keysgrp {
+		pinctrl_gpio_keys: gpio-keysgrp {
 			fsl,pins = <
 				/* Home Button: J14 pin 5 */
 				MX6QDL_PAD_GPIO_18__GPIO7_IO13		0x1b0b0
@@ -457,7 +435,7 @@
 			>;
 		};
 
-		pinctrl_wlan_vmmc: wlan_vmmcgrp {
+		pinctrl_wlan_vmmc: wlan-vmmcgrp {
 			fsl,pins = <
 				MX6QDL_PAD_NANDF_CLE__GPIO6_IO07	0x030b0
 			>;
-- 
2.9.3

^ permalink raw reply related

* [PATCH v2 3/5] ARM: dts: imx6qdl-nitrogen6x: use hyphens for nodes name
From: Gary Bisson @ 2016-11-01 17:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161101171006.24594-1-gary.bisson@boundarydevices.com>

Also aligning the panel nodes name across all platforms.

Signed-off-by: Gary Bisson <gary.bisson@boundarydevices.com>
---
 arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
index db868bc..e476d01 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
@@ -167,7 +167,7 @@
 		mux-ext-port = <3>;
 	};
 
-	backlight_lcd: backlight_lcd {
+	backlight_lcd: backlight-lcd {
 		compatible = "pwm-backlight";
 		pwms = <&pwm1 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -176,7 +176,7 @@
 		status = "okay";
 	};
 
-	backlight_lvds: backlight_lvds {
+	backlight_lvds: backlight-lvds {
 		compatible = "pwm-backlight";
 		pwms = <&pwm4 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -211,7 +211,7 @@
 		};
 	};
 
-	lcd_panel {
+	panel-lcd {
 		compatible = "okaya,rs800480t-7x0gp";
 		backlight = <&backlight_lcd>;
 
@@ -222,7 +222,7 @@
 		};
 	};
 
-	panel {
+	panel-lvds0 {
 		compatible = "hannstar,hsd100pxn1";
 		backlight = <&backlight_lvds>;
 
@@ -413,7 +413,7 @@
 			>;
 		};
 
-		pinctrl_gpio_keys: gpio_keysgrp {
+		pinctrl_gpio_keys: gpio-keysgrp {
 			fsl,pins = <
 				/* Power Button */
 				MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1b0b0
@@ -561,7 +561,7 @@
 			>;
 		};
 
-		pinctrl_wlan_vmmc: wlan_vmmcgrp {
+		pinctrl_wlan_vmmc: wlan-vmmcgrp {
 			fsl,pins = <
 				MX6QDL_PAD_NANDF_CS0__GPIO6_IO11	0x100b0
 				MX6QDL_PAD_NANDF_CS2__GPIO6_IO15	0x000b0
-- 
2.9.3

^ permalink raw reply related

* [PATCH v2 2/5] ARM: dts: imx6qdl-sabrelite: use hyphens for nodes name
From: Gary Bisson @ 2016-11-01 17:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161101171006.24594-1-gary.bisson@boundarydevices.com>

Also aligning the panel nodes name across all platforms.

Signed-off-by: Gary Bisson <gary.bisson@boundarydevices.com>
---
 arch/arm/boot/dts/imx6qdl-sabrelite.dtsi | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
index 81dd6cd..1f9076e 100644
--- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
@@ -153,7 +153,7 @@
 		mux-ext-port = <4>;
 	};
 
-	backlight_lcd: backlight_lcd {
+	backlight_lcd: backlight-lcd {
 		compatible = "pwm-backlight";
 		pwms = <&pwm1 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -162,7 +162,7 @@
 		status = "okay";
 	};
 
-	backlight_lvds: backlight_lvds {
+	backlight_lvds: backlight-lvds {
 		compatible = "pwm-backlight";
 		pwms = <&pwm4 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -197,7 +197,7 @@
 		};
 	};
 
-	lcd_panel {
+	panel-lcd {
 		compatible = "okaya,rs800480t-7x0gp";
 		backlight = <&backlight_lcd>;
 
@@ -208,7 +208,7 @@
 		};
 	};
 
-	panel {
+	panel-lvds0 {
 		compatible = "hannstar,hsd100pxn1";
 		backlight = <&backlight_lvds>;
 
@@ -378,7 +378,7 @@
 			>;
 		};
 
-		pinctrl_gpio_keys: gpio_keysgrp {
+		pinctrl_gpio_keys: gpio-keysgrp {
 			fsl,pins = <
 				/* Power Button */
 				MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1b0b0
-- 
2.9.3

^ permalink raw reply related

* [PATCH v2 1/5] ARM: dts: imx: add Boundary Devices Nitrogen6_SOM2 support
From: Gary Bisson @ 2016-11-01 17:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161101171006.24594-1-gary.bisson@boundarydevices.com>

SoM based on i.MX6 Quad with 1GB of DDR3.

https://boundarydevices.com/product/nit6x-som-v2/

Signed-off-by: Gary Bisson <gary.bisson@boundarydevices.com>
---
 arch/arm/boot/dts/Makefile                    |   1 +
 arch/arm/boot/dts/imx6q-nitrogen6_som2.dts    |  53 ++
 arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi | 770 ++++++++++++++++++++++++++
 3 files changed, 824 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx6q-nitrogen6_som2.dts
 create mode 100644 arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 224e2a5..0572d68 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -387,6 +387,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6q-marsboard.dtb \
 	imx6q-nitrogen6x.dtb \
 	imx6q-nitrogen6_max.dtb \
+	imx6q-nitrogen6_som2.dtb \
 	imx6q-novena.dtb \
 	imx6q-phytec-pbab01.dtb \
 	imx6q-rex-pro.dtb \
diff --git a/arch/arm/boot/dts/imx6q-nitrogen6_som2.dts b/arch/arm/boot/dts/imx6q-nitrogen6_som2.dts
new file mode 100644
index 0000000..cf4feef
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-nitrogen6_som2.dts
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016 Boundary Devices, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6qdl-nitrogen6_som2.dtsi"
+
+/ {
+	model = "Boundary Devices i.MX6 Quad Nitrogen6_SOM2 Board";
+	compatible = "boundary,imx6q-nitrogen6_som2", "fsl,imx6q";
+};
+
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi
new file mode 100644
index 0000000..d80f21a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi
@@ -0,0 +1,770 @@
+/*
+ * Copyright 2016 Boundary Devices, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	backlight_lcd: backlight-lcd {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+		power-supply = <&reg_3p3v>;
+		status = "okay";
+	};
+
+	backlight_lvds0: backlight-lvds0 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm4 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+		power-supply = <&reg_3p3v>;
+		status = "okay";
+	};
+
+	backlight_lvds1: backlight-lvds1 {
+		compatible = "gpio-backlight";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_backlight_lvds1>;
+		gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>;
+		default-on;
+		status = "okay";
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_keys>;
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_POWER>;
+			wakeup-source;
+		};
+
+		menu {
+			label = "Menu";
+			gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_MENU>;
+		};
+
+		home {
+			label = "Home";
+			gpios = <&gpio2 4 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_HOME>;
+		};
+
+		back {
+			label = "Back";
+			gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_BACK>;
+		};
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio7 13 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEUP>;
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio7 1 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEDOWN>;
+		};
+	};
+
+	lcd_display: display at di0 {
+		compatible = "fsl,imx-parallel-display";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interface-pix-fmt = "bgr666";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_j15>;
+		status = "okay";
+
+		port at 0 {
+			reg = <0>;
+
+			lcd_display_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp0>;
+			};
+		};
+
+		port at 1 {
+			reg = <1>;
+
+			lcd_display_out: endpoint {
+				remote-endpoint = <&lcd_panel_in>;
+			};
+		};
+	};
+
+	panel-lcd {
+		compatible = "okaya,rs800480t-7x0gp";
+		backlight = <&backlight_lcd>;
+
+		port {
+			lcd_panel_in: endpoint {
+				remote-endpoint = <&lcd_display_out>;
+			};
+		};
+	};
+
+	panel-lvds0 {
+		compatible = "hannstar,hsd100pxn1";
+		backlight = <&backlight_lvds0>;
+
+		port {
+			panel_in_lvds0: endpoint {
+				remote-endpoint = <&lvds0_out>;
+			};
+		};
+	};
+
+	panel-lvds1 {
+		compatible = "hannstar,hsd100pxn1";
+		backlight = <&backlight_lvds1>;
+
+		port {
+			panel_in_lvds1: endpoint {
+				remote-endpoint = <&lvds1_out>;
+			};
+		};
+	};
+
+	reg_1p8v: regulator-1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "1P8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+	};
+
+	reg_2p5v: regulator-2v5 {
+		compatible = "regulator-fixed";
+		regulator-name = "2P5V";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_can_xcvr: regulator-can-xcvr {
+		compatible = "regulator-fixed";
+		regulator-name = "CAN XCVR";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_can_xcvr>;
+		gpio = <&gpio1 2 GPIO_ACTIVE_LOW>;
+	};
+
+	reg_usb_h1_vbus: regulator-usb-h1-vbus {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_usbh1>;
+		regulator-name = "usb_h1_vbus";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		regulator-always-on;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_wlan_vmmc: regulator-wlan-vmmc {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_wlan_vmmc>;
+		regulator-name = "reg_wlan_vmmc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio6 15 GPIO_ACTIVE_HIGH>;
+		startup-delay-us = <70000>;
+		enable-active-high;
+	};
+
+	sound {
+		compatible = "fsl,imx6q-nitrogen6_som2-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx6q-nitrogen6_som2-sgtl5000";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_sgtl5000>;
+		ssi-controller = <&ssi1>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <1>;
+		mux-ext-port = <3>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can1>;
+	xceiver-supply = <&reg_can_xcvr>;
+	status = "okay";
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
+				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+};
+
+&ecspi1 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	status = "okay";
+
+	flash: m25p80 at 0 {
+		compatible = "microchip,sst25vf016b";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
+			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
+	fsl,err006687-workaround-present;
+	status = "okay";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c2>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	codec: sgtl5000 at 0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+
+	rtc at 68 {
+		compatible = "st,rv4162";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_rv4162>;
+		reg = <0x68>;
+		interrupts-extended = <&gpio6 7 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	touchscreen at 04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+		wakeup-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
+	};
+
+	touchscreen at 38 {
+		compatible = "edt,edt-ft5x06";
+		reg = <0x38>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+	};
+};
+
+&iomuxc {
+	pinctrl_audmux: audmuxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT7__AUD3_RXD		0x130b0
+			MX6QDL_PAD_CSI0_DAT4__AUD3_TXC		0x130b0
+			MX6QDL_PAD_CSI0_DAT5__AUD3_TXD		0x110b0
+			MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS		0x130b0
+		>;
+	};
+
+	pinctrl_backlight_lvds1: backlight-lvds1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB3__GPIO2_IO31		0x0b0b0
+		>;
+	};
+
+	pinctrl_can1: can1grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX	0x1b0b0
+			MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX	0x1b0b0
+		>;
+	};
+
+	pinctrl_can_xcvr: can-xcvrgrp {
+		fsl,pins = <
+			/* Flexcan XCVR enable */
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x0b0b0
+		>;
+	};
+
+	pinctrl_ecspi1: ecspi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
+			MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
+			MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
+			MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x000b1
+		>;
+	};
+
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x100b0
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x100b0
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x100b0
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x100b0
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x100b0
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x100b0
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x100b0
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x130b0
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x130b0
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x130b0
+			MX6QDL_PAD_ENET_RXD0__GPIO1_IO27	0x030b0
+			MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x1b0b0
+			MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
+		>;
+	};
+
+	pinctrl_gpio_keys: gpio-keysgrp {
+		fsl,pins = <
+			/* Power Button */
+			MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1b0b0
+			/* Menu Button */
+			MX6QDL_PAD_NANDF_D1__GPIO2_IO01		0x1b0b0
+			/* Home Button */
+			MX6QDL_PAD_NANDF_D4__GPIO2_IO04		0x1b0b0
+			/* Back Button */
+			MX6QDL_PAD_NANDF_D2__GPIO2_IO02		0x1b0b0
+			/* Volume Up Button */
+			MX6QDL_PAD_GPIO_18__GPIO7_IO13		0x1b0b0
+			/* Volume Down Button */
+			MX6QDL_PAD_SD3_DAT4__GPIO7_IO01		0x1b0b0
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL	0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA	0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL	0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA	0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_5__I2C3_SCL	0x4001b8b1
+			MX6QDL_PAD_GPIO_16__I2C3_SDA	0x4001b8b1
+			MX6QDL_PAD_GPIO_9__GPIO1_IO09	0x1b0b0
+		>;
+	};
+
+	pinctrl_i2c3mux: i2c3muxgrp {
+		fsl,pins = <
+			/* PCIe I2C enable */
+			MX6QDL_PAD_EIM_OE__GPIO2_IO25	0x000b0
+		>;
+	};
+
+	pinctrl_j15: j15grp {
+		fsl,pins = <
+			MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+			MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15       0x10
+			MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02        0x10
+			MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03        0x10
+			MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00   0x10
+			MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01   0x10
+			MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02   0x10
+			MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03   0x10
+			MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04   0x10
+			MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05   0x10
+			MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06   0x10
+			MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07   0x10
+			MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08   0x10
+			MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09   0x10
+			MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10  0x10
+			MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11  0x10
+			MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12  0x10
+			MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13  0x10
+			MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14  0x10
+			MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15  0x10
+			MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16  0x10
+			MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17  0x10
+			MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18  0x10
+			MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19  0x10
+			MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20  0x10
+			MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21  0x10
+			MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22  0x10
+			MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23  0x10
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			/* PCIe reset */
+			MX6QDL_PAD_EIM_BCLK__GPIO6_IO31	0x030b0
+			MX6QDL_PAD_EIM_DA4__GPIO3_IO04	0x030b0
+		>;
+	};
+
+	pinctrl_pwm1: pwm1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT3__PWM1_OUT	0x030b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT	0x030b1
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__PWM4_OUT	0x030b1
+		>;
+	};
+
+	pinctrl_rv4162: rv4162grp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__GPIO6_IO07	0x1b0b0
+		>;
+	};
+
+	pinctrl_sgtl5000: sgtl5000grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_0__CCM_CLKO1		0x000b0
+			MX6QDL_PAD_EIM_D29__GPIO3_IO29		0x130b0
+			MX6QDL_PAD_EIM_DA2__GPIO3_IO02		0x130b0
+			MX6QDL_PAD_ENET_RX_ER__GPIO1_IO24	0x130b0
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D27__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D23__UART3_CTS_B		0x1b0b1
+			MX6QDL_PAD_EIM_D31__UART3_RTS_B		0x1b0b1
+		>;
+	};
+
+	pinctrl_usbh1: usbh1grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_17__GPIO7_IO12		0x030b0
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			MX6QDL_PAD_KEY_COL4__USB_OTG_OC		0x1b0b0
+			/* power enable, high active */
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x030b0
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_CLK__SD2_CLK		0x10071
+			MX6QDL_PAD_SD2_CMD__SD2_CMD		0x17071
+			MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x17071
+			MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17071
+			MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17071
+			MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17071
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10071
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17071
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17071
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17071
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17071
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17071
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x1b0b0
+		>;
+	};
+
+	pinctrl_usdhc4: usdhc4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_CMD__SD4_CMD		0x17059
+			MX6QDL_PAD_SD4_CLK__SD4_CLK		0x10059
+			MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x17059
+			MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x17059
+			MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x17059
+			MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x17059
+			MX6QDL_PAD_SD4_DAT4__SD4_DATA4		0x17059
+			MX6QDL_PAD_SD4_DAT5__SD4_DATA5		0x17059
+			MX6QDL_PAD_SD4_DAT6__SD4_DATA6		0x17059
+			MX6QDL_PAD_SD4_DAT7__SD4_DATA7		0x17059
+		>;
+	};
+
+	pinctrl_wlan_vmmc: wlan-vmmcgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CS1__GPIO6_IO14	0x100b0
+			MX6QDL_PAD_NANDF_CS2__GPIO6_IO15	0x030b0
+			MX6QDL_PAD_NANDF_CS3__GPIO6_IO16	0x030b0
+			MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT	0x000b0
+		>;
+	};
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&lcd_display_in>;
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel at 0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		port at 4 {
+			reg = <4>;
+
+			lvds0_out: endpoint {
+				remote-endpoint = <&panel_in_lvds0>;
+			};
+		};
+	};
+
+	lvds-channel at 1 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		port at 4 {
+			reg = <4>;
+
+			lvds1_out: endpoint {
+				remote-endpoint = <&panel_in_lvds1>;
+			};
+		};
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio6 31 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>;
+	status = "okay";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&ssi1 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	bus-width = <4>;
+	non-removable;
+	vmmc-supply = <&reg_wlan_vmmc>;
+	cap-power-off-card;
+	keep-power-in-suspend;
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore at 2 {
+		compatible = "ti,wl1271";
+		reg = <2>;
+		interrupt-parent = <&gpio6>;
+		interrupts = <14 IRQ_TYPE_LEVEL_HIGH>;
+		ref-clock-frequency = <38400000>;
+	};
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+	bus-width = <4>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	bus-width = <8>;
+	non-removable;
+	vmmc-supply = <&reg_1p8v>;
+	keep-power-in-suspend;
+	status = "okay";
+};
-- 
2.9.3

^ permalink raw reply related


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